Rationalizing ASI (was: simple shorter function syntax)

# Mark S. Miller (14 years ago)

On Sat, Jul 24, 2010 at 9:21 AM, Kevin Curtis <kevinc1846 at gmail.com> wrote: [...]

Also, is anything proposed for rationalizing ASI in Harmony.

I would welcome ideas. I was sad when we gave up on this for ES5/strict. To get this started, he's one possibility:

Applying the same rules used to recognized the "use strict" directive, within the scope of a "use strict semicolons" directive, any code that would have caused ASI is instead rejected as a static error.

Other suggestions welcome. I hate JavaScript's ASI rules.

# Brendan Eich (14 years ago)

On Jul 24, 2010, at 11:58 AM, Mark S. Miller wrote:

On Sat, Jul 24, 2010 at 9:21 AM, Kevin Curtis <kevinc1846 at gmail.com> wrote: [...] Also, is anything proposed for rationalizing ASI in Harmony.

I would welcome ideas. I was sad when we gave up on this for ES5/strict. To get this started, he's one possibility:

Applying the same rules used to recognized the "use strict" directive, within the scope of a "use strict semicolons" directive, any code that would have caused ASI is instead rejected as a static error.

Other suggestions welcome. I hate JavaScript's ASI rules.

This is quixotic in my view, and BTW Yoda said hate leads to the dark side :-|.

ASI has two parts: syntax error correction + restricted productions. The pain users feel from ASI in my experience is mostly not from the well-specified error correction part. It's mainly due to those infernal restricted productions, especially

ReturnStatement: return [no LineTerminator here] Expressionopt ;

We talked at the July 2008 Oslo ("Harmony") meeting about one way to mitigate the unreported dead-code error that results from

function foo() { if (some) { if (deep) { if (random) { if (logic) { if (ending) { if (in_a_very_long) { return "I believe in the 80 column limit, so I wrapped"; } } } } } } return "LOL"; }

does not burn users. But this is "hard", as we discusssed at that meeting two years ago -- consider the case where the braces were left off.

If we eliminate restricted productions by requiring semicolon after return, break, continue, throw (why is throw restricted? it does not seem necessary given the lack of a throw; form), and postfix ++/--, is it better to go all the way and eliminate the syntactic error correction part of ASI?

The syntactic error correction part does burn users too, in my experience. Specifically in the way discussed in the spec:

The source

a = b + c
(d + e).print()

is not transformed by automatic semicolon insertion, because the parenthesised expression that begins the second line can be interpreted as an argument list for a function call:

a = b + c(d + e).print()

Here there's no syntax error to correct, just the mistaken expectation of ASI. So this is really a case where ASI as a whole would need to go, to try to prevent user confusion of this sort. But I argue (a) it's way too late; (b) users will get confused anyway, even if we give ASI the boot.

Meanwhile, code that runs things together on one line and uses semicolons well everywhere except before }, will be punished harshly. Why?

# Maciej Stachowiak (14 years ago)

On Jul 24, 2010, at 12:40 PM, Brendan Eich wrote:

On Jul 24, 2010, at 11:58 AM, Mark S. Miller wrote:

On Sat, Jul 24, 2010 at 9:21 AM, Kevin Curtis <kevinc1846 at gmail.com> wrote: [...] Also, is anything proposed for rationalizing ASI in Harmony.

I would welcome ideas. I was sad when we gave up on this for ES5/strict. To get this started, he's one possibility:

Applying the same rules used to recognized the "use strict" directive, within the scope of a "use strict semicolons" directive, any code that would have caused ASI is instead rejected as a static error.

Other suggestions welcome. I hate JavaScript's ASI rules.

This is quixotic in my view, and BTW Yoda said hate leads to the dark side :-|.

ASI has two parts: syntax error correction + restricted productions. The pain users feel from ASI in my experience is mostly not from the well-specified error correction part. It's mainly due to those infernal restricted productions, especially

ReturnStatement: return [no LineTerminator here] Expressionopt ;

That's a good point. If we had a "disable ASI" mode, would it just insert syntax errors wherever a semicolon would have been inserted, or would it make statements that could be valid multiline statements but for ASI have their expected multiline meaning? The latter would remove more of the annoyance of ASI, but it wouldn't be a subset of the language. I could see an argument for either, or for no change.

, Maciej

# Brendan Eich (14 years ago)

On Jul 24, 2010, at 3:38 PM, Maciej Stachowiak wrote:

ASI has two parts: syntax error correction + restricted productions. The pain users feel from ASI in my experience is mostly not from the well-specified error correction part. It's mainly due to those infernal restricted productions, especially

ReturnStatement: return [no LineTerminator here] Expressionopt ;

