Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is 019 not a JavaScript syntax error? Or why is 019 > 020

If I type 019 > 020 in the JavaScript console (tested in both Chrome and Firefox), I get the answer true.

This is due to 020 being interpreted as an OctalIntegerLiteral (equals 16) whereas 019 is apparently being interpreted as DecimalLiteral (and equals 19). As 19 is greater than 16, 019 > 020 is true.

What puzzles me is why 019 is interpreted as a DecimalLiteral in first place. Which production is it? DecimalIntegerLiteral does not allow 019:

DecimalIntegerLiteral ::     0     NonZeroDigit DecimalDigits_opt 

OctalIntegerLiteral also does not allow 019 (as 9 is not an octal digit):

OctalIntegerLiteral ::     0 OctalDigit     OctalIntegerLiteral OctalDigit  OctalDigit :: one of     0 1 2 3 4 5 6 7 

So from what I see in the specification, 019 should actually be rejected, I don't see why it is interpreted as a decimal integer.

I guess there's some kind of compatibility rule in place here but I have failed to find a formal definition. Could please anyone help me with this?

(Why I need this: I'm developing a JavaScript/ECMAScript parser for Java with JavaCC and have to pay a special attention to the specification - and deviations thereof.)

like image 409
lexicore Avatar asked Jan 24 '15 15:01

lexicore


People also ask

What is syntax error in JavaScript?

The SyntaxError object represents an error when trying to interpret syntactically invalid code. It is thrown when the JavaScript engine encounters tokens or token order that does not conform to the syntax of the language when parsing code.

What is reference error and syntax error in JavaScript?

ReferenceError: Raised when an invalid reference is used. SyntaxError: Raised when a syntax error occurs while parsing JavaScript code. TypeError: Raised when the type of a variable is not as expected. strong text URIError: Raised when the encodeURI() or decodeURI() functions are used in an incorrect manner.


1 Answers

From what I could find, it seems that some implementations of JavaScript just don't follow the spec on that point.

From the MDN site:

Note that decimal literals can start with a zero (0) followed by another decimal digit, but If the next digit after the leading 0 is smaller than 8, the number gets parsed as an octal number. This won't throw in JavaScript, see bug 957513. See also the page about parseInt().

This still doesn't explain why 019 == 19, given that the next digit after the leading 0 is 1 and the whole number should therefore be parsed as octal. But the referenced bug does seem related to your case. Its description says:

The following JavaScript program should throw an error:

08 

As per the spec, DecimalIntegerLiteral can never be 0 directly followed by another decimal digit, although Chrome/Opera, PrestOpera, and Firefox do support it.

The bug is closed as WONTFIX

However, 019 would be a valid decimal literal, with value equal to 19, according to the draft of the next edition:

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-additional-syntax-numeric-literals

(I've marked the relevant rules)

The syntax and semantics of 11.8.3 is extended as follows except that  this extension is not allowed for strict mode code:  [...]  DecimalIntegerLiteral ::     0     NonZeroDigit DecimalDigits_opt     NonOctalDecimalIntegerLiteral                         // (1)  NonOctalDecimalIntegerLiteral ::     0 NonOctalDigit     LegacyOctalLikeDecimalIntegerLiteral NonOctalDigit    // (2)     NonOctalDecimalIntegerLiteral DecimalDigit  LegacyOctalLikeDecimalIntegerLiteral ::     0 OctalDigit                                          // (3)     LegacyOctalLikeDecimalIntegerLiteral OctalDigit 

So 01 is a LegacyOctalLikeDecimalIntegerLiteral (3) . Then 019 is a NonOctalDecimalIntegerLiteral (2) which in turn is a DecimalIntegerLiteral (1).

like image 164
abl Avatar answered Oct 09 '22 19:10

abl