swc_ecma_transforms_base/resolver/
mod.rs

1use rustc_hash::{FxHashMap, FxHashSet};
2use swc_atoms::Atom;
3use swc_common::{Mark, SyntaxContext};
4use swc_ecma_ast::*;
5use swc_ecma_utils::{find_pat_ids, stack_size::maybe_grow_default};
6use swc_ecma_visit::{
7    noop_visit_mut_type, visit_mut_obj_and_computed, visit_mut_pass, VisitMut, VisitMutWith,
8};
9use tracing::{debug, span, Level};
10
11use crate::scope::{DeclKind, IdentType, ScopeKind};
12
13#[cfg(test)]
14mod tests;
15
16const LOG: bool = false && cfg!(debug_assertions);
17
18/// See [Ident] for know how does swc manages identifiers.
19///
20/// # When to run
21///
22/// The resolver expects 'clean' ast. You can get clean ast by parsing, or by
23/// removing all syntax context in ast nodes.
24///
25/// # What does it do
26///
27/// Firstly all scopes (fn, block) has it's own SyntaxContext.
28/// Resolver visits all identifiers in module, and look for binding identifies
29/// in the scope. Those identifiers now have the SyntaxContext of scope (fn,
30/// block). While doing so, resolver tries to resolve normal identifiers (no
31/// hygiene info) as a reference to identifier of scope. If the resolver find
32/// suitable variable, the identifier reference will have same context as the
33/// variable.
34///
35///
36/// # Panics
37///
38/// `top_level_mark` should not be root.
39///
40/// # Example
41///
42/// ```js
43/// let a = 1;
44/// {
45///     let a = 2;
46///     use(a);
47/// }
48/// use(a)
49/// ```
50///
51/// resolver does
52///
53/// 1. Define `a` with top level context.
54///
55/// 2. Found a block, so visit block with a new syntax context.
56///
57/// 3. Defined `a` with syntax context of the block statement.
58///
59/// 4. Found usage of `a`, and determines that it's reference to `a` in the
60///    block. So the reference to `a` will have same syntax context as `a` in
61///    the block.
62///
63/// 5. Found usage of `a` (last line), and determines that it's a reference to
64///    top-level `a`, and change syntax context of `a` on last line to top-level
65///    syntax context.
66///
67///
68/// # Parameters
69///
70/// ## `unresolved_mark`
71///
72/// [Mark] applied to unresolved references.
73///
74/// A pass should accept this [Mark] if it's going to generate a refernce to
75/// globals like `require`.
76///
77/// e.g. `common_js` pass generates calls to `require`, and this should not
78/// be shadowed by a declaration named `require` in the same file.
79/// So it uses this value.
80///
81/// ## `top_level_mark`
82///
83/// [Mark] applied to top-level bindings.
84///
85/// **NOTE**: This is **not** globals. This is for top level items declared by
86/// users.
87///
88/// A pass should accept this [Mark] if it requires user-defined top-level
89/// items.
90///
91/// e.g. `jsx` pass requires to call `React` imported by the user.
92///
93/// ```js
94/// import React from 'react';
95/// ```
96///
97/// In the code above, `React` has this [Mark]. `jsx` passes need to
98/// reference this [Mark], so it accpets this.
99///
100/// This [Mark] should be used for referencing top-level bindings written by
101/// user. If you are going to create a binding, use `private_ident`
102/// instead.
103///
104/// In other words, **this [Mark] should not be used for determining if a
105/// variable is top-level.** This is simply a configuration of the `resolver`
106/// pass.
107///
108///
109/// ## `typescript`
110///
111/// Enable this only if you are going to strip types or apply type-aware
112/// passes like decorators pass.
113///
114///
115/// # FAQ
116///
117/// ## Does a pair `(Atom, SyntaxContext)` always uniquely identifiers a
118/// variable binding?
119///
120/// Yes, but multiple variables can have the exactly same name.
121///
122/// In the code below,
123///
124/// ```js
125/// var a = 1, a = 2;
126/// ```
127///
128/// both of them have the same name, so the `(Atom, SyntaxContext)` pair will
129/// be also identical.
130pub fn resolver(
131    unresolved_mark: Mark,
132    top_level_mark: Mark,
133    typescript: bool,
134) -> impl 'static + Pass + VisitMut {
135    assert_ne!(
136        unresolved_mark,
137        Mark::root(),
138        "Marker provided to resolver should not be the root mark"
139    );
140
141    let _ = SyntaxContext::empty().apply_mark(unresolved_mark);
142    let _ = SyntaxContext::empty().apply_mark(top_level_mark);
143
144    visit_mut_pass(Resolver {
145        current: Scope::new(ScopeKind::Fn, top_level_mark, None),
146        ident_type: IdentType::Ref,
147        in_type: false,
148        is_module: false,
149        in_ts_module: false,
150        decl_kind: DeclKind::Lexical,
151        strict_mode: false,
152        config: InnerConfig {
153            handle_types: typescript,
154            unresolved_mark,
155            top_level_mark,
156        },
157    })
158}
159
160#[derive(Debug, Clone)]
161struct Scope<'a> {
162    /// Parent scope of the scope
163    parent: Option<&'a Scope<'a>>,
164
165    /// Kind of the scope.
166    kind: ScopeKind,
167
168    /// [Mark] of the current scope.
169    mark: Mark,
170
171    /// All declarations in the scope
172    declared_symbols: FxHashMap<Atom, DeclKind>,
173
174    /// All types declared in the scope
175    declared_types: FxHashSet<Atom>,
176}
177
178impl<'a> Scope<'a> {
179    pub fn new(kind: ScopeKind, mark: Mark, parent: Option<&'a Scope<'a>>) -> Self {
180        Scope {
181            parent,
182            kind,
183            mark,
184            declared_symbols: Default::default(),
185            declared_types: Default::default(),
186        }
187    }
188
189    fn is_declared(&self, symbol: &Atom) -> Option<&DeclKind> {
190        self.declared_symbols
191            .get(symbol)
192            .or_else(|| self.parent?.is_declared(symbol))
193    }
194}
195
196/// # Phases
197///
198/// ## Hoisting phase
199///
200/// ## Resolving phase
201struct Resolver<'a> {
202    current: Scope<'a>,
203    ident_type: IdentType,
204    in_type: bool,
205    is_module: bool,
206    in_ts_module: bool,
207    decl_kind: DeclKind,
208    strict_mode: bool,
209
210    config: InnerConfig,
211}
212
213#[derive(Debug, Clone, Copy)]
214struct InnerConfig {
215    handle_types: bool,
216    unresolved_mark: Mark,
217    top_level_mark: Mark,
218}
219
220#[allow(clippy::needless_lifetimes)]
221impl<'a> Resolver<'a> {
222    #[cfg(test)]
223    fn new(current: Scope<'a>, config: InnerConfig) -> Self {
224        Resolver {
225            current,
226            ident_type: IdentType::Ref,
227            in_type: false,
228            is_module: false,
229            in_ts_module: false,
230            config,
231            decl_kind: DeclKind::Lexical,
232            strict_mode: false,
233        }
234    }
235
236    fn with_child<F>(&self, kind: ScopeKind, op: F)
237    where
238        F: for<'aa> FnOnce(&mut Resolver<'aa>),
239    {
240        let mut child = Resolver {
241            current: Scope::new(
242                kind,
243                Mark::fresh(self.config.top_level_mark),
244                Some(&self.current),
245            ),
246            ident_type: IdentType::Ref,
247            config: self.config,
248            in_type: self.in_type,
249            is_module: self.is_module,
250            in_ts_module: self.in_ts_module,
251            decl_kind: self.decl_kind,
252            strict_mode: self.strict_mode,
253        };
254
255        op(&mut child);
256    }
257
258    fn visit_mut_stmt_within_child_scope(&mut self, s: &mut Stmt) {
259        self.with_child(ScopeKind::Block, |child| match s {
260            Stmt::Block(s) => {
261                child.mark_block(&mut s.ctxt);
262                s.visit_mut_children_with(child);
263            }
264            _ => s.visit_mut_with(child),
265        });
266    }
267
268    /// Returns a [Mark] for an identifier reference.
269    fn mark_for_ref(&self, sym: &Atom) -> Option<Mark> {
270        self.mark_for_ref_inner(sym, false)
271    }
272
273    fn mark_for_ref_inner(&self, sym: &Atom, stop_an_fn_scope: bool) -> Option<Mark> {
274        if self.config.handle_types && self.in_type {
275            let mut mark = self.current.mark;
276            let mut scope = Some(&self.current);
277
278            while let Some(cur) = scope {
279                // if cur.declared_types.contains(sym) ||
280                // cur.hoisted_symbols.borrow().contains(sym) {
281                if cur.declared_types.contains(sym) {
282                    if mark == Mark::root() {
283                        break;
284                    }
285                    return Some(mark);
286                }
287
288                if cur.kind == ScopeKind::Fn && stop_an_fn_scope {
289                    return None;
290                }
291
292                if let Some(parent) = &cur.parent {
293                    mark = parent.mark;
294                }
295                scope = cur.parent;
296            }
297        }
298
299        let mut mark = self.current.mark;
300        let mut scope = Some(&self.current);
301
302        while let Some(cur) = scope {
303            if cur.declared_symbols.contains_key(sym) {
304                if mark == Mark::root() {
305                    return None;
306                }
307
308                return match &**sym {
309                    // https://tc39.es/ecma262/multipage/global-object.html#sec-value-properties-of-the-global-object-infinity
310                    // non configurable global value
311                    "undefined" | "NaN" | "Infinity"
312                        if mark == self.config.top_level_mark && !self.is_module =>
313                    {
314                        Some(self.config.unresolved_mark)
315                    }
316                    _ => Some(mark),
317                };
318            }
319
320            if cur.kind == ScopeKind::Fn && stop_an_fn_scope {
321                return None;
322            }
323
324            if let Some(parent) = &cur.parent {
325                mark = parent.mark;
326            }
327            scope = cur.parent;
328        }
329
330        None
331    }
332
333    /// Modifies a binding identifier.
334    fn modify(&mut self, id: &mut Ident, kind: DeclKind) {
335        if cfg!(debug_assertions) && LOG {
336            debug!(
337                "Binding (type = {}) {}{:?} {:?}",
338                self.in_type, id.sym, id.ctxt, kind
339            );
340        }
341
342        if id.ctxt != SyntaxContext::empty() {
343            return;
344        }
345
346        if self.in_type {
347            self.current.declared_types.insert(id.sym.clone());
348        } else {
349            self.current.declared_symbols.insert(id.sym.clone(), kind);
350        }
351
352        let mark = self.current.mark;
353
354        if mark != Mark::root() {
355            id.ctxt = id.ctxt.apply_mark(mark);
356        }
357    }
358
359    fn mark_block(&mut self, ctxt: &mut SyntaxContext) {
360        if *ctxt != SyntaxContext::empty() {
361            return;
362        }
363
364        let mark = self.current.mark;
365
366        if mark != Mark::root() {
367            *ctxt = ctxt.apply_mark(mark)
368        }
369    }
370
371    fn try_resolving_as_type(&mut self, i: &mut Ident) {
372        if i.ctxt.outer() == self.config.unresolved_mark {
373            i.ctxt = SyntaxContext::empty()
374        }
375
376        self.in_type = true;
377        i.visit_mut_with(self);
378        self.in_type = false;
379    }
380}
381
382macro_rules! typed {
383    ($name:ident, $T:ty) => {
384        fn $name(&mut self, node: &mut $T) {
385            if self.config.handle_types {
386                node.visit_mut_children_with(self)
387            }
388        }
389    };
390}
391
392macro_rules! typed_ref {
393    ($name:ident, $T:ty) => {
394        fn $name(&mut self, node: &mut $T) {
395            if self.config.handle_types {
396                let in_type = self.in_type;
397                let ident_type = self.ident_type;
398                self.in_type = true;
399                node.visit_mut_children_with(self);
400                self.ident_type = ident_type;
401                self.in_type = in_type;
402            }
403        }
404    };
405}
406
407macro_rules! typed_ref_init {
408    ($name:ident, $T:ty) => {
409        fn $name(&mut self, node: &mut $T) {
410            if self.config.handle_types {
411                let in_type = self.in_type;
412                let ident_type = self.ident_type;
413                self.ident_type = IdentType::Ref;
414                self.in_type = true;
415                node.visit_mut_children_with(self);
416                self.ident_type = ident_type;
417                self.in_type = in_type;
418            }
419        }
420    };
421}
422
423macro_rules! typed_decl {
424    ($name:ident, $T:ty) => {
425        fn $name(&mut self, node: &mut $T) {
426            if self.config.handle_types {
427                let in_type = self.in_type;
428                self.ident_type = IdentType::Binding;
429                self.in_type = true;
430                node.visit_mut_children_with(self);
431                self.in_type = in_type;
432            }
433        }
434    };
435}
436
437macro_rules! noop {
438    ($name:ident, $T:ty) => {
439        #[inline]
440        fn $name(&mut self, _: &mut $T) {}
441    };
442}
443
444impl VisitMut for Resolver<'_> {
445    noop!(visit_mut_accessibility, Accessibility);
446
447    noop!(visit_mut_true_plus_minus, TruePlusMinus);
448
449    noop!(visit_mut_ts_keyword_type, TsKeywordType);
450
451    noop!(visit_mut_ts_keyword_type_kind, TsKeywordTypeKind);
452
453    noop!(visit_mut_ts_type_operator_op, TsTypeOperatorOp);
454
455    noop!(visit_mut_ts_enum_member_id, TsEnumMemberId);
456
457    noop!(visit_mut_ts_external_module_ref, TsExternalModuleRef);
458
459    noop!(visit_mut_ts_module_name, TsModuleName);
460
461    noop!(visit_mut_ts_this_type, TsThisType);
462
463    typed_ref!(visit_mut_ts_array_type, TsArrayType);
464
465    typed_ref!(visit_mut_ts_conditional_type, TsConditionalType);
466
467    typed_ref_init!(
468        visit_mut_ts_type_param_instantiation,
469        TsTypeParamInstantiation
470    );
471
472    typed_ref!(visit_mut_ts_type_query, TsTypeQuery);
473
474    typed_ref!(visit_mut_ts_type_query_expr, TsTypeQueryExpr);
475
476    typed_ref!(visit_mut_ts_type_operator, TsTypeOperator);
477
478    typed_ref_init!(visit_mut_ts_type, TsType);
479
480    typed_ref_init!(visit_mut_ts_type_ann, TsTypeAnn);
481
482    typed!(
483        visit_mut_ts_union_or_intersection_type,
484        TsUnionOrIntersectionType
485    );
486
487    typed!(visit_mut_ts_fn_or_constructor_type, TsFnOrConstructorType);
488
489    typed_ref!(visit_mut_ts_union_type, TsUnionType);
490
491    typed_ref!(visit_mut_ts_infer_type, TsInferType);
492
493    typed_ref!(visit_mut_ts_tuple_type, TsTupleType);
494
495    typed_ref!(visit_mut_ts_intersection_type, TsIntersectionType);
496
497    typed_ref!(visit_mut_ts_type_ref, TsTypeRef);
498
499    typed_decl!(visit_mut_ts_type_param_decl, TsTypeParamDecl);
500
501    typed!(visit_mut_ts_fn_param, TsFnParam);
502
503    typed!(visit_mut_ts_indexed_access_type, TsIndexedAccessType);
504
505    typed!(visit_mut_ts_index_signature, TsIndexSignature);
506
507    typed!(visit_mut_ts_interface_body, TsInterfaceBody);
508
509    typed!(visit_mut_ts_parenthesized_type, TsParenthesizedType);
510
511    typed!(visit_mut_ts_type_lit, TsTypeLit);
512
513    typed!(visit_mut_ts_type_element, TsTypeElement);
514
515    typed!(visit_mut_ts_optional_type, TsOptionalType);
516
517    typed!(visit_mut_ts_rest_type, TsRestType);
518
519    typed!(visit_mut_ts_type_predicate, TsTypePredicate);
520
521    typed_ref!(visit_mut_ts_this_type_or_ident, TsThisTypeOrIdent);
522
523    visit_mut_obj_and_computed!();
524
525    // TODO: How should I handle this?
526    typed!(visit_mut_ts_namespace_export_decl, TsNamespaceExportDecl);
527
528    fn visit_mut_arrow_expr(&mut self, e: &mut ArrowExpr) {
529        self.with_child(ScopeKind::Fn, |child| {
530            e.type_params.visit_mut_with(child);
531
532            let old = child.ident_type;
533            child.ident_type = IdentType::Binding;
534            {
535                let params = e
536                    .params
537                    .iter()
538                    .filter(|p| !p.is_rest())
539                    .flat_map(find_pat_ids::<_, Id>);
540
541                for id in params {
542                    child.current.declared_symbols.insert(id.0, DeclKind::Param);
543                }
544            }
545            e.params.visit_mut_with(child);
546            child.ident_type = old;
547
548            match &mut *e.body {
549                BlockStmtOrExpr::BlockStmt(s) => {
550                    child.mark_block(&mut s.ctxt);
551
552                    let old_strict_mode = child.strict_mode;
553
554                    if !child.strict_mode {
555                        child.strict_mode = s
556                            .stmts
557                            .first()
558                            .map(|stmt| stmt.is_use_strict())
559                            .unwrap_or(false);
560                    }
561                    // Prevent creating new scope.
562                    s.stmts.visit_mut_with(child);
563                    child.strict_mode = old_strict_mode;
564                }
565                BlockStmtOrExpr::Expr(e) => e.visit_mut_with(child),
566            }
567
568            e.return_type.visit_mut_with(child);
569        });
570    }
571
572    fn visit_mut_assign_pat(&mut self, node: &mut AssignPat) {
573        // visit the type first so that it doesn't resolve any
574        // identifiers from the others
575        node.left.visit_mut_with(self);
576        node.right.visit_mut_with(self);
577    }
578
579    fn visit_mut_binding_ident(&mut self, i: &mut BindingIdent) {
580        let ident_type = self.ident_type;
581        let in_type = self.in_type;
582
583        self.ident_type = IdentType::Ref;
584        i.type_ann.visit_mut_with(self);
585
586        self.ident_type = ident_type;
587        i.id.visit_mut_with(self);
588
589        self.in_type = in_type;
590        self.ident_type = ident_type;
591    }
592
593    fn visit_mut_block_stmt(&mut self, block: &mut BlockStmt) {
594        self.with_child(ScopeKind::Block, |child| {
595            child.mark_block(&mut block.ctxt);
596            block.visit_mut_children_with(child);
597        })
598    }
599
600    fn visit_mut_break_stmt(&mut self, s: &mut BreakStmt) {
601        let old = self.ident_type;
602        self.ident_type = IdentType::Label;
603        s.label.visit_mut_with(self);
604        self.ident_type = old;
605    }
606
607    fn visit_mut_catch_clause(&mut self, c: &mut CatchClause) {
608        // Child folder
609
610        self.with_child(ScopeKind::Fn, |child| {
611            child.ident_type = IdentType::Binding;
612            c.param.visit_mut_with(child);
613            child.ident_type = IdentType::Ref;
614
615            child.mark_block(&mut c.body.ctxt);
616            c.body.visit_mut_children_with(child);
617        });
618    }
619
620    fn visit_mut_class(&mut self, c: &mut Class) {
621        let old_strict_mode = self.strict_mode;
622        self.strict_mode = true;
623
624        let old = self.ident_type;
625        self.ident_type = IdentType::Ref;
626        c.decorators.visit_mut_with(self);
627
628        self.ident_type = IdentType::Ref;
629        c.super_class.visit_mut_with(self);
630
631        self.ident_type = IdentType::Binding;
632        c.type_params.visit_mut_with(self);
633
634        self.ident_type = IdentType::Ref;
635        c.super_type_params.visit_mut_with(self);
636
637        self.ident_type = IdentType::Ref;
638        c.implements.visit_mut_with(self);
639        self.ident_type = old;
640
641        c.body.visit_mut_with(self);
642        self.strict_mode = old_strict_mode;
643    }
644
645    fn visit_mut_class_decl(&mut self, n: &mut ClassDecl) {
646        if n.declare && !self.config.handle_types {
647            return;
648        }
649        self.modify(&mut n.ident, DeclKind::Lexical);
650
651        n.class.decorators.visit_mut_with(self);
652
653        // Create a child scope. The class name is only accessible within the class.
654
655        self.with_child(ScopeKind::Fn, |child| {
656            child.ident_type = IdentType::Ref;
657
658            n.class.visit_mut_with(child);
659        });
660    }
661
662    fn visit_mut_class_expr(&mut self, n: &mut ClassExpr) {
663        // Create a child scope. The class name is only accessible within the class.
664
665        n.class.super_class.visit_mut_with(self);
666
667        self.with_child(ScopeKind::Fn, |child| {
668            child.ident_type = IdentType::Binding;
669            n.ident.visit_mut_with(child);
670            child.ident_type = IdentType::Ref;
671
672            n.class.visit_mut_with(child);
673        });
674    }
675
676    fn visit_mut_class_method(&mut self, m: &mut ClassMethod) {
677        m.key.visit_mut_with(self);
678
679        for p in m.function.params.iter_mut() {
680            p.decorators.visit_mut_with(self);
681        }
682
683        self.with_child(ScopeKind::Fn, |child| m.function.visit_mut_with(child));
684    }
685
686    fn visit_mut_class_prop(&mut self, p: &mut ClassProp) {
687        p.decorators.visit_mut_with(self);
688
689        if let PropName::Computed(key) = &mut p.key {
690            let old = self.ident_type;
691            self.ident_type = IdentType::Binding;
692            key.expr.visit_mut_with(self);
693            self.ident_type = old;
694        }
695
696        let old = self.ident_type;
697        self.ident_type = IdentType::Ref;
698        p.value.visit_mut_with(self);
699        self.ident_type = old;
700
701        p.type_ann.visit_mut_with(self);
702    }
703
704    fn visit_mut_constructor(&mut self, c: &mut Constructor) {
705        for p in c.params.iter_mut() {
706            match p {
707                ParamOrTsParamProp::TsParamProp(p) => {
708                    p.decorators.visit_mut_with(self);
709                }
710                ParamOrTsParamProp::Param(p) => {
711                    p.decorators.visit_mut_with(self);
712                }
713            }
714        }
715
716        self.with_child(ScopeKind::Fn, |child| {
717            let old = child.ident_type;
718            child.ident_type = IdentType::Binding;
719            {
720                let params = c
721                    .params
722                    .iter()
723                    .filter(|p| match p {
724                        ParamOrTsParamProp::TsParamProp(_) => false,
725                        ParamOrTsParamProp::Param(p) => !p.pat.is_rest(),
726                    })
727                    .flat_map(find_pat_ids::<_, Id>);
728
729                for id in params {
730                    child.current.declared_symbols.insert(id.0, DeclKind::Param);
731                }
732            }
733            c.params.visit_mut_with(child);
734            child.ident_type = old;
735
736            if let Some(body) = &mut c.body {
737                child.mark_block(&mut body.ctxt);
738                body.visit_mut_children_with(child);
739            }
740        });
741    }
742
743    fn visit_mut_continue_stmt(&mut self, s: &mut ContinueStmt) {
744        let old = self.ident_type;
745        self.ident_type = IdentType::Label;
746        s.label.visit_mut_with(self);
747        self.ident_type = old;
748    }
749
750    fn visit_mut_export_default_decl(&mut self, e: &mut ExportDefaultDecl) {
751        // Treat default exported functions and classes as declarations
752        // even though they are parsed as expressions.
753        match &mut e.decl {
754            DefaultDecl::Fn(f) => {
755                if f.ident.is_some() {
756                    self.with_child(ScopeKind::Fn, |child| {
757                        f.function.visit_mut_with(child);
758                    });
759                } else {
760                    f.visit_mut_with(self)
761                }
762            }
763            DefaultDecl::Class(c) => {
764                // Skip class expression visitor to treat as a declaration.
765                c.class.visit_mut_with(self)
766            }
767            _ => e.visit_mut_children_with(self),
768        }
769    }
770
771    fn visit_mut_export_default_expr(&mut self, node: &mut ExportDefaultExpr) {
772        node.expr.visit_mut_with(self);
773
774        if self.config.handle_types {
775            if let Expr::Ident(i) = &mut *node.expr {
776                self.try_resolving_as_type(i);
777            }
778        }
779    }
780
781    fn visit_mut_export_named_specifier(&mut self, e: &mut ExportNamedSpecifier) {
782        e.visit_mut_children_with(self);
783
784        if self.config.handle_types {
785            match &mut e.orig {
786                ModuleExportName::Ident(orig) => {
787                    self.try_resolving_as_type(orig);
788                }
789                ModuleExportName::Str(_) => {}
790            }
791        }
792    }
793
794    fn visit_mut_export_specifier(&mut self, s: &mut ExportSpecifier) {
795        let old = self.ident_type;
796        self.ident_type = IdentType::Ref;
797        s.visit_mut_children_with(self);
798        self.ident_type = old;
799    }
800
801    fn visit_mut_expr(&mut self, expr: &mut Expr) {
802        let _span = if LOG {
803            Some(span!(Level::ERROR, "visit_mut_expr").entered())
804        } else {
805            None
806        };
807
808        let old = self.ident_type;
809        self.ident_type = IdentType::Ref;
810        maybe_grow_default(|| expr.visit_mut_children_with(self));
811        self.ident_type = old;
812    }
813
814    fn visit_mut_fn_decl(&mut self, node: &mut FnDecl) {
815        if node.declare && !self.config.handle_types {
816            return;
817        }
818
819        // We don't fold ident as Hoister handles this.
820        node.function.decorators.visit_mut_with(self);
821
822        self.with_child(ScopeKind::Fn, |child| node.function.visit_mut_with(child));
823    }
824
825    fn visit_mut_fn_expr(&mut self, e: &mut FnExpr) {
826        e.function.decorators.visit_mut_with(self);
827
828        if let Some(ident) = &mut e.ident {
829            self.with_child(ScopeKind::Fn, |child| {
830                child.modify(ident, DeclKind::Function);
831                child.with_child(ScopeKind::Fn, |child| {
832                    e.function.visit_mut_with(child);
833                });
834            });
835        } else {
836            self.with_child(ScopeKind::Fn, |child| {
837                e.function.visit_mut_with(child);
838            });
839        }
840    }
841
842    fn visit_mut_for_in_stmt(&mut self, n: &mut ForInStmt) {
843        self.with_child(ScopeKind::Block, |child| {
844            n.left.visit_mut_with(child);
845            n.right.visit_mut_with(child);
846
847            child.visit_mut_stmt_within_child_scope(&mut n.body);
848        });
849    }
850
851    fn visit_mut_for_of_stmt(&mut self, n: &mut ForOfStmt) {
852        self.with_child(ScopeKind::Block, |child| {
853            n.left.visit_mut_with(child);
854            n.right.visit_mut_with(child);
855
856            child.visit_mut_stmt_within_child_scope(&mut n.body);
857        });
858    }
859
860    fn visit_mut_for_stmt(&mut self, n: &mut ForStmt) {
861        self.with_child(ScopeKind::Block, |child| {
862            child.ident_type = IdentType::Binding;
863            n.init.visit_mut_with(child);
864            child.ident_type = IdentType::Ref;
865            n.test.visit_mut_with(child);
866            child.ident_type = IdentType::Ref;
867            n.update.visit_mut_with(child);
868
869            child.visit_mut_stmt_within_child_scope(&mut n.body);
870        });
871    }
872
873    fn visit_mut_function(&mut self, f: &mut Function) {
874        self.mark_block(&mut f.ctxt);
875        f.type_params.visit_mut_with(self);
876
877        self.ident_type = IdentType::Ref;
878        f.decorators.visit_mut_with(self);
879
880        {
881            let params = f
882                .params
883                .iter()
884                .filter(|p| !p.pat.is_rest())
885                .flat_map(find_pat_ids::<_, Id>);
886
887            for id in params {
888                self.current.declared_symbols.insert(id.0, DeclKind::Param);
889            }
890        }
891        self.ident_type = IdentType::Binding;
892        f.params.visit_mut_with(self);
893
894        f.return_type.visit_mut_with(self);
895
896        self.ident_type = IdentType::Ref;
897        if let Some(body) = &mut f.body {
898            self.mark_block(&mut body.ctxt);
899            let old_strict_mode = self.strict_mode;
900            if !self.strict_mode {
901                self.strict_mode = body
902                    .stmts
903                    .first()
904                    .map(|stmt| stmt.is_use_strict())
905                    .unwrap_or(false);
906            }
907            // Prevent creating new scope.
908            body.visit_mut_children_with(self);
909            self.strict_mode = old_strict_mode;
910        }
911    }
912
913    fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) {
914        let old = self.ident_type;
915        self.ident_type = IdentType::Ref;
916        f.key.visit_mut_with(self);
917        self.ident_type = old;
918
919        f.type_ann.visit_mut_with(self);
920
921        f.body.visit_mut_with(self);
922    }
923
924    fn visit_mut_jsx_element_name(&mut self, node: &mut JSXElementName) {
925        if let JSXElementName::Ident(i) = node {
926            if i.as_ref().starts_with(|c: char| c.is_ascii_lowercase()) {
927                if cfg!(debug_assertions) && LOG {
928                    debug!("\t -> JSXElementName");
929                }
930
931                let ctxt = i.ctxt.apply_mark(self.config.unresolved_mark);
932
933                if cfg!(debug_assertions) && LOG {
934                    debug!("\t -> {:?}", ctxt);
935                }
936
937                i.ctxt = ctxt;
938
939                return;
940            }
941        }
942
943        node.visit_mut_children_with(self);
944    }
945
946    fn visit_mut_ident(&mut self, i: &mut Ident) {
947        if i.ctxt != SyntaxContext::empty() {
948            return;
949        }
950
951        match self.ident_type {
952            IdentType::Binding => self.modify(i, self.decl_kind),
953            IdentType::Ref => {
954                let Ident { sym, ctxt, .. } = i;
955
956                if cfg!(debug_assertions) && LOG {
957                    debug!("IdentRef (type = {}) {}{:?}", self.in_type, sym, ctxt);
958                }
959
960                if *ctxt != SyntaxContext::empty() {
961                    return;
962                }
963
964                if let Some(mark) = self.mark_for_ref(sym) {
965                    let ctxt = ctxt.apply_mark(mark);
966
967                    if cfg!(debug_assertions) && LOG {
968                        debug!("\t -> {:?}", ctxt);
969                    }
970                    i.ctxt = ctxt;
971                } else {
972                    if cfg!(debug_assertions) && LOG {
973                        debug!("\t -> Unresolved");
974                    }
975
976                    let ctxt = ctxt.apply_mark(self.config.unresolved_mark);
977
978                    if cfg!(debug_assertions) && LOG {
979                        debug!("\t -> {:?}", ctxt);
980                    }
981
982                    i.ctxt = ctxt;
983                    // Support hoisting
984                    self.modify(i, self.decl_kind)
985                }
986            }
987            // We currently does not touch labels
988            IdentType::Label => {}
989        }
990    }
991
992    fn visit_mut_import_decl(&mut self, n: &mut ImportDecl) {
993        // Always resolve the import declaration identifiers even if it's type only.
994        // We need to analyze these identifiers for type stripping purposes.
995        self.ident_type = IdentType::Binding;
996        let old_in_type = self.in_type;
997        self.in_type = n.type_only;
998        n.visit_mut_children_with(self);
999        self.in_type = old_in_type;
1000    }
1001
1002    fn visit_mut_import_named_specifier(&mut self, s: &mut ImportNamedSpecifier) {
1003        let old = self.ident_type;
1004        self.ident_type = IdentType::Binding;
1005        s.local.visit_mut_with(self);
1006        if self.config.handle_types {
1007            self.current.declared_types.insert(s.local.sym.clone());
1008        }
1009        self.ident_type = old;
1010    }
1011
1012    fn visit_mut_import_specifier(&mut self, s: &mut ImportSpecifier) {
1013        let old = self.ident_type;
1014        self.ident_type = IdentType::Binding;
1015
1016        match s {
1017            ImportSpecifier::Named(ImportNamedSpecifier { imported: None, .. })
1018            | ImportSpecifier::Namespace(..)
1019            | ImportSpecifier::Default(..) => s.visit_mut_children_with(self),
1020            ImportSpecifier::Named(s) => s.local.visit_mut_with(self),
1021        }
1022
1023        self.ident_type = old;
1024    }
1025
1026    /// Ignore.
1027    ///
1028    /// See https://github.com/swc-project/swc/issues/2854
1029    fn visit_mut_jsx_attr_name(&mut self, _: &mut JSXAttrName) {}
1030
1031    fn visit_mut_key_value_pat_prop(&mut self, n: &mut KeyValuePatProp) {
1032        n.key.visit_mut_with(self);
1033        n.value.visit_mut_with(self);
1034    }
1035
1036    fn visit_mut_labeled_stmt(&mut self, s: &mut LabeledStmt) {
1037        let old = self.ident_type;
1038        self.ident_type = IdentType::Label;
1039        s.label.visit_mut_with(self);
1040        self.ident_type = old;
1041
1042        s.body.visit_mut_with(self);
1043    }
1044
1045    fn visit_mut_method_prop(&mut self, m: &mut MethodProp) {
1046        m.key.visit_mut_with(self);
1047
1048        // Child folder
1049        self.with_child(ScopeKind::Fn, |child| m.function.visit_mut_with(child));
1050    }
1051
1052    fn visit_mut_module(&mut self, module: &mut Module) {
1053        self.strict_mode = true;
1054        self.is_module = true;
1055        module.visit_mut_children_with(self)
1056    }
1057
1058    fn visit_mut_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
1059        if !self.in_ts_module && self.current.kind != ScopeKind::Fn {
1060            return stmts.visit_mut_children_with(self);
1061        }
1062
1063        // Phase 1: Handle hoisting
1064        {
1065            let mut hoister = Hoister {
1066                kind: self.decl_kind,
1067                resolver: self,
1068                in_block: false,
1069                in_catch_body: false,
1070                catch_param_decls: Default::default(),
1071                excluded_from_catch: Default::default(),
1072            };
1073            stmts.visit_mut_with(&mut hoister)
1074        }
1075
1076        // Phase 2.
1077        stmts.visit_mut_children_with(self)
1078    }
1079
1080    fn visit_mut_named_export(&mut self, e: &mut NamedExport) {
1081        if e.src.is_some() {
1082            return;
1083        }
1084
1085        e.visit_mut_children_with(self);
1086    }
1087
1088    fn visit_mut_object_lit(&mut self, o: &mut ObjectLit) {
1089        self.with_child(ScopeKind::Block, |child| {
1090            o.visit_mut_children_with(child);
1091        });
1092    }
1093
1094    fn visit_mut_param(&mut self, param: &mut Param) {
1095        self.ident_type = IdentType::Binding;
1096        param.visit_mut_children_with(self);
1097    }
1098
1099    fn visit_mut_pat(&mut self, p: &mut Pat) {
1100        p.visit_mut_children_with(self);
1101    }
1102
1103    fn visit_mut_private_method(&mut self, m: &mut PrivateMethod) {
1104        m.key.visit_mut_with(self);
1105
1106        {
1107            // Child folder
1108
1109            self.with_child(ScopeKind::Fn, |child| m.function.visit_mut_with(child));
1110        }
1111    }
1112
1113    fn visit_mut_private_name(&mut self, _: &mut PrivateName) {}
1114
1115    fn visit_mut_prop_name(&mut self, n: &mut PropName) {
1116        if let PropName::Computed(c) = n {
1117            c.visit_mut_with(self);
1118        }
1119    }
1120
1121    fn visit_mut_rest_pat(&mut self, node: &mut RestPat) {
1122        node.arg.visit_mut_with(self);
1123        node.type_ann.visit_mut_with(self);
1124    }
1125
1126    fn visit_mut_script(&mut self, script: &mut Script) {
1127        self.strict_mode = script
1128            .body
1129            .first()
1130            .map(|stmt| stmt.is_use_strict())
1131            .unwrap_or(false);
1132        script.visit_mut_children_with(self)
1133    }
1134
1135    fn visit_mut_setter_prop(&mut self, n: &mut SetterProp) {
1136        n.key.visit_mut_with(self);
1137
1138        {
1139            self.with_child(ScopeKind::Fn, |child| {
1140                child.ident_type = IdentType::Binding;
1141                n.this_param.visit_mut_with(child);
1142                n.param.visit_mut_with(child);
1143                n.body.visit_mut_with(child);
1144            });
1145        };
1146    }
1147
1148    fn visit_mut_stmts(&mut self, stmts: &mut Vec<Stmt>) {
1149        let _span = if LOG {
1150            Some(span!(Level::ERROR, "visit_mut_stmts").entered())
1151        } else {
1152            None
1153        };
1154
1155        // Phase 1: Handle hoisting
1156        {
1157            let _span = if LOG {
1158                Some(span!(Level::ERROR, "hoist").entered())
1159            } else {
1160                None
1161            };
1162
1163            let mut hoister = Hoister {
1164                kind: self.decl_kind,
1165                resolver: self,
1166                in_block: false,
1167                in_catch_body: false,
1168                catch_param_decls: Default::default(),
1169                excluded_from_catch: Default::default(),
1170            };
1171            stmts.visit_mut_with(&mut hoister)
1172        }
1173
1174        // Phase 2.
1175        stmts.visit_mut_children_with(self)
1176    }
1177
1178    fn visit_mut_switch_case(&mut self, n: &mut SwitchCase) {
1179        n.cons.visit_mut_with(self);
1180
1181        n.test.visit_mut_with(self);
1182    }
1183
1184    fn visit_mut_switch_stmt(&mut self, s: &mut SwitchStmt) {
1185        s.discriminant.visit_mut_with(self);
1186
1187        self.with_child(ScopeKind::Block, |child| {
1188            s.cases.visit_mut_with(child);
1189        });
1190    }
1191
1192    fn visit_mut_ts_as_expr(&mut self, n: &mut TsAsExpr) {
1193        if self.config.handle_types {
1194            n.type_ann.visit_mut_with(self);
1195        }
1196
1197        n.expr.visit_mut_with(self);
1198    }
1199
1200    fn visit_mut_ts_call_signature_decl(&mut self, n: &mut TsCallSignatureDecl) {
1201        if !self.config.handle_types {
1202            return;
1203        }
1204
1205        self.with_child(ScopeKind::Fn, |child| {
1206            child.in_type = true;
1207
1208            n.type_params.visit_mut_with(child);
1209            n.params.visit_mut_with(child);
1210            n.type_ann.visit_mut_with(child);
1211        });
1212    }
1213
1214    fn visit_mut_ts_construct_signature_decl(&mut self, decl: &mut TsConstructSignatureDecl) {
1215        if !self.config.handle_types {
1216            return;
1217        }
1218
1219        // Child folder
1220        self.with_child(ScopeKind::Fn, |child| {
1221            child.in_type = true;
1222
1223            // order is important
1224            decl.type_params.visit_mut_with(child);
1225            decl.params.visit_mut_with(child);
1226            decl.type_ann.visit_mut_with(child);
1227        });
1228    }
1229
1230    fn visit_mut_ts_constructor_type(&mut self, ty: &mut TsConstructorType) {
1231        if !self.config.handle_types {
1232            return;
1233        }
1234
1235        self.with_child(ScopeKind::Fn, |child| {
1236            child.in_type = true;
1237
1238            ty.type_params.visit_mut_with(child);
1239            ty.params.visit_mut_with(child);
1240            ty.type_ann.visit_mut_with(child);
1241        });
1242    }
1243
1244    fn visit_mut_ts_enum_decl(&mut self, decl: &mut TsEnumDecl) {
1245        if decl.declare && !self.config.handle_types {
1246            return;
1247        }
1248        self.modify(&mut decl.id, DeclKind::Lexical);
1249
1250        self.with_child(ScopeKind::Block, |child| {
1251            // add the enum member names as declared symbols for this scope
1252            // Ex. `enum Foo { a, b = a }`
1253            let member_names = decl.members.iter().filter_map(|m| match &m.id {
1254                TsEnumMemberId::Ident(id) => Some((id.sym.clone(), DeclKind::Lexical)),
1255                TsEnumMemberId::Str(_) => None,
1256            });
1257            child.current.declared_symbols.extend(member_names);
1258
1259            decl.members.visit_mut_with(child);
1260        });
1261    }
1262
1263    fn visit_mut_ts_export_assignment(&mut self, node: &mut TsExportAssignment) {
1264        node.expr.visit_mut_with(self);
1265
1266        if self.config.handle_types {
1267            if let Some(i) = leftmost(&mut node.expr) {
1268                self.try_resolving_as_type(i);
1269            }
1270        }
1271    }
1272
1273    fn visit_mut_ts_expr_with_type_args(&mut self, n: &mut TsExprWithTypeArgs) {
1274        if self.config.handle_types {
1275            let old = self.in_type;
1276            self.in_type = true;
1277            n.visit_mut_children_with(self);
1278            self.in_type = old;
1279        }
1280    }
1281
1282    fn visit_mut_ts_fn_type(&mut self, ty: &mut TsFnType) {
1283        if !self.config.handle_types {
1284            return;
1285        }
1286
1287        self.with_child(ScopeKind::Fn, |child| {
1288            child.in_type = true;
1289
1290            ty.type_params.visit_mut_with(child);
1291            ty.params.visit_mut_with(child);
1292            ty.type_ann.visit_mut_with(child);
1293        });
1294    }
1295
1296    fn visit_mut_ts_getter_signature(&mut self, n: &mut TsGetterSignature) {
1297        if n.computed {
1298            n.key.visit_mut_with(self);
1299        }
1300
1301        n.type_ann.visit_mut_with(self);
1302    }
1303
1304    fn visit_mut_ts_import_equals_decl(&mut self, n: &mut TsImportEqualsDecl) {
1305        self.modify(&mut n.id, DeclKind::Lexical);
1306
1307        n.module_ref.visit_mut_with(self);
1308    }
1309
1310    fn visit_mut_ts_import_type(&mut self, n: &mut TsImportType) {
1311        if !self.config.handle_types {
1312            return;
1313        }
1314
1315        n.type_args.visit_mut_with(self);
1316    }
1317
1318    fn visit_mut_ts_interface_decl(&mut self, n: &mut TsInterfaceDecl) {
1319        // always resolve the identifier for type stripping purposes
1320        let old_in_type = self.in_type;
1321        let old_ident_type = self.ident_type;
1322
1323        self.in_type = true;
1324        self.ident_type = IdentType::Ref;
1325
1326        self.modify(&mut n.id, DeclKind::Type);
1327
1328        if !self.config.handle_types {
1329            self.in_type = old_in_type;
1330            self.ident_type = old_ident_type;
1331            return;
1332        }
1333
1334        self.with_child(ScopeKind::Fn, |child| {
1335            child.in_type = true;
1336
1337            n.type_params.visit_mut_with(child);
1338            n.extends.visit_mut_with(child);
1339            n.body.visit_mut_with(child);
1340        });
1341
1342        self.in_type = old_in_type;
1343        self.ident_type = old_ident_type;
1344    }
1345
1346    fn visit_mut_ts_mapped_type(&mut self, n: &mut TsMappedType) {
1347        if !self.config.handle_types {
1348            return;
1349        }
1350
1351        self.ident_type = IdentType::Binding;
1352        n.type_param.visit_mut_with(self);
1353        self.ident_type = IdentType::Ref;
1354        n.name_type.visit_mut_with(self);
1355
1356        self.ident_type = IdentType::Ref;
1357        n.type_ann.visit_mut_with(self);
1358    }
1359
1360    fn visit_mut_ts_method_signature(&mut self, n: &mut TsMethodSignature) {
1361        if !self.config.handle_types {
1362            return;
1363        }
1364
1365        self.with_child(ScopeKind::Fn, |child| {
1366            child.in_type = true;
1367
1368            n.type_params.visit_mut_with(child);
1369            if n.computed {
1370                n.key.visit_mut_with(child);
1371            }
1372            n.params.visit_mut_with(child);
1373            n.type_ann.visit_mut_with(child);
1374        });
1375    }
1376
1377    fn visit_mut_ts_module_decl(&mut self, decl: &mut TsModuleDecl) {
1378        if decl.declare && !self.config.handle_types {
1379            return;
1380        }
1381
1382        match &mut decl.id {
1383            TsModuleName::Ident(i) => {
1384                self.modify(i, DeclKind::Lexical);
1385            }
1386            TsModuleName::Str(_) => {}
1387        }
1388
1389        self.with_child(ScopeKind::Block, |child| {
1390            child.in_ts_module = true;
1391
1392            decl.body.visit_mut_children_with(child);
1393        });
1394    }
1395
1396    fn visit_mut_ts_namespace_decl(&mut self, n: &mut TsNamespaceDecl) {
1397        if n.declare && !self.config.handle_types {
1398            return;
1399        }
1400
1401        self.modify(&mut n.id, DeclKind::Lexical);
1402
1403        n.body.visit_mut_with(self);
1404    }
1405
1406    fn visit_mut_ts_param_prop_param(&mut self, n: &mut TsParamPropParam) {
1407        self.ident_type = IdentType::Binding;
1408        n.visit_mut_children_with(self)
1409    }
1410
1411    fn visit_mut_ts_property_signature(&mut self, n: &mut TsPropertySignature) {
1412        if !self.config.handle_types {
1413            return;
1414        }
1415
1416        if n.computed {
1417            n.key.visit_mut_with(self);
1418        }
1419
1420        self.with_child(ScopeKind::Fn, |child| {
1421            child.in_type = true;
1422
1423            n.type_ann.visit_mut_with(child);
1424        });
1425    }
1426
1427    fn visit_mut_ts_qualified_name(&mut self, n: &mut TsQualifiedName) {
1428        self.ident_type = IdentType::Ref;
1429
1430        n.left.visit_mut_with(self)
1431    }
1432
1433    fn visit_mut_ts_satisfies_expr(&mut self, n: &mut TsSatisfiesExpr) {
1434        if self.config.handle_types {
1435            n.type_ann.visit_mut_with(self);
1436        }
1437
1438        n.expr.visit_mut_with(self);
1439    }
1440
1441    fn visit_mut_ts_setter_signature(&mut self, n: &mut TsSetterSignature) {
1442        if n.computed {
1443            n.key.visit_mut_with(self);
1444        }
1445
1446        n.param.visit_mut_with(self);
1447    }
1448
1449    fn visit_mut_ts_tuple_element(&mut self, e: &mut TsTupleElement) {
1450        if !self.config.handle_types {
1451            return;
1452        }
1453        self.ident_type = IdentType::Ref;
1454        e.ty.visit_mut_with(self);
1455    }
1456
1457    fn visit_mut_ts_type_alias_decl(&mut self, n: &mut TsTypeAliasDecl) {
1458        // always resolve the identifier for type stripping purposes
1459        let old_in_type = self.in_type;
1460        self.in_type = true;
1461        self.modify(&mut n.id, DeclKind::Type);
1462
1463        if !self.config.handle_types {
1464            self.in_type = old_in_type;
1465            return;
1466        }
1467
1468        self.with_child(ScopeKind::Fn, |child| {
1469            child.in_type = true;
1470
1471            n.type_params.visit_mut_with(child);
1472            n.type_ann.visit_mut_with(child);
1473        });
1474        self.in_type = old_in_type;
1475    }
1476
1477    fn visit_mut_ts_type_assertion(&mut self, n: &mut TsTypeAssertion) {
1478        if self.config.handle_types {
1479            n.type_ann.visit_mut_with(self);
1480        }
1481
1482        n.expr.visit_mut_with(self);
1483    }
1484
1485    fn visit_mut_ts_type_param(&mut self, param: &mut TsTypeParam) {
1486        if !self.config.handle_types {
1487            return;
1488        }
1489        param.name.visit_mut_with(self);
1490
1491        let ident_type = self.ident_type;
1492        param.default.visit_mut_with(self);
1493        param.constraint.visit_mut_with(self);
1494        self.ident_type = ident_type;
1495    }
1496
1497    fn visit_mut_ts_type_params(&mut self, params: &mut Vec<TsTypeParam>) {
1498        for param in params.iter_mut() {
1499            param.name.visit_mut_with(self);
1500        }
1501
1502        params.visit_mut_children_with(self);
1503    }
1504
1505    fn visit_mut_using_decl(&mut self, decl: &mut UsingDecl) {
1506        let old_kind = self.decl_kind;
1507        self.decl_kind = DeclKind::Lexical;
1508        decl.decls.visit_mut_with(self);
1509        self.decl_kind = old_kind;
1510    }
1511
1512    fn visit_mut_var_decl(&mut self, decl: &mut VarDecl) {
1513        if decl.declare && !self.config.handle_types {
1514            return;
1515        }
1516
1517        let old_kind = self.decl_kind;
1518        self.decl_kind = decl.kind.into();
1519        decl.decls.visit_mut_with(self);
1520        self.decl_kind = old_kind;
1521    }
1522
1523    fn visit_mut_var_declarator(&mut self, decl: &mut VarDeclarator) {
1524        // order is important
1525
1526        let old_type = self.ident_type;
1527        self.ident_type = IdentType::Binding;
1528        decl.name.visit_mut_with(self);
1529        self.ident_type = old_type;
1530
1531        decl.init.visit_mut_children_with(self);
1532    }
1533}
1534
1535fn leftmost(expr: &mut Expr) -> Option<&mut Ident> {
1536    match expr {
1537        Expr::Ident(i) => Some(i),
1538        Expr::Member(MemberExpr { obj, .. }) => leftmost(obj),
1539        Expr::Paren(ParenExpr { expr, .. }) => leftmost(expr),
1540        _ => None,
1541    }
1542}
1543
1544/// The folder which handles var / function hoisting.
1545struct Hoister<'a, 'b> {
1546    resolver: &'a mut Resolver<'b>,
1547    kind: DeclKind,
1548    /// Hoister should not touch let / const in the block.
1549    in_block: bool,
1550
1551    in_catch_body: bool,
1552
1553    excluded_from_catch: FxHashSet<Atom>,
1554    catch_param_decls: FxHashSet<Atom>,
1555}
1556
1557impl Hoister<'_, '_> {
1558    fn add_pat_id(&mut self, id: &mut BindingIdent) {
1559        if self.in_catch_body {
1560            // If we have a binding, it's different variable.
1561            if self.resolver.mark_for_ref_inner(&id.sym, true).is_some()
1562                && self.catch_param_decls.contains(&id.sym)
1563            {
1564                return;
1565            }
1566
1567            self.excluded_from_catch.insert(id.sym.clone());
1568        } else {
1569            // Behavior is different
1570            if self.catch_param_decls.contains(&id.sym)
1571                && !self.excluded_from_catch.contains(&id.sym)
1572            {
1573                return;
1574            }
1575        }
1576
1577        self.resolver.modify(id, self.kind)
1578    }
1579}
1580
1581impl VisitMut for Hoister<'_, '_> {
1582    noop_visit_mut_type!();
1583
1584    #[inline]
1585    fn visit_mut_arrow_expr(&mut self, _: &mut ArrowExpr) {}
1586
1587    fn visit_mut_assign_pat_prop(&mut self, node: &mut AssignPatProp) {
1588        node.visit_mut_children_with(self);
1589
1590        self.add_pat_id(&mut node.key);
1591    }
1592
1593    fn visit_mut_block_stmt(&mut self, n: &mut BlockStmt) {
1594        let old_in_block = self.in_block;
1595        self.in_block = true;
1596        n.visit_mut_children_with(self);
1597        self.in_block = old_in_block;
1598    }
1599
1600    /// The code below prints "PASS"
1601    ///
1602    /// ```js
1603    /// 
1604    ///      var a = "PASS";
1605    ///      try {
1606    ///          throw "FAIL1";
1607    ///          } catch (a) {
1608    ///          var a = "FAIL2";
1609    ///      }
1610    ///      console.log(a);
1611    /// ```
1612    ///
1613    /// While the code below does not throw **ReferenceError** for `b`
1614    ///
1615    /// ```js
1616    /// 
1617    ///      b()
1618    ///      try {
1619    ///      } catch (b) {
1620    ///          var b;
1621    ///      }
1622    /// ```
1623    ///
1624    /// while the code below throws **ReferenceError**
1625    ///
1626    /// ```js
1627    /// 
1628    ///      b()
1629    ///      try {
1630    ///      } catch (b) {
1631    ///      }
1632    /// ```
1633    #[inline]
1634    fn visit_mut_catch_clause(&mut self, c: &mut CatchClause) {
1635        let old_exclude = self.excluded_from_catch.clone();
1636        self.excluded_from_catch = Default::default();
1637
1638        let old_in_catch_body = self.in_catch_body;
1639
1640        let params: Vec<Id> = find_pat_ids(&c.param);
1641
1642        let orig = self.catch_param_decls.clone();
1643
1644        self.catch_param_decls
1645            .extend(params.into_iter().map(|v| v.0));
1646
1647        self.in_catch_body = true;
1648        c.body.visit_mut_with(self);
1649
1650        // let mut excluded = find_ids::<_, Id>(&c.body);
1651
1652        // excluded.retain(|id| {
1653        //     // If we already have a declartion named a, `var a` in the catch body is
1654        //     // different var.
1655
1656        //     self.resolver.mark_for_ref(&id.0).is_none()
1657        // });
1658
1659        self.in_catch_body = false;
1660        c.param.visit_mut_with(self);
1661
1662        self.catch_param_decls = orig;
1663
1664        self.in_catch_body = old_in_catch_body;
1665        self.excluded_from_catch = old_exclude;
1666    }
1667
1668    fn visit_mut_class_decl(&mut self, node: &mut ClassDecl) {
1669        if node.declare && !self.resolver.config.handle_types {
1670            return;
1671        }
1672        if self.in_block {
1673            return;
1674        }
1675        self.resolver.modify(&mut node.ident, DeclKind::Lexical);
1676
1677        if self.resolver.config.handle_types {
1678            self.resolver
1679                .current
1680                .declared_types
1681                .insert(node.ident.sym.clone());
1682        }
1683    }
1684
1685    #[inline]
1686    fn visit_mut_constructor(&mut self, _: &mut Constructor) {}
1687
1688    #[inline]
1689    fn visit_mut_decl(&mut self, decl: &mut Decl) {
1690        decl.visit_mut_children_with(self);
1691
1692        if self.resolver.config.handle_types {
1693            match decl {
1694                Decl::TsInterface(i) => {
1695                    if self.in_block {
1696                        return;
1697                    }
1698
1699                    let old_in_type = self.resolver.in_type;
1700                    self.resolver.in_type = true;
1701                    self.resolver.modify(&mut i.id, DeclKind::Type);
1702                    self.resolver.in_type = old_in_type;
1703                }
1704
1705                Decl::TsTypeAlias(a) => {
1706                    let old_in_type = self.resolver.in_type;
1707                    self.resolver.in_type = true;
1708                    self.resolver.modify(&mut a.id, DeclKind::Type);
1709                    self.resolver.in_type = old_in_type;
1710                }
1711
1712                Decl::TsEnum(e) => {
1713                    if !self.in_block {
1714                        let old_in_type = self.resolver.in_type;
1715                        self.resolver.in_type = false;
1716                        self.resolver.modify(&mut e.id, DeclKind::Lexical);
1717                        self.resolver.in_type = old_in_type;
1718                    }
1719                }
1720
1721                Decl::TsModule(v)
1722                    if matches!(
1723                        &**v,
1724                        TsModuleDecl {
1725                            global: false,
1726                            id: TsModuleName::Ident(_),
1727                            ..
1728                        },
1729                    ) =>
1730                {
1731                    if !self.in_block {
1732                        let old_in_type = self.resolver.in_type;
1733                        self.resolver.in_type = false;
1734                        let id = v.id.as_mut_ident().unwrap();
1735                        self.resolver.modify(id, DeclKind::Lexical);
1736                        self.resolver.in_type = old_in_type;
1737                    }
1738                }
1739                _ => {}
1740            }
1741        }
1742    }
1743
1744    fn visit_mut_export_default_decl(&mut self, node: &mut ExportDefaultDecl) {
1745        // Treat default exported functions and classes as declarations
1746        // even though they are parsed as expressions.
1747        match &mut node.decl {
1748            DefaultDecl::Fn(f) => {
1749                if let Some(id) = &mut f.ident {
1750                    self.resolver.modify(id, DeclKind::Var);
1751                }
1752
1753                f.visit_mut_with(self)
1754            }
1755            DefaultDecl::Class(c) => {
1756                if let Some(id) = &mut c.ident {
1757                    self.resolver.modify(id, DeclKind::Lexical);
1758                }
1759
1760                c.visit_mut_with(self)
1761            }
1762            _ => {
1763                node.visit_mut_children_with(self);
1764            }
1765        }
1766    }
1767
1768    #[inline]
1769    fn visit_mut_expr(&mut self, _: &mut Expr) {}
1770
1771    fn visit_mut_fn_decl(&mut self, node: &mut FnDecl) {
1772        if node.declare && !self.resolver.config.handle_types {
1773            return;
1774        }
1775
1776        if self.catch_param_decls.contains(&node.ident.sym) {
1777            return;
1778        }
1779
1780        if self.in_block {
1781            // function declaration is block scoped in strict mode
1782            if self.resolver.strict_mode {
1783                return;
1784            }
1785            // If we are in nested block, and variable named `foo` is lexically declared or
1786            // a parameter, we should ignore function foo while handling upper scopes.
1787            if let Some(DeclKind::Lexical | DeclKind::Param) =
1788                self.resolver.current.is_declared(&node.ident.sym)
1789            {
1790                return;
1791            }
1792        }
1793
1794        self.resolver.modify(&mut node.ident, DeclKind::Function);
1795    }
1796
1797    #[inline]
1798    fn visit_mut_function(&mut self, _: &mut Function) {}
1799
1800    fn visit_mut_import_default_specifier(&mut self, n: &mut ImportDefaultSpecifier) {
1801        n.visit_mut_children_with(self);
1802
1803        self.resolver.modify(&mut n.local, DeclKind::Lexical);
1804
1805        if self.resolver.config.handle_types {
1806            self.resolver
1807                .current
1808                .declared_types
1809                .insert(n.local.sym.clone());
1810        }
1811    }
1812
1813    fn visit_mut_import_named_specifier(&mut self, n: &mut ImportNamedSpecifier) {
1814        n.visit_mut_children_with(self);
1815
1816        self.resolver.modify(&mut n.local, DeclKind::Lexical);
1817
1818        if self.resolver.config.handle_types {
1819            self.resolver
1820                .current
1821                .declared_types
1822                .insert(n.local.sym.clone());
1823        }
1824    }
1825
1826    fn visit_mut_import_star_as_specifier(&mut self, n: &mut ImportStarAsSpecifier) {
1827        n.visit_mut_children_with(self);
1828
1829        self.resolver.modify(&mut n.local, DeclKind::Lexical);
1830
1831        if self.resolver.config.handle_types {
1832            self.resolver
1833                .current
1834                .declared_types
1835                .insert(n.local.sym.clone());
1836        }
1837    }
1838
1839    #[inline]
1840    fn visit_mut_param(&mut self, _: &mut Param) {}
1841
1842    fn visit_mut_pat(&mut self, node: &mut Pat) {
1843        match node {
1844            Pat::Ident(i) => {
1845                self.add_pat_id(i);
1846            }
1847
1848            _ => node.visit_mut_children_with(self),
1849        }
1850    }
1851
1852    #[inline]
1853    fn visit_mut_assign_target(&mut self, _: &mut AssignTarget) {}
1854
1855    #[inline]
1856    fn visit_mut_setter_prop(&mut self, _: &mut SetterProp) {}
1857
1858    fn visit_mut_switch_stmt(&mut self, s: &mut SwitchStmt) {
1859        s.discriminant.visit_mut_with(self);
1860
1861        let old_in_block = self.in_block;
1862        self.in_block = true;
1863        s.cases.visit_mut_with(self);
1864        self.in_block = old_in_block;
1865    }
1866
1867    #[inline]
1868    fn visit_mut_tagged_tpl(&mut self, _: &mut TaggedTpl) {}
1869
1870    #[inline]
1871    fn visit_mut_tpl(&mut self, _: &mut Tpl) {}
1872
1873    #[inline]
1874    fn visit_mut_ts_module_block(&mut self, _: &mut TsModuleBlock) {}
1875
1876    #[inline]
1877    fn visit_mut_using_decl(&mut self, _: &mut UsingDecl) {}
1878
1879    fn visit_mut_var_decl(&mut self, node: &mut VarDecl) {
1880        if node.declare && !self.resolver.config.handle_types {
1881            return;
1882        }
1883
1884        if self.in_block {
1885            match node.kind {
1886                VarDeclKind::Const | VarDeclKind::Let => return,
1887                _ => {}
1888            }
1889        }
1890
1891        let old_kind = self.kind;
1892        self.kind = node.kind.into();
1893
1894        node.visit_mut_children_with(self);
1895
1896        self.kind = old_kind;
1897    }
1898
1899    fn visit_mut_var_decl_or_expr(&mut self, n: &mut VarDeclOrExpr) {
1900        match n {
1901            VarDeclOrExpr::VarDecl(v)
1902                if matches!(
1903                    &**v,
1904                    VarDecl {
1905                        kind: VarDeclKind::Let | VarDeclKind::Const,
1906                        ..
1907                    }
1908                ) => {}
1909            _ => {
1910                n.visit_mut_children_with(self);
1911            }
1912        }
1913    }
1914
1915    fn visit_mut_for_head(&mut self, n: &mut ForHead) {
1916        match n {
1917            ForHead::VarDecl(v)
1918                if matches!(
1919                    &**v,
1920                    VarDecl {
1921                        kind: VarDeclKind::Let | VarDeclKind::Const,
1922                        ..
1923                    }
1924                ) => {}
1925            // Hoister should not handle lhs of for in statement below
1926            //
1927            // const b = [];
1928            // {
1929            //   let a;
1930            //   for (a in b) {
1931            //     console.log(a);
1932            //   }
1933            // }
1934            ForHead::Pat(..) => {}
1935            _ => {
1936                n.visit_mut_children_with(self);
1937            }
1938        }
1939    }
1940
1941    #[inline]
1942    fn visit_mut_var_declarator(&mut self, node: &mut VarDeclarator) {
1943        node.name.visit_mut_with(self);
1944    }
1945
1946    /// should visit var decls first, cause var decl may appear behind the
1947    /// usage. this can deal with code below:
1948    /// ```js
1949    /// try {} catch (Ic) {
1950    ///   throw Ic;
1951    /// }
1952    /// var Ic;
1953    /// ```
1954    /// the `Ic` defined by catch param and the `Ic` defined by `var Ic` are
1955    /// different variables.
1956    /// If we deal with the `var Ic` first, we can know
1957    /// that there is already an global declaration of Ic when deal with the try
1958    /// block.
1959    fn visit_mut_module_items(&mut self, items: &mut Vec<ModuleItem>) {
1960        items.iter_mut().for_each(|item| match item {
1961            ModuleItem::Stmt(Stmt::Decl(Decl::Var(v)))
1962            | ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
1963                decl: Decl::Var(v),
1964                ..
1965            })) if matches!(
1966                &**v,
1967                VarDecl {
1968                    kind: VarDeclKind::Var,
1969                    ..
1970                }
1971            ) =>
1972            {
1973                item.visit_mut_with(self);
1974            }
1975
1976            ModuleItem::Stmt(Stmt::Decl(Decl::Fn(..)))
1977            | ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
1978                decl: Decl::Fn(..),
1979                ..
1980            })) => {
1981                item.visit_mut_with(self);
1982            }
1983            _ => item.visit_mut_with(self),
1984        });
1985    }
1986
1987    /// see docs for `self.visit_mut_module_items`
1988    fn visit_mut_stmts(&mut self, stmts: &mut Vec<Stmt>) {
1989        let others = stmts
1990            .iter_mut()
1991            .filter_map(|item| match item {
1992                Stmt::Decl(Decl::Var(..)) => {
1993                    item.visit_mut_with(self);
1994                    None
1995                }
1996                Stmt::Decl(Decl::Fn(..)) => {
1997                    item.visit_mut_with(self);
1998                    None
1999                }
2000                _ => Some(item),
2001            })
2002            .collect::<Vec<_>>();
2003
2004        for other_stmt in others {
2005            other_stmt.visit_mut_with(self);
2006        }
2007    }
2008}