Browse Source

Fix setting properties inside `with` blocks (#2847)

This preserves the semantics of the abstract operation `Set` on `with` blocks; setting non-writable properties on non-strict mode just silently fails.
pull/2852/head
José Julián Espina 2 years ago
parent
commit
65f910523b
  1. 6
      boa_engine/src/environments/runtime.rs
  2. 6
      boa_engine/src/vm/opcode/define/mod.rs
  3. 7
      boa_engine/src/vm/opcode/set/name.rs

6
boa_engine/src/environments/runtime.rs

@ -951,6 +951,7 @@ impl Context<'_> {
mut binding_index: usize, mut binding_index: usize,
name: Identifier, name: Identifier,
value: JsValue, value: JsValue,
strict: bool,
) -> JsResult<bool> { ) -> JsResult<bool> {
for env_index in (environment_index + 1..self.vm.environments.stack.len()).rev() { for env_index in (environment_index + 1..self.vm.environments.stack.len()).rev() {
let env = self.environment_expect(env_index); let env = self.environment_expect(env_index);
@ -983,7 +984,7 @@ impl Context<'_> {
continue; continue;
} }
} }
return o.set(key, value, true, self); return o.set(key, value, strict, self);
} }
} }
} }
@ -1017,6 +1018,7 @@ impl Context<'_> {
&mut self, &mut self,
name: Identifier, name: Identifier,
value: &JsValue, value: &JsValue,
strict: bool,
) -> JsResult<bool> { ) -> JsResult<bool> {
for env_index in (0..self.vm.environments.stack.len()).rev() { for env_index in (0..self.vm.environments.stack.len()).rev() {
let env = self.environment_expect(env_index); let env = self.environment_expect(env_index);
@ -1056,7 +1058,7 @@ impl Context<'_> {
continue; continue;
} }
} }
return o.set(key, value.clone(), true, self); return o.set(key, value.clone(), strict, self);
} }
} }
} }

6
boa_engine/src/vm/opcode/define/mod.rs

@ -59,7 +59,11 @@ impl Operation for DefInitVar {
binding_locator.throw_mutate_immutable(context)?; binding_locator.throw_mutate_immutable(context)?;
if binding_locator.is_global() { if binding_locator.is_global() {
if !context.put_value_if_global_poisoned(binding_locator.name(), &value)? { if !context.put_value_if_global_poisoned(
binding_locator.name(),
&value,
context.vm.frame().code_block.strict,
)? {
let key = context let key = context
.interner() .interner()
.resolve_expect(binding_locator.name().sym()) .resolve_expect(binding_locator.name().sym())

7
boa_engine/src/vm/opcode/set/name.rs

@ -25,7 +25,11 @@ impl Operation for SetName {
binding_locator.throw_mutate_immutable(context)?; binding_locator.throw_mutate_immutable(context)?;
if binding_locator.is_global() { if binding_locator.is_global() {
if !context.put_value_if_global_poisoned(binding_locator.name(), &value)? { if !context.put_value_if_global_poisoned(
binding_locator.name(),
&value,
context.vm.frame().code_block.strict,
)? {
let key: JsString = context let key: JsString = context
.interner() .interner()
.resolve_expect(binding_locator.name().sym()) .resolve_expect(binding_locator.name().sym())
@ -55,6 +59,7 @@ impl Operation for SetName {
binding_locator.binding_index(), binding_locator.binding_index(),
binding_locator.name(), binding_locator.name(),
value, value,
context.vm.frame().code_block.strict,
)? { )? {
return Err(JsNativeError::reference() return Err(JsNativeError::reference()
.with_message(format!( .with_message(format!(

Loading…
Cancel
Save