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,
} => {
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);

52
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<Node>,
},
@ -536,7 +537,7 @@ pub enum BindingPatternTypeObject {
///
/// [spec1]: https://tc39.es/ecma262/#prod-BindingProperty
BindingPattern {
ident: Sym,
ident: PropertyName,
pattern: DeclarationPattern,
default_init: Option<Node>,
},
@ -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)));
}

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

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

@ -36,7 +36,10 @@ use self::{
try_stm::TryStatement,
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::{
ast::{
node::{
@ -48,7 +51,7 @@ use crate::syntax::{
},
Keyword, Node, Position, Punctuator,
},
lexer::{Error as LexError, InputElement, TokenKind},
lexer::{Error as LexError, InputElement, Token, TokenKind},
parser::expression::{await_expr::AwaitExpression, Initializer},
};
use boa_interner::{Interner, Sym};
@ -650,11 +653,13 @@ where
let mut rest_property_name = None;
loop {
let property_name = match cursor
.peek(0, interner)?
let next_token_is_colon = *cursor
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
== TokenKind::Punctuator(Punctuator::Colon);
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
match token.kind() {
TokenKind::Punctuator(Punctuator::CloseBlock) => {
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,
});
}
}
}
}
}

7
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,
},
],

Loading…
Cancel
Save