diff --git a/crates/swc/tests/tsc-references/deleteChain.1.normal.js b/crates/swc/tests/tsc-references/deleteChain.1.normal.js index 5b46be87487..b65d0770fa5 100644 --- a/crates/swc/tests/tsc-references/deleteChain.1.normal.js +++ b/crates/swc/tests/tsc-references/deleteChain.1.normal.js @@ -1,37 +1,15 @@ //// [deleteChain.ts] -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 4 | delete (o1?.b); -//! : ^^^^^ -//! `---- -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 8 | delete (o2?.b.c); -//! : ^^^^^^^ -//! `---- -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 12 | delete (o3.b?.c); -//! : ^^^^^^^ -//! `---- -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 17 | delete (o4.b?.c.d?.e); -//! : ^^^^^^^^^^^^ -//! `---- -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 21 | delete (o5.b?.().c.d?.e); -//! : ^^^^^^^^^^^^^^^ -//! `---- -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 25 | delete (o6.b?.['c'].d?.['e']); -//! : ^^^^^^^^^^^^^^^^^^^^ -//! `---- +var ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, ref10, ref11, ref12, ref13, ref14, ref15; +o1 === null || o1 === void 0 ? void 0 : delete o1.b; +delete (o1 === null || o1 === void 0 ? void 0 : o1.b); +o2 === null || o2 === void 0 ? void 0 : delete o2.b.c; +delete (o2 === null || o2 === void 0 ? void 0 : o2.b.c); +(ref = o3.b) === null || ref === void 0 ? void 0 : delete ref.c; +delete ((ref1 = o3.b) === null || ref1 === void 0 ? void 0 : ref1.c); +(ref3 = (ref2 = o4.b) === null || ref2 === void 0 ? void 0 : ref2.c.d) === null || ref3 === void 0 ? void 0 : delete ref3.e; +(ref5 = (ref4 = o4.b) === null || ref4 === void 0 ? void 0 : ref4.c.d) === null || ref5 === void 0 ? void 0 : delete ref5.e; +delete ((ref7 = (ref6 = o4.b) === null || ref6 === void 0 ? void 0 : ref6.c.d) === null || ref7 === void 0 ? void 0 : ref7.e); +(ref9 = (ref8 = o5.b) === null || ref8 === void 0 ? void 0 : ref8.call(o5).c.d) === null || ref9 === void 0 ? void 0 : delete ref9.e; +delete ((ref11 = (ref10 = o5.b) === null || ref10 === void 0 ? void 0 : ref10.call(o5).c.d) === null || ref11 === void 0 ? void 0 : ref11.e); +(ref13 = (ref12 = o6.b) === null || ref12 === void 0 ? void 0 : ref12["c"].d) === null || ref13 === void 0 ? void 0 : delete ref13["e"]; +delete ((ref15 = (ref14 = o6.b) === null || ref14 === void 0 ? void 0 : ref14["c"].d) === null || ref15 === void 0 ? void 0 : ref15["e"]); diff --git a/crates/swc/tests/tsc-references/deleteChain.2.minified.js b/crates/swc/tests/tsc-references/deleteChain.2.minified.js index 5b46be87487..cb841fa722d 100644 --- a/crates/swc/tests/tsc-references/deleteChain.2.minified.js +++ b/crates/swc/tests/tsc-references/deleteChain.2.minified.js @@ -1,37 +1,3 @@ //// [deleteChain.ts] -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 4 | delete (o1?.b); -//! : ^^^^^ -//! `---- -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 8 | delete (o2?.b.c); -//! : ^^^^^^^ -//! `---- -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 12 | delete (o3.b?.c); -//! : ^^^^^^^ -//! `---- -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 17 | delete (o4.b?.c.d?.e); -//! : ^^^^^^^^^^^^ -//! `---- -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 21 | delete (o5.b?.().c.d?.e); -//! : ^^^^^^^^^^^^^^^ -//! `---- -//! -//! x The operand of a delete operator must be a property reference. -//! ,---- -//! 25 | delete (o6.b?.['c'].d?.['e']); -//! : ^^^^^^^^^^^^^^^^^^^^ -//! `---- +var ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, ref10, ref11, ref12, ref13, ref14, ref15; +null == o1 || delete o1.b, delete (null == o1 ? void 0 : o1.b), null == o2 || delete o2.b.c, delete (null == o2 ? void 0 : o2.b.c), null === (ref = o3.b) || void 0 === ref || delete ref.c, delete (null === (ref1 = o3.b) || void 0 === ref1 ? void 0 : ref1.c), null === (ref3 = null === (ref2 = o4.b) || void 0 === ref2 ? void 0 : ref2.c.d) || void 0 === ref3 || delete ref3.e, null === (ref5 = null === (ref4 = o4.b) || void 0 === ref4 ? void 0 : ref4.c.d) || void 0 === ref5 || delete ref5.e, delete (null === (ref7 = null === (ref6 = o4.b) || void 0 === ref6 ? void 0 : ref6.c.d) || void 0 === ref7 ? void 0 : ref7.e), null === (ref9 = null === (ref8 = o5.b) || void 0 === ref8 ? void 0 : ref8.call(o5).c.d) || void 0 === ref9 || delete ref9.e, delete (null === (ref11 = null === (ref10 = o5.b) || void 0 === ref10 ? void 0 : ref10.call(o5).c.d) || void 0 === ref11 ? void 0 : ref11.e), null === (ref13 = null === (ref12 = o6.b) || void 0 === ref12 ? void 0 : ref12.c.d) || void 0 === ref13 || delete ref13.e, delete (null === (ref15 = null === (ref14 = o6.b) || void 0 === ref14 ? void 0 : ref14.c.d) || void 0 === ref15 ? void 0 : ref15.e); diff --git a/crates/swc_ecma_ast/src/expr.rs b/crates/swc_ecma_ast/src/expr.rs index 30470d815c0..c085f795f63 100644 --- a/crates/swc_ecma_ast/src/expr.rs +++ b/crates/swc_ecma_ast/src/expr.rs @@ -172,10 +172,11 @@ impl Expr { /// /// If `self` is not a parenthesized expression, it will be returned as is. pub fn unwrap_parens(&self) -> &Expr { - match self { - Expr::Paren(ParenExpr { expr, .. }) => expr.unwrap_parens(), - _ => self, + let mut cur = self; + while let Expr::Paren(ref expr) = cur { + cur = &expr.expr; } + cur } /// Normalize parenthesized expressions. @@ -184,10 +185,11 @@ impl Expr { /// /// If `self` is not a parenthesized expression, it will be returned as is. pub fn unwrap_parens_mut(&mut self) -> &mut Expr { - match self { - Expr::Paren(ParenExpr { expr, .. }) => expr.unwrap_parens_mut(), - _ => self, + let mut cur = self; + while let Expr::Paren(ref mut expr) = cur { + cur = &mut expr.expr; } + cur } /// Creates an expression from `exprs`. This will return first element if diff --git a/crates/swc_ecma_parser/src/parser/expr/ops.rs b/crates/swc_ecma_parser/src/parser/expr/ops.rs index e19ebeac26e..417e40daf18 100644 --- a/crates/swc_ecma_parser/src/parser/expr/ops.rs +++ b/crates/swc_ecma_parser/src/parser/expr/ops.rs @@ -294,19 +294,20 @@ impl Parser { } if self.input.syntax().typescript() && op == op!("delete") { - fn unwrap_paren(e: &Expr) -> &Expr { - match *e { - Expr::Paren(ref p) => unwrap_paren(&p.expr), - _ => e, + fn is_valid_arg(e: &Expr) -> bool { + match e { + Expr::Member(..) + | Expr::OptChain(OptChainExpr { + base: OptChainBase::Member(..), + .. + }) => true, + Expr::Paren(expr) => is_valid_arg(expr.expr.unwrap_parens()), + _ => false, } } - match &*arg { - Expr::Member(..) => {} - Expr::OptChain(OptChainExpr { - base: OptChainBase::Member(..), - .. - }) => {} - _ => self.emit_err(unwrap_paren(&arg).span(), SyntaxError::TS2703), + + if !is_valid_arg(&arg) { + self.emit_err(arg.unwrap_parens().span(), SyntaxError::TS2703); } }