diff --git a/crates/swc_ecma_transforms_base/src/resolver/mod.rs b/crates/swc_ecma_transforms_base/src/resolver/mod.rs index 556b2135293..21e9b01afbd 100644 --- a/crates/swc_ecma_transforms_base/src/resolver/mod.rs +++ b/crates/swc_ecma_transforms_base/src/resolver/mod.rs @@ -1027,7 +1027,7 @@ impl<'a> VisitMut for Resolver<'a> { catch_param_decls: Default::default(), excluded_from_catch: Default::default(), }; - stmts.visit_mut_children_with(&mut hoister) + stmts.visit_mut_with(&mut hoister) } // Phase 2. @@ -1823,4 +1823,40 @@ impl VisitMut for Hoister<'_, '_> { fn visit_mut_var_declarator(&mut self, node: &mut VarDeclarator) { node.name.visit_mut_with(self); } + + /// should visit var decls first, cause val decl may appear behind the + /// usage. this can deal with code below: + /// ```js + /// try {} catch (Ic) { + /// throw Ic; + /// } + /// var Ic; + /// ``` + /// the `Ic` defined by catch param and the `Ic` defined by `var Ic` are + /// different variables. + /// If we deal with the `var Ic` first, we can know + /// that there is already an global declaration of Ic when deal with the try + /// block. + fn visit_mut_module_items(&mut self, items: &mut Vec) { + let mut other_items = vec![]; + + for item in items { + match item { + ModuleItem::Stmt(Stmt::Decl(Decl::Var(decl))) + | ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl { + decl: Decl::Var(decl), + .. + })) if decl.kind == VarDeclKind::Var => { + item.visit_mut_with(self); + } + _ => { + other_items.push(item); + } + } + } + + for other_item in other_items { + other_item.visit_mut_with(self); + } + } } diff --git a/crates/swc_ecma_transforms_base/tests/resolver/minifier/13/input.js b/crates/swc_ecma_transforms_base/tests/resolver/minifier/13/input.js new file mode 100644 index 00000000000..aff98aadb38 --- /dev/null +++ b/crates/swc_ecma_transforms_base/tests/resolver/minifier/13/input.js @@ -0,0 +1,8 @@ +try { + console.log(111); +} catch (Ic) { + throw Ic; +} + +var jc, Ic; +(Ic = jc).PV = "page_view"; diff --git a/crates/swc_ecma_transforms_base/tests/resolver/minifier/13/output.js b/crates/swc_ecma_transforms_base/tests/resolver/minifier/13/output.js new file mode 100644 index 00000000000..b208a9fdcb3 --- /dev/null +++ b/crates/swc_ecma_transforms_base/tests/resolver/minifier/13/output.js @@ -0,0 +1,7 @@ +try { + console.log(111); +} catch (Ic__3) { + throw Ic__3; +} +var jc__1, Ic__1; +(Ic__1 = jc__1).PV = "page_view"; diff --git a/crates/swc_ecma_transforms_base/tests/resolver/minifier/14/input.js b/crates/swc_ecma_transforms_base/tests/resolver/minifier/14/input.js new file mode 100644 index 00000000000..58c2f922302 --- /dev/null +++ b/crates/swc_ecma_transforms_base/tests/resolver/minifier/14/input.js @@ -0,0 +1,8 @@ +try { + console.log(111); +} catch (Ic) { + throw Ic; +} + +export var jc, Ic; +(Ic = jc).PV = "page_view"; diff --git a/crates/swc_ecma_transforms_base/tests/resolver/minifier/14/output.js b/crates/swc_ecma_transforms_base/tests/resolver/minifier/14/output.js new file mode 100644 index 00000000000..01eb00f9ee5 --- /dev/null +++ b/crates/swc_ecma_transforms_base/tests/resolver/minifier/14/output.js @@ -0,0 +1,7 @@ +try { + console.log(111); +} catch (Ic__3) { + throw Ic__3; +} +export var jc__1, Ic__1; +(Ic__1 = jc__1).PV = "page_view";