Browse Source

Allow `PropertyName`s in `BindingProperty`in `ObjectBindingPattern` (#2022)

This Pull Request changes the following:

- Allow `PropertyName`s in `BindingProperty`in `ObjectBindingPattern`. Previously only `BindingIdentifier`s where allowed.
pull/2023/head
raskad 3 years ago
parent
commit
314e4ca656
  1. 26
      boa_engine/src/bytecompiler.rs
  2. 52
      boa_engine/src/syntax/ast/node/declaration/mod.rs
  3. 4
      boa_engine/src/syntax/ast/node/operator/assign/mod.rs
  4. 89
      boa_engine/src/syntax/parser/statement/mod.rs
  5. 7
      boa_engine/src/syntax/parser/statement/try_stm/tests.rs

26
boa_engine/src/bytecompiler.rs

@ -2076,8 +2076,17 @@ impl<'b> ByteCompiler<'b> {
default_init, default_init,
} => { } => {
self.emit_opcode(Opcode::Dup); self.emit_opcode(Opcode::Dup);
let index = self.get_or_insert_name(*property_name); match property_name {
self.emit(Opcode::GetPropertyByName, &[index]); 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 { if let Some(init) = default_init {
let skip = self.jump_with_custom_opcode(Opcode::JumpIfNotUndefined); let skip = self.jump_with_custom_opcode(Opcode::JumpIfNotUndefined);
@ -2129,8 +2138,17 @@ impl<'b> ByteCompiler<'b> {
default_init, default_init,
} => { } => {
self.emit_opcode(Opcode::Dup); self.emit_opcode(Opcode::Dup);
let index = self.get_or_insert_name(*ident); match ident {
self.emit(Opcode::GetPropertyByName, &[index]); 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 { if let Some(init) = default_init {
let skip = self.jump_with_custom_opcode(Opcode::JumpIfNotUndefined); let skip = self.jump_with_custom_opcode(Opcode::JumpIfNotUndefined);

52
boa_engine/src/syntax/ast/node/declaration/mod.rs

@ -2,6 +2,7 @@
use crate::syntax::ast::node::{ use crate::syntax::ast::node::{
field::{GetConstField, GetField}, field::{GetConstField, GetField},
join_nodes, join_nodes,
object::PropertyName,
statement_list::StatementList, statement_list::StatementList,
Identifier, Node, Identifier, Node,
}; };
@ -497,7 +498,7 @@ pub enum BindingPatternTypeObject {
/// [spec2]: https://tc39.es/ecma262/#prod-BindingProperty /// [spec2]: https://tc39.es/ecma262/#prod-BindingProperty
SingleName { SingleName {
ident: Sym, ident: Sym,
property_name: Sym, property_name: PropertyName,
default_init: Option<Node>, default_init: Option<Node>,
}, },
@ -536,7 +537,7 @@ pub enum BindingPatternTypeObject {
/// ///
/// [spec1]: https://tc39.es/ecma262/#prod-BindingProperty /// [spec1]: https://tc39.es/ecma262/#prod-BindingProperty
BindingPattern { BindingPattern {
ident: Sym, ident: PropertyName,
pattern: DeclarationPattern, pattern: DeclarationPattern,
default_init: Option<Node>, default_init: Option<Node>,
}, },
@ -551,14 +552,24 @@ impl ToInternedString for BindingPatternTypeObject {
property_name, property_name,
default_init, default_init,
} => { } => {
let mut buf = if ident == property_name { let mut buf = match property_name {
format!(" {}", interner.resolve_expect(*ident)) PropertyName::Literal(name) if *name == *ident => {
} else { format!(" {}", interner.resolve_expect(*ident))
format!( }
" {} : {}", PropertyName::Literal(name) => {
interner.resolve_expect(*property_name), format!(
interner.resolve_expect(*ident) " {} : {}",
) 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 { if let Some(ref init) = default_init {
buf.push_str(&format!(" = {}", init.to_interned_string(interner))); buf.push_str(&format!(" = {}", init.to_interned_string(interner)));
@ -581,11 +592,22 @@ impl ToInternedString for BindingPatternTypeObject {
pattern, pattern,
default_init, default_init,
} => { } => {
let mut buf = format!( let mut buf = match property_name {
" {} : {}", PropertyName::Literal(name) => {
interner.resolve_expect(*property_name), format!(
pattern.to_interned_string(interner) " {} : {}",
); 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 { if let Some(ref init) = default_init {
buf.push_str(&format!(" = {}", init.to_interned_string(interner))); buf.push_str(&format!(" = {}", init.to_interned_string(interner)));
} }

4
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<Decl
excluded_keys.push(*ident); excluded_keys.push(*ident);
bindings.push(BindingPatternTypeObject::SingleName { bindings.push(BindingPatternTypeObject::SingleName {
ident: *ident, ident: *ident,
property_name: *ident, property_name: PropertyName::Literal(*ident),
default_init: None, default_init: None,
}); });
} }
@ -158,7 +158,7 @@ pub(crate) fn object_decl_to_declaration_pattern(object: &Object) -> Option<Decl
excluded_keys.push(*name); excluded_keys.push(*name);
bindings.push(BindingPatternTypeObject::SingleName { bindings.push(BindingPatternTypeObject::SingleName {
ident: *name, ident: *name,
property_name: *name, property_name: PropertyName::Literal(*name),
default_init: None, default_init: None,
}); });
} }

89
boa_engine/src/syntax/parser/statement/mod.rs

@ -36,7 +36,10 @@ use self::{
try_stm::TryStatement, try_stm::TryStatement,
variable::VariableStatement, variable::VariableStatement,
}; };
use super::{AllowAwait, AllowIn, AllowReturn, AllowYield, Cursor, ParseError, TokenParser}; use super::{
expression::PropertyName, AllowAwait, AllowIn, AllowReturn, AllowYield, Cursor, ParseError,
TokenParser,
};
use crate::syntax::{ use crate::syntax::{
ast::{ ast::{
node::{ node::{
@ -48,7 +51,7 @@ use crate::syntax::{
}, },
Keyword, Node, Position, Punctuator, Keyword, Node, Position, Punctuator,
}, },
lexer::{Error as LexError, InputElement, TokenKind}, lexer::{Error as LexError, InputElement, Token, TokenKind},
parser::expression::{await_expr::AwaitExpression, Initializer}, parser::expression::{await_expr::AwaitExpression, Initializer},
}; };
use boa_interner::{Interner, Sym}; use boa_interner::{Interner, Sym};
@ -650,11 +653,13 @@ where
let mut rest_property_name = None; let mut rest_property_name = None;
loop { loop {
let property_name = match cursor let next_token_is_colon = *cursor
.peek(0, interner)? .peek(1, interner)?
.ok_or(ParseError::AbruptEnd)? .ok_or(ParseError::AbruptEnd)?
.kind() .kind()
{ == TokenKind::Punctuator(Punctuator::Colon);
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
match token.kind() {
TokenKind::Punctuator(Punctuator::CloseBlock) => { TokenKind::Punctuator(Punctuator::CloseBlock) => {
cursor.expect( cursor.expect(
TokenKind::Punctuator(Punctuator::CloseBlock), TokenKind::Punctuator(Punctuator::CloseBlock),
@ -680,35 +685,27 @@ where
)?; )?;
break; break;
} }
_ => BindingIdentifier::new(self.allow_yield, self.allow_await) _ => {
.parse(cursor, interner)?, let is_property_name = match token.kind() {
}; TokenKind::Punctuator(Punctuator::OpenBracket)
| TokenKind::StringLiteral(_)
property_names.push(property_name); | TokenKind::NumericLiteral(_) => true,
TokenKind::Identifier(_) if next_token_is_colon => true,
if let Some(peek_token) = cursor.peek(0, interner)? { TokenKind::Keyword(_) if next_token_is_colon => true,
match peek_token.kind() { _ => false,
TokenKind::Punctuator(Punctuator::Assign) => { };
let init = Initializer::new(
Some(property_name), if is_property_name {
self.allow_in, let property_name = PropertyName::new(self.allow_yield, self.allow_await)
self.allow_yield, .parse(cursor, interner)?;
self.allow_await, if let Some(name) = property_name.prop_name() {
) property_names.push(name);
.parse(cursor, interner)?; }
patterns.push(BindingPatternTypeObject::SingleName {
ident: property_name,
property_name,
default_init: Some(init),
});
}
TokenKind::Punctuator(Punctuator::Colon) => {
cursor.expect( cursor.expect(
TokenKind::Punctuator(Punctuator::Colon), TokenKind::Punctuator(Punctuator::Colon),
"object binding pattern", "object binding pattern",
interner, interner,
)?; )?;
if let Some(peek_token) = cursor.peek(0, interner)? { if let Some(peek_token) = cursor.peek(0, interner)? {
match peek_token.kind() { match peek_token.kind() {
TokenKind::Punctuator(Punctuator::OpenBlock) => { TokenKind::Punctuator(Punctuator::OpenBlock) => {
@ -842,13 +839,33 @@ where
} }
} }
} }
} } else {
_ => { let name = BindingIdentifier::new(self.allow_yield, self.allow_await)
patterns.push(BindingPatternTypeObject::SingleName { .parse(cursor, interner)?;
ident: property_name, property_names.push(name);
property_name, match cursor.peek(0, interner)?.map(Token::kind) {
default_init: None, 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,
});
}
}
} }
} }
} }

7
boa_engine/src/syntax/parser/statement/try_stm/tests.rs

@ -2,6 +2,7 @@ use crate::syntax::{
ast::{ ast::{
node::{ node::{
declaration::{BindingPatternTypeArray, BindingPatternTypeObject}, declaration::{BindingPatternTypeArray, BindingPatternTypeObject},
object::PropertyName,
Block, Catch, Declaration, DeclarationList, Finally, Try, Block, Catch, Declaration, DeclarationList, Finally, Try,
}, },
Const, Const,
@ -173,12 +174,14 @@ fn check_inline_with_binding_pattern_object() {
vec![ vec![
BindingPatternTypeObject::SingleName { BindingPatternTypeObject::SingleName {
ident: a, ident: a,
property_name: a, property_name: PropertyName::Literal(a),
default_init: None, default_init: None,
}, },
BindingPatternTypeObject::SingleName { BindingPatternTypeObject::SingleName {
ident: interner.get_or_intern_static("c"), 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, default_init: None,
}, },
], ],

Loading…
Cancel
Save