Fix for in/of loop initializer environment
This Pull Request changes the following:
Add an additional environment when a for in/of loop is initialized with a `let` or `const` binding.
@@ -1355,7 +1355,28 @@ impl<'b> ByteCompiler<'b> {
self.emit_opcode(Opcode::PopEnvironment);
}
Node::ForInLoop(for_in_loop) => {
+ 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);
@@ -1438,7 +1459,28 @@ impl<'b> ByteCompiler<'b> {
self.patch_jump(early_exit);
}
Node::ForOfLoop(for_of_loop) => {
+ 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);