That's a good point. If we had a "disable ASI" mode, would it just insert syntax errors wherever a semicolon would have been inserted, or would it make statements that could be valid multiline statements but for ASI have their expected multiline meaning? The latter would remove more of the annoyance of ASI, but it wouldn't be a subset of the language. I could see an argument for either, or for no change.

I see three tenable alternatives:

  1. Remove ASI in some opt-in version, in full -- no error correction, no restricted productions.

  2. Remove ASI's restricted productions in some opt-in version, but keep the error correction aspect of ASI (i.e., remove rule 3 of the three rules of ASI at ECMA-262 7.9.1).

  3. No change.

I don't see why you'd remove error correction but leave the restricted productions just to have a subset language. We're adding new syntax to Harmony edition(s). Beyond this, the source of most ASI pain is the restricted productions. Error correction, especially via ASI rule 1 second bullet (inserting a ; before a }) is a win for usability.

I strongly suspect we'll stick with 3 indefinitely, but I'm open to discussing 2 briefly. Better than discussing would be some codesearch.google type study of a large swath of web JS, measuring how much would break under 2.

# Mark S. Miller (14 years ago)

I started to reply, but found it too confusing to talk about options #1, #2, and #3 and about ASI rules #1, #2, and #3. I'm resending your text edited with your options relabeled as #A, #B, and #C. I'll then reply to this edited version. I encourage others to do likewise.

---------- Forwarded message ---------- From: Brendan Eich <brendan at mozilla.com>

Date: Sat, Jul 24, 2010 at 10:28 PM Subject: Re: Rationalizing ASI (was: simple shorter function syntax) To: Maciej Stachowiak <mjs at apple.com>, "Mark S. Miller" <erights at google.com>

Cc: es-discuss <es-discuss at mozilla.org>

On Jul 24, 2010, at 3:38 PM, Maciej Stachowiak wrote:

ASI has two parts: syntax error correction + restricted productions. The

pain users feel from ASI in my experience is mostly not from the well-specified error correction part. It's mainly due to those infernal restricted productions, especially

ReturnStatement: return [no LineTerminator here] Expressionopt ;

That's a good point. If we had a "disable ASI" mode, would it just insert

syntax errors wherever a semicolon would have been inserted, or would it make statements that could be valid multiline statements but for ASI have their expected multiline meaning? The latter would remove more of the annoyance of ASI, but it wouldn't be a subset of the language. I could see an argument for either, or for no change.

I see three tenable alternatives:

A. Remove ASI in some opt-in version, in full -- no error correction, no restricted productions.

B. Remove ASI's restricted productions in some opt-in version, but keep the error correction aspect of ASI (i.e., remove rule 3 of the three rules of ASI at ECMA-262 7.9.1).

C. No change.

I don't see why you'd remove error correction but leave the restricted productions just to have a subset language. We're adding new syntax to Harmony edition(s). Beyond this, the source of most ASI pain is the restricted productions. Error correction, especially via ASI rule 1 second bullet (inserting a ; before a }) is a win for usability.

I strongly suspect we'll stick with #C indefinitely, but I'm open to discussing #B briefly. Better than discussing would be some codesearch.google type study of a large swath of web JS, measuring how much would break under #B.

# Mark S. Miller (14 years ago)

First, I agree that we should gather and examine data before making any decisions. That said, here are my data-free reactions. I may well change my mind about any of this once we have data to examine.

On Sat, Jul 24, 2010 at 11:16 PM, Mark S. Miller <erights at google.com> wrote:

Hi Brendan, I started to reply, but found it too confusing to talk about options #1, #2, and #3 and about ASI rules #1, #2, and #3. I'm resending your text edited with your options relabeled as #A, #B, and #C. I'll then reply to this edited version. I encourage others to do likewise.

---------- Forwarded message ---------- From: Brendan Eich <brendan at mozilla.com> Date: Sat, Jul 24, 2010 at 10:28 PM Subject: Re: Rationalizing ASI (was: simple shorter function syntax) To: Maciej Stachowiak <mjs at apple.com>, "Mark S. Miller" < erights at google.com> Cc: es-discuss <es-discuss at mozilla.org>

On Jul 24, 2010, at 3:38 PM, Maciej Stachowiak wrote:

ASI has two parts: syntax error correction + restricted productions. The pain users feel from ASI in my experience is mostly not from the well-specified error correction part. It's mainly due to those infernal restricted productions, especially

ReturnStatement: return [no LineTerminator here] Expressionopt ;

That's a good point. If we had a "disable ASI" mode, would it just insert syntax errors wherever a semicolon would have been inserted, or would it make statements that could be valid multiline statements but for ASI have their expected multiline meaning? The latter would remove more of the annoyance of ASI, but it wouldn't be a subset of the language. I could see an argument for either, or for no change.

I see three tenable alternatives:

A. Remove ASI in some opt-in version, in full -- no error correction, no restricted productions.

