diff --git a/boa_engine/src/bytecompiler.rs b/boa_engine/src/bytecompiler.rs index c3c5a41337e..b79ca8d0298 100644 --- a/boa_engine/src/bytecompiler.rs +++ b/boa_engine/src/bytecompiler.rs @@ -2076,8 +2076,17 @@ impl<'b> ByteCompiler<'b> { default_init, } => { self.emit_opcode(Opcode::Dup); - let index = self.get_or_insert_name(*property_name); - self.emit(Opcode::GetPropertyByName, &[index]); + match property_name { + PropertyName::Literal(name) => { + let index = self.get_or_insert_name(*name); + self.emit(Opcode::GetPropertyByName, &[index]); + } + PropertyName::Computed(node) => { + self.compile_expr(node, true)?; + self.emit_opcode(Opcode::Swap); + self.emit_opcode(Opcode::GetPropertyByValue); + } + } if let Some(init) = default_init { let skip = self.jump_with_custom_opcode(Opcode::JumpIfNotUndefined); @@ -2129,8 +2138,17 @@ impl<'b> ByteCompiler<'b> { default_init, } => { self.emit_opcode(Opcode::Dup); - let index = self.get_or_insert_name(*ident); - self.emit(Opcode::GetPropertyByName, &[index]); + match ident { + PropertyName::Literal(name) => { + let index = self.get_or_insert_name(*name); + self.emit(Opcode::GetPropertyByName, &[index]); + } + PropertyName::Computed(node) => { + self.compile_expr(node, true)?; + self.emit_opcode(Opcode::Swap); + self.emit_opcode(Opcode::GetPropertyByValue); + } + } if let Some(init) = default_init { let skip = self.jump_with_custom_opcode(Opcode::JumpIfNotUndefined); diff --git a/boa_engine/src/syntax/ast/node/declaration/mod.rs b/boa_engine/src/syntax/ast/node/declaration/mod.rs index 37c98eb03da..c668f7d00ea 100644 --- a/boa_engine/src/syntax/ast/node/declaration/mod.rs +++ b/boa_engine/src/syntax/ast/node/declaration/mod.rs @@ -2,6 +2,7 @@ use crate::syntax::ast::node::{ field::{GetConstField, GetField}, join_nodes, + object::PropertyName, statement_list::StatementList, Identifier, Node, }; @@ -497,7 +498,7 @@ pub enum BindingPatternTypeObject { /// [spec2]: https://tc39.es/ecma262/#prod-BindingProperty SingleName { ident: Sym, - property_name: Sym, + property_name: PropertyName, default_init: Option, }, @@ -536,7 +537,7 @@ pub enum BindingPatternTypeObject { /// /// [spec1]: https://tc39.es/ecma262/#prod-BindingProperty BindingPattern { - ident: Sym, + ident: PropertyName, pattern: DeclarationPattern, default_init: Option, }, @@ -551,14 +552,24 @@ impl ToInternedString for BindingPatternTypeObject { property_name, default_init, } => { - let mut buf = if ident == property_name { - format!(" {}", interner.resolve_expect(*ident)) - } else { - format!( - " {} : {}", - interner.resolve_expect(*property_name), - interner.resolve_expect(*ident) - ) + let mut buf = match property_name { + PropertyName::Literal(name) if *name == *ident => { + format!(" {}", interner.resolve_expect(*ident)) + } + PropertyName::Literal(name) => { + format!( + " {} : {}", + interner.resolve_expect(*name), + interner.resolve_expect(*ident) + ) + } + PropertyName::Computed(node) => { + format!( + " [{}] : {}", + node.to_interned_string(interner), + interner.resolve_expect(*ident) + ) + } }; if let Some(ref init) = default_init { buf.push_str(&format!(" = {}", init.to_interned_string(interner))); @@ -581,11 +592,22 @@ impl ToInternedString for BindingPatternTypeObject { pattern, default_init, } => { - let mut buf = format!( - " {} : {}", - interner.resolve_expect(*property_name), - pattern.to_interned_string(interner) - ); + let mut buf = match property_name { + PropertyName::Literal(name) => { + format!( + " {} : {}", + interner.resolve_expect(*name), + pattern.to_interned_string(interner), + ) + } + PropertyName::Computed(node) => { + format!( + " [{}] : {}", + node.to_interned_string(interner), + pattern.to_interned_string(interner), + ) + } + }; if let Some(ref init) = default_init { buf.push_str(&format!(" = {}", init.to_interned_string(interner))); } diff --git a/boa_engine/src/syntax/ast/node/operator/assign/mod.rs b/boa_engine/src/syntax/ast/node/operator/assign/mod.rs index bbe875968cc..59ca9ba33e3 100644 --- a/boa_engine/src/syntax/ast/node/operator/assign/mod.rs +++ b/boa_engine/src/syntax/ast/node/operator/assign/mod.rs @@ -149,7 +149,7 @@ pub(crate) fn object_decl_to_declaration_pattern(object: &Object) -> Option Option { cursor.expect( TokenKind::Punctuator(Punctuator::CloseBlock), @@ -680,35 +685,27 @@ where )?; break; } - _ => BindingIdentifier::new(self.allow_yield, self.allow_await) - .parse(cursor, interner)?, - }; - - property_names.push(property_name); - - if let Some(peek_token) = cursor.peek(0, interner)? { - match peek_token.kind() { - TokenKind::Punctuator(Punctuator::Assign) => { - let init = Initializer::new( - Some(property_name), - self.allow_in, - self.allow_yield, - self.allow_await, - ) - .parse(cursor, interner)?; - patterns.push(BindingPatternTypeObject::SingleName { - ident: property_name, - property_name, - default_init: Some(init), - }); - } - TokenKind::Punctuator(Punctuator::Colon) => { + _ => { + let is_property_name = match token.kind() { + TokenKind::Punctuator(Punctuator::OpenBracket) + | TokenKind::StringLiteral(_) + | TokenKind::NumericLiteral(_) => true, + TokenKind::Identifier(_) if next_token_is_colon => true, + TokenKind::Keyword(_) if next_token_is_colon => true, + _ => false, + }; + + if is_property_name { + let property_name = PropertyName::new(self.allow_yield, self.allow_await) + .parse(cursor, interner)?; + if let Some(name) = property_name.prop_name() { + property_names.push(name); + } cursor.expect( TokenKind::Punctuator(Punctuator::Colon), "object binding pattern", interner, )?; - if let Some(peek_token) = cursor.peek(0, interner)? { match peek_token.kind() { TokenKind::Punctuator(Punctuator::OpenBlock) => { @@ -842,13 +839,33 @@ where } } } - } - _ => { - patterns.push(BindingPatternTypeObject::SingleName { - ident: property_name, - property_name, - default_init: None, - }); + } else { + let name = BindingIdentifier::new(self.allow_yield, self.allow_await) + .parse(cursor, interner)?; + property_names.push(name); + match cursor.peek(0, interner)?.map(Token::kind) { + Some(TokenKind::Punctuator(Punctuator::Assign)) => { + let init = Initializer::new( + Some(name), + self.allow_in, + self.allow_yield, + self.allow_await, + ) + .parse(cursor, interner)?; + patterns.push(BindingPatternTypeObject::SingleName { + ident: name, + property_name: name.into(), + default_init: Some(init), + }); + } + _ => { + patterns.push(BindingPatternTypeObject::SingleName { + ident: name, + property_name: name.into(), + default_init: None, + }); + } + } } } } diff --git a/boa_engine/src/syntax/parser/statement/try_stm/tests.rs b/boa_engine/src/syntax/parser/statement/try_stm/tests.rs index 657bdc8fe83..002660921d3 100644 --- a/boa_engine/src/syntax/parser/statement/try_stm/tests.rs +++ b/boa_engine/src/syntax/parser/statement/try_stm/tests.rs @@ -2,6 +2,7 @@ use crate::syntax::{ ast::{ node::{ declaration::{BindingPatternTypeArray, BindingPatternTypeObject}, + object::PropertyName, Block, Catch, Declaration, DeclarationList, Finally, Try, }, Const, @@ -173,12 +174,14 @@ fn check_inline_with_binding_pattern_object() { vec![ BindingPatternTypeObject::SingleName { ident: a, - property_name: a, + property_name: PropertyName::Literal(a), default_init: None, }, BindingPatternTypeObject::SingleName { ident: interner.get_or_intern_static("c"), - property_name: interner.get_or_intern_static("b"), + property_name: PropertyName::Literal( + interner.get_or_intern_static("b"), + ), default_init: None, }, ],