mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 03:55:24 +00:00
LibJS: Allow reserved words as keys in object expressions.
This commit is contained in:
parent
0345fdcb77
commit
bf5b251684
Notes:
sideshowbarker
2024-07-19 07:29:33 +09:00
Author: https://github.com/sunverwerth Commit: https://github.com/SerenityOS/serenity/commit/bf5b2516841 Pull-request: https://github.com/SerenityOS/serenity/pull/1849 Issue: https://github.com/SerenityOS/serenity/issues/1768
5 changed files with 61 additions and 3 deletions
|
@ -437,8 +437,8 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
|||
|
||||
while (!done() && !match(TokenType::CurlyClose)) {
|
||||
FlyString property_name;
|
||||
if (match(TokenType::Identifier)) {
|
||||
property_name = consume(TokenType::Identifier).value();
|
||||
if (match_identifier_name()) {
|
||||
property_name = consume().value();
|
||||
} else if (match(TokenType::StringLiteral)) {
|
||||
property_name = consume(TokenType::StringLiteral).string_value();
|
||||
} else if (match(TokenType::NumericLiteral)) {
|
||||
|
@ -582,7 +582,9 @@ NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expre
|
|||
return create_ast_node<AssignmentExpression>(AssignmentOp::Assignment, move(lhs), parse_expression(min_precedence, associativity));
|
||||
case TokenType::Period:
|
||||
consume();
|
||||
return create_ast_node<MemberExpression>(move(lhs), parse_expression(min_precedence, associativity));
|
||||
if (!match_identifier_name())
|
||||
expected("IdentifierName");
|
||||
return create_ast_node<MemberExpression>(move(lhs), create_ast_node<Identifier>(consume().value()));
|
||||
case TokenType::BracketOpen: {
|
||||
consume(TokenType::BracketOpen);
|
||||
auto expression = create_ast_node<MemberExpression>(move(lhs), parse_expression(0), true);
|
||||
|
@ -1072,6 +1074,11 @@ bool Parser::match_statement() const
|
|||
|| type == TokenType::Var;
|
||||
}
|
||||
|
||||
bool Parser::match_identifier_name() const
|
||||
{
|
||||
return m_parser_state.m_current_token.is_identifier_name();
|
||||
}
|
||||
|
||||
bool Parser::done() const
|
||||
{
|
||||
return match(TokenType::Eof);
|
||||
|
|
|
@ -84,6 +84,7 @@ private:
|
|||
bool match_secondary_expression() const;
|
||||
bool match_statement() const;
|
||||
bool match_variable_declaration() const;
|
||||
bool match_identifier_name() const;
|
||||
bool match(TokenType type) const;
|
||||
bool done() const;
|
||||
void expected(const char* what);
|
||||
|
|
|
@ -23,6 +23,14 @@ try {
|
|||
// Note : this test doesn't pass yet due to floating-point literals being coerced to i32 on access
|
||||
// assert(math[3.14] === "pi");
|
||||
|
||||
// This is also allowed! Watch out for syntax errors.
|
||||
var o2 = { return: 1, yield: 1, for: 1, catch: 1, break: 1 };
|
||||
assert(o2.return === 1);
|
||||
assert(o2.yield === 1);
|
||||
assert(o2.for === 1);
|
||||
assert(o2.catch === 1);
|
||||
assert(o2.break === 1);
|
||||
|
||||
console.log("PASS");
|
||||
} catch (e) {
|
||||
console.log("FAIL: " + e);
|
||||
|
|
|
@ -129,4 +129,44 @@ bool Token::bool_value() const
|
|||
return m_value == "true";
|
||||
}
|
||||
|
||||
bool Token::is_identifier_name() const
|
||||
{
|
||||
// IdentifierNames are Identifiers + ReservedWords
|
||||
// The standard defines this reversed: Identifiers are IdentifierNames except reserved words
|
||||
// https://www.ecma-international.org/ecma-262/5.1/#sec-7.6
|
||||
return m_type == TokenType::Identifier
|
||||
|| m_type == TokenType::Await
|
||||
|| m_type == TokenType::BoolLiteral
|
||||
|| m_type == TokenType::Break
|
||||
|| m_type == TokenType::Case
|
||||
|| m_type == TokenType::Catch
|
||||
|| m_type == TokenType::Class
|
||||
|| m_type == TokenType::Const
|
||||
|| m_type == TokenType::Continue
|
||||
|| m_type == TokenType::Default
|
||||
|| m_type == TokenType::Delete
|
||||
|| m_type == TokenType::Do
|
||||
|| m_type == TokenType::Else
|
||||
|| m_type == TokenType::Finally
|
||||
|| m_type == TokenType::For
|
||||
|| m_type == TokenType::Function
|
||||
|| m_type == TokenType::If
|
||||
|| m_type == TokenType::In
|
||||
|| m_type == TokenType::Instanceof
|
||||
|| m_type == TokenType::Interface
|
||||
|| m_type == TokenType::Let
|
||||
|| m_type == TokenType::New
|
||||
|| m_type == TokenType::NullLiteral
|
||||
|| m_type == TokenType::Return
|
||||
|| m_type == TokenType::Switch
|
||||
|| m_type == TokenType::This
|
||||
|| m_type == TokenType::Throw
|
||||
|| m_type == TokenType::Try
|
||||
|| m_type == TokenType::Typeof
|
||||
|| m_type == TokenType::Var
|
||||
|| m_type == TokenType::Void
|
||||
|| m_type == TokenType::While
|
||||
|| m_type == TokenType::Yield;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -153,6 +153,8 @@ public:
|
|||
String string_value() const;
|
||||
bool bool_value() const;
|
||||
|
||||
bool is_identifier_name() const;
|
||||
|
||||
private:
|
||||
TokenType m_type;
|
||||
StringView m_trivia;
|
||||
|
|
Loading…
Add table
Reference in a new issue