This seems best to me. I would have no objection to keeping the second bullet of ASI rule #1. I may even advocate keeping it; I'm not sure yet. However, the first bullet of rule #1 is a terrible hazard.

B. Remove ASI's restricted productions in some opt-in version, but keep the error correction aspect of ASI (i.e., remove rule 3 of the three rules of ASI at ECMA-262 7.9.1).

C. No change.

#B seems rather horrible to me. The restricted productions at least catch some of the errors that ASI causes. I strongly prefer #C to #B.

I don't see why you'd remove error correction but leave the restricted productions just to have a subset language.

Agreed. Once we remove the ASI hazards, we should also remove the inconveniences which are no longer needed to avoid these hazards.

We're adding new syntax to Harmony edition(s). Beyond this, the source of most ASI pain is the restricted productions. Error correction, especially via ASI rule 1 second bullet (inserting a ; before a }) is a win for usability.

I agree about the second bullet. I passionately disagree about the first bullet. That first bullet is way more painful than the restricted productions.

I strongly suspect we'll stick with #C indefinitely, but I'm open to discussing #B briefly. Better than discussing would be some codesearch.google type study of a large swath of web JS, measuring how much would break under #B.

Yes! Data! Bring it on!

# Mark S. Miller (14 years ago)

On Sat, Jul 24, 2010 at 11:28 PM, Mark S. Miller <erights at google.com> wrote:

First, I agree that we should gather and examine data before making any decisions. That said, here are my data-free reactions. I may well change my mind about any of this once we have data to examine.

On Sat, Jul 24, 2010 at 11:16 PM, Mark S. Miller <erights at google.com>wrote:

Hi Brendan, I started to reply, but found it too confusing to talk about options #1, #2, and #3 and about ASI rules #1, #2, and #3. I'm resending your text edited with your options relabeled as #A, #B, and #C. I'll then reply to this edited version. I encourage others to do likewise.

---------- Forwarded message ---------- From: Brendan Eich <brendan at mozilla.com> Date: Sat, Jul 24, 2010 at 10:28 PM Subject: Re: Rationalizing ASI (was: simple shorter function syntax) To: Maciej Stachowiak <mjs at apple.com>, "Mark S. Miller" < erights at google.com> Cc: es-discuss <es-discuss at mozilla.org>

On Jul 24, 2010, at 3:38 PM, Maciej Stachowiak wrote:

ASI has two parts: syntax error correction + restricted productions. The pain users feel from ASI in my experience is mostly not from the well-specified error correction part. It's mainly due to those infernal restricted productions, especially

ReturnStatement: return [no LineTerminator here] Expressionopt ;

That's a good point. If we had a "disable ASI" mode, would it just insert syntax errors wherever a semicolon would have been inserted, or would it make statements that could be valid multiline statements but for ASI have their expected multiline meaning? The latter would remove more of the annoyance of ASI, but it wouldn't be a subset of the language. I could see an argument for either, or for no change.

I see three tenable alternatives:

A. Remove ASI in some opt-in version, in full -- no error correction, no restricted productions.

This seems best to me. I would have no objection to keeping the second bullet of ASI rule #1. I may even advocate keeping it; I'm not sure yet. However, the first bullet of rule #1 is a terrible hazard.

I should add that I view ASI rule #2 as similar to the second bullet of ASI rule #1. It's harmless and helpful, and probably should be kept.

# Brendan Eich (14 years ago)

On Jul 24, 2010, at 11:30 PM, Mark S. Miller wrote:

From: Brendan Eich <brendan at mozilla.com> I see three tenable alternatives:

A. Remove ASI in some opt-in version, in full -- no error correction, no restricted productions.

This seems best to me. I would have no objection to keeping the second bullet of ASI rule #1. I may even advocate keeping it; I'm not sure yet. However, the first bullet of rule #1 is a terrible hazard.

Can you say more? It's hazardous because "X, Y, and Z" -- three concrete examples.

The hazard I see, which Garrett Smith mailed me about just now, is the one I already identified as "the mistaken expectation of ASI" -- the case where there's no syntax error for ASI to correct:

var MyWidget = function(){ this.name = "mike"; } /**

  • Initialize Widget / (function() { /...*/ });

(from jibbering.com/faq/notes/code-guidelines/asi.html).

This is simply a failure to use a semicolon where it is needed.

Removing ASI won't make this hazard go away unless (eventually, and in statistically significant numbers) developers stop "counting" on such magical "DWIM" ASI, and become more careful. But that is farfetched, since it's pretty easy to make this mistake even if one assiduously inserts semicolons manually.

Yes! Data! Bring it on!

That's your job :-P. I don't have access to the Google copy of the web, or sawzall.

# Mark S. Miller (14 years ago)

On Sat, Jul 24, 2010 at 11:46 PM, Brendan Eich <brendan at mozilla.com> wrote:

