Browse Source

Fix super property access (#3026)

* Fix super property access

* Add better documentation to compiler
pull/3047/head
raskad 1 year ago committed by GitHub
parent
commit
86726f1238
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      boa_engine/src/bytecompiler/class.rs
  2. 3
      boa_engine/src/bytecompiler/declaration/declaration_pattern.rs
  3. 13
      boa_engine/src/bytecompiler/expression/assign.rs
  4. 5
      boa_engine/src/bytecompiler/expression/mod.rs
  5. 139
      boa_engine/src/bytecompiler/expression/object_literal.rs
  6. 11
      boa_engine/src/bytecompiler/expression/update.rs
  7. 27
      boa_engine/src/bytecompiler/mod.rs
  8. 4
      boa_engine/src/vm/code_block.rs
  9. 4
      boa_engine/src/vm/flowgraph/mod.rs
  10. 9
      boa_engine/src/vm/opcode/get/property.rs
  11. 19
      boa_engine/src/vm/opcode/mod.rs
  12. 31
      boa_engine/src/vm/opcode/set/home_object.rs
  13. 13
      boa_engine/src/vm/opcode/set/property.rs

4
boa_engine/src/bytecompiler/class.rs

@ -353,7 +353,7 @@ impl ByteCompiler<'_, '_> {
self.functions.push(code);
self.emit(Opcode::GetFunction, &[index]);
self.emit_u8(0);
self.emit_opcode(Opcode::SetHomeObject);
self.emit_opcode(Opcode::SetHomeObjectClass);
self.emit(Opcode::Call, &[0]);
if let Some(name_index) = name_index {
self.emit(Opcode::DefineOwnPropertyByName, &[name_index]);
@ -401,7 +401,7 @@ impl ByteCompiler<'_, '_> {
self.functions.push(code);
self.emit(Opcode::GetFunction, &[index]);
self.emit_u8(0);
self.emit_opcode(Opcode::SetHomeObject);
self.emit_opcode(Opcode::SetHomeObjectClass);
self.emit(Opcode::Call, &[0]);
self.emit_opcode(Opcode::Pop);
}

3
boa_engine/src/bytecompiler/declaration/declaration_pattern.rs

@ -35,6 +35,7 @@ impl ByteCompiler<'_, '_> {
name,
default_init,
} => {
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
match name {
PropertyName::Literal(name) => {
@ -106,6 +107,7 @@ impl ByteCompiler<'_, '_> {
access,
default_init,
} => {
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
match name {
PropertyName::Literal(name) => {
@ -145,6 +147,7 @@ impl ByteCompiler<'_, '_> {
pattern,
default_init,
} => {
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
match name {
PropertyName::Literal(name) => {

13
boa_engine/src/bytecompiler/expression/assign.rs

@ -100,6 +100,7 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.emit(Opcode::GetPropertyByName, &[index]);
if short_circuit {
@ -119,11 +120,13 @@ impl ByteCompiler<'_, '_> {
PropertyAccessField::Expr(expr) => {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.compile_expr(expr, true);
self.emit_opcode(Opcode::GetPropertyByValuePush);
if short_circuit {
pop_count = 2;
pop_count = 3;
early_exit = Some(self.emit_opcode_with_operand(opcode));
self.compile_expr(assign.rhs(), true);
} else {
@ -164,6 +167,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::This);
self.emit_opcode(Opcode::Swap);
self.emit_opcode(Opcode::This);
self.emit(Opcode::GetPropertyByName, &[index]);
if short_circuit {
@ -183,6 +187,7 @@ impl ByteCompiler<'_, '_> {
PropertyAccessField::Expr(expr) => {
self.emit_opcode(Opcode::Super);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::This);
self.compile_expr(expr, true);
self.emit_opcode(Opcode::GetPropertyByValuePush);
@ -195,7 +200,11 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(opcode);
}
self.emit(Opcode::SetPropertyByValue, &[]);
self.emit_opcode(Opcode::This);
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(2);
self.emit_opcode(Opcode::SetPropertyByValue);
if !use_expr {
self.emit_opcode(Opcode::Pop);
}

5
boa_engine/src/bytecompiler/expression/mod.rs

@ -213,7 +213,8 @@ impl ByteCompiler<'_, '_> {
match template.tag() {
Expression::PropertyAccess(PropertyAccess::Simple(access)) => {
self.compile_expr(access.target(), true);
self.emit(Opcode::Dup, &[]);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
match access.field() {
PropertyAccessField::Const(field) => {
let index = self.get_or_insert_name((*field).into());
@ -221,7 +222,7 @@ impl ByteCompiler<'_, '_> {
}
PropertyAccessField::Expr(field) => {
self.compile_expr(field, true);
self.emit(Opcode::GetPropertyByValue, &[]);
self.emit_opcode(Opcode::GetPropertyByValue);
}
}
}

139
boa_engine/src/bytecompiler/expression/object_literal.rs

@ -1,10 +1,11 @@
use crate::{
bytecompiler::{Access, ByteCompiler},
bytecompiler::{Access, ByteCompiler, FunctionSpec},
vm::Opcode,
};
use boa_ast::{
expression::literal::ObjectLiteral,
property::{MethodDefinition, PropertyDefinition, PropertyName},
Expression,
};
use boa_interner::Sym;
@ -47,97 +48,91 @@ impl ByteCompiler<'_, '_> {
MethodDefinition::Get(expr) => match name {
PropertyName::Literal(name) => {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::SetPropertyGetterByName, &[index]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup);
self.object_method(expr.into());
self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(1);
self.emit_opcode(Opcode::SetPropertyGetterByValue);
self.compile_object_literal_computed_method(
name_node,
expr.into(),
MethodKind::Get,
);
}
},
MethodDefinition::Set(expr) => match name {
PropertyName::Literal(name) => {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::SetPropertySetterByName, &[index]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup);
self.object_method(expr.into());
self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(2);
self.emit_opcode(Opcode::SetPropertySetterByValue);
self.compile_object_literal_computed_method(
name_node,
expr.into(),
MethodKind::Set,
);
}
},
MethodDefinition::Ordinary(expr) => match name {
PropertyName::Literal(name) => {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup);
self.object_method(expr.into());
self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(0);
self.emit_opcode(Opcode::DefineOwnPropertyByValue);
self.compile_object_literal_computed_method(
name_node,
expr.into(),
MethodKind::Ordinary,
);
}
},
MethodDefinition::Async(expr) => match name {
PropertyName::Literal(name) => {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup);
self.object_method(expr.into());
self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(0);
self.emit_opcode(Opcode::DefineOwnPropertyByValue);
self.compile_object_literal_computed_method(
name_node,
expr.into(),
MethodKind::Ordinary,
);
}
},
MethodDefinition::Generator(expr) => match name {
PropertyName::Literal(name) => {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup);
self.object_method(expr.into());
self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(0);
self.emit_opcode(Opcode::DefineOwnPropertyByValue);
self.compile_object_literal_computed_method(
name_node,
expr.into(),
MethodKind::Ordinary,
);
}
},
MethodDefinition::AsyncGenerator(expr) => match name {
PropertyName::Literal(name) => {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup);
self.object_method(expr.into());
self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(0);
self.emit_opcode(Opcode::DefineOwnPropertyByValue);
self.compile_object_literal_computed_method(
name_node,
expr.into(),
MethodKind::Ordinary,
);
}
},
},
@ -157,4 +152,62 @@ impl ByteCompiler<'_, '_> {
self.emit(Opcode::Pop, &[]);
}
}
fn compile_object_literal_computed_method(
&mut self,
name: &Expression,
function: FunctionSpec<'_>,
kind: MethodKind,
) {
// stack: object, object
self.compile_expr(name, true);
// stack: object, object, name
self.emit_opcode(Opcode::ToPropertyKey);
// stack: object, object, ToPropertyKey(name)
self.emit_opcode(Opcode::Dup);
// stack: object, object, ToPropertyKey(name), ToPropertyKey(name)
self.object_method(function);
// stack: object, object, ToPropertyKey(name), ToPropertyKey(name), method
self.emit_opcode(Opcode::SetFunctionName);
match kind {
MethodKind::Get => self.emit_u8(1),
MethodKind::Set => self.emit_u8(2),
MethodKind::Ordinary => self.emit_u8(0),
}
// stack: object, object, ToPropertyKey(name), method
self.emit_opcode(Opcode::RotateLeft);
self.emit_u8(3);
// stack: object, ToPropertyKey(name), method, object
self.emit_opcode(Opcode::Swap);
// stack: object, ToPropertyKey(name), object, method
self.emit_opcode(Opcode::SetHomeObject);
// stack: object, ToPropertyKey(name), object, method
self.emit_opcode(Opcode::Swap);
// stack: object, ToPropertyKey(name), method, object
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(3);
// stack: object, object, ToPropertyKey(name), method
match kind {
MethodKind::Get => self.emit_opcode(Opcode::SetPropertyGetterByValue),
MethodKind::Set => self.emit_opcode(Opcode::SetPropertySetterByValue),
MethodKind::Ordinary => self.emit_opcode(Opcode::DefineOwnPropertyByValue),
}
}
}
#[derive(Debug, Clone, Copy)]
enum MethodKind {
Get,
Set,
Ordinary,
}

11
boa_engine/src/bytecompiler/expression/update.rs

@ -65,6 +65,7 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit_opcode(opcode);
@ -81,13 +82,15 @@ impl ByteCompiler<'_, '_> {
PropertyAccessField::Expr(expr) => {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.compile_expr(expr, true);
self.emit_opcode(Opcode::GetPropertyByValuePush);
self.emit_opcode(opcode);
if post {
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(4);
self.emit_u8(5);
}
self.emit_opcode(Opcode::SetPropertyByValue);
@ -120,6 +123,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::This);
self.emit_opcode(Opcode::Swap);
self.emit_opcode(Opcode::This);
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit_opcode(opcode);
@ -136,6 +140,7 @@ impl ByteCompiler<'_, '_> {
PropertyAccessField::Expr(expr) => {
self.emit_opcode(Opcode::Super);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::This);
self.compile_expr(expr, true);
self.emit_opcode(Opcode::GetPropertyByValuePush);
@ -145,6 +150,10 @@ impl ByteCompiler<'_, '_> {
self.emit_u8(2);
}
self.emit_opcode(Opcode::This);
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(2);
self.emit_opcode(Opcode::SetPropertyByValue);
if post {
self.emit_opcode(Opcode::Pop);

27
boa_engine/src/bytecompiler/mod.rs

@ -571,12 +571,14 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
PropertyAccessField::Const(name) => {
let index = self.get_or_insert_name((*name).into());
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.emit(Opcode::GetPropertyByName, &[index]);
}
PropertyAccessField::Expr(expr) => {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.compile_expr(expr, true);
self.emit(Opcode::GetPropertyByValue, &[]);
self.emit_opcode(Opcode::GetPropertyByValue);
}
},
PropertyAccess::Private(access) => {
@ -588,10 +590,12 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
PropertyAccessField::Const(field) => {
let index = self.get_or_insert_name((*field).into());
self.emit_opcode(Opcode::Super);
self.emit_opcode(Opcode::This);
self.emit(Opcode::GetPropertyByName, &[index]);
}
PropertyAccessField::Expr(expr) => {
self.emit_opcode(Opcode::Super);
self.emit_opcode(Opcode::This);
self.compile_expr(expr, true);
self.emit_opcode(Opcode::GetPropertyByValue);
}
@ -670,11 +674,12 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
}
PropertyAccessField::Expr(expr) => {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.compile_expr(expr, true);
expr_fn(self, 2);
self.emit(Opcode::SetPropertyByValue, &[]);
expr_fn(self, 3);
self.emit_opcode(Opcode::SetPropertyByValue);
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
},
@ -699,12 +704,13 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
}
}
PropertyAccessField::Expr(expr) => {
self.emit(Opcode::Super, &[]);
self.emit_opcode(Opcode::Super);
self.emit_opcode(Opcode::This);
self.compile_expr(expr, true);
expr_fn(self, 0);
self.emit(Opcode::SetPropertyByValue, &[]);
expr_fn(self, 1);
self.emit_opcode(Opcode::SetPropertyByValue);
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
},
@ -805,6 +811,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
PropertyAccess::Simple(access) => {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
match access.field() {
PropertyAccessField::Const(field) => {
let index = self.get_or_insert_name((*field).into());
@ -825,6 +832,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
PropertyAccess::Super(access) => {
self.emit_opcode(Opcode::This);
self.emit_opcode(Opcode::Super);
self.emit_opcode(Opcode::This);
match access.field() {
PropertyAccessField::Const(field) => {
let index = self.get_or_insert_name((*field).into());
@ -909,6 +917,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
fn compile_optional_item_kind(&mut self, kind: &OptionalOperationKind) {
match kind {
OptionalOperationKind::SimplePropertyAccess { field } => {
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
match field {
PropertyAccessField::Const(name) => {
@ -917,7 +926,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
}
PropertyAccessField::Expr(expr) => {
self.compile_expr(expr, true);
self.emit(Opcode::GetPropertyByValue, &[]);
self.emit_opcode(Opcode::GetPropertyByValue);
}
}
self.emit_opcode(Opcode::RotateLeft);

4
boa_engine/src/vm/code_block.rs

@ -455,6 +455,7 @@ impl CodeBlock {
| Opcode::PushClassPrototype
| Opcode::SetClassPrototype
| Opcode::SetHomeObject
| Opcode::SetHomeObjectClass
| Opcode::Add
| Opcode::Sub
| Opcode::Div
@ -609,8 +610,7 @@ impl CodeBlock {
| Opcode::Reserved47
| Opcode::Reserved48
| Opcode::Reserved49
| Opcode::Reserved50
| Opcode::Reserved51 => unreachable!("Reserved opcodes are unrechable"),
| Opcode::Reserved50 => unreachable!("Reserved opcodes are unrechable"),
}
}
}

4
boa_engine/src/vm/flowgraph/mod.rs

@ -534,6 +534,7 @@ impl CodeBlock {
| Opcode::PushClassPrototype
| Opcode::SetClassPrototype
| Opcode::SetHomeObject
| Opcode::SetHomeObjectClass
| Opcode::Add
| Opcode::Sub
| Opcode::Div
@ -708,8 +709,7 @@ impl CodeBlock {
| Opcode::Reserved47
| Opcode::Reserved48
| Opcode::Reserved49
| Opcode::Reserved50
| Opcode::Reserved51 => unreachable!("Reserved opcodes are unrechable"),
| Opcode::Reserved50 => unreachable!("Reserved opcodes are unrechable"),
}
}

9
boa_engine/src/vm/opcode/get/property.rs

@ -18,6 +18,7 @@ impl Operation for GetPropertyByName {
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u32>();
let receiver = context.vm.pop();
let value = context.vm.pop();
let object = if let Some(object) = value.as_object() {
object.clone()
@ -28,7 +29,7 @@ impl Operation for GetPropertyByName {
let key = context.vm.frame().code_block.names[index as usize]
.clone()
.into();
let result = object.__get__(&key, value, context)?;
let result = object.__get__(&key, receiver, context)?;
context.vm.push(result);
Ok(CompletionType::Normal)
@ -48,6 +49,7 @@ impl Operation for GetPropertyByValue {
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let key = context.vm.pop();
let receiver = context.vm.pop();
let value = context.vm.pop();
let object = if let Some(object) = value.as_object() {
object.clone()
@ -73,7 +75,7 @@ impl Operation for GetPropertyByValue {
}
// Slow path:
let result = object.__get__(&key, value, context)?;
let result = object.__get__(&key, receiver, context)?;
context.vm.push(result);
Ok(CompletionType::Normal)
@ -118,6 +120,7 @@ impl Operation for GetPropertyByValuePush {
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let key = context.vm.pop();
let receiver = context.vm.pop();
let value = context.vm.pop();
let object = if let Some(object) = value.as_object() {
object.clone()
@ -144,7 +147,7 @@ impl Operation for GetPropertyByValuePush {
}
// Slow path:
let result = object.__get__(&key, value, context)?;
let result = object.__get__(&key, receiver, context)?;
context.vm.push(key);
context.vm.push(result);

19
boa_engine/src/vm/opcode/mod.rs

@ -346,13 +346,20 @@ generate_impl! {
/// Stack: class, prototype **=>** class.prototype
SetClassPrototype,
/// Set home object internal slot of a function object.
/// Set home object internal slot of an object literal method.
///
/// Operands:
///
/// Stack: home, function **=>** home, function
SetHomeObject,
/// Set home object internal slot of a class method.
///
/// Operands:
///
/// Stack: home, function **=>** home, function
SetHomeObjectClass,
/// Set the prototype of an object if the value is an object or null.
///
/// Operands:
@ -729,7 +736,7 @@ generate_impl! {
///
/// Operands: name_index: `u32`
///
/// Stack: object **=>** value
/// Stack: object, receiver **=>** value
GetPropertyByName,
/// Get a property method or undefined if the property is null or undefined.
@ -746,7 +753,7 @@ generate_impl! {
///
/// Operands:
///
/// Stack: object, key **=>** value
/// Stack: object, receiver, key **=>** value
GetPropertyByValue,
/// Get a property by value from an object an push the key and value on the stack.
@ -755,7 +762,7 @@ generate_impl! {
///
/// Operands:
///
/// Stack: object, key **=>** key, value
/// Stack: object, receiver, key **=>** key, value
GetPropertyByValuePush,
/// Sets a property by name of an object.
@ -810,7 +817,7 @@ generate_impl! {
///
/// Operands:
///
/// Stack: object, key, value **=>** value
/// Stack: object, receiver, key, value **=>** value
SetPropertyByValue,
/// Defines a own property of an object by value.
@ -1819,8 +1826,6 @@ generate_impl! {
Reserved49 => Reserved,
/// Reserved [`Opcode`].
Reserved50 => Reserved,
/// Reserved [`Opcode`].
Reserved51 => Reserved,
}
}

31
boa_engine/src/vm/opcode/set/home_object.rs

@ -14,6 +14,37 @@ impl Operation for SetHomeObject {
const NAME: &'static str = "SetHomeObject";
const INSTRUCTION: &'static str = "INST - SetHomeObject";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let function = context.vm.pop();
let home = context.vm.pop();
{
let function_object = function.as_object().expect("must be object");
let home_object = home.as_object().expect("must be object");
let mut function_object_mut = function_object.borrow_mut();
let function_mut = function_object_mut
.as_function_mut()
.expect("must be function object");
function_mut.set_home_object(home_object.clone());
}
context.vm.push(home);
context.vm.push(function);
Ok(CompletionType::Normal)
}
}
/// `SetHomeObjectClass` implements the Opcode Operation for `Opcode::SetHomeObjectClass`
///
/// Operation:
/// - Set home object internal slot of a function object.
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetHomeObjectClass;
impl Operation for SetHomeObjectClass {
const NAME: &'static str = "SetHomeObjectClass";
const INSTRUCTION: &'static str = "INST - SetHomeObjectClass";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let function = context.vm.pop();
let home = context.vm.pop();

13
boa_engine/src/vm/opcode/set/property.rs

@ -59,6 +59,7 @@ impl Operation for SetPropertyByValue {
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let value = context.vm.pop();
let key = context.vm.pop();
let receiver = context.vm.pop();
let object = context.vm.pop();
let object = if let Some(object) = object.as_object() {
object.clone()
@ -137,12 +138,12 @@ impl Operation for SetPropertyByValue {
}
// Slow path:
object.set(
key,
value.clone(),
context.vm.frame().code_block.strict(),
context,
)?;
let succeeded = object.__set__(key.clone(), value.clone(), receiver, context)?;
if !succeeded && context.vm.frame().code_block.strict() {
return Err(JsNativeError::typ()
.with_message(format!("cannot set non-writable property: {key}"))
.into());
}
context.vm.stack.push(value);
Ok(CompletionType::Normal)
}

Loading…
Cancel
Save