From a381fb8bce0ed82e7b0a201bb175acb13ce90205 Mon Sep 17 00:00:00 2001 From: OJ Kwon Date: Thu, 16 Dec 2021 22:08:22 -0800 Subject: [PATCH] fix(es/compat): Fix `block_scoping` (#3058) swc_ecma_transforms_compat: - `block_scoping`: Consider the location of variable declarations. (Closes #2998) --- .../src/es2015/block_scoping.rs | 21 ++++++++ .../tests/es2015_block_scoping.rs | 48 +++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/crates/swc_ecma_transforms_compat/src/es2015/block_scoping.rs b/crates/swc_ecma_transforms_compat/src/es2015/block_scoping.rs index ceca67a98a9d..f34c449791dd 100644 --- a/crates/swc_ecma_transforms_compat/src/es2015/block_scoping.rs +++ b/crates/swc_ecma_transforms_compat/src/es2015/block_scoping.rs @@ -30,6 +30,7 @@ pub fn block_scoping() -> impl Fold { scope: Default::default(), vars: vec![], var_decl_kind: VarDeclKind::Var, + in_loop_body_scope: false, }) } @@ -54,6 +55,7 @@ struct BlockScoping { scope: ScopeStack, vars: Vec, var_decl_kind: VarDeclKind, + in_loop_body_scope: bool, } impl BlockScoping { @@ -71,7 +73,9 @@ impl BlockScoping { }; self.scope.push(kind); + self.in_loop_body_scope = true; node.visit_mut_with(self); + self.in_loop_body_scope = false; if remove { self.scope.truncate(len); @@ -557,6 +561,23 @@ impl VisitMut for BlockScoping { self.var_decl_kind = old; var.kind = VarDeclKind::Var; + + if !self.in_loop_body_scope { + return; + } + + // If loop body contains same ident to loop node's ident, rename it to avoid + // variable hoisting overwrites inner declaration. + for decl in var.decls.iter_mut() { + if let Pat::Ident(name) = &mut decl.name { + if let Some(ScopeKind::ForLetLoop { args, .. }) = self.scope.last() { + let id = &(*name).id.to_id(); + if args.contains(id) { + (*name).id = private_ident!((*name).id.take().sym); + } + } + } + } } fn visit_mut_var_declarator(&mut self, var: &mut VarDeclarator) { diff --git a/crates/swc_ecma_transforms_compat/tests/es2015_block_scoping.rs b/crates/swc_ecma_transforms_compat/tests/es2015_block_scoping.rs index 35ec94fe30f1..84fc19b3177c 100644 --- a/crates/swc_ecma_transforms_compat/tests/es2015_block_scoping.rs +++ b/crates/swc_ecma_transforms_compat/tests/es2015_block_scoping.rs @@ -956,3 +956,51 @@ test!( for(var key in keys)_loop(key); " ); + +test!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + issue_2998_1, + " + let a = 5; +for (let b = 0; b < a; b++) { + let c = 0, b = 10, d = 100; + console.log(b); +} + ", + " + var a = 5; +for(var b = 0; b < a; b++){ + var c = 0, b1 = 10, d = 100; + console.log(b); +} + " +); + +test!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + issue_2998_2, + " + for (var a; ;) { } + for (var a = ['a', 'b']; ;) { } + ", + " + for (var a; ;) { } + for (var a = ['a', 'b']; ;) { } + " +); + +test_exec!( + ::swc_ecma_parser::Syntax::default(), + |_| block_scoping(), + issue_2998_3, + "let a = 5; +const expected = []; +for (let b = 0; b < a; b++) { + let c = 0, b = 10, d = 100; + expected.push(b); +} +expect(expected).toEqual([0,1,2,3,4]); +" +);