Browse Source

Implement delete for references (#2395)

This Pull Request implements `delete` for variable references:

```Javascript
x = 5;
console.log(x) // 5;
delete x;
console.log(x) // ReferenceError
```

It changes the following:

- Implements delete for references.
- Fixes tests related to deletions of function definitions inside `eval`.
- Implements an op to throw an error on super property deletion.

This puts us at a conformance of 97.98% for the `test/language/expressions/delete` suite. The last 2 failing tests are related to `with` statements ([11.4.1-4.a-5.js](b5d3192914/test/language/expressions/delete/11.4.1-4.a-5.js (L1)) and [11.4.1-4.a-6.js](b5d3192914/test/language/expressions/delete/11.4.1-4.a-6.js (L18))).
pull/2402/head
José Julián Espina 2 years ago
parent
commit
c72e4c20c9
  1. 12
      boa_engine/src/bytecompiler/function.rs
  2. 288
      boa_engine/src/bytecompiler/mod.rs
  3. 4
      boa_engine/src/context/mod.rs
  4. 9
      boa_engine/src/environments/compile.rs
  5. 39
      boa_engine/src/environments/runtime.rs
  6. 17
      boa_engine/src/object/internal_methods/global.rs
  7. 4
      boa_engine/src/vm/code_block.rs
  8. 2
      boa_engine/src/vm/opcode/await_stm/mod.rs
  9. 6
      boa_engine/src/vm/opcode/binary_ops/logical.rs
  10. 2
      boa_engine/src/vm/opcode/binary_ops/macro_defined.rs
  11. 10
      boa_engine/src/vm/opcode/binary_ops/mod.rs
  12. 8
      boa_engine/src/vm/opcode/call/mod.rs
  13. 2
      boa_engine/src/vm/opcode/concat/mod.rs
  14. 2
      boa_engine/src/vm/opcode/copy/mod.rs
  15. 4
      boa_engine/src/vm/opcode/define/class/getter.rs
  16. 4
      boa_engine/src/vm/opcode/define/class/method.rs
  17. 4
      boa_engine/src/vm/opcode/define/class/setter.rs
  18. 8
      boa_engine/src/vm/opcode/define/mod.rs
  19. 4
      boa_engine/src/vm/opcode/define/own_property.rs
  20. 79
      boa_engine/src/vm/opcode/delete/mod.rs
  21. 2
      boa_engine/src/vm/opcode/dup/mod.rs
  22. 10
      boa_engine/src/vm/opcode/environment/mod.rs
  23. 6
      boa_engine/src/vm/opcode/generator/mod.rs
  24. 2
      boa_engine/src/vm/opcode/generator/yield_stm.rs
  25. 6
      boa_engine/src/vm/opcode/get/function.rs
  26. 4
      boa_engine/src/vm/opcode/get/generator.rs
  27. 8
      boa_engine/src/vm/opcode/get/name.rs
  28. 2
      boa_engine/src/vm/opcode/get/private.rs
  29. 6
      boa_engine/src/vm/opcode/get/property.rs
  30. 4
      boa_engine/src/vm/opcode/iteration/for_await.rs
  31. 4
      boa_engine/src/vm/opcode/iteration/for_in.rs
  32. 4
      boa_engine/src/vm/opcode/iteration/init.rs
  33. 6
      boa_engine/src/vm/opcode/iteration/iterator.rs
  34. 6
      boa_engine/src/vm/opcode/iteration/loop_ops.rs
  35. 8
      boa_engine/src/vm/opcode/jump/mod.rs
  36. 16
      boa_engine/src/vm/opcode/mod.rs
  37. 4
      boa_engine/src/vm/opcode/new/mod.rs
  38. 2
      boa_engine/src/vm/opcode/nop/mod.rs
  39. 10
      boa_engine/src/vm/opcode/pop/mod.rs
  40. 6
      boa_engine/src/vm/opcode/promise/mod.rs
  41. 8
      boa_engine/src/vm/opcode/push/array.rs
  42. 4
      boa_engine/src/vm/opcode/push/class/field.rs
  43. 2
      boa_engine/src/vm/opcode/push/class/mod.rs
  44. 6
      boa_engine/src/vm/opcode/push/class/private.rs
  45. 4
      boa_engine/src/vm/opcode/push/environment.rs
  46. 2
      boa_engine/src/vm/opcode/push/literal.rs
  47. 2
      boa_engine/src/vm/opcode/push/mod.rs
  48. 2
      boa_engine/src/vm/opcode/push/new_target.rs
  49. 4
      boa_engine/src/vm/opcode/push/numbers.rs
  50. 2
      boa_engine/src/vm/opcode/push/object.rs
  51. 2
      boa_engine/src/vm/opcode/require/mod.rs
  52. 4
      boa_engine/src/vm/opcode/rest_parameter/mod.rs
  53. 2
      boa_engine/src/vm/opcode/return_stm/mod.rs
  54. 2
      boa_engine/src/vm/opcode/set/class_prototype.rs
  55. 2
      boa_engine/src/vm/opcode/set/home_object.rs
  56. 4
      boa_engine/src/vm/opcode/set/name.rs
  57. 10
      boa_engine/src/vm/opcode/set/private.rs
  58. 12
      boa_engine/src/vm/opcode/set/property.rs
  59. 6
      boa_engine/src/vm/opcode/swap/mod.rs
  60. 4
      boa_engine/src/vm/opcode/switch/mod.rs
  61. 2
      boa_engine/src/vm/opcode/throw/mod.rs
  62. 4
      boa_engine/src/vm/opcode/to/mod.rs
  63. 10
      boa_engine/src/vm/opcode/try_catch/mod.rs
  64. 4
      boa_engine/src/vm/opcode/unary_ops/decrement.rs
  65. 4
      boa_engine/src/vm/opcode/unary_ops/increment.rs
  66. 2
      boa_engine/src/vm/opcode/unary_ops/logical.rs
  67. 8
      boa_engine/src/vm/opcode/unary_ops/mod.rs
  68. 2
      boa_engine/src/vm/opcode/unary_ops/void.rs
  69. 2
      boa_engine/src/vm/opcode/value/mod.rs

12
boa_engine/src/bytecompiler/function.rs

@ -109,7 +109,7 @@ impl FunctionCompiler {
if !(self.arrow) && !parameters.has_arguments() {
compiler
.context
.create_mutable_binding(Sym::ARGUMENTS.into(), false);
.create_mutable_binding(Sym::ARGUMENTS.into(), false, false);
compiler.code_block.arguments_binding = Some(
compiler
.context
@ -124,7 +124,9 @@ impl FunctionCompiler {
match parameter.variable().binding() {
Binding::Identifier(ident) => {
compiler.context.create_mutable_binding(*ident, false);
compiler
.context
.create_mutable_binding(*ident, false, false);
// TODO: throw custom error if ident is in init
if let Some(init) = parameter.variable().init() {
let skip = compiler.emit_opcode_with_operand(Opcode::JumpIfNotUndefined);
@ -135,7 +137,7 @@ impl FunctionCompiler {
}
Binding::Pattern(pattern) => {
for ident in pattern.idents() {
compiler.context.create_mutable_binding(ident, false);
compiler.context.create_mutable_binding(ident, false, false);
}
// TODO: throw custom error if ident is in init
if let Some(init) = parameter.variable().init() {
@ -168,8 +170,8 @@ impl FunctionCompiler {
compiler.emit_opcode(Opcode::Yield);
}
compiler.create_decls(body);
compiler.compile_statement_list(body, false)?;
compiler.create_decls(body, false);
compiler.compile_statement_list(body, false, false)?;
if let Some(env_label) = env_label {
let (num_bindings, compile_environment) =

288
boa_engine/src/bytecompiler/mod.rs

@ -816,33 +816,39 @@ impl<'b> ByteCompiler<'b> {
PropertyAccessField::Expr(expr) => {
self.compile_expr(access.target(), true)?;
self.compile_expr(expr, true)?;
self.emit(Opcode::DeletePropertyByValue, &[]);
self.emit_opcode(Opcode::DeletePropertyByValue);
}
},
// TODO: throw ReferenceError on super deletion.
PropertyAccess::Super(_) => self.emit(Opcode::PushFalse, &[]),
PropertyAccess::Super(_) => self.emit_opcode(Opcode::DeleteSuperThrow),
PropertyAccess::Private(_) => {
unreachable!("deleting private properties should always throw early errors.")
}
},
// TODO: implement delete on references.
Access::Variable { .. } => {
self.emit(Opcode::PushFalse, &[]);
Access::Variable { name } => {
let binding = self.context.get_binding_value(name);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::DeleteName, &[index]);
}
Access::This => {
self.emit(Opcode::PushTrue, &[]);
self.emit_opcode(Opcode::PushTrue);
}
}
Ok(())
}
#[inline]
pub fn compile_statement_list(&mut self, list: &StatementList, use_expr: bool) -> JsResult<()> {
pub fn compile_statement_list(
&mut self,
list: &StatementList,
use_expr: bool,
configurable_globals: bool,
) -> JsResult<()> {
if let Some((last, items)) = list.statements().split_last() {
for node in items {
self.compile_stmt_list_item(node, false)?;
self.compile_stmt_list_item(node, false, configurable_globals)?;
}
self.compile_stmt_list_item(last, use_expr)?;
self.compile_stmt_list_item(last, use_expr, configurable_globals)?;
}
Ok(())
}
@ -858,13 +864,13 @@ impl<'b> ByteCompiler<'b> {
self.context.push_compile_time_environment(strict);
let push_env = self.emit_opcode_with_two_operands(Opcode::PushDeclarativeEnvironment);
self.create_decls(list);
self.create_decls(list, true);
if let Some((last, items)) = list.statements().split_last() {
for node in items {
self.compile_stmt_list_item(node, false)?;
self.compile_stmt_list_item(node, false, true)?;
}
self.compile_stmt_list_item(last, use_expr)?;
self.compile_stmt_list_item(last, use_expr, true)?;
}
let (num_bindings, compile_environment) = self.context.pop_compile_time_environment();
@ -964,6 +970,7 @@ impl<'b> ByteCompiler<'b> {
if let Some(access) = Access::from_expression(unary.target()) {
self.access_delete(access)?;
} else {
self.compile_expr(unary.target(), false)?;
self.emit(Opcode::PushTrue, &[]);
}
None
@ -1788,9 +1795,12 @@ impl<'b> ByteCompiler<'b> {
&mut self,
item: &StatementListItem,
use_expr: bool,
configurable_globals: bool,
) -> JsResult<()> {
match item {
StatementListItem::Statement(stmt) => self.compile_stmt(stmt, use_expr),
StatementListItem::Statement(stmt) => {
self.compile_stmt(stmt, use_expr, configurable_globals)
}
StatementListItem::Declaration(decl) => self.compile_decl(decl),
}
}
@ -1816,7 +1826,12 @@ impl<'b> ByteCompiler<'b> {
}
#[inline]
pub fn compile_for_loop(&mut self, for_loop: &ForLoop, label: Option<Sym>) -> JsResult<()> {
pub fn compile_for_loop(
&mut self,
for_loop: &ForLoop,
label: Option<Sym>,
configurable_globals: bool,
) -> JsResult<()> {
self.context.push_compile_time_environment(false);
let push_env = self.emit_opcode_with_two_operands(Opcode::PushDeclarativeEnvironment);
@ -1824,7 +1839,7 @@ impl<'b> ByteCompiler<'b> {
match init {
ForLoopInitializer::Expression(expr) => self.compile_expr(expr, false)?,
ForLoopInitializer::Var(decl) => {
self.create_decls_from_var_decl(decl);
self.create_decls_from_var_decl(decl, configurable_globals);
self.compile_var_decl(decl)?;
}
ForLoopInitializer::Lexical(decl) => {
@ -1854,7 +1869,7 @@ impl<'b> ByteCompiler<'b> {
}
let exit = self.jump_if_false();
self.compile_stmt(for_loop.body(), false)?;
self.compile_stmt(for_loop.body(), false, configurable_globals)?;
self.emit(Opcode::Jump, &[start_address]);
@ -1875,6 +1890,7 @@ impl<'b> ByteCompiler<'b> {
&mut self,
for_in_loop: &ForInLoop,
label: Option<Sym>,
configurable_globals: bool,
) -> JsResult<()> {
let init_bound_names = for_in_loop.initializer().bound_names();
if init_bound_names.is_empty() {
@ -1884,7 +1900,7 @@ impl<'b> ByteCompiler<'b> {
let push_env = self.emit_opcode_with_two_operands(Opcode::PushDeclarativeEnvironment);
for name in init_bound_names {
self.context.create_mutable_binding(name, false);
self.context.create_mutable_binding(name, false, false);
}
self.compile_expr(for_in_loop.target(), true)?;
@ -1908,7 +1924,7 @@ impl<'b> ByteCompiler<'b> {
match for_in_loop.initializer() {
IterableLoopInitializer::Identifier(ident) => {
self.context.create_mutable_binding(*ident, true);
self.context.create_mutable_binding(*ident, true, true);
let binding = self.context.set_mutable_binding(*ident);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::DefInitVar, &[index]);
@ -1922,24 +1938,25 @@ impl<'b> ByteCompiler<'b> {
}
IterableLoopInitializer::Var(declaration) => match declaration {
Binding::Identifier(ident) => {
self.context.create_mutable_binding(*ident, true);
self.context
.create_mutable_binding(*ident, true, configurable_globals);
self.emit_binding(BindingOpcode::InitVar, *ident);
}
Binding::Pattern(pattern) => {
for ident in pattern.idents() {
self.context.create_mutable_binding(ident, true);
self.context.create_mutable_binding(ident, true, false);
}
self.compile_declaration_pattern(pattern, BindingOpcode::InitVar)?;
}
},
IterableLoopInitializer::Let(declaration) => match declaration {
Binding::Identifier(ident) => {
self.context.create_mutable_binding(*ident, false);
self.context.create_mutable_binding(*ident, false, false);
self.emit_binding(BindingOpcode::InitLet, *ident);
}
Binding::Pattern(pattern) => {
for ident in pattern.idents() {
self.context.create_mutable_binding(ident, false);
self.context.create_mutable_binding(ident, false, false);
}
self.compile_declaration_pattern(pattern, BindingOpcode::InitLet)?;
}
@ -1958,13 +1975,13 @@ impl<'b> ByteCompiler<'b> {
},
IterableLoopInitializer::Pattern(pattern) => {
for ident in pattern.idents() {
self.context.create_mutable_binding(ident, true);
self.context.create_mutable_binding(ident, true, true);
}
self.compile_declaration_pattern(pattern, BindingOpcode::InitVar)?;
}
}
self.compile_stmt(for_in_loop.body(), false)?;
self.compile_stmt(for_in_loop.body(), false, configurable_globals)?;
let (num_bindings, compile_environment) = self.context.pop_compile_time_environment();
let index_compile_environment = self.push_compile_environment(compile_environment);
@ -1988,6 +2005,7 @@ impl<'b> ByteCompiler<'b> {
&mut self,
for_of_loop: &ForOfLoop,
label: Option<Sym>,
configurable_globals: bool,
) -> JsResult<()> {
let init_bound_names = for_of_loop.init().bound_names();
if init_bound_names.is_empty() {
@ -1997,7 +2015,7 @@ impl<'b> ByteCompiler<'b> {
let push_env = self.emit_opcode_with_two_operands(Opcode::PushDeclarativeEnvironment);
for name in init_bound_names {
self.context.create_mutable_binding(name, false);
self.context.create_mutable_binding(name, false, false);
}
self.compile_expr(for_of_loop.iterable(), true)?;
@ -2033,7 +2051,7 @@ impl<'b> ByteCompiler<'b> {
match for_of_loop.init() {
IterableLoopInitializer::Identifier(ref ident) => {
self.context.create_mutable_binding(*ident, true);
self.context.create_mutable_binding(*ident, true, true);
let binding = self.context.set_mutable_binding(*ident);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::DefInitVar, &[index]);
@ -2047,24 +2065,24 @@ impl<'b> ByteCompiler<'b> {
}
IterableLoopInitializer::Var(declaration) => match declaration {
Binding::Identifier(ident) => {
self.context.create_mutable_binding(*ident, true);
self.context.create_mutable_binding(*ident, true, false);
self.emit_binding(BindingOpcode::InitVar, *ident);
}
Binding::Pattern(pattern) => {
for ident in pattern.idents() {
self.context.create_mutable_binding(ident, true);
self.context.create_mutable_binding(ident, true, false);
}
self.compile_declaration_pattern(pattern, BindingOpcode::InitVar)?;
}
},
IterableLoopInitializer::Let(declaration) => match declaration {
Binding::Identifier(ident) => {
self.context.create_mutable_binding(*ident, false);
self.context.create_mutable_binding(*ident, false, false);
self.emit_binding(BindingOpcode::InitLet, *ident);
}
Binding::Pattern(pattern) => {
for ident in pattern.idents() {
self.context.create_mutable_binding(ident, false);
self.context.create_mutable_binding(ident, false, false);
}
self.compile_declaration_pattern(pattern, BindingOpcode::InitLet)?;
}
@ -2083,13 +2101,13 @@ impl<'b> ByteCompiler<'b> {
},
IterableLoopInitializer::Pattern(pattern) => {
for ident in pattern.idents() {
self.context.create_mutable_binding(ident, true);
self.context.create_mutable_binding(ident, true, true);
}
self.compile_declaration_pattern(pattern, BindingOpcode::InitVar)?;
}
}
self.compile_stmt(for_of_loop.body(), false)?;
self.compile_stmt(for_of_loop.body(), false, configurable_globals)?;
let (num_bindings, compile_environment) = self.context.pop_compile_time_environment();
let index_compile_environment = self.push_compile_environment(compile_environment);
@ -2111,6 +2129,7 @@ impl<'b> ByteCompiler<'b> {
&mut self,
while_loop: &WhileLoop,
label: Option<Sym>,
configurable_globals: bool,
) -> JsResult<()> {
self.emit_opcode(Opcode::LoopStart);
let start_address = self.next_opcode_location();
@ -2119,7 +2138,7 @@ impl<'b> ByteCompiler<'b> {
self.compile_expr(while_loop.condition(), true)?;
let exit = self.jump_if_false();
self.compile_stmt(while_loop.body(), false)?;
self.compile_stmt(while_loop.body(), false, configurable_globals)?;
self.emit(Opcode::Jump, &[start_address]);
self.patch_jump(exit);
@ -2133,6 +2152,7 @@ impl<'b> ByteCompiler<'b> {
&mut self,
do_while_loop: &DoWhileLoop,
label: Option<Sym>,
configurable_globals: bool,
) -> JsResult<()> {
self.emit_opcode(Opcode::LoopStart);
let initial_label = self.jump();
@ -2147,7 +2167,7 @@ impl<'b> ByteCompiler<'b> {
self.patch_jump(initial_label);
self.compile_stmt(do_while_loop.body(), false)?;
self.compile_stmt(do_while_loop.body(), false, configurable_globals)?;
self.emit(Opcode::Jump, &[condition_label_address]);
self.patch_jump(exit);
@ -2162,6 +2182,7 @@ impl<'b> ByteCompiler<'b> {
block: &Block,
label: Option<Sym>,
use_expr: bool,
configurable_globals: bool,
) -> JsResult<()> {
if let Some(label) = label {
let next = self.next_opcode_location();
@ -2170,8 +2191,8 @@ impl<'b> ByteCompiler<'b> {
self.context.push_compile_time_environment(false);
let push_env = self.emit_opcode_with_two_operands(Opcode::PushDeclarativeEnvironment);
self.create_decls(block.statement_list());
self.compile_statement_list(block.statement_list(), use_expr)?;
self.create_decls(block.statement_list(), configurable_globals);
self.compile_statement_list(block.statement_list(), use_expr, configurable_globals)?;
let (num_bindings, compile_environment) = self.context.pop_compile_time_environment();
let index_compile_environment = self.push_compile_environment(compile_environment);
self.patch_jump_with_target(push_env.0, num_bindings as u32);
@ -2186,14 +2207,19 @@ impl<'b> ByteCompiler<'b> {
}
#[inline]
pub fn compile_stmt(&mut self, node: &Statement, use_expr: bool) -> JsResult<()> {
pub fn compile_stmt(
&mut self,
node: &Statement,
use_expr: bool,
configurable_globals: bool,
) -> JsResult<()> {
match node {
Statement::Var(var) => self.compile_var_decl(var)?,
Statement::If(node) => {
self.compile_expr(node.cond(), true)?;
let jelse = self.jump_if_false();
self.compile_stmt(node.body(), false)?;
self.compile_stmt(node.body(), false, configurable_globals)?;
match node.else_node() {
None => {
@ -2202,40 +2228,75 @@ impl<'b> ByteCompiler<'b> {
Some(else_body) => {
let exit = self.jump();
self.patch_jump(jelse);
self.compile_stmt(else_body, false)?;
self.compile_stmt(else_body, false, configurable_globals)?;
self.patch_jump(exit);
}
}
}
Statement::ForLoop(for_loop) => self.compile_for_loop(for_loop, None)?,
Statement::ForInLoop(for_in_loop) => self.compile_for_in_loop(for_in_loop, None)?,
Statement::ForOfLoop(for_of_loop) => self.compile_for_of_loop(for_of_loop, None)?,
Statement::WhileLoop(while_loop) => self.compile_while_loop(while_loop, None)?,
Statement::ForLoop(for_loop) => {
self.compile_for_loop(for_loop, None, configurable_globals)?;
}
Statement::ForInLoop(for_in_loop) => {
self.compile_for_in_loop(for_in_loop, None, configurable_globals)?;
}
Statement::ForOfLoop(for_of_loop) => {
self.compile_for_of_loop(for_of_loop, None, configurable_globals)?;
}
Statement::WhileLoop(while_loop) => {
self.compile_while_loop(while_loop, None, configurable_globals)?;
}
Statement::DoWhileLoop(do_while_loop) => {
self.compile_do_while_loop(do_while_loop, None)?;
self.compile_do_while_loop(do_while_loop, None, configurable_globals)?;
}
Statement::Block(block) => {
self.compile_block(block, None, use_expr, configurable_globals)?;
}
Statement::Block(block) => self.compile_block(block, None, use_expr)?,
Statement::Labelled(labelled) => match labelled.item() {
LabelledItem::Statement(stmt) => match stmt {
Statement::ForLoop(for_loop) => {
self.compile_for_loop(for_loop, Some(labelled.label()))?;
self.compile_for_loop(
for_loop,
Some(labelled.label()),
configurable_globals,
)?;
}
Statement::ForInLoop(for_in_loop) => {
self.compile_for_in_loop(for_in_loop, Some(labelled.label()))?;
self.compile_for_in_loop(
for_in_loop,
Some(labelled.label()),
configurable_globals,
)?;
}
Statement::ForOfLoop(for_of_loop) => {
self.compile_for_of_loop(for_of_loop, Some(labelled.label()))?;
self.compile_for_of_loop(
for_of_loop,
Some(labelled.label()),
configurable_globals,
)?;
}
Statement::WhileLoop(while_loop) => {
self.compile_while_loop(while_loop, Some(labelled.label()))?;
self.compile_while_loop(
while_loop,
Some(labelled.label()),
configurable_globals,
)?;
}
Statement::DoWhileLoop(do_while_loop) => {
self.compile_do_while_loop(do_while_loop, Some(labelled.label()))?;
self.compile_do_while_loop(
do_while_loop,
Some(labelled.label()),
configurable_globals,
)?;
}
Statement::Block(block) => {
self.compile_block(block, Some(labelled.label()), use_expr)?;
}
stmt => self.compile_stmt(stmt, use_expr)?,
self.compile_block(
block,
Some(labelled.label()),
use_expr,
configurable_globals,
)?;
}
stmt => self.compile_stmt(stmt, use_expr, configurable_globals)?,
},
LabelledItem::Function(f) => {
self.function(f.into(), NodeKind::Declaration, false)?;
@ -2388,7 +2449,7 @@ impl<'b> ByteCompiler<'b> {
let push_env =
self.emit_opcode_with_two_operands(Opcode::PushDeclarativeEnvironment);
for case in switch.cases() {
self.create_decls(case.body());
self.create_decls(case.body(), configurable_globals);
}
self.emit_opcode(Opcode::LoopStart);
@ -2406,13 +2467,13 @@ impl<'b> ByteCompiler<'b> {
for (label, case) in labels.into_iter().zip(switch.cases()) {
self.patch_jump(label);
self.compile_statement_list(case.body(), false)?;
self.compile_statement_list(case.body(), false, configurable_globals)?;
}
self.patch_jump(exit);
if let Some(body) = switch.default() {
self.create_decls(body);
self.compile_statement_list(body, false)?;
self.create_decls(body, configurable_globals);
self.compile_statement_list(body, false, configurable_globals)?;
}
self.pop_switch_control_info();
@ -2442,8 +2503,12 @@ impl<'b> ByteCompiler<'b> {
let push_env =
self.emit_opcode_with_two_operands(Opcode::PushDeclarativeEnvironment);
self.create_decls(t.block().statement_list());
self.compile_statement_list(t.block().statement_list(), use_expr)?;
self.create_decls(t.block().statement_list(), configurable_globals);
self.compile_statement_list(
t.block().statement_list(),
use_expr,
configurable_globals,
)?;
let (num_bindings, compile_environment) =
self.context.pop_compile_time_environment();
@ -2469,12 +2534,12 @@ impl<'b> ByteCompiler<'b> {
if let Some(binding) = catch.parameter() {
match binding {
Binding::Identifier(ident) => {
self.context.create_mutable_binding(*ident, false);
self.context.create_mutable_binding(*ident, false, false);
self.emit_binding(BindingOpcode::InitLet, *ident);
}
Binding::Pattern(pattern) => {
for ident in pattern.idents() {
self.context.create_mutable_binding(ident, false);
self.context.create_mutable_binding(ident, false, false);
}
self.compile_declaration_pattern(pattern, BindingOpcode::InitLet)?;
}
@ -2483,8 +2548,12 @@ impl<'b> ByteCompiler<'b> {
self.emit_opcode(Opcode::Pop);
}
self.create_decls(catch.block().statement_list());
self.compile_statement_list(catch.block().statement_list(), use_expr)?;
self.create_decls(catch.block().statement_list(), configurable_globals);
self.compile_statement_list(
catch.block().statement_list(),
use_expr,
configurable_globals,
)?;
let (num_bindings, compile_environment) =
self.context.pop_compile_time_environment();
@ -2520,8 +2589,12 @@ impl<'b> ByteCompiler<'b> {
let push_env =
self.emit_opcode_with_two_operands(Opcode::PushDeclarativeEnvironment);
self.create_decls(finally.statement_list());
self.compile_statement_list(finally.statement_list(), false)?;
self.create_decls(finally.statement_list(), configurable_globals);
self.compile_statement_list(
finally.statement_list(),
false,
configurable_globals,
)?;
let (num_bindings, compile_environment) =
self.context.pop_compile_time_environment();
@ -2924,13 +2997,17 @@ impl<'b> ByteCompiler<'b> {
Ok(())
}
pub(crate) fn create_decls(&mut self, stmt_list: &StatementList) {
pub(crate) fn create_decls(&mut self, stmt_list: &StatementList, configurable_globals: bool) {
for node in stmt_list.statements() {
self.create_decls_from_stmt_list_item(node);
self.create_decls_from_stmt_list_item(node, configurable_globals);
}
}
pub(crate) fn create_decls_from_var_decl(&mut self, list: &VarDeclaration) -> bool {
pub(crate) fn create_decls_from_var_decl(
&mut self,
list: &VarDeclaration,
configurable_globals: bool,
) -> bool {
let mut has_identifier_argument = false;
for decl in list.0.as_ref() {
match decl.binding() {
@ -2939,14 +3016,16 @@ impl<'b> ByteCompiler<'b> {
if *ident == Sym::ARGUMENTS {
has_identifier_argument = true;
}
self.context.create_mutable_binding(*ident, true);
self.context
.create_mutable_binding(*ident, true, configurable_globals);
}
Binding::Pattern(pattern) => {
for ident in pattern.idents() {
if ident == Sym::ARGUMENTS {
has_identifier_argument = true;
}
self.context.create_mutable_binding(ident, true);
self.context
.create_mutable_binding(ident, true, configurable_globals);
}
}
}
@ -2965,14 +3044,14 @@ impl<'b> ByteCompiler<'b> {
if *ident == Sym::ARGUMENTS {
has_identifier_argument = true;
}
self.context.create_mutable_binding(*ident, false);
self.context.create_mutable_binding(*ident, false, false);
}
Binding::Pattern(pattern) => {
for ident in pattern.idents() {
if ident == Sym::ARGUMENTS {
has_identifier_argument = true;
}
self.context.create_mutable_binding(ident, false);
self.context.create_mutable_binding(ident, false, false);
}
}
}
@ -3004,61 +3083,74 @@ impl<'b> ByteCompiler<'b> {
}
#[inline]
pub(crate) fn create_decls_from_decl(&mut self, declaration: &Declaration) -> bool {
pub(crate) fn create_decls_from_decl(
&mut self,
declaration: &Declaration,
configurable_globals: bool,
) -> bool {
match declaration {
Declaration::Lexical(decl) => self.create_decls_from_lexical_decl(decl),
Declaration::Function(decl) => {
let ident = decl.name().expect("function declaration must have a name");
self.context.create_mutable_binding(ident, true);
self.context
.create_mutable_binding(ident, true, configurable_globals);
ident == Sym::ARGUMENTS
}
Declaration::Generator(decl) => {
let ident = decl.name().expect("generator declaration must have a name");
self.context.create_mutable_binding(ident, true);
self.context
.create_mutable_binding(ident, true, configurable_globals);
ident == Sym::ARGUMENTS
}
Declaration::AsyncFunction(decl) => {
let ident = decl
.name()
.expect("async function declaration must have a name");
self.context.create_mutable_binding(ident, true);
self.context
.create_mutable_binding(ident, true, configurable_globals);
ident == Sym::ARGUMENTS
}
Declaration::AsyncGenerator(decl) => {
let ident = decl
.name()
.expect("async generator declaration must have a name");
self.context.create_mutable_binding(ident, true);
self.context
.create_mutable_binding(ident, true, configurable_globals);
ident == Sym::ARGUMENTS
}
Declaration::Class(decl) => {
let ident = decl.name().expect("class declaration must have a name");
self.context.create_mutable_binding(ident, false);
self.context
.create_mutable_binding(ident, false, configurable_globals);
false
}
}
}
#[inline]
pub(crate) fn create_decls_from_stmt(&mut self, statement: &Statement) -> bool {
pub(crate) fn create_decls_from_stmt(
&mut self,
statement: &Statement,
configurable_globals: bool,
) -> bool {
match statement {
Statement::Var(var) => self.create_decls_from_var_decl(var),
Statement::Var(var) => self.create_decls_from_var_decl(var, configurable_globals),
Statement::DoWhileLoop(do_while_loop) => {
if !matches!(do_while_loop.body(), Statement::Block(_)) {
self.create_decls_from_stmt(do_while_loop.body());
self.create_decls_from_stmt(do_while_loop.body(), configurable_globals);
}
false
}
Statement::ForInLoop(for_in_loop) => {
if !matches!(for_in_loop.body(), Statement::Block(_)) {
self.create_decls_from_stmt(for_in_loop.body());
self.create_decls_from_stmt(for_in_loop.body(), configurable_globals);
}
false
}
Statement::ForOfLoop(for_of_loop) => {
if !matches!(for_of_loop.body(), Statement::Block(_)) {
self.create_decls_from_stmt(for_of_loop.body());
self.create_decls_from_stmt(for_of_loop.body(), configurable_globals);
}
false
}
@ -3067,10 +3159,18 @@ impl<'b> ByteCompiler<'b> {
}
#[inline]
pub(crate) fn create_decls_from_stmt_list_item(&mut self, item: &StatementListItem) -> bool {
pub(crate) fn create_decls_from_stmt_list_item(
&mut self,
item: &StatementListItem,
configurable_globals: bool,
) -> bool {
match item {
StatementListItem::Declaration(decl) => self.create_decls_from_decl(decl),
StatementListItem::Statement(stmt) => self.create_decls_from_stmt(stmt),
StatementListItem::Declaration(decl) => {
self.create_decls_from_decl(decl, configurable_globals)
}
StatementListItem::Statement(stmt) => {
self.create_decls_from_stmt(stmt, configurable_globals)
}
}
}
@ -3101,7 +3201,7 @@ impl<'b> ByteCompiler<'b> {
compiler.code_block.params = expr.parameters().clone();
compiler
.context
.create_mutable_binding(Sym::ARGUMENTS.into(), false);
.create_mutable_binding(Sym::ARGUMENTS.into(), false, false);
compiler.code_block.arguments_binding = Some(
compiler
.context
@ -3114,7 +3214,9 @@ impl<'b> ByteCompiler<'b> {
match parameter.variable().binding() {
Binding::Identifier(ident) => {
compiler.context.create_mutable_binding(*ident, false);
compiler
.context
.create_mutable_binding(*ident, false, false);
if let Some(init) = parameter.variable().init() {
let skip =
compiler.emit_opcode_with_operand(Opcode::JumpIfNotUndefined);
@ -3125,7 +3227,7 @@ impl<'b> ByteCompiler<'b> {
}
Binding::Pattern(pattern) => {
for ident in pattern.idents() {
compiler.context.create_mutable_binding(ident, false);
compiler.context.create_mutable_binding(ident, false, false);
}
compiler.compile_declaration_pattern(pattern, BindingOpcode::InitArg)?;
}
@ -3143,8 +3245,8 @@ impl<'b> ByteCompiler<'b> {
} else {
None
};
compiler.create_decls(expr.body());
compiler.compile_statement_list(expr.body(), false)?;
compiler.create_decls(expr.body(), false);
compiler.compile_statement_list(expr.body(), false, false)?;
if let Some(env_label) = env_label {
let (num_bindings, compile_environment) =
compiler.context.pop_compile_time_environment();
@ -3433,8 +3535,8 @@ impl<'b> ByteCompiler<'b> {
self.emit_opcode(Opcode::Dup);
let mut compiler = ByteCompiler::new(Sym::EMPTY_STRING, true, self.context);
compiler.context.push_compile_time_environment(true);
compiler.create_decls(statement_list);
compiler.compile_statement_list(statement_list, false)?;
compiler.create_decls(statement_list, false);
compiler.compile_statement_list(statement_list, false, false)?;
let (num_bindings, compile_environment) =
compiler.context.pop_compile_time_environment();
compiler

4
boa_engine/src/context/mod.rs

@ -487,8 +487,8 @@ impl Context {
pub fn compile(&mut self, statement_list: &StatementList) -> JsResult<Gc<CodeBlock>> {
let _timer = Profiler::global().start_event("Compilation", "Main");
let mut compiler = ByteCompiler::new(Sym::MAIN, statement_list.strict(), self);
compiler.create_decls(statement_list);
compiler.compile_statement_list(statement_list, true)?;
compiler.create_decls(statement_list, false);
compiler.compile_statement_list(statement_list, true, false)?;
Ok(Gc::new(compiler.finish()))
}

9
boa_engine/src/environments/compile.rs

@ -288,7 +288,12 @@ impl Context {
///
/// Panics if the global environment is not function scoped.
#[inline]
pub(crate) fn create_mutable_binding(&mut self, name: Identifier, function_scope: bool) {
pub(crate) fn create_mutable_binding(
&mut self,
name: Identifier,
function_scope: bool,
configurable: bool,
) {
if !self
.realm
.compile_env
@ -311,7 +316,7 @@ impl Context {
.value(JsValue::Undefined)
.writable(true)
.enumerable(true)
.configurable(true)
.configurable(configurable)
.build(),
);
}

39
boa_engine/src/environments/runtime.rs

@ -556,7 +556,7 @@ impl DeclarativeEnvironmentStack {
/// This only considers function environments that are poisoned.
/// All other bindings are accessed via indices.
#[inline]
pub(crate) fn get_value_global_poisoned(&self, name: Identifier) -> Option<JsValue> {
pub(crate) fn get_value_if_global_poisoned(&self, name: Identifier) -> Option<JsValue> {
for env in self.stack.iter().rev() {
if !env.poisoned.get() {
return None;
@ -689,7 +689,11 @@ impl DeclarativeEnvironmentStack {
///
/// Panics if the environment or binding index are out of range.
#[inline]
pub(crate) fn put_value_global_poisoned(&mut self, name: Identifier, value: &JsValue) -> bool {
pub(crate) fn put_value_if_global_poisoned(
&mut self,
name: Identifier,
value: &JsValue,
) -> bool {
for env in self.stack.iter().rev() {
if !env.poisoned.get() {
return false;
@ -713,6 +717,37 @@ impl DeclarativeEnvironmentStack {
}
false
}
/// Checks if the name only exists as a global property.
///
/// A binding could be marked as `global`, and at the same time, exist in a deeper environment
/// context; if the global context is poisoned, an `eval` call could have added a binding that is
/// not global with the same name as the global binding. This double checks that the binding name
/// is truly a global property.
///
/// # Panics
///
/// Panics if the environment or binding index are out of range.
#[inline]
pub(crate) fn is_only_global_property(&mut self, name: Identifier) -> bool {
for env in self
.stack
.split_first()
.expect("global environment must exist")
.1
.iter()
.rev()
{
if !env.poisoned.get() {
return true;
}
let compile = env.compile.borrow();
if compile.is_function() && compile.get_binding(name).is_some() {
return false;
}
}
true
}
}
/// A binding locator contains all information about a binding that is needed to resolve it at runtime.

17
boa_engine/src/object/internal_methods/global.rs

@ -387,11 +387,26 @@ pub(crate) fn global_set_no_receiver(
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinarydelete
#[inline]
#[allow(clippy::unnecessary_wraps)]
#[allow(clippy::unnecessary_wraps, clippy::needless_pass_by_value)]
pub(crate) fn global_delete(
_obj: &JsObject,
key: &PropertyKey,
context: &mut Context,
) -> JsResult<bool> {
global_delete_no_receiver(key, context)
}
/// Abstract operation `OrdinaryDelete`.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-ordinarydelete
#[inline]
#[allow(clippy::unnecessary_wraps)]
pub(crate) fn global_delete_no_receiver(
key: &PropertyKey,
context: &mut Context,
) -> JsResult<bool> {
let _timer = Profiler::global().start_event("Object::global_delete", "object");
// 1. Assert: IsPropertyKey(P) is true.

4
boa_engine/src/vm/code_block.rs

@ -250,7 +250,8 @@ impl CodeBlock {
| Opcode::DefInitConst
| Opcode::GetName
| Opcode::GetNameOrUndefined
| Opcode::SetName => {
| Opcode::SetName
| Opcode::DeleteName => {
let operand = self.read::<u32>(*pc);
*pc += size_of::<u32>();
format!(
@ -344,6 +345,7 @@ impl CodeBlock {
| Opcode::SetPropertySetterByValue
| Opcode::DefineClassSetterByValue
| Opcode::DeletePropertyByValue
| Opcode::DeleteSuperThrow
| Opcode::ToPropertyKey
| Opcode::ToBoolean
| Opcode::Throw

2
boa_engine/src/vm/opcode/await_stm/mod.rs

@ -9,7 +9,7 @@ use crate::{
///
/// Operation:
/// - Stops the current Async function and schedules it to resume later.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Await;
impl Operation for Await {

6
boa_engine/src/vm/opcode/binary_ops/logical.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Binary logical `&&` operation
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct LogicalAnd;
impl Operation for LogicalAnd {
@ -29,7 +29,7 @@ impl Operation for LogicalAnd {
///
/// Operation:
/// - Binary logical `||` operation
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct LogicalOr;
impl Operation for LogicalOr {
@ -51,7 +51,7 @@ impl Operation for LogicalOr {
///
/// Operation:
/// - Binary logical `||` operation
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Coalesce;
impl Operation for Coalesce {

2
boa_engine/src/vm/opcode/binary_ops/macro_defined.rs

@ -9,7 +9,7 @@ macro_rules! implement_bin_ops {
#[doc= "\n"]
#[doc="Operation:\n"]
#[doc= concat!(" - ", $doc_string)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct $name;
impl Operation for $name {

10
boa_engine/src/vm/opcode/binary_ops/mod.rs

@ -14,7 +14,7 @@ pub(crate) use macro_defined::*;
///
/// Operation:
/// - Binary `!=` operation
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct NotEq;
impl Operation for NotEq {
@ -34,7 +34,7 @@ impl Operation for NotEq {
///
/// Operation:
/// - Binary `===` operation
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct StrictEq;
impl Operation for StrictEq {
@ -53,7 +53,7 @@ impl Operation for StrictEq {
///
/// Operation:
/// - Binary `!==` operation
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct StrictNotEq;
impl Operation for StrictNotEq {
@ -72,7 +72,7 @@ impl Operation for StrictNotEq {
///
/// Operation:
/// - Binary `in` operation
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct In;
impl Operation for In {
@ -102,7 +102,7 @@ impl Operation for In {
///
/// Operation:
/// - Binary `instanceof` operation
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct InstanceOf;
impl Operation for InstanceOf {

8
boa_engine/src/vm/opcode/call/mod.rs

@ -9,7 +9,7 @@ use crate::{
///
/// Operation:
/// - Call a function named "eval".
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct CallEval;
impl Operation for CallEval {
@ -65,7 +65,7 @@ impl Operation for CallEval {
///
/// Operation:
/// - Call a function named "eval" where the arguments contain spreads.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct CallEvalSpread;
impl Operation for CallEvalSpread {
@ -127,7 +127,7 @@ impl Operation for CallEvalSpread {
///
/// Operation:
/// - Call a function
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Call;
impl Operation for Call {
@ -166,7 +166,7 @@ impl Operation for Call {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct CallSpread;
impl Operation for CallSpread {

2
boa_engine/src/vm/opcode/concat/mod.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Concat multiple stack objects into a string.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct ConcatToString;
impl Operation for ConcatToString {

2
boa_engine/src/vm/opcode/copy/mod.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Copy all properties of one object to another object.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct CopyDataProperties;
impl Operation for CopyDataProperties {

4
boa_engine/src/vm/opcode/define/class/getter.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Defines a class getter by name.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DefineClassGetterByName;
impl Operation for DefineClassGetterByName {
@ -56,7 +56,7 @@ impl Operation for DefineClassGetterByName {
///
/// Operation:
/// - Defines a class getter by value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DefineClassGetterByValue;
impl Operation for DefineClassGetterByValue {

4
boa_engine/src/vm/opcode/define/class/method.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Defines a class method by name.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DefineClassMethodByName;
impl Operation for DefineClassMethodByName {
@ -51,7 +51,7 @@ impl Operation for DefineClassMethodByName {
///
/// Operation:
/// - Defines a class method by value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DefineClassMethodByValue;
impl Operation for DefineClassMethodByValue {

4
boa_engine/src/vm/opcode/define/class/setter.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Defines a class setter by name.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DefineClassSetterByName;
impl Operation for DefineClassSetterByName {
@ -56,7 +56,7 @@ impl Operation for DefineClassSetterByName {
///
/// Operation:
/// - Defines a class setter by value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DefineClassSetterByValue;
impl Operation for DefineClassSetterByValue {

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

@ -14,7 +14,7 @@ pub(crate) use own_property::*;
///
/// Operation:
/// - Declare `var` type variable.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DefVar;
impl Operation for DefVar {
@ -53,7 +53,7 @@ impl Operation for DefVar {
///
/// Operation:
/// - Declare and initialize a function argument.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DefInitVar;
impl Operation for DefInitVar {
@ -88,7 +88,7 @@ impl Operation for DefInitVar {
///
/// Operation:
/// - Declare `let` type variable.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DefLet;
impl Operation for DefLet {
@ -113,7 +113,7 @@ macro_rules! implement_declaritives {
#[doc= "\n"]
#[doc="Operation:\n"]
#[doc= concat!(" - ", $doc_string)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct $name;
impl Operation for $name {

4
boa_engine/src/vm/opcode/define/own_property.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Defines a own property of an object by name.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DefineOwnPropertyByName;
impl Operation for DefineOwnPropertyByName {
@ -47,7 +47,7 @@ impl Operation for DefineOwnPropertyByName {
///
/// Operation:
/// - Defines a own property of an object by value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DefineOwnPropertyByValue;
impl Operation for DefineOwnPropertyByValue {

79
boa_engine/src/vm/opcode/delete/mod.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Deletes a property by name of an object
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DeletePropertyByName;
impl Operation for DeletePropertyByName {
@ -39,7 +39,7 @@ impl Operation for DeletePropertyByName {
///
/// Operation:
/// - Deletes a property by value of an object
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DeletePropertyByValue;
impl Operation for DeletePropertyByValue {
@ -61,3 +61,78 @@ impl Operation for DeletePropertyByValue {
Ok(ShouldExit::False)
}
}
/// `DeleteName` implements the Opcode Operation for `Opcode::DeleteName`
///
/// Operation:
/// - Deletes a property by value of an object
#[derive(Debug, Clone, Copy)]
pub(crate) struct DeleteName;
impl Operation for DeleteName {
const NAME: &'static str = "DeleteName";
const INSTRUCTION: &'static str = "INST - DeleteName";
fn execute(context: &mut Context) -> JsResult<ShouldExit> {
let index = context.vm.read::<u32>();
let binding_locator = context.vm.frame().code.bindings[index as usize];
binding_locator.throw_mutate_immutable(context)?;
let deleted = if binding_locator.is_global()
&& context
.realm
.environments
.is_only_global_property(binding_locator.name())
{
let key: JsString = context
.interner()
.resolve_expect(binding_locator.name().sym())
.into_common(false);
let deleted = crate::object::internal_methods::global::global_delete_no_receiver(
&key.clone().into(),
context,
)?;
if !deleted && context.vm.frame().code.strict {
return Err(JsNativeError::typ()
.with_message(format!(
"property `{}` is non-configurable and cannot be deleted",
key.to_std_string_escaped()
))
.into());
}
deleted
} else {
context
.realm
.environments
.get_value_optional(
binding_locator.environment_index(),
binding_locator.binding_index(),
binding_locator.name(),
)
.is_none()
};
context.vm.push(deleted);
Ok(ShouldExit::False)
}
}
/// `DeleteSuperThrow` implements the Opcode Operation for `Opcode::DeleteSuperThrow`
///
/// Operation:
/// - Throws an error when trying to delete a property of `super`.
#[derive(Debug, Clone, Copy)]
pub(crate) struct DeleteSuperThrow;
impl Operation for DeleteSuperThrow {
const NAME: &'static str = "DeleteSuperThrow";
const INSTRUCTION: &'static str = "INST - DeleteSuperThrow";
fn execute(_: &mut Context) -> JsResult<ShouldExit> {
Err(JsNativeError::reference()
.with_message("cannot delete a property of `super`")
.into())
}
}

2
boa_engine/src/vm/opcode/dup/mod.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Push a copy of the top value on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Dup;
impl Operation for Dup {

10
boa_engine/src/vm/opcode/environment/mod.rs

@ -9,7 +9,7 @@ use crate::{
///
/// Operation:
/// - Pushes `this` value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct This;
impl Operation for This {
@ -33,7 +33,7 @@ impl Operation for This {
///
/// Operation:
/// - Pushes the current `super` value to the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Super;
impl Operation for Super {
@ -75,7 +75,7 @@ impl Operation for Super {
///
/// Operation:
/// - Execute the `super()` method.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SuperCall;
impl Operation for SuperCall {
@ -141,7 +141,7 @@ impl Operation for SuperCall {
///
/// Operation:
/// - Execute the `super()` method where the arguments contain spreads.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SuperCallSpread;
impl Operation for SuperCallSpread {
@ -212,7 +212,7 @@ impl Operation for SuperCallSpread {
///
/// Operation:
/// - Execute the `super()` method when no constructor of the class is defined.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SuperCallDerived;
impl Operation for SuperCallDerived {

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

@ -20,7 +20,7 @@ pub(crate) use yield_stm::*;
///
/// Operation:
/// - Resumes the current generator function.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GeneratorNext;
impl Operation for GeneratorNext {
@ -62,7 +62,7 @@ impl Operation for GeneratorNext {
///
/// Operation:
/// - Resumes the current generator function.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct AsyncGeneratorNext;
impl Operation for AsyncGeneratorNext {
@ -126,7 +126,7 @@ impl Operation for AsyncGeneratorNext {
///
/// Operation:
/// - Delegates the current generator function another generator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GeneratorNextDelegate;
impl Operation for GeneratorNextDelegate {

2
boa_engine/src/vm/opcode/generator/yield_stm.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Yield from the current execution.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Yield;
impl Operation for Yield {

6
boa_engine/src/vm/opcode/get/function.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Get arrow function from the pre-compiled inner functions.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetArrowFunction;
impl Operation for GetArrowFunction {
@ -27,7 +27,7 @@ impl Operation for GetArrowFunction {
///
/// Operation:
/// - Get function from the pre-compiled inner functions.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetFunction;
impl Operation for GetFunction {
@ -47,7 +47,7 @@ impl Operation for GetFunction {
///
/// Operation:
/// - Get async function from the pre-compiled inner functions.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetFunctionAsync;
impl Operation for GetFunctionAsync {

4
boa_engine/src/vm/opcode/get/generator.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Get generator function from the pre-compiled inner functions.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetGenerator;
impl Operation for GetGenerator {
@ -27,7 +27,7 @@ impl Operation for GetGenerator {
///
/// Operation:
/// - Get async generator function from the pre-compiled inner functions.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetGeneratorAsync;
impl Operation for GetGeneratorAsync {

8
boa_engine/src/vm/opcode/get/name.rs

@ -9,7 +9,7 @@ use crate::{
///
/// Operation:
/// - Find a binding on the environment chain and push its value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetName;
impl Operation for GetName {
@ -25,7 +25,7 @@ impl Operation for GetName {
if let Some(value) = context
.realm
.environments
.get_value_global_poisoned(binding_locator.name())
.get_value_if_global_poisoned(binding_locator.name())
{
value
} else {
@ -83,7 +83,7 @@ impl Operation for GetName {
///
/// Operation:
/// - Find a binding on the environment chain and push its value. If the binding does not exist push undefined.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetNameOrUndefined;
impl Operation for GetNameOrUndefined {
@ -98,7 +98,7 @@ impl Operation for GetNameOrUndefined {
if let Some(value) = context
.realm
.environments
.get_value_global_poisoned(binding_locator.name())
.get_value_if_global_poisoned(binding_locator.name())
{
value
} else {

2
boa_engine/src/vm/opcode/get/private.rs

@ -9,7 +9,7 @@ use crate::{
///
/// Operation:
/// - Get a private property by name from an object an push it on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetPrivateField;
impl Operation for GetPrivateField {

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

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Get a property by name from an object an push it on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetPropertyByName;
impl Operation for GetPropertyByName {
@ -42,7 +42,7 @@ impl Operation for GetPropertyByName {
///
/// Operation:
/// - Get a property by value from an object an push it on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetPropertyByValue;
impl Operation for GetPropertyByValue {
@ -70,7 +70,7 @@ impl Operation for GetPropertyByValue {
///
/// Operation:
/// - Get a property by value from an object an push the key and value on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct GetPropertyByValuePush;
impl Operation for GetPropertyByValuePush {

4
boa_engine/src/vm/opcode/iteration/for_await.rs

@ -9,7 +9,7 @@ use crate::{
///
/// Operation:
/// - Move to the next value in a for await..of loop.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct ForAwaitOfLoopIterate;
impl Operation for ForAwaitOfLoopIterate {
@ -43,7 +43,7 @@ impl Operation for ForAwaitOfLoopIterate {
///
/// Operation:
/// - Get the value from a for await..of loop next result.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct ForAwaitOfLoopNext;
impl Operation for ForAwaitOfLoopNext {

4
boa_engine/src/vm/opcode/iteration/for_in.rs

@ -10,7 +10,7 @@ use crate::{
///
/// Operation:
/// - Initialize the iterator for a for..in loop or jump to after the loop if object is null or undefined.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct ForInLoopInitIterator;
impl Operation for ForInLoopInitIterator {
@ -46,7 +46,7 @@ impl Operation for ForInLoopInitIterator {
///
/// Operation:
/// - Move to the next value in a for..in loop or jump to exit of the loop if done.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct ForInLoopNext;
impl Operation for ForInLoopNext {

4
boa_engine/src/vm/opcode/iteration/init.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Initialize an iterator
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct InitIterator;
impl Operation for InitIterator {
@ -29,7 +29,7 @@ impl Operation for InitIterator {
///
/// Operation:
/// - Initialize an async iterator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct InitIteratorAsync;
impl Operation for InitIteratorAsync {

6
boa_engine/src/vm/opcode/iteration/iterator.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Advance the iterator by one and put the value on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct IteratorNext;
impl Operation for IteratorNext {
@ -46,7 +46,7 @@ impl Operation for IteratorNext {
///
/// Operation:
/// - Close an iterator
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct IteratorClose;
impl Operation for IteratorClose {
@ -74,7 +74,7 @@ impl Operation for IteratorClose {
///
/// Operation:
/// - Consume the iterator and construct and array with all the values.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct IteratorToArray;
impl Operation for IteratorToArray {

6
boa_engine/src/vm/opcode/iteration/loop_ops.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Push loop start marker.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct LoopStart;
impl Operation for LoopStart {
@ -25,7 +25,7 @@ impl Operation for LoopStart {
///
/// Operation:
/// - Clean up environments when a loop continues.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct LoopContinue;
impl Operation for LoopContinue {
@ -52,7 +52,7 @@ impl Operation for LoopContinue {
///
/// Operation:
/// - Clean up enviroments at the end of a lopp.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct LoopEnd;
impl Operation for LoopEnd {

8
boa_engine/src/vm/opcode/jump/mod.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Unconditional jump to address.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Jump;
impl Operation for Jump {
@ -25,7 +25,7 @@ impl Operation for Jump {
///
/// Operation:
/// - Conditional jump to address.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct JumpIfFalse;
impl Operation for JumpIfFalse {
@ -45,7 +45,7 @@ impl Operation for JumpIfFalse {
///
/// Operation:
/// - Conditional jump to address.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct JumpIfNotUndefined;
impl Operation for JumpIfNotUndefined {
@ -67,7 +67,7 @@ impl Operation for JumpIfNotUndefined {
///
/// Operation:
/// - Conditional jump to address.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct JumpIfNullOrUndefined;
impl Operation for JumpIfNullOrUndefined {

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

@ -164,7 +164,7 @@ pub(crate) trait Operation {
}
generate_impl! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum Opcode {
/// Pop the top value from the stack.
@ -687,6 +687,13 @@ generate_impl! {
/// Stack: value **=>**
SetName,
/// Deletes a property of the global object.
///
/// Operands: name_index: `u32`
///
/// Stack: **=>** deleted
DeleteName,
/// Get a property by name from an object an push it on the stack.
///
/// Like `object.name`
@ -939,6 +946,13 @@ generate_impl! {
/// Stack: object, key **=>**
DeletePropertyByValue,
/// Throws an error when trying to delete a property of `super`
///
/// Operands:
///
/// Stack: **=>**
DeleteSuperThrow,
/// Copy all properties of one object to another object.
///
/// Operands: excluded_key_count: `u32`, excluded_key_count_computed: `u32`

4
boa_engine/src/vm/opcode/new/mod.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Call construct on a function.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct New;
impl Operation for New {
@ -47,7 +47,7 @@ impl Operation for New {
///
/// Operation:
/// - Call construct on a function where the arguments contain spreads.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct NewSpread;
impl Operation for NewSpread {

2
boa_engine/src/vm/opcode/nop/mod.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - No-operation instruction, does nothing
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Nop;
impl Operation for Nop {

10
boa_engine/src/vm/opcode/pop/mod.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Pop the top value from the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Pop;
impl Operation for Pop {
@ -24,7 +24,7 @@ impl Operation for Pop {
///
/// Operation:
/// - Pop the top value from the stack if the last try block has thrown a value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PopIfThrown;
impl Operation for PopIfThrown {
@ -45,7 +45,7 @@ impl Operation for PopIfThrown {
///
/// Operation:
/// - Pop the current environment.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PopEnvironment;
impl Operation for PopEnvironment {
@ -64,7 +64,7 @@ impl Operation for PopEnvironment {
///
/// Operation:
/// - Add one to the pop on return count.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PopOnReturnAdd;
impl Operation for PopOnReturnAdd {
@ -81,7 +81,7 @@ impl Operation for PopOnReturnAdd {
///
/// Operation:
/// - Subtract one from the pop on return count.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PopOnReturnSub;
impl Operation for PopOnReturnSub {

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

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Start of a finally block.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct FinallyStart;
impl Operation for FinallyStart {
@ -29,7 +29,7 @@ impl Operation for FinallyStart {
///
/// Operation:
/// - End of a finally block.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct FinallyEnd;
impl Operation for FinallyEnd {
@ -60,7 +60,7 @@ impl Operation for FinallyEnd {
///
/// Operation:
/// - Set the address for a finally jump.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct FinallySetJump;
impl Operation for FinallySetJump {

8
boa_engine/src/vm/opcode/push/array.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Push an empty array value on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushNewArray;
impl Operation for PushNewArray {
@ -27,7 +27,7 @@ impl Operation for PushNewArray {
///
/// Operation:
/// - Push a value to an array.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushValueToArray;
impl Operation for PushValueToArray {
@ -52,7 +52,7 @@ impl Operation for PushValueToArray {
///
/// Operation:
/// - Push an empty element/hole to an array.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushElisionToArray;
impl Operation for PushElisionToArray {
@ -77,7 +77,7 @@ impl Operation for PushElisionToArray {
///
/// Operation:
/// - Push all iterator values to an array.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushIteratorToArray;
impl Operation for PushIteratorToArray {

4
boa_engine/src/vm/opcode/push/class/field.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Push a field to a class.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushClassField;
impl Operation for PushClassField {
@ -48,7 +48,7 @@ impl Operation for PushClassField {
///
/// Operation:
/// - Push a private field to the class.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushClassFieldPrivate;
impl Operation for PushClassFieldPrivate {

2
boa_engine/src/vm/opcode/push/class/mod.rs

@ -15,7 +15,7 @@ pub(crate) use private::*;
///
/// Operation:
/// - Get the prototype of a superclass and push it on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushClassPrototype;
impl Operation for PushClassPrototype {

6
boa_engine/src/vm/opcode/push/class/private.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Push a private method to the class.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushClassPrivateMethod;
impl Operation for PushClassPrivateMethod {
@ -36,7 +36,7 @@ impl Operation for PushClassPrivateMethod {
///
/// Operation:
/// - Push a private getter to the class.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushClassPrivateGetter;
impl Operation for PushClassPrivateGetter {
@ -70,7 +70,7 @@ impl Operation for PushClassPrivateGetter {
///
/// Operation:
/// - Push a private setter to the class.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushClassPrivateSetter;
impl Operation for PushClassPrivateSetter {

4
boa_engine/src/vm/opcode/push/environment.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Push a declarative environment
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushDeclarativeEnvironment;
impl Operation for PushDeclarativeEnvironment {
@ -34,7 +34,7 @@ impl Operation for PushDeclarativeEnvironment {
///
/// Operation:
/// - Push a function environment.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushFunctionEnvironment;
impl Operation for PushFunctionEnvironment {

2
boa_engine/src/vm/opcode/push/literal.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Push literal value on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushLiteral;
impl Operation for PushLiteral {

2
boa_engine/src/vm/opcode/push/mod.rs

@ -25,7 +25,7 @@ macro_rules! implement_push_generics {
#[doc= "\n"]
#[doc="Operation:\n"]
#[doc= concat!(" - ", $doc_string)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct $name;
impl Operation for $name {

2
boa_engine/src/vm/opcode/push/new_target.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Push the current new target to the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushNewTarget;
impl Operation for PushNewTarget {

4
boa_engine/src/vm/opcode/push/numbers.rs

@ -9,7 +9,7 @@ macro_rules! implement_push_numbers_with_conversion {
#[doc= "\n"]
#[doc="Operation:\n"]
#[doc= concat!(" - ", $doc_string)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct $name;
impl Operation for $name {
@ -31,7 +31,7 @@ macro_rules! implement_push_numbers_no_conversion {
#[doc= "\n"]
#[doc="Operation:\n"]
#[doc= concat!(" - ", $doc_string)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct $name;
impl Operation for $name {

2
boa_engine/src/vm/opcode/push/object.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Push empty object `{}` value on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct PushEmptyObject;
impl Operation for PushEmptyObject {

2
boa_engine/src/vm/opcode/require/mod.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Call `RequireObjectCoercible` on the stack value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct RequireObjectCoercible;
impl Operation for RequireObjectCoercible {

4
boa_engine/src/vm/opcode/rest_parameter/mod.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Initialize the rest parameter value of a function from the remaining arguments.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct RestParameterInit;
impl Operation for RestParameterInit {
@ -42,7 +42,7 @@ impl Operation for RestParameterInit {
///
/// Operation:
/// - Pop the remaining arguments of a function.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct RestParameterPop;
impl Operation for RestParameterPop {

2
boa_engine/src/vm/opcode/return_stm/mod.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Return from a function.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Return;
impl Operation for Return {

2
boa_engine/src/vm/opcode/set/class_prototype.rs

@ -9,7 +9,7 @@ use crate::{
///
/// Operation:
/// - Set the prototype of a class object.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetClassPrototype;
impl Operation for SetClassPrototype {

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

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Set home object internal slot of a function object.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetHomeObject;
impl Operation for SetHomeObject {

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

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Find a binding on the environment chain and assign its value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetName;
impl Operation for SetName {
@ -25,7 +25,7 @@ impl Operation for SetName {
if !context
.realm
.environments
.put_value_global_poisoned(binding_locator.name(), &value)
.put_value_if_global_poisoned(binding_locator.name(), &value)
{
let key: JsString = context
.interner()

10
boa_engine/src/vm/opcode/set/private.rs

@ -9,7 +9,7 @@ use crate::{
///
/// Operation:
/// - Assign the value of a private property of an object by it's name.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct AssignPrivateField;
impl Operation for AssignPrivateField {
@ -66,7 +66,7 @@ impl Operation for AssignPrivateField {
///
/// Operation:
/// - Set a private property of a class constructor by it's name.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetPrivateField;
impl Operation for SetPrivateField {
@ -104,7 +104,7 @@ impl Operation for SetPrivateField {
///
/// Operation:
/// - Set a private method of a class constructor by it's name.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetPrivateMethod;
impl Operation for SetPrivateMethod {
@ -134,7 +134,7 @@ impl Operation for SetPrivateMethod {
///
/// Operation:
/// - Set a private setter property of a class constructor by it's name.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetPrivateSetter;
impl Operation for SetPrivateSetter {
@ -163,7 +163,7 @@ impl Operation for SetPrivateSetter {
///
/// Operation:
/// - Set a private getter property of a class constructor by it's name.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetPrivateGetter;
impl Operation for SetPrivateGetter {

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

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Sets a property by name of an object.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetPropertyByName;
impl Operation for SetPropertyByName {
@ -43,7 +43,7 @@ impl Operation for SetPropertyByName {
///
/// Operation:
/// - Sets a property by value of an object.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetPropertyByValue;
impl Operation for SetPropertyByValue {
@ -71,7 +71,7 @@ impl Operation for SetPropertyByValue {
///
/// Operation:
/// - Sets a getter property by name of an object.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetPropertyGetterByName;
impl Operation for SetPropertyGetterByName {
@ -112,7 +112,7 @@ impl Operation for SetPropertyGetterByName {
///
/// Operation:
/// - Sets a getter property by value of an object.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetPropertyGetterByValue;
impl Operation for SetPropertyGetterByValue {
@ -148,7 +148,7 @@ impl Operation for SetPropertyGetterByValue {
///
/// Operation:
/// - Sets a setter property by name of an object.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetPropertySetterByName;
impl Operation for SetPropertySetterByName {
@ -189,7 +189,7 @@ impl Operation for SetPropertySetterByName {
///
/// Operation:
/// - Sets a setter property by value of an object.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct SetPropertySetterByValue;
impl Operation for SetPropertySetterByValue {

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

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Swap the top two values on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Swap;
impl Operation for Swap {
@ -28,7 +28,7 @@ impl Operation for Swap {
///
/// Operation:
/// - Rotates the n top values to the left.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct RotateLeft;
impl Operation for RotateLeft {
@ -47,7 +47,7 @@ impl Operation for RotateLeft {
///
/// Operation:
/// - Rotates the n top values to the right.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct RotateRight;
impl Operation for RotateRight {

4
boa_engine/src/vm/opcode/switch/mod.rs

@ -8,7 +8,7 @@ use crate::{
/// Operation:
/// - Pop the two values of the stack, strict equal compares the two values,
/// if true jumps to address, otherwise push the second pop'ed value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Case;
impl Operation for Case {
@ -33,7 +33,7 @@ impl Operation for Case {
///
/// Operation:
/// - Pops the top of stack and jump to address.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Default;
impl Operation for Default {

2
boa_engine/src/vm/opcode/throw/mod.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Throw exception.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Throw;
impl Operation for Throw {

4
boa_engine/src/vm/opcode/to/mod.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Pops value converts it to boolean and pushes it back.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct ToBoolean;
impl Operation for ToBoolean {
@ -25,7 +25,7 @@ impl Operation for ToBoolean {
///
/// Operation:
/// - Call `ToPropertyKey` on the value on the stack.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct ToPropertyKey;
impl Operation for ToPropertyKey {

10
boa_engine/src/vm/opcode/try_catch/mod.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Start of a try block.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct TryStart;
impl Operation for TryStart {
@ -37,7 +37,7 @@ impl Operation for TryStart {
///
/// Operation:
/// - End of a try block
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct TryEnd;
impl Operation for TryEnd {
@ -79,7 +79,7 @@ impl Operation for TryEnd {
///
/// Operation:
/// - Start of a catch block.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct CatchStart;
impl Operation for CatchStart {
@ -105,7 +105,7 @@ impl Operation for CatchStart {
///
/// Operation:
/// - End of a catch block.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct CatchEnd;
impl Operation for CatchEnd {
@ -147,7 +147,7 @@ impl Operation for CatchEnd {
///
/// Operation:
/// - End of a catch block
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct CatchEnd2;
impl Operation for CatchEnd2 {

4
boa_engine/src/vm/opcode/unary_ops/decrement.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Unary `--` operator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Dec;
impl Operation for Dec {
@ -31,7 +31,7 @@ impl Operation for Dec {
///
/// Operation:
/// - Unary postfix `--` operator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct DecPost;
impl Operation for DecPost {

4
boa_engine/src/vm/opcode/unary_ops/increment.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Unary `++` operator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Inc;
impl Operation for Inc {
@ -31,7 +31,7 @@ impl Operation for Inc {
///
/// Operation:
/// - Unary postfix `++` operator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct IncPost;
impl Operation for IncPost {

2
boa_engine/src/vm/opcode/unary_ops/logical.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Unary logical `!` operator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct LogicalNot;
impl Operation for LogicalNot {

8
boa_engine/src/vm/opcode/unary_ops/mod.rs

@ -20,7 +20,7 @@ pub(crate) use void::*;
///
/// Operation:
/// - Unary `typeof` operator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct TypeOf;
impl Operation for TypeOf {
@ -38,7 +38,7 @@ impl Operation for TypeOf {
///
/// Operation:
/// - Unary `+` operator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Pos;
impl Operation for Pos {
@ -57,7 +57,7 @@ impl Operation for Pos {
///
/// Operation:
/// - Unary `-` operator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Neg;
impl Operation for Neg {
@ -78,7 +78,7 @@ impl Operation for Neg {
///
/// Operation:
/// - Unary bitwise `~` operator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct BitNot;
impl Operation for BitNot {

2
boa_engine/src/vm/opcode/unary_ops/void.rs

@ -7,7 +7,7 @@ use crate::{
///
/// Operation:
/// - Unary `void` operator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct Void;
impl Operation for Void {

2
boa_engine/src/vm/opcode/value/mod.rs

@ -8,7 +8,7 @@ use crate::{
///
/// Operation:
/// - Require the stack value to be neither null nor undefined.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy)]
pub(crate) struct ValueNotNullOrUndefined;
impl Operation for ValueNotNullOrUndefined {

Loading…
Cancel
Save