Skip to content

Commit

Permalink
Implement delete operator in the vm (#1649)
Browse files Browse the repository at this point in the history
  • Loading branch information
raskad authored Oct 11, 2021
1 parent 829a26d commit b624be6
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 14 deletions.
30 changes: 26 additions & 4 deletions boa/src/bytecompiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
let index = self.get_or_insert_name(get_const_field.field());
self.compile_expr(get_const_field.obj(), true);
self.emit(Opcode::DeletePropertyByName, &[index]);
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),
Expand All @@ -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) => {
Expand Down
11 changes: 2 additions & 9 deletions boa/src/syntax/ast/node/operator/unary_op/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
})
Expand Down
4 changes: 3 additions & 1 deletion boa/src/vm/code_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ impl CodeBlock {
| Opcode::GetName
| Opcode::SetName
| Opcode::GetPropertyByName
| Opcode::SetPropertyByName => {
| Opcode::SetPropertyByName
| Opcode::DeletePropertyByName => {
let operand = self.read::<u32>(*pc);
*pc += size_of::<u32>();
format!("{:04}: '{}'", operand, self.variables[operand as usize])
Expand Down Expand Up @@ -207,6 +208,7 @@ impl CodeBlock {
| Opcode::Neg
| Opcode::GetPropertyByValue
| Opcode::SetPropertyByValue
| Opcode::DeletePropertyByValue
| Opcode::ToBoolean
| Opcode::Throw
| Opcode::This
Expand Down
15 changes: 15 additions & 0 deletions boa/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,21 @@ impl Context {
let key = key.to_property_key(self)?;
object.set(key, value, true, self)?;
}
Opcode::DeletePropertyByName => {
let index = self.vm.read::<u32>();
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();
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);
Expand Down
20 changes: 20 additions & 0 deletions boa/src/vm/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,24 @@ 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]`
///
/// Operands:
///
/// Stack: key, object **=>**
DeletePropertyByValue,

/// Unconditional jump to address.
///
/// Operands: address: `u32`
Expand Down Expand Up @@ -605,6 +623,8 @@ impl Opcode {
Opcode::GetPropertyByValue => "GetPropertyByValue",
Opcode::SetPropertyByName => "SetPropertyByName",
Opcode::SetPropertyByValue => "SetPropertyByValue",
Opcode::DeletePropertyByName => "DeletePropertyByName",
Opcode::DeletePropertyByValue => "DeletePropertyByValue",
Opcode::Jump => "Jump",
Opcode::JumpIfFalse => "JumpIfFalse",
Opcode::JumpIfTrue => "JumpIfTrue",
Expand Down

0 comments on commit b624be6

Please sign in to comment.