From a5b787318a2563d068a77ee2125d9991dca95612 Mon Sep 17 00:00:00 2001 From: raskad <32105367+raskad@users.noreply.github.com> Date: Fri, 8 Oct 2021 01:31:35 +0200 Subject: [PATCH 1/3] Implement `delete` in the vm --- boa/src/bytecompiler.rs | 30 ++++++++++++++++--- .../syntax/ast/node/operator/unary_op/mod.rs | 11 ++----- boa/src/vm/code_block.rs | 1 + boa/src/vm/mod.rs | 8 +++++ boa/src/vm/opcode.rs | 10 +++++++ 5 files changed, 47 insertions(+), 13 deletions(-) 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", From 93ae403927d979ce68096cd0cf96d9c18e5dd83d Mon Sep 17 00:00:00 2001 From: raskad <32105367+raskad@users.noreply.github.com> Date: Sat, 9 Oct 2021 21:16:26 +0200 Subject: [PATCH 2/3] Add `DeletePropertyByName` vm opcode --- boa/src/bytecompiler.rs | 4 ++-- boa/src/vm/code_block.rs | 1 + boa/src/vm/mod.rs | 7 +++++++ boa/src/vm/opcode.rs | 10 ++++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/boa/src/bytecompiler.rs b/boa/src/bytecompiler.rs index 94cc00bcaf1..5f83383079b 100644 --- a/boa/src/bytecompiler.rs +++ b/boa/src/bytecompiler.rs @@ -372,9 +372,9 @@ impl ByteCompiler { UnaryOp::DecrementPost => todo!(), UnaryOp::Delete => match unary.target() { Node::GetConstField(ref get_const_field) => { - self.emit_push_literal(Literal::String(get_const_field.field().into())); + let index = self.get_or_insert_name(get_const_field.field()); self.compile_expr(get_const_field.obj(), true); - self.emit(Opcode::DeletePropertyByValue, &[]); + self.emit(Opcode::DeletePropertyByName, &[index]); None } Node::GetField(ref get_field) => { diff --git a/boa/src/vm/code_block.rs b/boa/src/vm/code_block.rs index 533b8ec39e1..c5ef69546af 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::DeletePropertyByName | Opcode::DeletePropertyByValue | Opcode::ToBoolean | Opcode::Throw diff --git a/boa/src/vm/mod.rs b/boa/src/vm/mod.rs index 713bcd3a8e6..528b48fef3a 100644 --- a/boa/src/vm/mod.rs +++ b/boa/src/vm/mod.rs @@ -411,6 +411,13 @@ impl Context { let key = key.to_property_key(self)?; object.set(key, value, true, self)?; } + Opcode::DeletePropertyByName => { + let index = self.vm.read::(); + let key = self.vm.frame().code.variables[index as usize].clone(); + let object = self.vm.pop(); + let result = object.to_object(self)?.__delete__(&key.into(), self)?; + self.vm.push(result); + } Opcode::DeletePropertyByValue => { let object = self.vm.pop(); let key = self.vm.pop(); diff --git a/boa/src/vm/opcode.rs b/boa/src/vm/opcode.rs index 68af28bccdb..f7901b35945 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 name of an object. + /// + /// Like `delete object.key.` + /// + /// Operands: name_index: `u32` + /// + /// Stack: object **=>** + DeletePropertyByName, + /// Deletes a property by value of an object. /// /// Like `delete object[key]` @@ -614,6 +623,7 @@ impl Opcode { Opcode::GetPropertyByValue => "GetPropertyByValue", Opcode::SetPropertyByName => "SetPropertyByName", Opcode::SetPropertyByValue => "SetPropertyByValue", + Opcode::DeletePropertyByName => "DeletePropertyByName", Opcode::DeletePropertyByValue => "DeletePropertyByValue", Opcode::Jump => "Jump", Opcode::JumpIfFalse => "JumpIfFalse", From ec9d4132c753852be7a72a3ff3623d90580b3ac0 Mon Sep 17 00:00:00 2001 From: raskad <32105367+raskad@users.noreply.github.com> Date: Sun, 10 Oct 2021 16:03:21 +0200 Subject: [PATCH 3/3] Fix `DeletePropertyByName` in `instruction_operands` --- boa/src/vm/code_block.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boa/src/vm/code_block.rs b/boa/src/vm/code_block.rs index c5ef69546af..80361bf095d 100644 --- a/boa/src/vm/code_block.rs +++ b/boa/src/vm/code_block.rs @@ -159,7 +159,8 @@ impl CodeBlock { | Opcode::GetName | Opcode::SetName | Opcode::GetPropertyByName - | Opcode::SetPropertyByName => { + | Opcode::SetPropertyByName + | Opcode::DeletePropertyByName => { let operand = self.read::(*pc); *pc += size_of::(); format!("{:04}: '{}'", operand, self.variables[operand as usize]) @@ -207,7 +208,6 @@ impl CodeBlock { | Opcode::Neg | Opcode::GetPropertyByValue | Opcode::SetPropertyByValue - | Opcode::DeletePropertyByName | Opcode::DeletePropertyByValue | Opcode::ToBoolean | Opcode::Throw