Browse Source

Fix remaining object literal tests (#2906)

pull/2910/head
raskad 2 years ago committed by GitHub
parent
commit
484cc16bb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 39
      boa_engine/src/builtins/function/mod.rs
  2. 19
      boa_engine/src/builtins/mod.rs
  3. 8
      boa_engine/src/bytecompiler/declarations.rs
  4. 24
      boa_engine/src/bytecompiler/expression/object_literal.rs
  5. 87
      boa_engine/src/bytecompiler/mod.rs
  6. 20
      boa_engine/src/object/mod.rs
  7. 42
      boa_engine/src/vm/code_block.rs
  8. 16
      boa_engine/src/vm/flowgraph/mod.rs
  9. 6
      boa_engine/src/vm/opcode/get/generator.rs
  10. 4
      boa_engine/src/vm/opcode/mod.rs
  11. 3
      boa_parser/src/parser/expression/assignment/yield.rs
  12. 2
      boa_parser/src/parser/expression/primary/object_initializer/mod.rs

39
boa_engine/src/builtins/function/mod.rs

@ -292,17 +292,6 @@ pub struct Function {
} }
impl Function { impl Function {
/// Returns true if the function object is a constructor.
pub fn is_constructor(&self) -> bool {
match &self.kind {
FunctionKind::Native { constructor, .. } => constructor.is_some(),
FunctionKind::Generator { .. }
| FunctionKind::AsyncGenerator { .. }
| FunctionKind::Async { .. } => false,
FunctionKind::Ordinary { code, .. } => !(code.this_mode == ThisMode::Lexical),
}
}
/// Returns the codeblock of the function, or `None` if the function is a [`NativeFunction`]. /// Returns the codeblock of the function, or `None` if the function is a [`NativeFunction`].
pub fn codeblock(&self) -> Option<&CodeBlock> { pub fn codeblock(&self) -> Option<&CodeBlock> {
match &self.kind { match &self.kind {
@ -725,22 +714,9 @@ impl BuiltInFunctionObject {
let environments = context.vm.environments.pop_to_global(); let environments = context.vm.environments.pop_to_global();
let function_object = if generator { let function_object = if generator {
crate::vm::create_generator_function_object( crate::vm::create_generator_function_object(code, r#async, Some(prototype), context)
code,
r#async,
false,
Some(prototype),
context,
)
} else { } else {
crate::vm::create_function_object( crate::vm::create_function_object(code, r#async, prototype, context)
code,
r#async,
false,
Some(prototype),
false,
context,
)
}; };
context.vm.environments.extend(environments); context.vm.environments.extend(environments);
@ -761,7 +737,6 @@ impl BuiltInFunctionObject {
let function_object = crate::vm::create_generator_function_object( let function_object = crate::vm::create_generator_function_object(
code, code,
r#async, r#async,
false,
Some(prototype), Some(prototype),
context, context,
); );
@ -777,14 +752,8 @@ impl BuiltInFunctionObject {
); );
let environments = context.vm.environments.pop_to_global(); let environments = context.vm.environments.pop_to_global();
let function_object = crate::vm::create_function_object( let function_object =
code, crate::vm::create_function_object(code, r#async, prototype, context);
r#async,
false,
Some(prototype),
false,
context,
);
context.vm.environments.extend(environments); context.vm.environments.extend(environments);
Ok(function_object) Ok(function_object)

19
boa_engine/src/builtins/mod.rs

@ -538,13 +538,16 @@ impl ApplyToObject for OrdinaryFunction {
impl<S: ApplyToObject + IsConstructor> ApplyToObject for Callable<S> { impl<S: ApplyToObject + IsConstructor> ApplyToObject for Callable<S> {
fn apply_to(self, object: &mut BuiltInObjectInitializer) { fn apply_to(self, object: &mut BuiltInObjectInitializer) {
let function = ObjectData::function(function::Function::new( let function = ObjectData::function(
function::FunctionKind::Native { function::Function::new(
function: NativeFunction::from_fn_ptr(self.function), function::FunctionKind::Native {
constructor: S::IS_CONSTRUCTOR.then_some(function::ConstructorKind::Base), function: NativeFunction::from_fn_ptr(self.function),
}, constructor: S::IS_CONSTRUCTOR.then_some(function::ConstructorKind::Base),
self.realm, },
)); self.realm,
),
S::IS_CONSTRUCTOR,
);
object.set_data(function); object.set_data(function);
object.insert( object.insert(
utf16!("length"), utf16!("length"),
@ -922,7 +925,7 @@ impl BuiltInCallable<'_> {
let function = function::Function::new(function, self.realm.clone()); let function = function::Function::new(function, self.realm.clone());
let object = self.realm.intrinsics().templates().function().create( let object = self.realm.intrinsics().templates().function().create(
ObjectData::function(function), ObjectData::function(function, false),
vec![JsValue::new(self.length), JsValue::new(self.name)], vec![JsValue::new(self.length), JsValue::new(self.name)],
); );

8
boa_engine/src/bytecompiler/declarations.rs

@ -195,7 +195,7 @@ impl ByteCompiler<'_, '_> {
// b. Let fo be InstantiateFunctionObject of f with arguments env and privateEnv. // b. Let fo be InstantiateFunctionObject of f with arguments env and privateEnv.
let function = if generator { let function = if generator {
create_generator_function_object(code, r#async, false, None, self.context) create_generator_function_object(code, r#async, None, self.context)
} else { } else {
create_function_object_fast(code, r#async, false, false, self.context) create_function_object_fast(code, r#async, false, false, self.context)
}; };
@ -502,7 +502,7 @@ impl ByteCompiler<'_, '_> {
if var_environment_is_global { if var_environment_is_global {
// b. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv. // b. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
let function = if generator { let function = if generator {
create_generator_function_object(code, r#async, false, None, self.context) create_generator_function_object(code, r#async, None, self.context)
} else { } else {
create_function_object_fast(code, r#async, false, false, self.context) create_function_object_fast(code, r#async, false, false, self.context)
}; };
@ -525,7 +525,9 @@ impl ByteCompiler<'_, '_> {
} else { } else {
self.emit(Opcode::GetFunction, &[index]); self.emit(Opcode::GetFunction, &[index]);
} }
self.emit_u8(0); if !generator {
self.emit_u8(0);
}
// i. Let bindingExists be ! varEnv.HasBinding(fn). // i. Let bindingExists be ! varEnv.HasBinding(fn).
let binding_exists = self.has_binding_eval(name, strict); let binding_exists = self.has_binding_eval(name, strict);

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

@ -46,7 +46,7 @@ impl ByteCompiler<'_, '_> {
PropertyDefinition::MethodDefinition(name, kind) => match kind { PropertyDefinition::MethodDefinition(name, kind) => match kind {
MethodDefinition::Get(expr) => match name { MethodDefinition::Get(expr) => match name {
PropertyName::Literal(name) => { PropertyName::Literal(name) => {
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
let index = self.get_or_insert_name((*name).into()); let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::SetPropertyGetterByName, &[index]); self.emit(Opcode::SetPropertyGetterByName, &[index]);
} }
@ -54,7 +54,7 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(name_node, true); self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey); self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup); self.emit_opcode(Opcode::Dup);
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
self.emit_opcode(Opcode::SetFunctionName); self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(1); self.emit_u8(1);
self.emit_opcode(Opcode::SetPropertyGetterByValue); self.emit_opcode(Opcode::SetPropertyGetterByValue);
@ -62,7 +62,7 @@ impl ByteCompiler<'_, '_> {
}, },
MethodDefinition::Set(expr) => match name { MethodDefinition::Set(expr) => match name {
PropertyName::Literal(name) => { PropertyName::Literal(name) => {
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
let index = self.get_or_insert_name((*name).into()); let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::SetPropertySetterByName, &[index]); self.emit(Opcode::SetPropertySetterByName, &[index]);
} }
@ -70,7 +70,7 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(name_node, true); self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey); self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup); self.emit_opcode(Opcode::Dup);
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
self.emit_opcode(Opcode::SetFunctionName); self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(2); self.emit_u8(2);
self.emit_opcode(Opcode::SetPropertySetterByValue); self.emit_opcode(Opcode::SetPropertySetterByValue);
@ -78,7 +78,7 @@ impl ByteCompiler<'_, '_> {
}, },
MethodDefinition::Ordinary(expr) => match name { MethodDefinition::Ordinary(expr) => match name {
PropertyName::Literal(name) => { PropertyName::Literal(name) => {
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
let index = self.get_or_insert_name((*name).into()); let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]); self.emit(Opcode::DefineOwnPropertyByName, &[index]);
} }
@ -86,7 +86,7 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(name_node, true); self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey); self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup); self.emit_opcode(Opcode::Dup);
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
self.emit_opcode(Opcode::SetFunctionName); self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(0); self.emit_u8(0);
self.emit_opcode(Opcode::DefineOwnPropertyByValue); self.emit_opcode(Opcode::DefineOwnPropertyByValue);
@ -94,7 +94,7 @@ impl ByteCompiler<'_, '_> {
}, },
MethodDefinition::Async(expr) => match name { MethodDefinition::Async(expr) => match name {
PropertyName::Literal(name) => { PropertyName::Literal(name) => {
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
let index = self.get_or_insert_name((*name).into()); let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]); self.emit(Opcode::DefineOwnPropertyByName, &[index]);
} }
@ -102,7 +102,7 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(name_node, true); self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey); self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup); self.emit_opcode(Opcode::Dup);
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
self.emit_opcode(Opcode::SetFunctionName); self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(0); self.emit_u8(0);
self.emit_opcode(Opcode::DefineOwnPropertyByValue); self.emit_opcode(Opcode::DefineOwnPropertyByValue);
@ -110,7 +110,7 @@ impl ByteCompiler<'_, '_> {
}, },
MethodDefinition::Generator(expr) => match name { MethodDefinition::Generator(expr) => match name {
PropertyName::Literal(name) => { PropertyName::Literal(name) => {
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
let index = self.get_or_insert_name((*name).into()); let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]); self.emit(Opcode::DefineOwnPropertyByName, &[index]);
} }
@ -118,7 +118,7 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(name_node, true); self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey); self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup); self.emit_opcode(Opcode::Dup);
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
self.emit_opcode(Opcode::SetFunctionName); self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(0); self.emit_u8(0);
self.emit_opcode(Opcode::DefineOwnPropertyByValue); self.emit_opcode(Opcode::DefineOwnPropertyByValue);
@ -126,7 +126,7 @@ impl ByteCompiler<'_, '_> {
}, },
MethodDefinition::AsyncGenerator(expr) => match name { MethodDefinition::AsyncGenerator(expr) => match name {
PropertyName::Literal(name) => { PropertyName::Literal(name) => {
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
let index = self.get_or_insert_name((*name).into()); let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]); self.emit(Opcode::DefineOwnPropertyByName, &[index]);
} }
@ -134,7 +134,7 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(name_node, true); self.compile_expr(name_node, true);
self.emit_opcode(Opcode::ToPropertyKey); self.emit_opcode(Opcode::ToPropertyKey);
self.emit_opcode(Opcode::Dup); self.emit_opcode(Opcode::Dup);
self.function(expr.into(), NodeKind::Expression, true); self.object_method(expr.into(), NodeKind::Expression, true);
self.emit_opcode(Opcode::SetFunctionName); self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(0); self.emit_u8(0);
self.emit_opcode(Opcode::DefineOwnPropertyByValue); self.emit_opcode(Opcode::DefineOwnPropertyByValue);

87
boa_engine/src/bytecompiler/mod.rs

@ -1100,7 +1100,88 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
} else { } else {
self.emit(Opcode::GetFunction, &[index]); self.emit(Opcode::GetFunction, &[index]);
} }
self.emit_u8(0); if !generator {
self.emit_u8(0);
}
match node_kind {
NodeKind::Declaration => {
self.emit_binding(
BindingOpcode::InitVar,
name.expect("function declaration must have a name"),
);
}
NodeKind::Expression => {
if !use_expr {
self.emit(Opcode::Pop, &[]);
}
}
}
}
/// Compile an object method AST Node into bytecode.
pub(crate) fn object_method(
&mut self,
function: FunctionSpec<'_>,
node_kind: NodeKind,
use_expr: bool,
) {
let (generator, r#async, arrow) = (
function.is_generator(),
function.is_async(),
function.is_arrow(),
);
let FunctionSpec {
name,
parameters,
body,
has_binding_identifier,
..
} = function;
let binding_identifier = if has_binding_identifier {
if let Some(name) = name {
Some(name.sym())
} else {
Some(Sym::EMPTY_STRING)
}
} else {
None
};
let code = FunctionCompiler::new()
.name(name.map(Identifier::sym))
.generator(generator)
.r#async(r#async)
.strict(self.strict)
.arrow(arrow)
.binding_identifier(binding_identifier)
.compile(
parameters,
body,
self.current_environment.clone(),
self.context,
);
let index = self.functions.len() as u32;
self.functions.push(code);
if r#async && generator {
self.emit(Opcode::GetGeneratorAsync, &[index]);
} else if generator {
self.emit(Opcode::GetGenerator, &[index]);
} else if r#async && arrow {
self.emit(Opcode::GetAsyncArrowFunction, &[index]);
} else if r#async {
self.emit(Opcode::GetFunctionAsync, &[index]);
} else if arrow {
self.emit(Opcode::GetArrowFunction, &[index]);
} else {
self.emit(Opcode::GetFunction, &[index]);
}
if !generator {
self.emit_u8(1);
}
match node_kind { match node_kind {
NodeKind::Declaration => { NodeKind::Declaration => {
@ -1179,7 +1260,9 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
} else { } else {
self.emit(Opcode::GetFunction, &[index]); self.emit(Opcode::GetFunction, &[index]);
} }
self.emit_u8(1); if !generator {
self.emit_u8(1);
}
match node_kind { match node_kind {
NodeKind::Declaration => { NodeKind::Declaration => {

20
boa_engine/src/object/mod.rs

@ -407,11 +407,7 @@ impl ObjectData {
/// Create the `AsyncGeneratorFunction` object data /// Create the `AsyncGeneratorFunction` object data
pub fn async_generator_function(function: Function) -> Self { pub fn async_generator_function(function: Function) -> Self {
Self { Self {
internal_methods: if function.is_constructor() { internal_methods: &FUNCTION_INTERNAL_METHODS,
&CONSTRUCTOR_INTERNAL_METHODS
} else {
&FUNCTION_INTERNAL_METHODS
},
kind: ObjectKind::GeneratorFunction(function), kind: ObjectKind::GeneratorFunction(function),
} }
} }
@ -518,9 +514,9 @@ impl ObjectData {
} }
/// Create the `Function` object data /// Create the `Function` object data
pub fn function(function: Function) -> Self { pub fn function(function: Function, constructor: bool) -> Self {
Self { Self {
internal_methods: if function.is_constructor() { internal_methods: if constructor {
&CONSTRUCTOR_INTERNAL_METHODS &CONSTRUCTOR_INTERNAL_METHODS
} else { } else {
&FUNCTION_INTERNAL_METHODS &FUNCTION_INTERNAL_METHODS
@ -552,11 +548,7 @@ impl ObjectData {
/// Create the `GeneratorFunction` object data /// Create the `GeneratorFunction` object data
pub fn generator_function(function: Function) -> Self { pub fn generator_function(function: Function) -> Self {
Self { Self {
internal_methods: if function.is_constructor() { internal_methods: &FUNCTION_INTERNAL_METHODS,
&CONSTRUCTOR_INTERNAL_METHODS
} else {
&FUNCTION_INTERNAL_METHODS
},
kind: ObjectKind::GeneratorFunction(function), kind: ObjectKind::GeneratorFunction(function),
} }
} }
@ -1868,7 +1860,7 @@ impl<'ctx, 'host> FunctionObjectBuilder<'ctx, 'host> {
self.context.realm().clone(), self.context.realm().clone(),
); );
let object = self.context.intrinsics().templates().function().create( let object = self.context.intrinsics().templates().function().create(
ObjectData::function(function), ObjectData::function(function, self.constructor.is_some()),
vec![self.length.into(), self.name.into()], vec![self.length.into(), self.name.into()],
); );
@ -2303,7 +2295,7 @@ impl<'ctx, 'host> ConstructorBuilder<'ctx, 'host> {
let mut constructor = self.constructor_object; let mut constructor = self.constructor_object;
constructor.insert(utf16!("length"), length); constructor.insert(utf16!("length"), length);
constructor.insert(utf16!("name"), name); constructor.insert(utf16!("name"), name);
let data = ObjectData::function(function); let data = ObjectData::function(function, self.kind.is_some());
constructor.kind = data.kind; constructor.kind = data.kind;

42
boa_engine/src/vm/code_block.rs

@ -313,9 +313,7 @@ impl CodeBlock {
Opcode::GetArrowFunction Opcode::GetArrowFunction
| Opcode::GetAsyncArrowFunction | Opcode::GetAsyncArrowFunction
| Opcode::GetFunction | Opcode::GetFunction
| Opcode::GetFunctionAsync | Opcode::GetFunctionAsync => {
| Opcode::GetGenerator
| Opcode::GetGeneratorAsync => {
let operand = self.read::<u32>(*pc); let operand = self.read::<u32>(*pc);
*pc += size_of::<u32>() + size_of::<u8>(); *pc += size_of::<u32>() + size_of::<u8>();
format!( format!(
@ -324,6 +322,14 @@ impl CodeBlock {
self.functions[operand as usize].length self.functions[operand as usize].length
) )
} }
Opcode::GetGenerator | Opcode::GetGeneratorAsync => {
let operand = self.read::<u32>(*pc);
format!(
"{operand:04}: '{}' (length: {})",
interner.resolve_expect(self.functions[operand as usize].name),
self.functions[operand as usize].length
)
}
Opcode::DefInitArg Opcode::DefInitArg
| Opcode::DefVar | Opcode::DefVar
| Opcode::DefInitVar | Opcode::DefInitVar
@ -582,18 +588,11 @@ impl ToInternedString for CodeBlock {
pub(crate) fn create_function_object( pub(crate) fn create_function_object(
code: Gc<CodeBlock>, code: Gc<CodeBlock>,
r#async: bool, r#async: bool,
arrow: bool, prototype: JsObject,
prototype: Option<JsObject>,
method: bool,
context: &mut Context<'_>, context: &mut Context<'_>,
) -> JsObject { ) -> JsObject {
let _timer = Profiler::global().start_event("create_function_object", "vm"); let _timer = Profiler::global().start_event("create_function_object", "vm");
let Some(prototype) = prototype else {
// fast path
return create_function_object_fast(code, r#async, arrow, method, context);
};
let name: JsValue = context let name: JsValue = context
.interner() .interner()
.resolve_expect(code.name) .resolve_expect(code.name)
@ -627,11 +626,11 @@ pub(crate) fn create_function_object(
) )
}; };
let data = ObjectData::function(function); let data = ObjectData::function(function, !r#async);
let templates = context.intrinsics().templates(); let templates = context.intrinsics().templates();
let (mut template, storage, constructor_prototype) = if r#async || arrow || method { let (mut template, storage, constructor_prototype) = if r#async {
( (
templates.function_without_proto().clone(), templates.function_without_proto().clone(),
vec![length, name], vec![length, name],
@ -653,12 +652,12 @@ pub(crate) fn create_function_object(
template.set_prototype(prototype); template.set_prototype(prototype);
let contructor = template.create(data, storage); let constructor = template.create(data, storage);
if let Some(constructor_prototype) = &constructor_prototype { if let Some(constructor_prototype) = &constructor_prototype {
constructor_prototype.borrow_mut().properties_mut().storage[0] = contructor.clone().into(); constructor_prototype.borrow_mut().properties_mut().storage[0] = constructor.clone().into();
} }
contructor constructor
} }
/// Creates a new function object. /// Creates a new function object.
@ -704,7 +703,7 @@ pub(crate) fn create_function_object_fast(
let function = Function::new(function, context.realm().clone()); let function = Function::new(function, context.realm().clone());
let data = ObjectData::function(function); let data = ObjectData::function(function, !method && !arrow && !r#async);
if r#async { if r#async {
context context
@ -741,7 +740,6 @@ pub(crate) fn create_function_object_fast(
pub(crate) fn create_generator_function_object( pub(crate) fn create_generator_function_object(
code: Gc<CodeBlock>, code: Gc<CodeBlock>,
r#async: bool, r#async: bool,
method: bool,
prototype: Option<JsObject>, prototype: Option<JsObject>,
context: &mut Context<'_>, context: &mut Context<'_>,
) -> JsObject { ) -> JsObject {
@ -829,11 +827,9 @@ pub(crate) fn create_generator_function_object(
.configurable(false) .configurable(false)
.build(); .build();
if !method { constructor
constructor .define_property_or_throw(PROTOTYPE, prototype_property, context)
.define_property_or_throw(PROTOTYPE, prototype_property, context) .expect("failed to define the prototype property of the generator function");
.expect("failed to define the prototype property of the generator function");
}
constructor constructor
.define_property_or_throw(utf16!("name"), name_property, context) .define_property_or_throw(utf16!("name"), name_property, context)
.expect("failed to define the name property of the generator function"); .expect("failed to define the name property of the generator function");

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

@ -380,9 +380,7 @@ impl CodeBlock {
Opcode::GetArrowFunction Opcode::GetArrowFunction
| Opcode::GetAsyncArrowFunction | Opcode::GetAsyncArrowFunction
| Opcode::GetFunction | Opcode::GetFunction
| Opcode::GetFunctionAsync | Opcode::GetFunctionAsync => {
| Opcode::GetGenerator
| Opcode::GetGeneratorAsync => {
let operand = self.read::<u32>(pc); let operand = self.read::<u32>(pc);
let fn_name = interner let fn_name = interner
.resolve_expect(self.functions[operand as usize].name) .resolve_expect(self.functions[operand as usize].name)
@ -395,6 +393,18 @@ impl CodeBlock {
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None); graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line); graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
} }
Opcode::GetGenerator | Opcode::GetGeneratorAsync => {
let operand = self.read::<u32>(pc);
let fn_name = interner
.resolve_expect(self.functions[operand as usize].name)
.to_string();
let label = format!(
"{opcode_str} '{fn_name}' (length: {})",
self.functions[operand as usize].length
);
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
}
Opcode::DefInitArg Opcode::DefInitArg
| Opcode::DefVar | Opcode::DefVar
| Opcode::DefInitVar | Opcode::DefInitVar

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

@ -16,9 +16,8 @@ impl Operation for GetGenerator {
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u32>(); let index = context.vm.read::<u32>();
let method = context.vm.read::<u8>() != 0;
let code = context.vm.frame().code_block.functions[index as usize].clone(); let code = context.vm.frame().code_block.functions[index as usize].clone();
let function = create_generator_function_object(code, false, method, None, context); let function = create_generator_function_object(code, false, None, context);
context.vm.push(function); context.vm.push(function);
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
} }
@ -37,9 +36,8 @@ impl Operation for GetGeneratorAsync {
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let index = context.vm.read::<u32>(); let index = context.vm.read::<u32>();
let method = context.vm.read::<u8>() != 0;
let code = context.vm.frame().code_block.functions[index as usize].clone(); let code = context.vm.frame().code_block.functions[index as usize].clone();
let function = create_generator_function_object(code, true, method, None, context); let function = create_generator_function_object(code, true, None, context);
context.vm.push(function); context.vm.push(function);
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
} }

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

@ -1293,14 +1293,14 @@ generate_impl! {
/// Get generator function from the pre-compiled inner functions. /// Get generator function from the pre-compiled inner functions.
/// ///
/// Operands: address: `u32`, method: `u8` /// Operands: address: `u32`,
/// ///
/// Stack: **=>** func /// Stack: **=>** func
GetGenerator, GetGenerator,
/// Get async generator function from the pre-compiled inner functions. /// Get async generator function from the pre-compiled inner functions.
/// ///
/// Operands: address: `u32`, method: `u8` /// Operands: address: `u32`,
/// ///
/// Stack: **=>** func /// Stack: **=>** func
GetGeneratorAsync, GetGeneratorAsync,

3
boa_parser/src/parser/expression/assignment/yield.rs

@ -98,7 +98,8 @@ where
| Keyword::This | Keyword::This
| Keyword::Function | Keyword::Function
| Keyword::Class | Keyword::Class
| Keyword::Async, | Keyword::Async
| Keyword::Super,
_, _,
)) ))
| TokenKind::BooleanLiteral(_) | TokenKind::BooleanLiteral(_)

2
boa_parser/src/parser/expression/primary/object_initializer/mod.rs

@ -583,7 +583,7 @@ where
TokenKind::Punctuator(Punctuator::OpenBracket) => { TokenKind::Punctuator(Punctuator::OpenBracket) => {
cursor.advance(interner); cursor.advance(interner);
let node = let node =
AssignmentExpression::new(None, false, self.allow_yield, self.allow_await) AssignmentExpression::new(None, true, self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
cursor.expect(Punctuator::CloseBracket, "expected token ']'", interner)?; cursor.expect(Punctuator::CloseBracket, "expected token ']'", interner)?;
return Ok(node.into()); return Ok(node.into());

Loading…
Cancel
Save