On Jul 24, 2010, at 11:30 PM, Mark S. Miller wrote:

From: Brendan Eich <brendan at mozilla.com> I see three tenable alternatives:

A. Remove ASI in some opt-in version, in full -- no error correction, no restricted productions.

This seems best to me. I would have no objection to keeping the second bullet of ASI rule #1. I may even advocate keeping it; I'm not sure yet. However, the first bullet of rule #1 is a terrible hazard.

Can you say more? It's hazardous because "X, Y, and Z" -- three concrete examples.

The hazard I see, which Garrett Smith mailed me about just now, is the one I already identified as "the mistaken expectation of ASI" -- the case where there's no syntax error for ASI to correct:

var MyWidget = function(){ this.name = "mike"; } /**

  • Initialize Widget / (function() { /...*/ });

(from jibbering.com/faq/notes/code-guidelines/asi.html).

This is simply a failure to use a semicolon where it is needed.

Removing ASI won't make this hazard go away unless (eventually, and in statistically significant numbers) developers stop "counting" on such magical "DWIM" ASI, and become more careful. But that is farfetched, since it's pretty easy to make this mistake even if one assiduously inserts semicolons manually.

This is a perfect example, and I agree with most of your analysis of it, but not with your conclusion.

<detail>

A slightly better example is

obj.widget = function(){
  this.name = "mike";
}

since the first one can be easily avoid by using function declarations where they're appropriate. </detail>

The problem is that as long as ASI exists, one will often see working code such as this, since it does usually work. This training of the eye is a kind of habituation, and in this case it is insidious because it desensitizes the programmer from a pattern that should look malformed but doesn't. In the absence of ASI, such code would never normally appear in running code. When it does appear in running code, that should alert the programmer that their program violates their intention and needs to be fixed.

# Brendan Eich (14 years ago)

On Jul 25, 2010, at 10:52 AM, Mark S. Miller wrote:

The problem is that as long as ASI exists, one will often see working code such as this, since it does usually work. This training of the eye is a kind of habituation, and in this case it is insidious because it desensitizes the programmer from a pattern that should look malformed but doesn't.

Ok, I'll grant you ASI desensitization is a factor in human readers missing this kind of bug.

In the absence of ASI, such code would never normally appear in running code.

Come on! "Never" ("normally" doesn't count, it's just hedging in a way that tends to assume the conclusion) must mean that if only we didn't suffer from ASI-based desensitization to missing semicolons, we would have perfect manual semicolon insertion and perfect code auditing and testing. But utopia is not an option.

This hazard is insidious because testing may fail to uncover it, since tests have bugs too, test coverage is never perfect, and what's more, if the function expression itself returns a similar enough function, the caller of the stored method might not notice any malfunction.

So let's agree on "less often" -- not "never".

When it does appear in running code, that should alert the programmer that their program violates their intention and needs to be fixed.

That's nice, but "should" is not good enough. Empirically, it doesn't work that way. I'm not just going by my experience, but by the jibbering page, the bug reports I've seen, the Dojo guys who do use semicolons still having to ward off this hazard with a leading ; in each source file.

Let's not go in circles. I claim:

  • The horses are long gone from the barn.
  • The mistake is easy to overlook even for JS coders who do use semicolons.
  • The trade-off of banning ASI rule 1 first bullet to reduce desensitization and eventually reduce the incidence of this kind of bug is not a clear win, vs. migration tax into Harmony and usability problems even writing fresh code.

In order to reliably remove this hazard, we would need to ban statements from starting with '('. Perhaps we should consider doing so.

# Mark S. Miller (14 years ago)

On Sun, Jul 25, 2010 at 11:36 AM, Brendan Eich <brendan at mozilla.com> wrote:

On Jul 25, 2010, at 10:52 AM, Mark S. Miller wrote:

The problem is that as long as ASI exists, one will often see working code such as this, since it does usually work. This training of the eye is a kind of habituation, and in this case it is insidious because it desensitizes the programmer from a pattern that should look malformed but doesn't.

Ok, I'll grant you ASI desensitization is a factor in human readers missing this kind of bug.

In the absence of ASI, such code would never normally appear in running code.

Come on! "Never" ("normally" doesn't count, it's just hedging in a way that tends to assume the conclusion) must mean that if only we didn't suffer from ASI-based desensitization to missing semicolons, we would have perfect manual semicolon insertion and perfect code auditing and testing. But utopia is not an option.

This hazard is insidious because testing may fail to uncover it, since tests have bugs too, test coverage is never perfect, and what's more, if the function expression itself returns a similar enough function, the caller of the stored method might not notice any malfunction.

So let's agree on "less often" -- not "never".

Sure.

When it does appear in running code, that should alert the programmer that their program violates their intention and needs to be fixed.

