From d86b56927ea1cacb69ec300030f234e6de70ef43 Mon Sep 17 00:00:00 2001 From: David M <36610621+davimiku@users.noreply.github.com> Date: Wed, 25 Aug 2021 09:03:34 -0500 Subject: [PATCH] Implement parsing for object shorthand properties (#1324) --- .../primary/object_initializer/mod.rs | 22 +++++++ .../primary/object_initializer/tests.rs | 62 ++++++++++++++++++- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs b/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs index 9a450c8cef..c4c03b8266 100644 --- a/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs +++ b/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs @@ -9,6 +9,7 @@ #[cfg(test)] mod tests; +use crate::syntax::ast::node::Identifier; use crate::syntax::lexer::TokenKind; use crate::{ syntax::{ @@ -134,6 +135,27 @@ where return Ok(node::PropertyDefinition::SpreadObject(node)); } + // Peek for '}' or ',' to indicate shorthand property name + if let Some(next_token) = cursor.peek(1)? { + match next_token.kind() { + TokenKind::Punctuator(Punctuator::CloseBlock) + | TokenKind::Punctuator(Punctuator::Comma) => { + let token = cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?; + if let TokenKind::Identifier(ident) = token.kind() { + // ident is both the name and value in a shorthand property + let name = ident.to_string(); + let value = Identifier::from(ident.to_owned()); + cursor.next()?.expect("token vanished"); // Consume the token. + return Ok(node::PropertyDefinition::property(name, value)); + } else { + // Anything besides an identifier is a syntax error + return Err(ParseError::unexpected(token.clone(), "object literal")); + } + } + _ => {} + } + } + let prop_name = cursor.next()?.ok_or(ParseError::AbruptEnd)?.to_string(); if cursor.next_if(Punctuator::Colon)?.is_some() { let val = AssignmentExpression::new(true, self.allow_yield, self.allow_await) diff --git a/boa/src/syntax/parser/expression/primary/object_initializer/tests.rs b/boa/src/syntax/parser/expression/primary/object_initializer/tests.rs index c01c3a9653..fdb7d6f28d 100644 --- a/boa/src/syntax/parser/expression/primary/object_initializer/tests.rs +++ b/boa/src/syntax/parser/expression/primary/object_initializer/tests.rs @@ -1,8 +1,8 @@ use crate::syntax::{ ast::{ node::{ - Declaration, DeclarationList, FormalParameter, FunctionExpr, MethodDefinitionKind, - Object, PropertyDefinition, + Declaration, DeclarationList, FormalParameter, FunctionExpr, Identifier, + MethodDefinitionKind, Object, PropertyDefinition, }, Const, }, @@ -203,3 +203,61 @@ fn check_object_short_function_set() { .into()], ); } + +#[test] +fn check_object_shorthand_property_names() { + let object_properties = vec![PropertyDefinition::property("a", Identifier::from("a"))]; + + check_parser( + "const a = true; + const x = { a }; + ", + vec![ + DeclarationList::Const( + vec![Declaration::new("a", Some(Const::from(true).into()))].into(), + ) + .into(), + DeclarationList::Const( + vec![Declaration::new( + "x", + Some(Object::from(object_properties).into()), + )] + .into(), + ) + .into(), + ], + ); +} + +#[test] +fn check_object_shorthand_multiple_properties() { + let object_properties = vec![ + PropertyDefinition::property("a", Identifier::from("a")), + PropertyDefinition::property("b", Identifier::from("b")), + ]; + + check_parser( + "const a = true; + const b = false; + const x = { a, b, }; + ", + vec![ + DeclarationList::Const( + vec![Declaration::new("a", Some(Const::from(true).into()))].into(), + ) + .into(), + DeclarationList::Const( + vec![Declaration::new("b", Some(Const::from(false).into()))].into(), + ) + .into(), + DeclarationList::Const( + vec![Declaration::new( + "x", + Some(Object::from(object_properties).into()), + )] + .into(), + ) + .into(), + ], + ); +}