From d9fd074e7e9258b1f1ce19c0dd1443a48725b9a6 Mon Sep 17 00:00:00 2001 From: raskad <32105367+raskad@users.noreply.github.com> Date: Sun, 23 Apr 2023 03:48:40 +0200 Subject: [PATCH] Initialize `var` bindings in runtime environments with `undefined` --- boa_engine/src/bytecompiler/class.rs | 19 +++++++++++++++++++ boa_engine/src/environments/compile.rs | 14 ++++++++++++++ boa_engine/src/environments/runtime.rs | 14 ++++++++++++-- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/boa_engine/src/bytecompiler/class.rs b/boa_engine/src/bytecompiler/class.rs index e571b1e3b17..79bcf6256e9 100644 --- a/boa_engine/src/bytecompiler/class.rs +++ b/boa_engine/src/bytecompiler/class.rs @@ -113,6 +113,18 @@ impl ByteCompiler<'_, '_> { self.emit(Opcode::GetFunction, &[index]); self.emit_u8(0); + let class_env = if let Some(class_name) = class.name() { + if class.has_binding_identifier() { + self.push_compile_environment(false); + self.create_immutable_binding(class_name, true); + Some(self.emit_opcode_with_two_operands(Opcode::PushDeclarativeEnvironment)) + } else { + None + } + } else { + None + }; + self.emit_opcode(Opcode::Dup); if let Some(node) = class.super_ref() { self.compile_expr(node, true); @@ -544,6 +556,13 @@ impl ByteCompiler<'_, '_> { self.emit_opcode(Opcode::Pop); + if let Some(class_env) = class_env { + let env_info = self.pop_compile_environment(); + self.patch_jump_with_target(class_env.0, env_info.num_bindings as u32); + self.patch_jump_with_target(class_env.1, env_info.index as u32); + self.emit_opcode(Opcode::PopEnvironment); + } + if !expression { self.emit_binding( BindingOpcode::InitVar, diff --git a/boa_engine/src/environments/compile.rs b/boa_engine/src/environments/compile.rs index 18771b54dfe..13ecdf2f884 100644 --- a/boa_engine/src/environments/compile.rs +++ b/boa_engine/src/environments/compile.rs @@ -217,4 +217,18 @@ impl CompileTimeEnvironment { pub(crate) const fn environment_index(&self) -> usize { self.environment_index } + + /// Gets the indices of all `var` bindings in this environment. + pub(crate) fn var_binding_indices(&self) -> Vec { + self.bindings + .iter() + .filter_map(|(_, binding)| { + if binding.lex { + None + } else { + Some(binding.index) + } + }) + .collect() + } } diff --git a/boa_engine/src/environments/runtime.rs b/boa_engine/src/environments/runtime.rs index ecc536d9a71..d300e887712 100644 --- a/boa_engine/src/environments/runtime.rs +++ b/boa_engine/src/environments/runtime.rs @@ -480,9 +480,14 @@ impl DeclarativeEnvironmentStack { let this = this.unwrap_or(JsValue::Null); + let mut bindings = vec![None; num_bindings]; + for index in compile_environment.borrow().var_binding_indices() { + bindings[index] = Some(JsValue::Undefined); + } + self.stack .push(Environment::Declarative(Gc::new(DeclarativeEnvironment { - bindings: GcRefCell::new(vec![None; num_bindings]), + bindings: GcRefCell::new(bindings), compile: compile_environment, poisoned: Cell::new(poisoned), with: Cell::new(with), @@ -534,9 +539,14 @@ impl DeclarativeEnvironmentStack { ) }; + let mut bindings = vec![None; num_bindings]; + for index in compile_environment.borrow().var_binding_indices() { + bindings[index] = Some(JsValue::Undefined); + } + self.stack .push(Environment::Declarative(Gc::new(DeclarativeEnvironment { - bindings: GcRefCell::new(vec![None; num_bindings]), + bindings: GcRefCell::new(bindings), compile: compile_environment, poisoned: Cell::new(poisoned), with: Cell::new(with),