Closed Bug 1786121 Opened 4 years ago Closed 4 years ago

Incorrect object literal parsing

Categories

(DevTools :: Console, defect)

Firefox 103
defect

Tracking

(Not tracked)

RESOLVED DUPLICATE of bug 972530

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.

  1. Open Firefox Developer Tools Console (or use eval() for the examples below)
  2. Type a simple object literal, a one of: {foo: 10, bar: 11}, {"foo": 10, "bar": 11}, {"foo": 10}
  3. Observe: Uncaught SyntaxError: unexpected token: ':'
  4. 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} produces 10
  • 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) produces 10
  • ({foo: 10}["foo"]) produces 10

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

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.

Component: JavaScript Engine → Console
Product: Core → DevTools

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:

  1. eval("10 === {foo:10}.foo") produces true
  2. eval("{foo:10}.foo === 10") produces SyntaxError: expected expression, got '.'
  3. eval("-{foo:10}.foo === -10") produces true
  4. eval("null === {foo:10, bar:20}") produces false
  5. eval("{foo:10, bar:20} === null") produces SyntaxError: unexpected token: ':'

In my understanding, cases 1 & 2 should produce a symmetrical AST, as well as cases 4 & 5. What am I missing?

(closing as duplicate of Bug 972530)

Status: UNCONFIRMED → RESOLVED
Closed: 4 years ago
Resolution: --- → DUPLICATE

(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.

You need to log in before you can comment on or make changes to this bug.