Skip to content

Commit

Permalink
Fix for in/of loop initializer environment (#2135)
Browse files Browse the repository at this point in the history
This Pull Request changes the following:

- Add an additional environment when a for in/of loop is initialized with a `let` or `const` binding.
  • Loading branch information
raskad committed Jun 21, 2022
1 parent 3f4232b commit 613f4c3
Showing 1 changed file with 44 additions and 2 deletions.
46 changes: 44 additions & 2 deletions boa_engine/src/bytecompiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1355,7 +1355,28 @@ impl<'b> ByteCompiler<'b> {
self.emit_opcode(Opcode::PopEnvironment);
}
Node::ForInLoop(for_in_loop) => {
self.compile_expr(for_in_loop.expr(), true)?;
let init_bound_names = for_in_loop.init().bound_names();
if init_bound_names.is_empty() {
self.compile_expr(for_in_loop.expr(), true)?;
} else {
self.context.push_compile_time_environment(false);
let push_env =
self.emit_opcode_with_two_operands(Opcode::PushDeclarativeEnvironment);

for name in init_bound_names {
self.context.create_mutable_binding(name, false);
}
self.compile_expr(for_in_loop.expr(), true)?;

let (num_bindings, compile_environment) =
self.context.pop_compile_time_environment();
let index_compile_environment =
self.push_compile_environment(compile_environment);
self.patch_jump_with_target(push_env.0, num_bindings as u32);
self.patch_jump_with_target(push_env.1, index_compile_environment as u32);
self.emit_opcode(Opcode::PopEnvironment);
}

let early_exit = self.emit_opcode_with_operand(Opcode::ForInLoopInitIterator);

self.emit_opcode(Opcode::LoopStart);
Expand Down Expand Up @@ -1438,7 +1459,28 @@ impl<'b> ByteCompiler<'b> {
self.patch_jump(early_exit);
}
Node::ForOfLoop(for_of_loop) => {
self.compile_expr(for_of_loop.iterable(), true)?;
let init_bound_names = for_of_loop.init().bound_names();
if init_bound_names.is_empty() {
self.compile_expr(for_of_loop.iterable(), true)?;
} else {
self.context.push_compile_time_environment(false);
let push_env =
self.emit_opcode_with_two_operands(Opcode::PushDeclarativeEnvironment);

for name in init_bound_names {
self.context.create_mutable_binding(name, false);
}
self.compile_expr(for_of_loop.iterable(), true)?;

let (num_bindings, compile_environment) =
self.context.pop_compile_time_environment();
let index_compile_environment =
self.push_compile_environment(compile_environment);
self.patch_jump_with_target(push_env.0, num_bindings as u32);
self.patch_jump_with_target(push_env.1, index_compile_environment as u32);
self.emit_opcode(Opcode::PopEnvironment);
}

self.emit_opcode(Opcode::InitIterator);

self.emit_opcode(Opcode::LoopStart);
Expand Down

0 comments on commit 613f4c3

Please sign in to comment.