Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Allow PropertyNames in BindingPropertyin ObjectBindingPattern #2022

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions boa_engine/src/bytecompiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
52 changes: 37 additions & 15 deletions boa_engine/src/syntax/ast/node/declaration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use crate::syntax::ast::node::{
field::{GetConstField, GetField},
join_nodes,
object::PropertyName,
statement_list::StatementList,
Identifier, Node,
};
Expand Down Expand Up @@ -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>,
},

Expand Down Expand Up @@ -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>,
},
Expand All @@ -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)));
Expand All @@ -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)));
}
Expand Down
4 changes: 2 additions & 2 deletions boa_engine/src/syntax/ast/node/operator/assign/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
}
Expand All @@ -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,
});
}
Expand Down
89 changes: 53 additions & 36 deletions boa_engine/src/syntax/parser/statement/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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};
Expand Down Expand Up @@ -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),
Expand All @@ -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) => {
Expand Down Expand Up @@ -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,
});
}
}
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions boa_engine/src/syntax/parser/statement/try_stm/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::syntax::{
ast::{
node::{
declaration::{BindingPatternTypeArray, BindingPatternTypeObject},
object::PropertyName,
Block, Catch, Declaration, DeclarationList, Finally, Try,
},
Const,
Expand Down Expand Up @@ -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,
},
],
Expand Down