swc_ecma_lexer/common/parser/
expr_ext.rs

1use swc_ecma_ast::{
2    EsReserved, Expr, MemberExpr, ParenExpr, TsAsExpr, TsInstantiation, TsNonNullExpr,
3    TsSatisfiesExpr, TsTypeAssertion,
4};
5
6pub trait ExprExt {
7    fn as_expr(&self) -> &Expr;
8
9    /// "IsValidSimpleAssignmentTarget" from spec.
10    fn is_valid_simple_assignment_target(&self, strict: bool) -> bool {
11        match self.as_expr() {
12            Expr::Ident(ident) => {
13                if strict && ident.is_reserved_in_strict_bind() {
14                    return false;
15                }
16                true
17            }
18
19            Expr::This(..)
20            | Expr::Lit(..)
21            | Expr::Array(..)
22            | Expr::Object(..)
23            | Expr::Fn(..)
24            | Expr::Class(..)
25            | Expr::Tpl(..)
26            | Expr::TaggedTpl(..) => false,
27            Expr::Paren(ParenExpr { expr, .. }) => expr.is_valid_simple_assignment_target(strict),
28
29            Expr::Member(MemberExpr { obj, .. }) => match obj.as_ref() {
30                Expr::Member(..) => obj.is_valid_simple_assignment_target(strict),
31                Expr::OptChain(..) => false,
32                _ => true,
33            },
34
35            Expr::SuperProp(..) => true,
36
37            Expr::New(..) | Expr::Call(..) => false,
38            // TODO: Spec only mentions `new.target`
39            Expr::MetaProp(..) => false,
40
41            Expr::Update(..) => false,
42
43            Expr::Unary(..) | Expr::Await(..) => false,
44
45            Expr::Bin(..) => false,
46
47            Expr::Cond(..) => false,
48
49            Expr::Yield(..) | Expr::Arrow(..) | Expr::Assign(..) => false,
50
51            Expr::Seq(..) => false,
52
53            Expr::OptChain(..) => false,
54
55            // MemberExpression is valid assignment target
56            Expr::PrivateName(..) => false,
57
58            // jsx
59            Expr::JSXMember(..)
60            | Expr::JSXNamespacedName(..)
61            | Expr::JSXEmpty(..)
62            | Expr::JSXElement(..)
63            | Expr::JSXFragment(..) => false,
64
65            // typescript
66            Expr::TsNonNull(TsNonNullExpr { ref expr, .. })
67            | Expr::TsTypeAssertion(TsTypeAssertion { ref expr, .. })
68            | Expr::TsAs(TsAsExpr { ref expr, .. })
69            | Expr::TsInstantiation(TsInstantiation { ref expr, .. })
70            | Expr::TsSatisfies(TsSatisfiesExpr { ref expr, .. }) => {
71                expr.is_valid_simple_assignment_target(strict)
72            }
73
74            Expr::TsConstAssertion(..) => false,
75
76            Expr::Invalid(..) => false,
77        }
78    }
79}
80
81impl ExprExt for Box<Expr> {
82    #[inline(always)]
83    fn as_expr(&self) -> &Expr {
84        self
85    }
86}
87impl ExprExt for Expr {
88    #[inline(always)]
89    fn as_expr(&self) -> &Expr {
90        self
91    }
92}