That's nice, but "should" is not good enough. Empirically, it doesn't work that way. I'm not just going by my experience, but by the jibbering page, the bug reports I've seen, the Dojo guys who do use semicolons still having to ward off this hazard with a leading ; in each source file.

Let's not go in circles. I claim:

  • The horses are long gone from the barn.
  • The mistake is easy to overlook even for JS coders who do use semicolons.
  • The trade-off of banning ASI rule 1 first bullet to reduce desensitization and eventually reduce the incidence of this kind of bug is not a clear win, vs. migration tax into Harmony and usability problems even writing fresh code.

In order to reliably remove this hazard, we would need to ban statements from starting with '('. Perhaps we should consider doing so.

The problem there is the common module pattern

(function(){
  ...
})();

Although less common, defining an anonymous object literal and using it inline is perfectly sensible:

({
  ... // includes methods mentioning "this"
}).foo(...);

Perhaps, under the hypothetical opt-in, we should also consider CallExpression a restricted production?

CallExpression : ...
    CallExpression [no newline here] Arguments

This would more reliably catch the above hazards without breaking pleasant legitimate uses.

# David Herman (14 years ago)

In order to reliably remove this hazard, we would need to ban statements from starting with '('. Perhaps we should consider doing so.

That's a REPL-killer: as is, you have to do unnatural paren-wrapping for object-literal expressions at a REPL:

> ({ foo: 42 })
({ foo: 42 })

Now you wouldn't even be allowed to do that.

# Brendan Eich (14 years ago)

On Jul 25, 2010, at 11:56 AM, David Herman wrote:

In order to reliably remove this hazard, we would need to ban statements from starting with '('. Perhaps we should consider doing so.

That's a REPL-killer: as is, you have to do unnatural paren-wrapping for object-literal expressions at a REPL:

({ foo: 42 }) ({ foo: 42 })

Now you wouldn't even be allowed to do that.

No free lunch! ;-)

Hey, we are merely considering, not jumping to a conclusion.

Mark's restricted production for CallExpression attacks the hazard even more directly, but apart from our aversion to restricted productions, what might it break?

# David Herman (14 years ago)

Mark's restricted production for CallExpression attacks the hazard even more directly, but apart from our aversion to restricted productions, what might it break?

I don't see offhand what it might break. This question seems easy to investigate empirically-- crawl the web looking for "violations" of the restriction.

Personally, I'm not enthusiastic about this line of pursuit. It smells of excessive fool-proofing. Ad-hoc restrictions seem both unlikely to provide clear guarantees and likely to have unintended consequences. Irregular syntax is bumpy terrain; obfuscation we will always have with us. In the absence of strong evidence of a need, I'd prefer to relegate such syntactic restrictions to third-party lint tools and let them experiment with them. Just my $.02.

# Brendan Eich (14 years ago)

On Jul 25, 2010, at 2:02 PM, David Herman wrote:

Mark's restricted production for CallExpression attacks the hazard even more directly, but apart from our aversion to restricted productions, what might it break?

I don't see offhand what it might break. This question seems easy to investigate empirically-- crawl the web looking for "violations" of the restriction.

Personally, I'm not enthusiastic about this line of pursuit. It smells of excessive fool-proofing. Ad-hoc restrictions seem both unlikely to provide clear guarantees and likely to have unintended consequences. Irregular syntax is bumpy terrain; obfuscation we will always have with us. In the absence of strong evidence of a need, I'd prefer to relegate such syntactic restrictions to third-party lint tools and let them experiment with them. Just my $.02.

I tend to agree, see "quixotic", "snipe hunt", etc. words in my recent posts.

Also, not another restricted production! But hats off to Mark for proposing it, since it zeroes in on the hard case.

