Incorrect object literal parsing
Categories
(DevTools :: Console, defect)
Tracking
(Not tracked)
People
(Reporter: mail4ilia, Unassigned)
Details
I'm not an expert in JavaScript, but the following seems to me like a bug in a Firefox JavaScript parser.
- Open Firefox Developer Tools Console (or use
eval()for the examples below) - Type a simple object literal, a one of:
{foo: 10, bar: 11},{"foo": 10, "bar": 11},{"foo": 10} - Observe:
Uncaught SyntaxError: unexpected token: ':' - Repeat in Chrome and observe no error
Note that the following is parsed in Firefox without a error:
({foo: 10, bar: 11})x={foo: 10, bar: 11}
Note also that {foo: 10} is parsed by Firefox without an exception, but seems to be treated as a {} block with foo being a label for the statement 10. I'm not sure about correctness, but it is different from the Chrome parser:
- in firefox:
{foo: 10}produces10 - in firefox:
({foo: 10})produces{foo: 10}object - in chrome: both
{foo: 10}and({foo: 10})produce{foo: 10}object
Looking at ECMAScript 2022 spec, sec 15.10.2.2 Expression Rules it seems like ObjectLiteral is a kind of PrimaryExpression and should behave in the same way. However, I was not able to quickly determine whether { foo: should be parsed as a start of a block with a label (LabelledStatement) or as an object literal. However, LabelIdentifier cannot be quoted, so { "foo": is only a valid prefix for an object literal without a label ambiguity.
While we are at object literal parsing, you may also want to determine the standard-conformant parsing result for another cases and add a unit test or alike:
{foo: 10}.foo{foo: 10}["foo"]
I'm unable to test them due to the above bug, but both cases parenthesized are handled correct:
({foo: 10}.foo)produces10({foo: 10}["foo"])produces10
A related bug in Chromium's V8 for {foo: 10}.foo and {"foo": 10}.foo cases:
https://bugs.chromium.org/p/v8/issues/detail?id=13219
Comment 2•4 years ago
|
||
Firefox's parsing here is correct. Chrome's devtools have some "magic" that treats these object literals like you wrote ({foo: 10, bar: 11}) instead. You can observe the correct behavior (the syntax error) in Chrome as well when using eval("{foo: 10, bar: 11}").
{foo: 10}.foo is just wrong syntax.
Updated•4 years ago
|
Thanks for pointing out that Chrome devtools accept illegal JavaScript code. I'm refreshing my JavaScript knowledge and I was under impression that the most popular implementations became strictly standard compliant in recent years.
Is there a formal way to check JS correctness against a spec without resorting to "specification by implementation" approach?
Are you aware of any tool to get a canonical AST from a JS snippet or otherwise check & debug standard conformance?
I try the following in Firefox dev tools and the results seem to me illogical:
eval("10 === {foo:10}.foo")producestrueeval("{foo:10}.foo === 10")producesSyntaxError: expected expression, got '.'eval("-{foo:10}.foo === -10")producestrueeval("null === {foo:10, bar:20}")producesfalseeval("{foo:10, bar:20} === null")producesSyntaxError: unexpected token: ':'
In my understanding, cases 1 & 2 should produce a symmetrical AST, as well as cases 4 & 5. What am I missing?
Comment 4•4 years ago
|
||
(closing as duplicate of Bug 972530)
Comment 5•4 years ago
|
||
(In reply to Ilia K. from comment #3)
In my understanding, cases 1 & 2 should produce a symmetrical AST, as well as cases 4 & 5. What am I missing?
Case 2 is parsed like this:
{
foo: 10
}
.foo === 10
So a block containing a label "foo" with an expression-statement 10 that has no effect. Case 1 is different because there we are already in an expression context so it's parsed as an object literal.
Description
•