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                #[cfg(swc_ast_unknown)]
567                _ => (),
568            }
569
570            e.return_type.visit_mut_with(child);
571        });
572    }
573
574    fn visit_mut_assign_pat(&mut self, node: &mut AssignPat) {
575        // visit the type first so that it doesn't resolve any
576        // identifiers from the others
577        node.left.visit_mut_with(self);
578        node.right.visit_mut_with(self);
579    }
580
581    fn visit_mut_binding_ident(&mut self, i: &mut BindingIdent) {
582        let ident_type = self.ident_type;
583        let in_type = self.in_type;
584
585        self.ident_type = IdentType::Ref;
586        i.type_ann.visit_mut_with(self);
587
588        self.ident_type = ident_type;
589        i.id.visit_mut_with(self);
590
591        self.in_type = in_type;
592        self.ident_type = ident_type;
593    }
594
595    fn visit_mut_block_stmt(&mut self, block: &mut BlockStmt) {
596        self.with_child(ScopeKind::Block, |child| {
597            child.mark_block(&mut block.ctxt);
598            block.visit_mut_children_with(child);
599        })
600    }
601
602    fn visit_mut_break_stmt(&mut self, s: &mut BreakStmt) {
603        let old = self.ident_type;
604        self.ident_type = IdentType::Label;
605        s.label.visit_mut_with(self);
606        self.ident_type = old;
607    }
608
609    fn visit_mut_catch_clause(&mut self, c: &mut CatchClause) {
610        // Child folder
611
612        self.with_child(ScopeKind::Fn, |child| {
613            child.ident_type = IdentType::Binding;
614            c.param.visit_mut_with(child);
615            child.ident_type = IdentType::Ref;
616
617            child.mark_block(&mut c.body.ctxt);
618            c.body.visit_mut_children_with(child);
619        });
620    }
621
622    fn visit_mut_class(&mut self, c: &mut Class) {
623        let old_strict_mode = self.strict_mode;
624        self.strict_mode = true;
625
626        let old = self.ident_type;
627        self.ident_type = IdentType::Ref;
628        c.decorators.visit_mut_with(self);
629
630        self.ident_type = IdentType::Ref;
631        c.super_class.visit_mut_with(self);
632
633        self.ident_type = IdentType::Binding;
634        c.type_params.visit_mut_with(self);
635
636        self.ident_type = IdentType::Ref;
637        c.super_type_params.visit_mut_with(self);
638
639        self.ident_type = IdentType::Ref;
640        c.implements.visit_mut_with(self);
641        self.ident_type = old;
642
643        c.body.visit_mut_with(self);
644        self.strict_mode = old_strict_mode;
645    }
646
647    fn visit_mut_class_decl(&mut self, n: &mut ClassDecl) {
648        if n.declare && !self.config.handle_types {
649            return;
650        }
651        self.modify(&mut n.ident, DeclKind::Lexical);
652
653        n.class.decorators.visit_mut_with(self);
654
655        // Create a child scope. The class name is only accessible within the class.
656
657        self.with_child(ScopeKind::Fn, |child| {
658            child.ident_type = IdentType::Ref;
659
660            n.class.visit_mut_with(child);
661        });
662    }
663
664    fn visit_mut_class_expr(&mut self, n: &mut ClassExpr) {
665        // Create a child scope. The class name is only accessible within the class.
666
667        n.class.super_class.visit_mut_with(self);
668
669        self.with_child(ScopeKind::Fn, |child| {
670            child.ident_type = IdentType::Binding;
671            n.ident.visit_mut_with(child);
672            child.ident_type = IdentType::Ref;
673
674            n.class.visit_mut_with(child);
675        });
676    }
677
678    fn visit_mut_class_method(&mut self, m: &mut ClassMethod) {
679        m.key.visit_mut_with(self);
680
681        for p in m.function.params.iter_mut() {
682            p.decorators.visit_mut_with(self);
683        }
684
685        self.with_child(ScopeKind::Fn, |child| m.function.visit_mut_with(child));
686    }
687
688    fn visit_mut_class_prop(&mut self, p: &mut ClassProp) {
689        p.decorators.visit_mut_with(self);
690
691        if let PropName::Computed(key) = &mut p.key {
692            let old = self.ident_type;
693            self.ident_type = IdentType::Binding;
694            key.expr.visit_mut_with(self);
695            self.ident_type = old;
696        }
697
698        let old = self.ident_type;
699        self.ident_type = IdentType::Ref;
700        p.value.visit_mut_with(self);
701        self.ident_type = old;
702
703        p.type_ann.visit_mut_with(self);
704    }
705
706    fn visit_mut_constructor(&mut self, c: &mut Constructor) {
707        for p in c.params.iter_mut() {
708            match p {
709                ParamOrTsParamProp::TsParamProp(p) => {
710                    p.decorators.visit_mut_with(self);
711                }
712                ParamOrTsParamProp::Param(p) => {
713                    p.decorators.visit_mut_with(self);
714                }
715                #[cfg(swc_ast_unknown)]
716                _ => (),
717            }
718        }
719
720        self.with_child(ScopeKind::Fn, |child| {
721            let old = child.ident_type;
722            child.ident_type = IdentType::Binding;
723            {
724                let params = c
725                    .params
726                    .iter()
727                    .filter(|p| match p {
728                        ParamOrTsParamProp::TsParamProp(_) => false,
729                        ParamOrTsParamProp::Param(p) => !p.pat.is_rest(),
730                        #[cfg(swc_ast_unknown)]
731                        _ => false,
732                    })
733                    .flat_map(find_pat_ids::<_, Id>);
734
735                for id in params {
736                    child.current.declared_symbols.insert(id.0, DeclKind::Param);
737                }
738            }
739            c.params.visit_mut_with(child);
740            child.ident_type = old;
741
742            if let Some(body) = &mut c.body {
743                child.mark_block(&mut body.ctxt);
744                body.visit_mut_children_with(child);
745            }
746        });
747    }
748
749    fn visit_mut_continue_stmt(&mut self, s: &mut ContinueStmt) {
750        let old = self.ident_type;
751        self.ident_type = IdentType::Label;
752        s.label.visit_mut_with(self);
753        self.ident_type = old;
754    }
755
756    fn visit_mut_export_default_decl(&mut self, e: &mut ExportDefaultDecl) {
757        // Treat default exported functions and classes as declarations
758        // even though they are parsed as expressions.
759        match &mut e.decl {
760            DefaultDecl::Fn(f) => {
761                if f.ident.is_some() {
762                    self.with_child(ScopeKind::Fn, |child| {
763                        f.function.visit_mut_with(child);
764                    });
765                } else {
766                    f.visit_mut_with(self)
767                }
768            }
769            DefaultDecl::Class(c) => {
770                // Skip class expression visitor to treat as a declaration.
771                c.class.visit_mut_with(self)
772            }
773            _ => e.visit_mut_children_with(self),
774        }
775    }
776
777    fn visit_mut_export_default_expr(&mut self, node: &mut ExportDefaultExpr) {
778        node.expr.visit_mut_with(self);
779
780        if self.config.handle_types {
781            if let Expr::Ident(i) = &mut *node.expr {
782                self.try_resolving_as_type(i);
783            }
784        }
785    }
786
787    fn visit_mut_export_named_specifier(&mut self, e: &mut ExportNamedSpecifier) {
788        e.visit_mut_children_with(self);
789
790        if self.config.handle_types {
791            match &mut e.orig {
792                ModuleExportName::Ident(orig) => {
793                    self.try_resolving_as_type(orig);
794                }
795                ModuleExportName::Str(_) => {}
796                #[cfg(swc_ast_unknown)]
797                _ => {}
798            }
799        }
800    }
801
802    fn visit_mut_export_specifier(&mut self, s: &mut ExportSpecifier) {
803        let old = self.ident_type;
804        self.ident_type = IdentType::Ref;
805        s.visit_mut_children_with(self);
806        self.ident_type = old;
807    }
808
809    fn visit_mut_expr(&mut self, expr: &mut Expr) {
810        let _span = if LOG {
811            Some(span!(Level::ERROR, "visit_mut_expr").entered())
812        } else {
813            None
814        };
815
816        let old = self.ident_type;
817        self.ident_type = IdentType::Ref;
818        maybe_grow_default(|| expr.visit_mut_children_with(self));
819        self.ident_type = old;
820    }
821
822    fn visit_mut_fn_decl(&mut self, node: &mut FnDecl) {
823        if node.declare && !self.config.handle_types {
824            return;
825        }
826
827        // We don't fold ident as Hoister handles this.
828        node.function.decorators.visit_mut_with(self);
829
830        self.with_child(ScopeKind::Fn, |child| node.function.visit_mut_with(child));
831    }
832
833    fn visit_mut_fn_expr(&mut self, e: &mut FnExpr) {
834        e.function.decorators.visit_mut_with(self);
835
836        if let Some(ident) = &mut e.ident {
837            self.with_child(ScopeKind::Fn, |child| {
838                child.modify(ident, DeclKind::Function);
839                child.with_child(ScopeKind::Fn, |child| {
840                    e.function.visit_mut_with(child);
841                });
842            });
843        } else {
844            self.with_child(ScopeKind::Fn, |child| {
845                e.function.visit_mut_with(child);
846            });
847        }
848    }
849
850    fn visit_mut_for_in_stmt(&mut self, n: &mut ForInStmt) {
851        self.with_child(ScopeKind::Block, |child| {
852            n.left.visit_mut_with(child);
853            n.right.visit_mut_with(child);
854
855            child.visit_mut_stmt_within_child_scope(&mut n.body);
856        });
857    }
858
859    fn visit_mut_for_of_stmt(&mut self, n: &mut ForOfStmt) {
860        self.with_child(ScopeKind::Block, |child| {
861            n.left.visit_mut_with(child);
862            n.right.visit_mut_with(child);
863
864            child.visit_mut_stmt_within_child_scope(&mut n.body);
865        });
866    }
867
868    fn visit_mut_for_stmt(&mut self, n: &mut ForStmt) {
869        self.with_child(ScopeKind::Block, |child| {
870            child.ident_type = IdentType::Binding;
871            n.init.visit_mut_with(child);
872            child.ident_type = IdentType::Ref;
873            n.test.visit_mut_with(child);
874            child.ident_type = IdentType::Ref;
875            n.update.visit_mut_with(child);
876
877            child.visit_mut_stmt_within_child_scope(&mut n.body);
878        });
879    }
880
881    fn visit_mut_function(&mut self, f: &mut Function) {
882        self.mark_block(&mut f.ctxt);
883        f.type_params.visit_mut_with(self);
884
885        self.ident_type = IdentType::Ref;
886        f.decorators.visit_mut_with(self);
887
888        {
889            let params = f
890                .params
891                .iter()
892                .filter(|p| !p.pat.is_rest())
893                .flat_map(find_pat_ids::<_, Id>);
894
895            for id in params {
896                self.current.declared_symbols.insert(id.0, DeclKind::Param);
897            }
898        }
899        self.ident_type = IdentType::Binding;
900        f.params.visit_mut_with(self);
901
902        f.return_type.visit_mut_with(self);
903
904        self.ident_type = IdentType::Ref;
905        if let Some(body) = &mut f.body {
906            self.mark_block(&mut body.ctxt);
907            let old_strict_mode = self.strict_mode;
908            if !self.strict_mode {
909                self.strict_mode = body
910                    .stmts
911                    .first()
912                    .map(|stmt| stmt.is_use_strict())
913                    .unwrap_or(false);
914            }
915            // Prevent creating new scope.
916            body.visit_mut_children_with(self);
917            self.strict_mode = old_strict_mode;
918        }
919    }
920
921    fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) {
922        let old = self.ident_type;
923        self.ident_type = IdentType::Ref;
924        f.key.visit_mut_with(self);
925        self.ident_type = old;
926
927        f.type_ann.visit_mut_with(self);
928
929        f.body.visit_mut_with(self);
930    }
931
932    fn visit_mut_jsx_element_name(&mut self, node: &mut JSXElementName) {
933        if let JSXElementName::Ident(i) = node {
934            if i.as_ref().starts_with(|c: char| c.is_ascii_lowercase()) {
935                if cfg!(debug_assertions) && LOG {
936                    debug!("\t -> JSXElementName");
937                }
938
939                let ctxt = i.ctxt.apply_mark(self.config.unresolved_mark);
940
941                if cfg!(debug_assertions) && LOG {
942                    debug!("\t -> {:?}", ctxt);
943                }
944
945                i.ctxt = ctxt;
946
947                return;
948            }
949        }
950
951        node.visit_mut_children_with(self);
952    }
953
954    fn visit_mut_ident(&mut self, i: &mut Ident) {
955        if i.ctxt != SyntaxContext::empty() {
956            return;
957        }
958
959        match self.ident_type {
960            IdentType::Binding => self.modify(i, self.decl_kind),
961            IdentType::Ref => {
962                let Ident { sym, ctxt, .. } = i;
963
964                if cfg!(debug_assertions) && LOG {
965                    debug!("IdentRef (type = {}) {}{:?}", self.in_type, sym, ctxt);
966                }
967
968                if *ctxt != SyntaxContext::empty() {
969                    return;
970                }
971
972                if let Some(mark) = self.mark_for_ref(sym) {
973                    let ctxt = ctxt.apply_mark(mark);
974
975                    if cfg!(debug_assertions) && LOG {
976                        debug!("\t -> {:?}", ctxt);
977                    }
978                    i.ctxt = ctxt;
979                } else {
980                    if cfg!(debug_assertions) && LOG {
981                        debug!("\t -> Unresolved");
982                    }
983
984                    let ctxt = ctxt.apply_mark(self.config.unresolved_mark);
985
986                    if cfg!(debug_assertions) && LOG {
987                        debug!("\t -> {:?}", ctxt);
988                    }
989
990                    i.ctxt = ctxt;
991                    // Support hoisting
992                    self.modify(i, self.decl_kind)
993                }
994            }
995            // We currently does not touch labels
996            IdentType::Label => {}
997        }
998    }
999
1000    fn visit_mut_import_decl(&mut self, n: &mut ImportDecl) {
1001        // Always resolve the import declaration identifiers even if it's type only.
1002        // We need to analyze these identifiers for type stripping purposes.
1003        self.ident_type = IdentType::Binding;
1004        let old_in_type = self.in_type;
1005        self.in_type = n.type_only;
1006        n.visit_mut_children_with(self);
1007        self.in_type = old_in_type;
1008    }
1009
1010    fn visit_mut_import_named_specifier(&mut self, s: &mut ImportNamedSpecifier) {
1011        let old = self.ident_type;
1012        self.ident_type = IdentType::Binding;
1013        s.local.visit_mut_with(self);
1014        if self.config.handle_types {
1015            self.current.declared_types.insert(s.local.sym.clone());
1016        }
1017        self.ident_type = old;
1018    }
1019
1020    fn visit_mut_import_specifier(&mut self, s: &mut ImportSpecifier) {
1021        let old = self.ident_type;
1022        self.ident_type = IdentType::Binding;
1023
1024        match s {
1025            ImportSpecifier::Named(ImportNamedSpecifier { imported: None, .. })
1026            | ImportSpecifier::Namespace(..)
1027            | ImportSpecifier::Default(..) => s.visit_mut_children_with(self),
1028            ImportSpecifier::Named(s) => s.local.visit_mut_with(self),
1029            #[cfg(swc_ast_unknown)]
1030            _ => (),
1031        }
1032
1033        self.ident_type = old;
1034    }
1035
1036    /// Ignore.
1037    ///
1038    /// See https://github.com/swc-project/swc/issues/2854
1039    fn visit_mut_jsx_attr_name(&mut self, _: &mut JSXAttrName) {}
1040
1041    fn visit_mut_key_value_pat_prop(&mut self, n: &mut KeyValuePatProp) {
1042        n.key.visit_mut_with(self);
1043        n.value.visit_mut_with(self);
1044    }
1045
1046    fn visit_mut_labeled_stmt(&mut self, s: &mut LabeledStmt) {
1047        let old = self.ident_type;
1048        self.ident_type = IdentType::Label;
1049        s.label.visit_mut_with(self);
1050        self.ident_type = old;
1051
1052        s.body.visit_mut_with(self);
1053    }
1054
1055    fn visit_mut_method_prop(&mut self, m: &mut MethodProp) {
1056        m.key.visit_mut_with(self);
1057
1058        // Child folder
1059        self.with_child(ScopeKind::Fn, |child| m.function.visit_mut_with(child));
1060    }
1061
1062    fn visit_mut_module(&mut self, module: &mut Module) {
1063        self.strict_mode = true;
1064        self.is_module = true;
1065        module.visit_mut_children_with(self)
1066    }
1067
1068    fn visit_mut_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
1069        if !self.in_ts_module && self.current.kind != ScopeKind::Fn {
1070            return stmts.visit_mut_children_with(self);
1071        }
1072
1073        // Phase 1: Handle hoisting
1074        {
1075            let mut hoister = Hoister {
1076                kind: self.decl_kind,
1077                resolver: self,
1078                in_block: false,
1079                in_catch_body: false,
1080                catch_param_decls: Default::default(),
1081                excluded_from_catch: Default::default(),
1082            };
1083            stmts.visit_mut_with(&mut hoister)
1084        }
1085
1086        // Phase 2.
1087        stmts.visit_mut_children_with(self)
1088    }
1089
1090    fn visit_mut_named_export(&mut self, e: &mut NamedExport) {
1091        if e.src.is_some() {
1092            return;
1093        }
1094
1095        e.visit_mut_children_with(self);
1096    }
1097
1098    fn visit_mut_object_lit(&mut self, o: &mut ObjectLit) {
1099        self.with_child(ScopeKind::Block, |child| {
1100            o.visit_mut_children_with(child);
1101        });
1102    }
1103
1104    fn visit_mut_param(&mut self, param: &mut Param) {
1105        self.ident_type = IdentType::Binding;
1106        param.visit_mut_children_with(self);
1107    }
1108
1109    fn visit_mut_pat(&mut self, p: &mut Pat) {
1110        p.visit_mut_children_with(self);
1111    }
1112
1113    fn visit_mut_private_method(&mut self, m: &mut PrivateMethod) {
1114        m.key.visit_mut_with(self);
1115
1116        {
1117            // Child folder
1118
1119            self.with_child(ScopeKind::Fn, |child| m.function.visit_mut_with(child));
1120        }
1121    }
1122
1123    fn visit_mut_private_name(&mut self, _: &mut PrivateName) {}
1124
1125    fn visit_mut_prop_name(&mut self, n: &mut PropName) {
1126        if let PropName::Computed(c) = n {
1127            c.visit_mut_with(self);
1128        }
1129    }
1130
1131    fn visit_mut_rest_pat(&mut self, node: &mut RestPat) {
1132        node.arg.visit_mut_with(self);
1133        node.type_ann.visit_mut_with(self);
1134    }
1135
1136    fn visit_mut_script(&mut self, script: &mut Script) {
1137        self.strict_mode = script
1138            .body
1139            .first()
1140            .map(|stmt| stmt.is_use_strict())
1141            .unwrap_or(false);
1142        script.visit_mut_children_with(self)
1143    }
1144
1145    fn visit_mut_setter_prop(&mut self, n: &mut SetterProp) {
1146        n.key.visit_mut_with(self);
1147
1148        {
1149            self.with_child(ScopeKind::Fn, |child| {
1150                child.ident_type = IdentType::Binding;
1151                n.this_param.visit_mut_with(child);
1152                n.param.visit_mut_with(child);
1153                n.body.visit_mut_with(child);
1154            });
1155        };
1156    }
1157
1158    fn visit_mut_stmts(&mut self, stmts: &mut Vec<Stmt>) {
1159        let _span = if LOG {
1160            Some(span!(Level::ERROR, "visit_mut_stmts").entered())
1161        } else {
1162            None
1163        };
1164
1165        // Phase 1: Handle hoisting
1166        {
1167            let _span = if LOG {
1168                Some(span!(Level::ERROR, "hoist").entered())
1169            } else {
1170                None
1171            };
1172
1173            let mut hoister = Hoister {
1174                kind: self.decl_kind,
1175                resolver: self,
1176                in_block: false,
1177                in_catch_body: false,
1178                catch_param_decls: Default::default(),
1179                excluded_from_catch: Default::default(),
1180            };
1181            stmts.visit_mut_with(&mut hoister)
1182        }
1183
1184        // Phase 2.
1185        stmts.visit_mut_children_with(self)
1186    }
1187
1188    fn visit_mut_switch_case(&mut self, n: &mut SwitchCase) {
1189        n.cons.visit_mut_with(self);
1190
1191        n.test.visit_mut_with(self);
1192    }
1193
1194    fn visit_mut_switch_stmt(&mut self, s: &mut SwitchStmt) {
1195        s.discriminant.visit_mut_with(self);
1196
1197        self.with_child(ScopeKind::Block, |child| {
1198            s.cases.visit_mut_with(child);
1199        });
1200    }
1201
1202    fn visit_mut_ts_as_expr(&mut self, n: &mut TsAsExpr) {
1203        if self.config.handle_types {
1204            n.type_ann.visit_mut_with(self);
1205        }
1206
1207        n.expr.visit_mut_with(self);
1208    }
1209
1210    fn visit_mut_ts_call_signature_decl(&mut self, n: &mut TsCallSignatureDecl) {
1211        if !self.config.handle_types {
1212            return;
1213        }
1214
1215        self.with_child(ScopeKind::Fn, |child| {
1216            child.in_type = true;
1217
1218            n.type_params.visit_mut_with(child);
1219            n.params.visit_mut_with(child);
1220            n.type_ann.visit_mut_with(child);
1221        });
1222    }
1223
1224    fn visit_mut_ts_construct_signature_decl(&mut self, decl: &mut TsConstructSignatureDecl) {
1225        if !self.config.handle_types {
1226            return;
1227        }
1228
1229        // Child folder
1230        self.with_child(ScopeKind::Fn, |child| {
1231            child.in_type = true;
1232
1233            // order is important
1234            decl.type_params.visit_mut_with(child);
1235            decl.params.visit_mut_with(child);
1236            decl.type_ann.visit_mut_with(child);
1237        });
1238    }
1239
1240    fn visit_mut_ts_constructor_type(&mut self, ty: &mut TsConstructorType) {
1241        if !self.config.handle_types {
1242            return;
1243        }
1244
1245        self.with_child(ScopeKind::Fn, |child| {
1246            child.in_type = true;
1247
1248            ty.type_params.visit_mut_with(child);
1249            ty.params.visit_mut_with(child);
1250            ty.type_ann.visit_mut_with(child);
1251        });
1252    }
1253
1254    fn visit_mut_ts_enum_decl(&mut self, decl: &mut TsEnumDecl) {
1255        if decl.declare && !self.config.handle_types {
1256            return;
1257        }
1258        self.modify(&mut decl.id, DeclKind::Lexical);
1259
1260        self.with_child(ScopeKind::Block, |child| {
1261            // add the enum member names as declared symbols for this scope
1262            // Ex. `enum Foo { a, b = a }`
1263            let member_names = decl.members.iter().filter_map(|m| match &m.id {
1264                TsEnumMemberId::Ident(id) => Some((id.sym.clone(), DeclKind::Lexical)),
1265                TsEnumMemberId::Str(_) => None,
1266                #[cfg(swc_ast_unknown)]
1267                _ => None,
1268            });
1269            child.current.declared_symbols.extend(member_names);
1270
1271            decl.members.visit_mut_with(child);
1272        });
1273    }
1274
1275    fn visit_mut_ts_export_assignment(&mut self, node: &mut TsExportAssignment) {
1276        node.expr.visit_mut_with(self);
1277
1278        if self.config.handle_types {
1279            if let Some(i) = leftmost(&mut node.expr) {
1280                self.try_resolving_as_type(i);
1281            }
1282        }
1283    }
1284
1285    fn visit_mut_ts_expr_with_type_args(&mut self, n: &mut TsExprWithTypeArgs) {
1286        if self.config.handle_types {
1287            let old = self.in_type;
1288            self.in_type = true;
1289            n.visit_mut_children_with(self);
1290            self.in_type = old;
1291        }
1292    }
1293
1294    fn visit_mut_ts_fn_type(&mut self, ty: &mut TsFnType) {
1295        if !self.config.handle_types {
1296            return;
1297        }
1298
1299        self.with_child(ScopeKind::Fn, |child| {
1300            child.in_type = true;
1301
1302            ty.type_params.visit_mut_with(child);
1303            ty.params.visit_mut_with(child);
1304            ty.type_ann.visit_mut_with(child);
1305        });
1306    }
1307
1308    fn visit_mut_ts_getter_signature(&mut self, n: &mut TsGetterSignature) {
1309        if n.computed {
1310            n.key.visit_mut_with(self);
1311        }
1312
1313        n.type_ann.visit_mut_with(self);
1314    }
1315
1316    fn visit_mut_ts_import_equals_decl(&mut self, n: &mut TsImportEqualsDecl) {
1317        self.modify(&mut n.id, DeclKind::Lexical);
1318
1319        n.module_ref.visit_mut_with(self);
1320    }
1321
1322    fn visit_mut_ts_import_type(&mut self, n: &mut TsImportType) {
1323        if !self.config.handle_types {
1324            return;
1325        }
1326
1327        n.type_args.visit_mut_with(self);
1328    }
1329
1330    fn visit_mut_ts_interface_decl(&mut self, n: &mut TsInterfaceDecl) {
1331        // always resolve the identifier for type stripping purposes
1332        let old_in_type = self.in_type;
1333        let old_ident_type = self.ident_type;
1334
1335        self.in_type = true;
1336        self.ident_type = IdentType::Ref;
1337
1338        self.modify(&mut n.id, DeclKind::Type);
1339
1340        if !self.config.handle_types {
1341            self.in_type = old_in_type;
1342            self.ident_type = old_ident_type;
1343            return;
1344        }
1345
1346        self.with_child(ScopeKind::Fn, |child| {
1347            child.in_type = true;
1348
1349            n.type_params.visit_mut_with(child);
1350            n.extends.visit_mut_with(child);
1351            n.body.visit_mut_with(child);
1352        });
1353
1354        self.in_type = old_in_type;
1355        self.ident_type = old_ident_type;
1356    }
1357
1358    fn visit_mut_ts_mapped_type(&mut self, n: &mut TsMappedType) {
1359        if !self.config.handle_types {
1360            return;
1361        }
1362
1363        self.ident_type = IdentType::Binding;
1364        n.type_param.visit_mut_with(self);
1365        self.ident_type = IdentType::Ref;
1366        n.name_type.visit_mut_with(self);
1367
1368        self.ident_type = IdentType::Ref;
1369        n.type_ann.visit_mut_with(self);
1370    }
1371
1372    fn visit_mut_ts_method_signature(&mut self, n: &mut TsMethodSignature) {
1373        if !self.config.handle_types {
1374            return;
1375        }
1376
1377        self.with_child(ScopeKind::Fn, |child| {
1378            child.in_type = true;
1379
1380            n.type_params.visit_mut_with(child);
1381            if n.computed {
1382                n.key.visit_mut_with(child);
1383            }
1384            n.params.visit_mut_with(child);
1385            n.type_ann.visit_mut_with(child);
1386        });
1387    }
1388
1389    fn visit_mut_ts_module_decl(&mut self, decl: &mut TsModuleDecl) {
1390        if decl.declare && !self.config.handle_types {
1391            return;
1392        }
1393
1394        match &mut decl.id {
1395            TsModuleName::Ident(i) => {
1396                self.modify(i, DeclKind::Lexical);
1397            }
1398            TsModuleName::Str(_) => {}
1399            #[cfg(swc_ast_unknown)]
1400            _ => {}
1401        }
1402
1403        self.with_child(ScopeKind::Block, |child| {
1404            child.in_ts_module = true;
1405
1406            decl.body.visit_mut_children_with(child);
1407        });
1408    }
1409
1410    fn visit_mut_ts_namespace_decl(&mut self, n: &mut TsNamespaceDecl) {
1411        if n.declare && !self.config.handle_types {
1412            return;
1413        }
1414
1415        self.modify(&mut n.id, DeclKind::Lexical);
1416
1417        n.body.visit_mut_with(self);
1418    }
1419
1420    fn visit_mut_ts_param_prop_param(&mut self, n: &mut TsParamPropParam) {
1421        self.ident_type = IdentType::Binding;
1422        n.visit_mut_children_with(self)
1423    }
1424
1425    fn visit_mut_ts_property_signature(&mut self, n: &mut TsPropertySignature) {
1426        if !self.config.handle_types {
1427            return;
1428        }
1429
1430        if n.computed {
1431            n.key.visit_mut_with(self);
1432        }
1433
1434        self.with_child(ScopeKind::Fn, |child| {
1435            child.in_type = true;
1436
1437            n.type_ann.visit_mut_with(child);
1438        });
1439    }
1440
1441    fn visit_mut_ts_qualified_name(&mut self, n: &mut TsQualifiedName) {
1442        self.ident_type = IdentType::Ref;
1443
1444        n.left.visit_mut_with(self)
1445    }
1446
1447    fn visit_mut_ts_satisfies_expr(&mut self, n: &mut TsSatisfiesExpr) {
1448        if self.config.handle_types {
1449            n.type_ann.visit_mut_with(self);
1450        }
1451
1452        n.expr.visit_mut_with(self);
1453    }
1454
1455    fn visit_mut_ts_setter_signature(&mut self, n: &mut TsSetterSignature) {
1456        if n.computed {
1457            n.key.visit_mut_with(self);
1458        }
1459
1460        n.param.visit_mut_with(self);
1461    }
1462
1463    fn visit_mut_ts_tuple_element(&mut self, e: &mut TsTupleElement) {
1464        if !self.config.handle_types {
1465            return;
1466        }
1467        self.ident_type = IdentType::Ref;
1468        e.ty.visit_mut_with(self);
1469    }
1470
1471    fn visit_mut_ts_type_alias_decl(&mut self, n: &mut TsTypeAliasDecl) {
1472        // always resolve the identifier for type stripping purposes
1473        let old_in_type = self.in_type;
1474        self.in_type = true;
1475        self.modify(&mut n.id, DeclKind::Type);
1476
1477        if !self.config.handle_types {
1478            self.in_type = old_in_type;
1479            return;
1480        }
1481
1482        self.with_child(ScopeKind::Fn, |child| {
1483            child.in_type = true;
1484
1485            n.type_params.visit_mut_with(child);
1486            n.type_ann.visit_mut_with(child);
1487        });
1488        self.in_type = old_in_type;
1489    }
1490
1491    fn visit_mut_ts_type_assertion(&mut self, n: &mut TsTypeAssertion) {
1492        if self.config.handle_types {
1493            n.type_ann.visit_mut_with(self);
1494        }
1495
1496        n.expr.visit_mut_with(self);
1497    }
1498
1499    fn visit_mut_ts_type_param(&mut self, param: &mut TsTypeParam) {
1500        if !self.config.handle_types {
1501            return;
1502        }
1503        param.name.visit_mut_with(self);
1504
1505        let ident_type = self.ident_type;
1506        param.default.visit_mut_with(self);
1507        param.constraint.visit_mut_with(self);
1508        self.ident_type = ident_type;
1509    }
1510
1511    fn visit_mut_ts_type_params(&mut self, params: &mut Vec<TsTypeParam>) {
1512        for param in params.iter_mut() {
1513            param.name.visit_mut_with(self);
1514        }
1515
1516        params.visit_mut_children_with(self);
1517    }
1518
1519    fn visit_mut_using_decl(&mut self, decl: &mut UsingDecl) {
1520        let old_kind = self.decl_kind;
1521        self.decl_kind = DeclKind::Lexical;
1522        decl.decls.visit_mut_with(self);
1523        self.decl_kind = old_kind;
1524    }
1525
1526    fn visit_mut_var_decl(&mut self, decl: &mut VarDecl) {
1527        if decl.declare && !self.config.handle_types {
1528            return;
1529        }
1530
1531        let old_kind = self.decl_kind;
1532        self.decl_kind = decl.kind.into();
1533        decl.decls.visit_mut_with(self);
1534        self.decl_kind = old_kind;
1535    }
1536
1537    fn visit_mut_var_declarator(&mut self, decl: &mut VarDeclarator) {
1538        // order is important
1539
1540        let old_type = self.ident_type;
1541        self.ident_type = IdentType::Binding;
1542        decl.name.visit_mut_with(self);
1543        self.ident_type = old_type;
1544
1545        decl.init.visit_mut_children_with(self);
1546    }
1547}
1548
1549fn leftmost(expr: &mut Expr) -> Option<&mut Ident> {
1550    match expr {
1551        Expr::Ident(i) => Some(i),
1552        Expr::Member(MemberExpr { obj, .. }) => leftmost(obj),
1553        Expr::Paren(ParenExpr { expr, .. }) => leftmost(expr),
1554        _ => None,
1555    }
1556}
1557
1558/// The folder which handles var / function hoisting.
1559struct Hoister<'a, 'b> {
1560    resolver: &'a mut Resolver<'b>,
1561    kind: DeclKind,
1562    /// Hoister should not touch let / const in the block.
1563    in_block: bool,
1564
1565    in_catch_body: bool,
1566
1567    excluded_from_catch: FxHashSet<Atom>,
1568    catch_param_decls: FxHashSet<Atom>,
1569}
1570
1571impl Hoister<'_, '_> {
1572    fn add_pat_id(&mut self, id: &mut BindingIdent) {
1573        if self.in_catch_body {
1574            // If we have a binding, it's different variable.
1575            if self.resolver.mark_for_ref_inner(&id.sym, true).is_some()
1576                && self.catch_param_decls.contains(&id.sym)
1577            {
1578                return;
1579            }
1580
1581            self.excluded_from_catch.insert(id.sym.clone());
1582        } else {
1583            // Behavior is different
1584            if self.catch_param_decls.contains(&id.sym)
1585                && !self.excluded_from_catch.contains(&id.sym)
1586            {
1587                return;
1588            }
1589        }
1590
1591        self.resolver.modify(id, self.kind)
1592    }
1593}
1594
1595impl VisitMut for Hoister<'_, '_> {
1596    noop_visit_mut_type!();
1597
1598    #[inline]
1599    fn visit_mut_arrow_expr(&mut self, _: &mut ArrowExpr) {}
1600
1601    fn visit_mut_assign_pat_prop(&mut self, node: &mut AssignPatProp) {
1602        node.visit_mut_children_with(self);
1603
1604        self.add_pat_id(&mut node.key);
1605    }
1606
1607    fn visit_mut_block_stmt(&mut self, n: &mut BlockStmt) {
1608        let old_in_block = self.in_block;
1609        self.in_block = true;
1610        n.visit_mut_children_with(self);
1611        self.in_block = old_in_block;
1612    }
1613
1614    /// The code below prints "PASS"
1615    ///
1616    /// ```js
1617    /// 
1618    ///      var a = "PASS";
1619    ///      try {
1620    ///          throw "FAIL1";
1621    ///          } catch (a) {
1622    ///          var a = "FAIL2";
1623    ///      }
1624    ///      console.log(a);
1625    /// ```
1626    ///
1627    /// While the code below does not throw **ReferenceError** for `b`
1628    ///
1629    /// ```js
1630    /// 
1631    ///      b()
1632    ///      try {
1633    ///      } catch (b) {
1634    ///          var b;
1635    ///      }
1636    /// ```
1637    ///
1638    /// while the code below throws **ReferenceError**
1639    ///
1640    /// ```js
1641    /// 
1642    ///      b()
1643    ///      try {
1644    ///      } catch (b) {
1645    ///      }
1646    /// ```
1647    #[inline]
1648    fn visit_mut_catch_clause(&mut self, c: &mut CatchClause) {
1649        let old_exclude = self.excluded_from_catch.clone();
1650        self.excluded_from_catch = Default::default();
1651
1652        let old_in_catch_body = self.in_catch_body;
1653
1654        let params: Vec<Id> = find_pat_ids(&c.param);
1655
1656        let orig = self.catch_param_decls.clone();
1657
1658        self.catch_param_decls
1659            .extend(params.into_iter().map(|v| v.0));
1660
1661        self.in_catch_body = true;
1662        c.body.visit_mut_with(self);
1663
1664        // let mut excluded = find_ids::<_, Id>(&c.body);
1665
1666        // excluded.retain(|id| {
1667        //     // If we already have a declartion named a, `var a` in the catch body is
1668        //     // different var.
1669
1670        //     self.resolver.mark_for_ref(&id.0).is_none()
1671        // });
1672
1673        self.in_catch_body = false;
1674        c.param.visit_mut_with(self);
1675
1676        self.catch_param_decls = orig;
1677
1678        self.in_catch_body = old_in_catch_body;
1679        self.excluded_from_catch = old_exclude;
1680    }
1681
1682    fn visit_mut_class_decl(&mut self, node: &mut ClassDecl) {
1683        if node.declare && !self.resolver.config.handle_types {
1684            return;
1685        }
1686        if self.in_block {
1687            return;
1688        }
1689        self.resolver.modify(&mut node.ident, DeclKind::Lexical);
1690
1691        if self.resolver.config.handle_types {
1692            self.resolver
1693                .current
1694                .declared_types
1695                .insert(node.ident.sym.clone());
1696        }
1697    }
1698
1699    #[inline]
1700    fn visit_mut_constructor(&mut self, _: &mut Constructor) {}
1701
1702    #[inline]
1703    fn visit_mut_decl(&mut self, decl: &mut Decl) {
1704        decl.visit_mut_children_with(self);
1705
1706        if self.resolver.config.handle_types {
1707            match decl {
1708                Decl::TsInterface(i) => {
1709                    if self.in_block {
1710                        return;
1711                    }
1712
1713                    let old_in_type = self.resolver.in_type;
1714                    self.resolver.in_type = true;
1715                    self.resolver.modify(&mut i.id, DeclKind::Type);
1716                    self.resolver.in_type = old_in_type;
1717                }
1718
1719                Decl::TsTypeAlias(a) => {
1720                    let old_in_type = self.resolver.in_type;
1721                    self.resolver.in_type = true;
1722                    self.resolver.modify(&mut a.id, DeclKind::Type);
1723                    self.resolver.in_type = old_in_type;
1724                }
1725
1726                Decl::TsEnum(e) => {
1727                    if !self.in_block {
1728                        let old_in_type = self.resolver.in_type;
1729                        self.resolver.in_type = false;
1730                        self.resolver.modify(&mut e.id, DeclKind::Lexical);
1731                        self.resolver.in_type = old_in_type;
1732                    }
1733                }
1734
1735                Decl::TsModule(v)
1736                    if matches!(
1737                        &**v,
1738                        TsModuleDecl {
1739                            global: false,
1740                            id: TsModuleName::Ident(_),
1741                            ..
1742                        },
1743                    ) =>
1744                {
1745                    if !self.in_block {
1746                        let old_in_type = self.resolver.in_type;
1747                        self.resolver.in_type = false;
1748                        let id = v.id.as_mut_ident().unwrap();
1749                        self.resolver.modify(id, DeclKind::Lexical);
1750                        self.resolver.in_type = old_in_type;
1751                    }
1752                }
1753                _ => {}
1754            }
1755        }
1756    }
1757
1758    fn visit_mut_export_default_decl(&mut self, node: &mut ExportDefaultDecl) {
1759        // Treat default exported functions and classes as declarations
1760        // even though they are parsed as expressions.
1761        match &mut node.decl {
1762            DefaultDecl::Fn(f) => {
1763                if let Some(id) = &mut f.ident {
1764                    self.resolver.modify(id, DeclKind::Var);
1765                }
1766
1767                f.visit_mut_with(self)
1768            }
1769            DefaultDecl::Class(c) => {
1770                if let Some(id) = &mut c.ident {
1771                    self.resolver.modify(id, DeclKind::Lexical);
1772                }
1773
1774                c.visit_mut_with(self)
1775            }
1776            _ => {
1777                node.visit_mut_children_with(self);
1778            }
1779        }
1780    }
1781
1782    #[inline]
1783    fn visit_mut_expr(&mut self, _: &mut Expr) {}
1784
1785    fn visit_mut_fn_decl(&mut self, node: &mut FnDecl) {
1786        if node.declare && !self.resolver.config.handle_types {
1787            return;
1788        }
1789
1790        if self.catch_param_decls.contains(&node.ident.sym) {
1791            return;
1792        }
1793
1794        if self.in_block {
1795            // function declaration is block scoped in strict mode
1796            if self.resolver.strict_mode {
1797                return;
1798            }
1799            // If we are in nested block, and variable named `foo` is lexically declared or
1800            // a parameter, we should ignore function foo while handling upper scopes.
1801            if let Some(DeclKind::Lexical | DeclKind::Param) =
1802                self.resolver.current.is_declared(&node.ident.sym)
1803            {
1804                return;
1805            }
1806        }
1807
1808        self.resolver.modify(&mut node.ident, DeclKind::Function);
1809    }
1810
1811    #[inline]
1812    fn visit_mut_function(&mut self, _: &mut Function) {}
1813
1814    fn visit_mut_import_default_specifier(&mut self, n: &mut ImportDefaultSpecifier) {
1815        n.visit_mut_children_with(self);
1816
1817        self.resolver.modify(&mut n.local, DeclKind::Lexical);
1818
1819        if self.resolver.config.handle_types {
1820            self.resolver
1821                .current
1822                .declared_types
1823                .insert(n.local.sym.clone());
1824        }
1825    }
1826
1827    fn visit_mut_import_named_specifier(&mut self, n: &mut ImportNamedSpecifier) {
1828        n.visit_mut_children_with(self);
1829
1830        self.resolver.modify(&mut n.local, DeclKind::Lexical);
1831
1832        if self.resolver.config.handle_types {
1833            self.resolver
1834                .current
1835                .declared_types
1836                .insert(n.local.sym.clone());
1837        }
1838    }
1839
1840    fn visit_mut_import_star_as_specifier(&mut self, n: &mut ImportStarAsSpecifier) {
1841        n.visit_mut_children_with(self);
1842
1843        self.resolver.modify(&mut n.local, DeclKind::Lexical);
1844
1845        if self.resolver.config.handle_types {
1846            self.resolver
1847                .current
1848                .declared_types
1849                .insert(n.local.sym.clone());
1850        }
1851    }
1852
1853    #[inline]
1854    fn visit_mut_param(&mut self, _: &mut Param) {}
1855
1856    fn visit_mut_pat(&mut self, node: &mut Pat) {
1857        match node {
1858            Pat::Ident(i) => {
1859                self.add_pat_id(i);
1860            }
1861
1862            _ => node.visit_mut_children_with(self),
1863        }
1864    }
1865
1866    #[inline]
1867    fn visit_mut_assign_target(&mut self, _: &mut AssignTarget) {}
1868
1869    #[inline]
1870    fn visit_mut_setter_prop(&mut self, _: &mut SetterProp) {}
1871
1872    fn visit_mut_switch_stmt(&mut self, s: &mut SwitchStmt) {
1873        s.discriminant.visit_mut_with(self);
1874
1875        let old_in_block = self.in_block;
1876        self.in_block = true;
1877        s.cases.visit_mut_with(self);
1878        self.in_block = old_in_block;
1879    }
1880
1881    #[inline]
1882    fn visit_mut_tagged_tpl(&mut self, _: &mut TaggedTpl) {}
1883
1884    #[inline]
1885    fn visit_mut_tpl(&mut self, _: &mut Tpl) {}
1886
1887    #[inline]
1888    fn visit_mut_ts_module_block(&mut self, _: &mut TsModuleBlock) {}
1889
1890    #[inline]
1891    fn visit_mut_using_decl(&mut self, node: &mut UsingDecl) {
1892        if self.in_block {
1893            return;
1894        }
1895
1896        let old_kind = self.kind;
1897        self.kind = DeclKind::Lexical;
1898        node.visit_mut_children_with(self);
1899        self.kind = old_kind;
1900    }
1901
1902    fn visit_mut_var_decl(&mut self, node: &mut VarDecl) {
1903        if node.declare && !self.resolver.config.handle_types {
1904            return;
1905        }
1906
1907        if self.in_block {
1908            match node.kind {
1909                VarDeclKind::Const | VarDeclKind::Let => return,
1910                _ => {}
1911            }
1912        }
1913
1914        let old_kind = self.kind;
1915        self.kind = node.kind.into();
1916
1917        node.visit_mut_children_with(self);
1918
1919        self.kind = old_kind;
1920    }
1921
1922    fn visit_mut_var_decl_or_expr(&mut self, n: &mut VarDeclOrExpr) {
1923        match n {
1924            VarDeclOrExpr::VarDecl(v)
1925                if matches!(
1926                    &**v,
1927                    VarDecl {
1928                        kind: VarDeclKind::Let | VarDeclKind::Const,
1929                        ..
1930                    }
1931                ) => {}
1932            _ => {
1933                n.visit_mut_children_with(self);
1934            }
1935        }
1936    }
1937
1938    fn visit_mut_for_head(&mut self, n: &mut ForHead) {
1939        match n {
1940            ForHead::VarDecl(v)
1941                if matches!(
1942                    &**v,
1943                    VarDecl {
1944                        kind: VarDeclKind::Let | VarDeclKind::Const,
1945                        ..
1946                    }
1947                ) => {}
1948            // Hoister should not handle lhs of for in statement below
1949            //
1950            // const b = [];
1951            // {
1952            //   let a;
1953            //   for (a in b) {
1954            //     console.log(a);
1955            //   }
1956            // }
1957            ForHead::Pat(..) => {}
1958            _ => {
1959                n.visit_mut_children_with(self);
1960            }
1961        }
1962    }
1963
1964    #[inline]
1965    fn visit_mut_var_declarator(&mut self, node: &mut VarDeclarator) {
1966        node.name.visit_mut_with(self);
1967    }
1968
1969    /// should visit var decls first, cause var decl may appear behind the
1970    /// usage. this can deal with code below:
1971    /// ```js
1972    /// try {} catch (Ic) {
1973    ///   throw Ic;
1974    /// }
1975    /// var Ic;
1976    /// ```
1977    /// the `Ic` defined by catch param and the `Ic` defined by `var Ic` are
1978    /// different variables.
1979    /// If we deal with the `var Ic` first, we can know
1980    /// that there is already an global declaration of Ic when deal with the try
1981    /// block.
1982    fn visit_mut_module_items(&mut self, items: &mut Vec<ModuleItem>) {
1983        items.iter_mut().for_each(|item| match item {
1984            ModuleItem::Stmt(Stmt::Decl(Decl::Var(v)))
1985            | ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
1986                decl: Decl::Var(v),
1987                ..
1988            })) if matches!(
1989                &**v,
1990                VarDecl {
1991                    kind: VarDeclKind::Var,
1992                    ..
1993                }
1994            ) =>
1995            {
1996                item.visit_mut_with(self);
1997            }
1998
1999            ModuleItem::Stmt(Stmt::Decl(Decl::Fn(..)))
2000            | ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
2001                decl: Decl::Fn(..),
2002                ..
2003            })) => {
2004                item.visit_mut_with(self);
2005            }
2006            _ => item.visit_mut_with(self),
2007        });
2008    }
2009
2010    /// see docs for `self.visit_mut_module_items`
2011    fn visit_mut_stmts(&mut self, stmts: &mut Vec<Stmt>) {
2012        let others = stmts
2013            .iter_mut()
2014            .filter_map(|item| match item {
2015                Stmt::Decl(Decl::Var(..)) => {
2016                    item.visit_mut_with(self);
2017                    None
2018                }
2019                Stmt::Decl(Decl::Fn(..)) => {
2020                    item.visit_mut_with(self);
2021                    None
2022                }
2023                _ => Some(item),
2024            })
2025            .collect::<Vec<_>>();
2026
2027        for other_stmt in others {
2028            other_stmt.visit_mut_with(self);
2029        }
2030    }
2031}