diff --git a/Userland/Libraries/LibJS/Parser.cpp b/Userland/Libraries/LibJS/Parser.cpp index a30d5e5cd1..a9cd247d63 100644 --- a/Userland/Libraries/LibJS/Parser.cpp +++ b/Userland/Libraries/LibJS/Parser.cpp @@ -2762,7 +2762,7 @@ RefPtr Parser::parse_binding_pattern(Parser::AllowDuplicates all name = static_ptr_cast(expression); else syntax_error("Invalid destructuring assignment target", expression_position); - } else if (match_identifier_name() || match(TokenType::StringLiteral) || match(TokenType::NumericLiteral)) { + } else if (match_identifier_name() || match(TokenType::StringLiteral) || match(TokenType::NumericLiteral) || match(TokenType::BigIntLiteral)) { if (match(TokenType::StringLiteral) || match(TokenType::NumericLiteral)) needs_alias = true; @@ -2773,6 +2773,12 @@ RefPtr Parser::parse_binding_pattern(Parser::AllowDuplicates all name = create_ast_node( { m_state.current_token.filename(), rule_start.position(), position() }, string_literal->value()); + } else if (match(TokenType::BigIntLiteral)) { + auto string_value = consume().flystring_value(); + VERIFY(string_value.ends_with("n"sv)); + name = create_ast_node( + { m_state.current_token.filename(), rule_start.position(), position() }, + FlyString(string_value.view().substring_view(0, string_value.length() - 1))); } else { name = create_ast_node( { m_state.current_token.filename(), rule_start.position(), position() }, diff --git a/Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js b/Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js index 575e658390..9d4653fa43 100644 --- a/Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js +++ b/Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js @@ -28,3 +28,26 @@ test("numeric properties", () => { "4294967296", // >= 2^32 - 1 ]); }); + +test("big int properties", () => { + const o = { + [-1n]: "foo", + 0n: "foo", + 1n: "foo", + [12345678901n]: "foo", + [4294967294n]: "foo", + [4294967295n]: "foo", + }; + // Numeric properties come first in Object.getOwnPropertyNames()'s output, + // which means we can test what each is treated as internally. + expect(Object.getOwnPropertyNames(o)).toEqual([ + // Numeric properties + "0", + "1", + "4294967294", + // Non-numeric properties + "-1", + "12345678901", // >= 2^32 - 1 + "4294967295", // >= 2^32 - 1 + ]); +}); diff --git a/Userland/Libraries/LibJS/Tests/syntax/destructuring-assignment.js b/Userland/Libraries/LibJS/Tests/syntax/destructuring-assignment.js index 9a7682ddbc..5654568a83 100644 --- a/Userland/Libraries/LibJS/Tests/syntax/destructuring-assignment.js +++ b/Userland/Libraries/LibJS/Tests/syntax/destructuring-assignment.js @@ -223,4 +223,11 @@ describe("evaluating", () => { expect(x).toBe("foo"); expect(a).toBe(o.a); }); + + test("can use big int values as number-like properties", () => { + let o = { "99999999999999999": 1 }; + let { 123n: a = "foo", 99999999999999999n: b = "bar" } = o; + expect(a).toBe("foo"); + expect(b).toBe(1); + }); });