diff --git a/boa/src/bytecompiler.rs b/boa/src/bytecompiler.rs index fa06b30e1b8..94cc00bcaf1 100644 --- a/boa/src/bytecompiler.rs +++ b/boa/src/bytecompiler.rs @@ -370,7 +370,29 @@ impl ByteCompiler { UnaryOp::DecrementPre => todo!(), UnaryOp::IncrementPost => todo!(), UnaryOp::DecrementPost => todo!(), - UnaryOp::Delete => todo!(), + UnaryOp::Delete => match unary.target() { + Node::GetConstField(ref get_const_field) => { + self.emit_push_literal(Literal::String(get_const_field.field().into())); + self.compile_expr(get_const_field.obj(), true); + self.emit(Opcode::DeletePropertyByValue, &[]); + None + } + Node::GetField(ref get_field) => { + self.compile_expr(get_field.field(), true); + self.compile_expr(get_field.obj(), true); + self.emit(Opcode::DeletePropertyByValue, &[]); + None + } + // TODO: implement delete on references. + Node::Identifier(_) => { + self.emit(Opcode::PushFalse, &[]); + None + } + _ => { + self.emit(Opcode::PushTrue, &[]); + None + } + }, UnaryOp::Minus => Some(Opcode::Neg), UnaryOp::Plus => Some(Opcode::Pos), UnaryOp::Not => Some(Opcode::LogicalNot), @@ -382,10 +404,10 @@ impl ByteCompiler { if let Some(opcode) = opcode { self.compile_expr(unary.target(), true); self.emit(opcode, &[]); + } - if !use_expr { - self.emit(Opcode::Pop, &[]); - } + if !use_expr { + self.emit(Opcode::Pop, &[]); } } Node::BinOp(binary) => { diff --git a/boa/src/syntax/ast/node/operator/unary_op/mod.rs b/boa/src/syntax/ast/node/operator/unary_op/mod.rs index 2ef824cf7bd..24069c96a3e 100644 --- a/boa/src/syntax/ast/node/operator/unary_op/mod.rs +++ b/boa/src/syntax/ast/node/operator/unary_op/mod.rs @@ -114,16 +114,9 @@ impl Executable for UnaryOp { .__delete__(&field.to_property_key(context)?, context)?; return Ok(JsValue::new(res)); } + // TODO: implement delete on references. Node::Identifier(_) => JsValue::new(false), - Node::ArrayDecl(_) - | Node::Block(_) - | Node::Const(_) - | Node::FunctionDecl(_) - | Node::FunctionExpr(_) - | Node::New(_) - | Node::Object(_) - | Node::UnaryOp(_) => JsValue::new(true), - _ => return context.throw_syntax_error(format!("wrong delete argument {}", self)), + _ => JsValue::new(true), }, op::UnaryOp::TypeOf => JsValue::new(self.target().run(context)?.type_of()), }) diff --git a/boa/src/vm/code_block.rs b/boa/src/vm/code_block.rs index a6f97cc89eb..533b8ec39e1 100644 --- a/boa/src/vm/code_block.rs +++ b/boa/src/vm/code_block.rs @@ -207,6 +207,7 @@ impl CodeBlock { | Opcode::Neg | Opcode::GetPropertyByValue | Opcode::SetPropertyByValue + | Opcode::DeletePropertyByValue | Opcode::ToBoolean | Opcode::Throw | Opcode::This diff --git a/boa/src/vm/mod.rs b/boa/src/vm/mod.rs index 4e6864e2751..713bcd3a8e6 100644 --- a/boa/src/vm/mod.rs +++ b/boa/src/vm/mod.rs @@ -411,6 +411,14 @@ impl Context { let key = key.to_property_key(self)?; object.set(key, value, true, self)?; } + Opcode::DeletePropertyByValue => { + let object = self.vm.pop(); + let key = self.vm.pop(); + let result = object + .to_object(self)? + .__delete__(&key.to_property_key(self)?, self)?; + self.vm.push(result); + } Opcode::Throw => { let value = self.vm.pop(); return Err(value); diff --git a/boa/src/vm/opcode.rs b/boa/src/vm/opcode.rs index 79bee2a75c4..68af28bccdb 100644 --- a/boa/src/vm/opcode.rs +++ b/boa/src/vm/opcode.rs @@ -442,6 +442,15 @@ pub enum Opcode { /// Stack: value, key, object **=>** SetPropertyByValue, + /// Deletes a property by value of an object. + /// + /// Like `delete object[key]` + /// + /// Operands: + /// + /// Stack: key, object **=>** + DeletePropertyByValue, + /// Unconditional jump to address. /// /// Operands: address: `u32` @@ -605,6 +614,7 @@ impl Opcode { Opcode::GetPropertyByValue => "GetPropertyByValue", Opcode::SetPropertyByName => "SetPropertyByName", Opcode::SetPropertyByValue => "SetPropertyByValue", + Opcode::DeletePropertyByValue => "DeletePropertyByValue", Opcode::Jump => "Jump", Opcode::JumpIfFalse => "JumpIfFalse", Opcode::JumpIfTrue => "JumpIfTrue",