fix(es/parser): Fix detection of wrong delete targets (#5754)

This commit is contained in:
IWANABETHATGUY 2022-09-05 21:36:24 +08:00 committed by GitHub
parent 912dd8f6a1
commit 9fc6eda89a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 89 deletions

View File

@ -1,37 +1,15 @@
//// [deleteChain.ts] //// [deleteChain.ts]
//! var ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, ref10, ref11, ref12, ref13, ref14, ref15;
//! x The operand of a delete operator must be a property reference. o1 === null || o1 === void 0 ? void 0 : delete o1.b;
//! ,---- delete (o1 === null || o1 === void 0 ? void 0 : o1.b);
//! 4 | delete (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);
//! x The operand of a delete operator must be a property reference. (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;
//! 8 | delete (o2?.b.c); 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"];
//! x The operand of a delete operator must be a property reference. delete ((ref15 = (ref14 = o6.b) === null || ref14 === void 0 ? void 0 : ref14["c"].d) === null || ref15 === void 0 ? void 0 : ref15["e"]);
//! ,----
//! 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']);
//! : ^^^^^^^^^^^^^^^^^^^^
//! `----

View File

@ -1,37 +1,3 @@
//// [deleteChain.ts] //// [deleteChain.ts]
//! var ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, ref10, ref11, ref12, ref13, ref14, ref15;
//! x The operand of a delete operator must be a property reference. 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);
//! ,----
//! 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']);
//! : ^^^^^^^^^^^^^^^^^^^^
//! `----

View File

@ -172,10 +172,11 @@ impl Expr {
/// ///
/// If `self` is not a parenthesized expression, it will be returned as is. /// If `self` is not a parenthesized expression, it will be returned as is.
pub fn unwrap_parens(&self) -> &Expr { pub fn unwrap_parens(&self) -> &Expr {
match self { let mut cur = self;
Expr::Paren(ParenExpr { expr, .. }) => expr.unwrap_parens(), while let Expr::Paren(ref expr) = cur {
_ => self, cur = &expr.expr;
} }
cur
} }
/// Normalize parenthesized expressions. /// Normalize parenthesized expressions.
@ -184,10 +185,11 @@ impl Expr {
/// ///
/// If `self` is not a parenthesized expression, it will be returned as is. /// If `self` is not a parenthesized expression, it will be returned as is.
pub fn unwrap_parens_mut(&mut self) -> &mut Expr { pub fn unwrap_parens_mut(&mut self) -> &mut Expr {
match self { let mut cur = self;
Expr::Paren(ParenExpr { expr, .. }) => expr.unwrap_parens_mut(), while let Expr::Paren(ref mut expr) = cur {
_ => self, cur = &mut expr.expr;
} }
cur
} }
/// Creates an expression from `exprs`. This will return first element if /// Creates an expression from `exprs`. This will return first element if

View File

@ -294,19 +294,20 @@ impl<I: Tokens> Parser<I> {
} }
if self.input.syntax().typescript() && op == op!("delete") { if self.input.syntax().typescript() && op == op!("delete") {
fn unwrap_paren(e: &Expr) -> &Expr { fn is_valid_arg(e: &Expr) -> bool {
match *e { match e {
Expr::Paren(ref p) => unwrap_paren(&p.expr), Expr::Member(..)
_ => e, | Expr::OptChain(OptChainExpr {
base: OptChainBase::Member(..),
..
}) => true,
Expr::Paren(expr) => is_valid_arg(expr.expr.unwrap_parens()),
_ => false,
} }
} }
match &*arg {
Expr::Member(..) => {} if !is_valid_arg(&arg) {
Expr::OptChain(OptChainExpr { self.emit_err(arg.unwrap_parens().span(), SyntaxError::TS2703);
base: OptChainBase::Member(..),
..
}) => {}
_ => self.emit_err(unwrap_paren(&arg).span(), SyntaxError::TS2703),
} }
} }