Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(es/transform_compat): should prepend generated _loop function to correct scope #6604

Merged
merged 2 commits into from
Dec 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,44 @@ impl BlockScoping {
*body = Box::new(call.take().into_stmt());
}
}

/// This method will turn stmt like
/// ```js
/// for (let i in [1, 2])
/// for (let j in [1, 2])
/// console.log(i, j)
/// ```
/// into
/// ```js
/// for (let i in [1, 2]) {
/// for (let j in [1, 2]) {
/// console.log(i, j)
/// }
/// }
/// ```
/// which fixes https://github.com/swc-project/swc/issues/6573
fn blockify_for_stmt_body(&self, body: &mut Box<Stmt>) -> bool {
if !body.is_block() {
*body = Box::new(Stmt::Block(BlockStmt {
span: Default::default(),
stmts: vec![*body.take()],
}));
true
} else {
false
}
}

fn undo_blockify_for_stmt_body(&self, body: &mut Box<Stmt>, blockifyed: bool) {
if blockifyed {
let stmt = body
.as_mut_block()
.and_then(|block| (block.stmts.len() == 1).then(|| block.stmts[0].take()));
if let Some(stmt) = stmt {
*body = Box::new(stmt)
}
}
}
}

#[swc_trace]
Expand Down Expand Up @@ -400,6 +438,7 @@ impl VisitMut for BlockScoping {
}

fn visit_mut_for_in_stmt(&mut self, node: &mut ForInStmt) {
let blockifyed = self.blockify_for_stmt_body(&mut node.body);
let lexical_var = if let VarDeclOrPat::VarDecl(decl) = &node.left {
find_lexical_vars(decl)
} else {
Expand All @@ -420,9 +459,11 @@ impl VisitMut for BlockScoping {

self.visit_mut_with_scope(kind, &mut node.body);
self.handle_capture_of_vars(&mut node.body);
self.undo_blockify_for_stmt_body(&mut node.body, blockifyed);
}

fn visit_mut_for_of_stmt(&mut self, node: &mut ForOfStmt) {
let blockifyed = self.blockify_for_stmt_body(&mut node.body);
let vars = if let VarDeclOrPat::VarDecl(decl) = &node.left {
find_lexical_vars(decl)
} else {
Expand All @@ -444,9 +485,11 @@ impl VisitMut for BlockScoping {

self.visit_mut_with_scope(kind, &mut node.body);
self.handle_capture_of_vars(&mut node.body);
self.undo_blockify_for_stmt_body(&mut node.body, blockifyed);
}

fn visit_mut_for_stmt(&mut self, node: &mut ForStmt) {
let blockifyed = self.blockify_for_stmt_body(&mut node.body);
let lexical_var = if let Some(VarDeclOrExpr::VarDecl(decl)) = &node.init {
find_lexical_vars(decl)
} else {
Expand All @@ -467,6 +510,7 @@ impl VisitMut for BlockScoping {
};
self.visit_mut_with_scope(kind, &mut node.body);
self.handle_capture_of_vars(&mut node.body);
self.undo_blockify_for_stmt_body(&mut node.body, blockifyed);
}

fn visit_mut_function(&mut self, f: &mut Function) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
let funcs = [];
for (let i = 0; i < 2; i++)
for (let j = 0; j < 2; j++)
funcs.push(() => console.log(i, j));

funcs.forEach((f) => f());
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
var _loop__7 = function(i__2) {
var _loop__6 = function(j__3) {
funcs__1.push(()=>console.log(i__2, j__3));
};
for(var j__3 = 0; j__3 < 2; j__3++)_loop__6(j__3);
};
var funcs__1 = [];
for(var i__2 = 0; i__2 < 2; i__2++)_loop__7(i__2);
funcs__1.forEach((f__5)=>f__5());
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
let funcs = [];
for (let i in [1, 2])
for (let j in [1, 2])
funcs.push(() => console.log(i, j));

funcs.forEach((f) => f());
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
var _loop__7 = function(i__2) {
var _loop__6 = function(j__3) {
funcs__1.push(()=>console.log(i__2, j__3));
};
for(var j__3 in [
1,
2
])_loop__6(j__3);
};
var funcs__1 = [];
for(var i__2 in [
1,
2
])_loop__7(i__2);
funcs__1.forEach((f__5)=>f__5());
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
let funcs = [];
for (let i of [1, 2])
for (let j of [1, 2])
funcs.push(() => console.log(i, j));

funcs.forEach((f) => f());
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
var _loop__7 = function(i__2) {
var _loop__6 = function(j__3) {
funcs__1.push(()=>console.log(i__2, j__3));
};
for (var j__3 of [
1,
2
])_loop__6(j__3);
};
var funcs__1 = [];
for (var i__2 of [
1,
2
])_loop__7(i__2);
funcs__1.forEach((f__5)=>f__5());