A good es-discuss thread (it's not like we have too many going at once) can clarify what may seem murky or overcomplicated issues. Just the emotion around ASI makes me want to reach for greater clarify and (if possible) improvements down the line. But yeah, it's low priority and the risk for reward looks high.

Google-sized code studying would be helpful. Can it be done? codesearch.google.com is not up to it, you need to parse.

# Brendan Eich (14 years ago)

On Jul 25, 2010, at 2:17 PM, Brendan Eich wrote:

Also, not another restricted production! But hats off to Mark for proposing it, since it zeroes in on the hard case.

A good es-discuss thread (it's not like we have too many going at once) can clarify what may seem murky or overcomplicated issues. Just the emotion around ASI makes me want to reach for greater clarify and (if possible) improvements down the line. But yeah, it's low priority and the risk for reward looks high.

Throwing out another idea: a stricter Harmony strict mode could make a parameter list starting with '(' on separate line from callee expression be an error. Among other ASI reforms, if any.

With Harmony built on ES5 strict, anyone migrating code containing "use strict" climbs the strictness ladder toward fewer actual hazards. If this bites back, remove the "use strict" and stay with ES5-level strict-by-default in Harmony.

Thoughts? I'm not in love with any of this, just trying alternatives on for size on a Sunday afternoon.

# Maciej Stachowiak (14 years ago)

On Jul 25, 2010, at 11:36 AM, Brendan Eich wrote:

Let's not go in circles. I claim:

  • The horses are long gone from the barn.
  • The mistake is easy to overlook even for JS coders who do use semicolons.
  • The trade-off of banning ASI rule 1 first bullet to reduce desensitization and eventually reduce the incidence of this kind of bug is not a clear win, vs. migration tax into Harmony and usability problems even writing fresh code.

In order to reliably remove this hazard, we would need to ban statements from starting with '('. Perhaps we should consider doing so.

Banning statements from starting with '(' would remove one of the easiest workarounds for the rules against statements starting with 'function' or statements starting with '{'.

, Maciej

# Brendan Eich (14 years ago)

On Jul 25, 2010, at 4:59 PM, Maciej Stachowiak wrote:

On Jul 25, 2010, at 11:36 AM, Brendan Eich wrote:

Let's not go in circles. I claim:

  • The horses are long gone from the barn.
  • The mistake is easy to overlook even for JS coders who do use semicolons.
  • The trade-off of banning ASI rule 1 first bullet to reduce desensitization and eventually reduce the incidence of this kind of bug is not a clear win, vs. migration tax into Harmony and usability problems even writing fresh code.

In order to reliably remove this hazard, we would need to ban statements from starting with '('. Perhaps we should consider doing so.

Banning statements from starting with '(' would remove one of the easiest workarounds for the rules against statements starting with 'function' or statements starting with '{'.

Yeah, that's too harsh -- you'd have to use an operator or assign to a dummy variable or declare an initialized binding.

Mark's restricted production idea is on target, if we think it's worth doing.

# Maciej Stachowiak (14 years ago)

On Jul 25, 2010, at 5:06 PM, Brendan Eich wrote:

On Jul 25, 2010, at 4:59 PM, Maciej Stachowiak wrote:

On Jul 25, 2010, at 11:36 AM, Brendan Eich wrote:

Let's not go in circles. I claim:

  • The horses are long gone from the barn.
  • The mistake is easy to overlook even for JS coders who do use semicolons.
  • The trade-off of banning ASI rule 1 first bullet to reduce desensitization and eventually reduce the incidence of this kind of bug is not a clear win, vs. migration tax into Harmony and usability problems even writing fresh code.

In order to reliably remove this hazard, we would need to ban statements from starting with '('. Perhaps we should consider doing so.

Banning statements from starting with '(' would remove one of the easiest workarounds for the rules against statements starting with 'function' or statements starting with '{'.

Yeah, that's too harsh -- you'd have to use an operator or assign to a dummy variable or declare an initialized binding.

Mark's restricted production idea is on target, if we think it's worth doing.

At least in C or C++, I've seen code like this:

veryLongObjectName.someOtherVeryVeryLongObjectName.ridiculouslyLongFunctionName (longArgument1, longArgument2, longArgument3, longArgument4, longArgument5);

If I understand correctly, Mark's proposal would make that a syntax error in JavaScript. I'm not sure offhand if JavaScript programmers write in this style, or would find the loss annoying. Of course, you could always write this as a single very long line, or make sure that at least the open paren is on the first line, but programmers can be picky about questions of style like this.

, Maciej

# Mark S. Miller (14 years ago)

On Sun, Jul 25, 2010 at 5:11 PM, Maciej Stachowiak <mjs at apple.com> wrote:

On Jul 25, 2010, at 5:06 PM, Brendan Eich wrote:

On Jul 25, 2010, at 4:59 PM, Maciej Stachowiak wrote:

On Jul 25, 2010, at 11:36 AM, Brendan Eich wrote:

Let's not go in circles. I claim:

  • The horses are long gone from the barn.
  • The mistake is easy to overlook even for JS coders who do use semicolons.
  • The trade-off of banning ASI rule 1 first bullet to reduce desensitization and eventually reduce the incidence of this kind of bug is not a clear win, vs. migration tax into Harmony and usability problems even writing fresh code.

In order to reliably remove this hazard, we would need to ban statements from starting with '('. Perhaps we should consider doing so.

Banning statements from starting with '(' would remove one of the easiest workarounds for the rules against statements starting with 'function' or statements starting with '{'.

Yeah, that's too harsh -- you'd have to use an operator or assign to a dummy variable or declare an initialized binding.

Mark's restricted production idea is on target, if we think it's worth doing.

At least in C or C++, I've seen code like this:

veryLongObjectName.someOtherVeryVeryLongObjectName.ridiculouslyLongFunctionName (longArgument1, longArgument2, longArgument3, longArgument4, longArgument5);

If I understand correctly, Mark's proposal would make that a syntax error in JavaScript. I'm not sure offhand if JavaScript programmers write in this style, or would find the loss annoying. Of course, you could always write this as a single very long line, or make sure that at least the open paren is on the first line, but programmers can be picky about questions of style like this.

Yes. Even in the absence of ASI issues, my inclination would be to put the open parent at the end of the first line. YMMV.

# Mike Shaver (14 years ago)

On Sun, Jul 25, 2010 at 8:15 PM, Mark S. Miller <erights at google.com> wrote:

veryLongObjectName.someOtherVeryVeryLongObjectName.ridiculouslyLongFunctionName    (longArgument1, longArgument2, longArgument3, longArgument4, longArgument5);

Yes. Even in the absence of ASI issues, my inclination would be to put the open parent at the end of the first line. YMMV.

Many (most? virtually all?) indent-helping editors prefer the LP on the second line, since otherwise they indent the argument list to start at the 75th column, or what have you. Not much point in splitting the lines in those cases without putting the LP on the second line.

Mike

# Dmitry A. Soshnikov (14 years ago)

On 26.07.2010 4:11, Maciej Stachowiak wrote:

On Jul 25, 2010, at 5:06 PM, Brendan Eich wrote:

On Jul 25, 2010, at 4:59 PM, Maciej Stachowiak wrote:

On Jul 25, 2010, at 11:36 AM, Brendan Eich wrote:

Let's not go in circles. I claim:

  • The horses are long gone from the barn.
  • The mistake is easy to overlook even for JS coders who do use semicolons.
  • The trade-off of banning ASI rule 1 first bullet to reduce desensitization and eventually reduce the incidence of this kind of bug is not a clear win, vs. migration tax into Harmony and usability problems even writing fresh code.

In order to reliably remove this hazard, we would need to ban statements from starting with '('. Perhaps we should consider doing so.

Banning statements from starting with '(' would remove one of the easiest workarounds for the rules against statements starting with 'function' or statements starting with '{'.

Yeah, that's too harsh -- you'd have to use an operator or assign to a dummy variable or declare an initialized binding.

Mark's restricted production idea is on target, if we think it's worth doing.

At least in C or C++, I've seen code like this:

veryLongObjectName.someOtherVeryVeryLongObjectName.ridiculouslyLongFunctionName (longArgument1, longArgument2, longArgument3, longArgument4, longArgument5);

If I understand correctly, Mark's proposal would make that a syntax error in JavaScript. I'm not sure offhand if JavaScript programmers write in this style, or would find the loss annoying. Of course, you could always write this as a single very long line, or make sure that at least the open paren is on the first line, but programmers can be picky about questions of style like this.

There is interesting "declarative" pattern which looks nicer if to place '(' on the next line. This pattern uses self-reproducible (or self-replicative) function -- when a function returns itself.

Instead of imperative:

myApp.keys.register([ ['w', panNorth], ['s', panSouth], ['a', panWest], ['d', panEast] ]);

Can be used (just declare keys):

myApp.keys ('w', panNorth) ('s', panSouth) ('a', panWest) ('d', panEast);

But in general, yeah, programmers tries to use '(' at the same line:

someFunction( argument, otherData );

Dmitry.

# Zachary Carter (14 years ago)

On Mon, Jul 26, 2010 at 2:46 AM, Dmitry A. Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On 26.07.2010 4:11, Maciej Stachowiak wrote:

On Jul 25, 2010, at 5:06 PM, Brendan Eich wrote:

On Jul 25, 2010, at 4:59 PM, Maciej Stachowiak wrote:

On Jul 25, 2010, at 11:36 AM, Brendan Eich wrote:

Let's not go in circles. I claim:

  • The horses are long gone from the barn.
  • The mistake is easy to overlook even for JS coders who do use semicolons.
  • The trade-off of banning ASI rule 1 first bullet to reduce desensitization and eventually reduce the incidence of this kind of bug is not a clear win, vs. migration tax into Harmony and usability problems even writing fresh code.

In order to reliably remove this hazard, we would need to ban statements from starting with '('. Perhaps we should consider doing so.

Banning statements from starting with '(' would remove one of the easiest workarounds for the rules against statements starting with 'function' or statements starting with '{'.

Yeah, that's too harsh -- you'd have to use an operator or assign to a dummy variable or declare an initialized binding.

Mark's restricted production idea is on target, if we think it's worth doing.

At least in C or C++, I've seen code like this:

veryLongObjectName.someOtherVeryVeryLongObjectName.ridiculouslyLongFunctionName (longArgument1, longArgument2, longArgument3, longArgument4, longArgument5);

If I understand correctly, Mark's proposal would make that a syntax error in JavaScript. I'm not sure offhand if JavaScript programmers write in this style, or would find the loss annoying. Of course, you could always write this as a single very long line, or make sure that at least the open paren is on the first line, but programmers can be picky about questions of style like this.

There is interesting "declarative" pattern which looks nicer if to place '(' on the next line. This pattern uses self-reproducible (or self-replicative) function -- when a function returns itself.

Instead of imperative:

myApp.keys.register([ ['w', panNorth], ['s', panSouth], ['a', panWest], ['d', panEast] ]);

Can be used (just declare keys):

myApp.keys ('w', panNorth) ('s', panSouth) ('a', panWest) ('d', panEast);

The (fab) library for Node takes this pattern to the extreme:

var fab = require("fab");

( fab )

( listen, 0xFAB )

( /^/hello/ )

( tmpl )
  ( "Hello, <%= this %>!" )

( /^\/(\w+)$/ )
  ( capture.at, 0 )
  ( "world" )

( 404 );

jed/fab

# Waldemar Horwat (14 years ago)

Maciej Stachowiak wrote:

On Jul 25, 2010, at 5:06 PM, Brendan Eich wrote:

Mark's restricted production idea is on target, if we think it's worth doing.

At least in C or C++, I've seen code like this:

veryLongObjectName.someOtherVeryVeryLongObjectName.ridiculouslyLongFunctionName (longArgument1, longArgument2, longArgument3, longArgument4, longArgument5);

If I understand correctly, Mark's proposal would make that a syntax error in JavaScript. I'm not sure offhand if JavaScript programmers write in this style, or would find the loss annoying. Of course, you could always write this as a single very long line, or make sure that at least the open paren is on the first line, but programmers can be picky about questions of style like this.

If you made function invocation a restricted production then semicolon insertion would turn the above code into:

veryLongObjectName.someOtherVeryVeryLongObjectName.ridiculouslyLongFunctionName; (longArgument1, longArgument2, longArgument3, longArgument4, longArgument5);

Waldemar
# Mark S. Miller (14 years ago)

I'm proposing that the same opt-in that makes function call a restricted production also turns off semicolon insertion, making that code into a static syntax error. For those cases where the language can't reliably tell what I mean, I don't want it to guess.

# Garrett Smith (14 years ago)

On 7/25/10, Mark S. Miller <erights at google.com> wrote:

On Sun, Jul 25, 2010 at 11:36 AM, Brendan Eich <brendan at mozilla.com> wrote:

On Jul 25, 2010, at 10:52 AM, Mark S. Miller wrote:

The problem is that as long as ASI exists, one will often see working code such as this, since it does usually work. This training of the eye is a kind of habituation, and in this case it is insidious because it desensitizes the programmer from a pattern that should look malformed but doesn't.

Ok, I'll grant you ASI desensitization is a factor in human readers missing this kind of bug.

In the absence of ASI, such code would never normally appear in running code.

Come on! "Never" ("normally" doesn't count, it's just hedging in a way that tends to assume the conclusion) must mean that if only we didn't suffer from ASI-based desensitization to missing semicolons, we would have perfect manual semicolon insertion and perfect code auditing and testing. But utopia is not an option.

This hazard is insidious because testing may fail to uncover it, since tests have bugs too, test coverage is never perfect, and what's more, if the function expression itself returns a similar enough function, the caller of the stored method might not notice any malfunction.

So let's agree on "less often" -- not "never".

Sure.

When it does appear in running code, that should alert the programmer that their program violates their intention and needs to be fixed.

That's nice, but "should" is not good enough. Empirically, it doesn't work that way. I'm not just going by my experience, but by the jibbering page, the bug reports I've seen, the Dojo guys who do use semicolons still having to ward off this hazard with a leading ; in each source file.

Let's not go in circles. I claim:

  • The horses are long gone from the barn.
  • The mistake is easy to overlook even for JS coders who do use semicolons.
  • The trade-off of banning ASI rule 1 first bullet to reduce desensitization and eventually reduce the incidence of this kind of bug is not a clear win, vs. migration tax into Harmony and usability problems even writing fresh code.

In order to reliably remove this hazard, we would need to ban statements from starting with '('. Perhaps we should consider doing so.

The problem there is the common module pattern

(besides breaking uses with eval)

(function(){
  ...
})();

A problem is that this module can become Arguments production in CallExpression (and possibly NewExpression, though less likely), depending on what comes before it (as in the asi.html example where global.name = "mike"); That is why some scripts (Dojo, for example) begin with a semicolon, as:

;(function(){ })();

Dojo does this, for example.

If ASI is removed from strict mode, then a semicolon will not be inserted at the end of the input stream. If ASI were disabled, then developers would realize right away that the problem if the Expression from file1.js missing a semicolon were to result in an error.

In that scenario, it wouldn't make sense to have CallExpression be a restricted production.

Garrett