Early error on '0' followed by '8' or '9' in numeric literals does not seem to be web-compatible

# Boris Zbarsky (10 years ago)

When SpiderMonkey tried to implement an early error for cases like this:

alert(08)

as the current spec draft requires, we got bug reports about web sites being broken as a result. Specifically, there were two issues we discovered:

  1. Things like new Date(2013,08,12);

  2. Servers sending things like account numbers as numeric literals, complete with leading zeros [yes, I know, this is so broken, they're still doing it].

I believe we'll be backing out this change; it doesn't seen to be worth the web compat hit.

# Jason Orendorff (10 years ago)

On Mon, Aug 4, 2014 at 11:39 AM, Boris Zbarsky <bzbarsky at mit.edu> wrote:

I believe we'll be backing out this change; it doesn't seen to be worth the web compat hit.

Barring some miracle, we will be backing out the change.

bugzilla.mozilla.org/show_bug.cgi?id=1022254

# Mark S. Miller (10 years ago)

Isn't the early error required only for strict code?

# Jason Orendorff (10 years ago)

On Mon, Aug 4, 2014 at 11:43 AM, Mark S. Miller <erights at google.com> wrote:

Isn't the early error required only for strict code?

Legacy octal integer literals are banned altogether in strict code. We implement that and have had no trouble with it.

We're talking about something different here, legacy decimal integer literals starting with 0 and containing 8 or 9. As far as I know, no version of ES has ever permitted this kind of nonsense, but supporting it is apparently required for Web compatibility. (One more great reason to write all your code under "use strict".)

Boris and I would like B.1.1 to be changed to match the horrible reality.

# Rick Waldron (10 years ago)

On Mon, Aug 4, 2014 at 9:55 AM, Jason Orendorff <jason.orendorff at gmail.com> wrote:

Boris and I would like B.1.1 to be changed to match the horrible reality.

I've started the Sept meeting agenda with this item: tc39/agendas/blob/master/2014/09.md

# Allen Wirfs-Brock (10 years ago)

On Aug 4, 2014, at 9:55 AM, Jason Orendorff wrote:

Boris and I would like B.1.1 to be changed to match the horrible reality.

there is already a bug open

# Brendan Eich (10 years ago)

Jason Orendorff wrote:

We're talking about something different here, legacydecimal integer literals starting with 0 and containing 8 or 9. As far as I know, no version of ES has ever permitted this kind of nonsense, but supporting it is apparently required for Web compatibility. (One more great reason to write all your code under "use strict".)

I confess I did it because C compilers from PCC to GCC allowed it. Dunno about Java back in May '95.

# Mathias Bynens (10 years ago)

On 5 Aug 2014, at 02:41, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

there is already a bug open on this ecmascript#2792

Older bug report: ecmascript#1553

We previously discussed this up at the April TC39 meeting: rwaldron/tc39-notes/blob/master/es6/2014-04/apr-9.md#change

# Mathias Bynens (10 years ago)

Never mind – I was confused. This topic is about numeric literals rather than string literals (although the underlying issue is more or less the same). Carry on!

# Mathias Bynens (10 years ago)

On 4 Aug 2014, at 18:55, Jason Orendorff <jason.orendorff at gmail.com> wrote:

We're talking about something different here, legacy decimal integer literals starting with 0 and containing 8 or 9. As far as I know, no version of ES has ever permitted this kind of nonsense, but supporting it is apparently required for Web compatibility. (One more great reason to write all your code under "use strict".)

I don’t understand this comment. What does strict mode have to do with this? Note that 08 and 09 are not octal literals, since 8 and 9 are not OctalDigits.

In non-strict mode, people.mozilla.org/~jorendorff/es6-draft.html#sec-additional-syntax-numeric-literals applies, but even then 08 and 09 should throw (as per the current spec) for the same reason.

Strict mode doesn’t make a difference as per the current spec when parsing this program:

08

It does in Firefox/Spidermonkey, but that seems like a bug. Test this in the most recent nightly:

(function() { 'use strict'; return 08; }())

This currently throws:

SyntaxError: octal literals and octal escape sequences are deprecated

…which is a misleading message. It should instead say something like:

# Allen Wirfs-Brock (10 years ago)

On Aug 4, 2014, at 9:55 AM, Jason Orendorff wrote:

On Mon, Aug 4, 2014 at 11:43 AM, Mark S. Miller <erights at google.com> wrote:

Isn't the early error required only for strict code?

There is actually no such Early Error in the ES6 spec, right? We're talking about what the BNF allows.

Legacy octal integer literals are banned altogether in strict code. We implement that and have had no trouble with it.

We're talking about something different here, legacy decimal integer literals starting with 0 and containing 8 or 9. As far as I know, no version of ES has ever permitted this kind of nonsense, but supporting it is apparently required for Web compatibility. (One more great reason to write all your code under "use strict".)

Just to be clear, FF rejects 08 in strict mode, and you don't intend to change that. Right?

We're only talking about Annex B, non-strict. Right?

Boris and I would like B.1.1 to be changed to match the horrible reality.

It would be great is somebody wanted to proposal the actual annex B language that is need to correctly describe the web reality semantics. Otherwise, I have to prioritize this as an Annex B thing that browsers already have right, so it isn't all that important. That means it's lower priority than new ES6 features and I may or may not get around to fixing in in the ES6 spec.

Regarding, leading 0 constants in strict mode. The long term plan is to eventually make them legal decimal constants. The only reason not to do that now is because it might screw up people who are migrating non-strict web reality code containing octal constants into strict mode.

# Alex Kocharin (10 years ago)

05.08.2014, 18:20, "Allen Wirfs-Brock" <allen at wirfs-brock.com>:

Regarding, leading 0 constants in strict mode. The long term plan is to eventually make them legal decimal constants. The only reason not to do that now is because it might screw up people who are migrating non-strict web reality code containing octal constants into strict mode.

What about allowing one-digit numbers with leading zeroes? "07" equals to 7 no matter whether it parsed as an octal or as a decimal. Thus, no harm there.

# Mathias Bynens (10 years ago)

On 5 Aug 2014, at 16:20, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

We're only talking about Annex B, non-strict. Right?

All engines are going to implement this anyway, so why make it Annex B only? I wouldn’t restrict it to non-strict mode either, as this decision seems to be purely based on the Firefox/SpiderMonkey bug that was discussed earlier.

It would be great is somebody wanted to proposal the actual annex B language that is need to correctly describe the web reality semantics.

In section 11.8.3 (Numeric Literals), the definition for DecimalIntegerLiteral should somehow be tweaked to match that of DecimalDigits, with the exception that if the first digit is 0 and all other digits are octal digits (0-7) it must be treated as a legacy octal literal.

Regarding, leading 0 constants in strict mode. The long term plan is to eventually make them legal decimal constants. The only reason not to do that now is because it might screw up people who are migrating non-strict web reality code containing octal constants into strict mode.

Firefox is the only browser that throws

# Mark S. Miller (10 years ago)

Because of compatibility constraints, JS history can generally proceed only in an additive manner, which means a steady degradation of quality along the "simplicity" dimension. An opt-in mode switch is the only way to escape that dynamic. Strict mode is the only one we've got, and the only one we're likely to have in the foreseeable future. Strict mode should not accept octal literals. Regarding sloppy mode, it continues to exist only for the sake of legacy compat, so adding more crap to it for better web compat is the right tradeoff -- as long as the crap stays quarantined within sloppy mode.

# Mathias Bynens (10 years ago)

On 5 Aug 2014, at 16:56, Alex Kocharin <alex at kocharin.ru> wrote:

What about allowing one-digit numbers with leading zeroes? "07" equals to 7 no matter whether it parsed as an octal or as a decimal. Thus, no harm there.

That wouldn’t solve the problem. Consider e.g. 01234567 (i.e. 342391) vs. 01234568 (which must equal 1234568 for compatibility with existing code).

# Mathias Bynens (10 years ago)

On 5 Aug 2014, at 17:05, Mark S. Miller <erights at google.com> wrote:

Because of compatibility constraints, JS history can generally proceed only in an additive manner, which means a steady degradation of quality along the "simplicity" dimension. An opt-in mode switch is the only way to escape that dynamic. Strict mode is the only one we've got, and the only one we're likely to have in the foreseeable future. Strict mode should not accept octal literals. Regarding sloppy mode, it continues to exist only for the sake of legacy compat, so adding more crap to it for better web compat is the right tradeoff -- as long as the crap stays quarantined within sloppy mode.

My point was that the crap under discussion is already available in strict mode in existing implementations (except for the one in Firefox/SpiderMonkey). It’s just not demonstrated yet if The Web depends on this functionality in strict mode too. (It not working in Firefox is an indication that it may not, sure.)

# Mathias Bynens (10 years ago)

On 5 Aug 2014, at 17:05, Mark S. Miller <erights at google.com> wrote:

Strict mode should not accept octal literals.

The literals under discussion (e.g. 08 and 09) are not octal literals.

# Mark S. Miller (10 years ago)

On Tue, Aug 5, 2014 at 8:14 AM, Mathias Bynens <mathias at qiwi.be> wrote:

On 5 Aug 2014, at 17:05, Mark S. Miller <erights at google.com> wrote:

Because of compatibility constraints, JS history can generally proceed only in an additive manner, which means a steady degradation of quality along the "simplicity" dimension. An opt-in mode switch is the only way to escape that dynamic. Strict mode is the only one we've got, and the only one we're likely to have in the foreseeable future. Strict mode should not accept octal literals. Regarding sloppy mode, it continues to exist only for the sake of legacy compat, so adding more crap to it for better web compat is the right tradeoff -- as long as the crap stays quarantined within sloppy mode.

My point was that the crap under discussion is already available in strict mode in existing implementations (except for the one in Firefox/SpiderMonkey). It’s just not demonstrated yet if The Web depends on this functionality in strict mode too. (It not working in Firefox is an indication that it may not, sure.)

Yes, the FF situation seems an adequate demonstration.

On Tue, Aug 5, 2014 at 8:17 AM, Mathias Bynens <mathias at qiwi.be> wrote:

On 5 Aug 2014, at 17:05, Mark S. Miller <erights at google.com> wrote:

Strict mode should not accept octal literals.

The literals under discussion (e.g. 08 and 09) are not octal literals.

Strict mode should reject these even more vehemently! (Allen, can we have an early vehement error?)

# Alex Kocharin (10 years ago)

05.08.2014, 19:07, "Mathias Bynens" <mathias at qiwi.be>:

On 5 Aug 2014, at 16:56, Alex Kocharin <alex at kocharin.ru> wrote:

What about allowing one-digit numbers with leading zeroes? "07" equals to 7 no matter whether it parsed as an octal or as a decimal. Thus, no harm there.

That wouldn’t solve the problem. Consider e.g. 01234567 (i.e. 342391) vs. 01234568 (which must equal 1234568 for compatibility with existing code).

This would solve the problem mentioned in the first message. new Date(2013,08,12); and new Date(2013,07,12); are harmless, since they always mean the same thing (even though first one is decimal and second one is octal).

01234567 should still be deprecated and replaced with 0o1234567, but I don't think it comes up as often as those single-digit ones.

# Mathias Bynens (10 years ago)

On 5 Aug 2014, at 17:19, Mark S. Miller <erights at google.com> wrote:

On Tue, Aug 5, 2014 at 8:17 AM, Mathias Bynens <mathias at qiwi.be> wrote:

The literals under discussion (e.g. 08 and 09) are not octal literals.

Strict mode should reject these even more vehemently! (Allen, can we have an early vehement error?)

Now I’m confused again. That contradicts what Allen said earlier in this thread:

On 5 Aug 2014, at 16:20, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

Regarding, leading 0 constants in strict mode. The long term plan is to eventually make them legal decimal constants.

I stand by my earlier suggestion:

  1. Accept decimal integer literals with leading 0, even in strict mode.
  2. Interpret the value of such literals as octal in case they consist of octal digits only. (Note: this is already in Annex B – see LegacyOctalIntegerLiteral.)

Strict mode would accept 08 as it’s a zero-prefixed decimal literal but not 07 since that’s an octal literal.

This matches what all browsers already do (except Firefox), and fulfills the long-term plan Allen was talking about.

# Allen Wirfs-Brock (10 years ago)

On Aug 5, 2014, at 8:38 AM, Mathias Bynens wrote:

On 5 Aug 2014, at 17:19, Mark S. Miller <erights at google.com> wrote:

On Tue, Aug 5, 2014 at 8:17 AM, Mathias Bynens <mathias at qiwi.be> wrote:

The literals under discussion (e.g. 08 and 09) are not octal literals.

Strict mode should reject these even more vehemently! (Allen, can we have an early vehement error?)

I think we weren't clear enough in the ES5 spec. The base-line grammar says that starting a decimal literal (other than a single '0') with a 'o' is not valid syntax. You should expect to get a syntax error for 00, or 07, or 08, or0123456789, or 01234567, etc. ES5 Annex B defines an extension that makes sequences of digits (excluding '8' or '9') legal syntax. But section 7.8.3 says that that particular extension is not allowed in strict mode code.

The problem is that there is another extensions (that is not in ES5 Annex B) that allows and gives meaning for '0' followed by digit sequences that include the digits '8' and/or '9'. I'm pretty sure that when drafting ES5 we thought the restriction in 7.8.3 was making making both of these extensions illegal in strict mode. Apparently most real world browsers didn't interpret things that way which is unfortunate.

Now I’m confused again. That contradicts what Allen said earlier in this thread:

On 5 Aug 2014, at 16:20, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

Regarding, leading 0 constants in strict mode. The long term plan is to eventually make them legal decimal constants.

I stand by my earlier suggestion:

  1. Accept decimal integer literals with leading 0, even in strict mode.
  2. Interpret the value of such literals as octal in case they consist of octal digits only. (Note: this is already in Annex B – see LegacyOctalIntegerLiteral.)

Strict mode would accept 08 as it’s a zero-prefixed decimal literal but not 07 since that’s an octal literal.

This matches what all browsers already do (except Firefox), and fulfills the long-term plan Allen was talking about.

I think this is more or less the strategy we should follow.

All browsers in all modes apparently interpret leading 0 numbers that contain the digits "8" or "9" as decimal literals. We should make that part of the base language for ES6.

The ES6 base language should make leading 0 numbers containing only octal digits ("1"-"7") syntactically illegal.

Annex B can continue to define the meaning for such leading 0 octal numbers. And strict mode still makes that annex B extension illegal

Someday, when strict mode/modules is more dominant we can relax the restriction of leaning 0 numbers without "8" or "9" and make all leading 0 numbers decimal literals in strict mode.

# Oliver Hunt (10 years ago)

JavaScriptCore has never allowed octal sequences (anything other than a . or x after 0) in strict mode, and we haven't had any problems with it.

# Brendan Eich (10 years ago)

Mark S. Miller wrote:

Because of compatibility constraints, JS history can generally proceed only in an additive manner, which means a steady degradation of quality along the "simplicity" dimension. An opt-in mode switch is the only way to escape that dynamic.

Not really relevant here, though: 08 and 09 were allowed from the dawn of JS.

Also, another way out than strict mode is to extend the language with better forms and let the bad old ones fade away. This does take time. Simplicity in teaching and actual practice can be addressed by subsets both taught and linted or even checked/compiled. Just sayin' ;-).

Strict mode is the only one we've got, and the only one we're likely to have in the foreseeable future. Strict mode should not accept octal literals. Regarding sloppy mode, it continues to exist only for the sake of legacy compat, so adding more crap to it for better web compat is the right tradeoff -- as long as the crap stays quarantined within sloppy mode.

The question is, are we extending strict mode? See Allen's mail before yours.

We've long agreed (more or less) not to reduce "simplicity" by adding more modes over time, including stricter strict mode.

# Allen Wirfs-Brock (10 years ago)

fixed a typo below. a "o" that need to be a "0".

# Chris Peterson (10 years ago)

On Aug 5, 2014, at 11:13 AM, Allen Wirfs-Brock <allen at

wirfs-brock.com> wrote:

I think this is more or less the strategy we should follow.

All browsers in all modes apparently interpret leading 0 numbers that

contain the digits "8" or "9" as decimal literals. We should make that part of the base language for ES6.

The ES6 base language should make leading 0 numbers containing only

octal digits ("1"-"7") syntactically illegal.

If the intent is to eventually permit leading 0 numbers as decimal literals, why forbid unambiguous numbers like 0107 in the meantime?

Many of the websites broken by Firefox's new DecimalIntegerLiteral error are processing dates like new Date(2014, 08, 06). Permitting 0009 (with any number of leading zeros) but forbidding ambiguous 01234567 would be forward-compatible with your plan to eventually permit leading zeros while not breaking websites using Dates today.

Whether 01234568 would be permitted as decimal 1234568 is a subtler question.

# Allen Wirfs-Brock (10 years ago)

On Aug 6, 2014, at 12:02 PM, Chris Peterson wrote:

If the intent is to eventually permit leading 0 numbers as decimal literals, why forbid unambiguous numbers like 0107 in the meantime?

It could be done, but it would be a more complicated specification. I still waiting for somebody to step up and volunteer to write a first draft of a spec. update.

# Bill Frantz (10 years ago)

On 8/5/14 at 8:05 AM, erights at google.com (Mark S. Miller) wrote:

Because of compatibility constraints, JS history can generally proceed only in an additive manner, which means a steady degradation of quality along the "simplicity" dimension. An opt-in mode switch is the only way to escape that dynamic. Strict mode is the only one we've got, and the only one we're likely to have in the foreseeable future. Strict mode should not accept octal literals. Regarding sloppy mode, it continues to exist only for the sake of legacy compat, so adding more crap to it for better web compat is the right tradeoff -- as long as the crap stays quarantined within sloppy mode.

So this horrible footgun, changing the value of a constant changes its radix, is only lurking in sloppy mode.

# Mathias Bynens (10 years ago)

It affects strict mode code too in existing implementations: there you go from not throwing

# Alex Kocharin (10 years ago)

Throw if value is ambiguous (i.e. 052), don't throw if value is unambiguous (i.e. 05, 082). Looks good to me.

It is not compiler job to prevent bad code style, it's what linters should do.

# Mark S. Miller (10 years ago)

It is partially the job of strict mode to prevent some egregiously confusing constructs. There is a line to draw between what strict mode prohibits and what linters warn about. But there's no one line statement of principle that captures this. Strict mode prohibits "with" and some other constructs that make it especially hard to reason about programs.

FF strict does prohibit 05 and 082 (I just checked on Nightly). This demonstrates that the saner rule is web compatible. This also better reflects the intent of what we thought we'd agreed to regarding what is allowed in strict mode.

# Alex Kocharin (10 years ago)

An HTML attachment was scrubbed... URL: esdiscuss/attachments/20140807/d30b0607/attachment-0001

# Mark S. Miller (10 years ago)

The web seems unable to shed its past. In the absence of opt-in (either "use strict";, classes, or modules) legacy web code will probably be sloppy forever. In sloppy mode, you can probably use "with" forever as well.

# Alex Kocharin (10 years ago)

An HTML attachment was scrubbed... URL: esdiscuss/attachments/20140807/78f44b97/attachment

# Mark S. Miller (10 years ago)

On Aug 7, 2014 8:52 AM, "Alex Kocharin" <alex at kocharin.ru> wrote:

So strict mode is mandatory in classes and modules, and can't be turned off.

Yes, classes and modules are optional. If you want to use with or 05, don't use classes or modules.

Since it is mandatory, it is no longer "strict mode" like it is in perl.

You can't opt out of it if you want to. Therefore all legacy constructs should be allowed there unless they are guaranteed to break the code in the future.

Sooner or later people will migrate their legacy code into es6 modules.

We would want to make this migration as easy as possible. And saying that "02468" is fine in es3, forbidden in es6, and allowed again in es8 with exactly the same meaning isn't helping.

# Mark S. Miller (10 years ago)

On Thu, Aug 7, 2014 at 8:52 AM, Alex Kocharin <alex at kocharin.ru> wrote:

So strict mode is mandatory in classes and modules, and can't be turned off. Since it is mandatory, it is no longer "strict mode" like it is in perl. You can't opt out of it if you want to. Therefore all legacy constructs should be allowed there unless they are guaranteed to break the code in the future.

Sooner or later people will migrate their legacy code into es6 modules. We would want to make this migration as easy as possible. And saying that "02468" is fine in es3, forbidden in es6, and allowed again in es8 with exactly the same meaning isn't helping.

I expect "with" and 02468 will continue to be allowed in es6 sloppy, es8 sloppy, and es1000 sloppy. The best way to think of sloppy code is "es3 compatibility mode". I don't see that there's any other sensible purpose for it. Why would you want to say "with" or 02468 for any purpose other than not breaking old legacy es3 code?

# Brendan Eich (10 years ago)

Mark S. Miller wrote:

The web seems unable to shed its past. In the absence of opt-in (either "use strict";, classes, or modules

Service Worker code, Web Components code, ... -- what else?

# Alex Kocharin (10 years ago)

An HTML attachment was scrubbed... URL: esdiscuss/attachments/20140807/9e7442ee/attachment

# Brendan Eich (10 years ago)

Alex Kocharin wrote:

Also, "es1000 sloppy" is a very bad idea. We should have one javascript mode. Two modes as of now bring no value, it just makes compilers more complex, and spec more lengthy for no reason. By the time es8 comes out, it should really deprecate either strict mode or sloppy mode, so the next javascript engine will be able to ditch it.

You seemed to miss the part where Mark wrote "The web seems unable to shed its past." Or as browser vendors say (because they lose share when they do it, generally), "don't break the web".

This doesn't mean strict mode failed. It does mean no-mo'-modes. We shouldn't add any more slop. We'll have to live with 'var'. I have made my peace with it (turd that it is).

# Anne van Kesteren (10 years ago)

On Thu, Aug 7, 2014 at 11:59 PM, Brendan Eich <brendan at mozilla.org> wrote:

This doesn't mean strict mode failed. It does mean no-mo'-modes.

Except for modules? (As they definitely require a mode switch (<module> instead of <script>). Perhaps at a higher-level than JavaScript, but that seems immaterial.)

# Mathias Bynens (10 years ago)

Claude Pache proposed the following spec patch: ecmascript#2792#c11

# Allen Wirfs-Brock (10 years ago)

Thank you, Claude