Proposal: disable automatic semicolon insertion (looking for champion)

I want to propose a way to disable automatic semicolon insertion (ASI), because its behaviours are a little confusing sometimes, and it's probably easier to remember to put in semicolons. Plus with all the tooling available, its much easier to prevent this in the first place now.

More info: GitHub - autumnblazey/proposal-disable-asi: proposal to disable automatic semicolon insertion (ASI)

Disabling it for your own code is already long-since achievable with a linter, and thus doesn't need a proposal.

Disabling it for code you didn't author is almost guaranteed to break your program, as well as the web in general, and so such a proposal would have a hard road to persuade others that it was a good idea.

4 Likes

Not all JS developers use semicolons. Some prefer the more python-ish look. StandardJS for example:

No semicolons
JavaScript Standard Style

2 Likes

yea probably should have said this in the original post, but I'm suggesting a way similar to "use strict" to make it toggleable

1 Like

What advantage do you see in this being a feature of the language? As opposed to using a tool like Eslint to achieve this.

/*eslint semi: ["error", "always"]*/

var name = "ESLint" // error!
1 Like

I feel like the presence of ASI leads to some behaviour that isn't wanted by both semi users and no semi users, and I believe its easier to have a way to turn off ASI and have the behaviour more consistent and not rely on some hacky methods to go around ASI and make it behave correctly all the time

1 Like

This type of request confounds me.

Other than in the "for" statement and minification it serves no non-duplicated useful purpose in the language. If one adopts the functional style of javascript (which is where the language has been heading) and chooses to use "while" instead of "for" the semicolon can be relegated to the same category as 'eval' or 'hasOwnProperty' . In other words it is useful for specific system-like housekeeping but that is all.

Unless you are a Mozart we should all heed the advice of Emperor Joseph

"There are simply too many notes" ; :)

true true, it does seem like a lot of work to implement for such a small thing, thanks for considering though c:

It seems rational in combination with a decision to prevent treating brackets located on a next line as belonged to current expression. Thus it will solve all the cases with redundant semicolons in classes or before arrays and expressions in round brackets.

// Accidental nested property read
let array = []
[1, 2, 3].forEach(v => console.log(v))  // ⚠️ TypeError


// Accidental nested call
let value = ""
(() => console.log('Hello'))()  // ⚠️ TypeError


// SyntaxError while parsing expressions in class body
class Rect {
  width = 0
  height = 0 // ⚠️ SyntaxError
  [Symbol.toStringTag]() {
    return this.width === this.height ? 'Square' : 'Rectangle'
  }
}

"use strict"
[1, 2, 3].forEach(v => console.log(v)) // ⚠️ TypeError

I think it might be implemented due to JS already has meaningful whitespaces in some corner cases: a+++b and a+ ++b have different behavior because of whitespace. Also it makes no sense to split function call or property reading expressions into several lines anyway. If you want to get a property from a value, you'll place a bracket right next to the value.

I'm not against semicolons, but I'm agree that current parser behavior should be made sane and logical. Now the attempt to satisfy two opposite behaviors works poorly and I'd prefer to have stricter and obvious solution. Linters are de facto a standard in DX and most of linter configs prescribe to use or to avoid semicolons.

3 Likes

I initially wanted to just remove ASI entirely because it's quite redundant (now and always, you should be testing your code before you ship), but I was thinking of backwards compatibility to avoid breaking people's code, so it seemed like a toggleable was the best option.

I believe that there is a very strong case for disabling it and it's nothing to do with whether the semi-colon is redundant or not; the assumption rules for whether an end-of-line can be treated as the end of a statement changes the syntax of the language.

In C# I commonly build multi-line chained methods (a-la Martin Fowler's FluentInterface) like this (taken from the link):

private void makeFluent(Customer customer) {
        customer.newOrder()
                .with(6, "TAL")
                .with(5, "HPK").skippable()
                .with(3, "LGV")
                .priorityRush();
    }

Using the dots on the new line to line up works really nicely and I actually often put the final semi-colon on a line on its own too because then you can single-line comment any of the lines to take them out of the chain for testing.

It makes it really nice and readable and consistent with multi-line functional style things with pipes or streams (rxJS etc)

Adding in the assumption that a newline can be a semicolon unless there's an open parenthesis etc. breaks this kind of syntax and whether you like that particular syntax or not, is just not worth the ambiguity and confusion and "breaking" that happens as a result.

1 Like

That syntax works just fine in JS, with ASI.

jQuery is built on those sorts of fluent APIs. It's a very common pattern in JavaScript. In general, JavaScript isn't trying to auto-insert semicolons at new-lines, it usually just tries to do it when it runs into a syntax error to see if the semicolon would fix that error.

Hmm - you're right - I jumped in here all bullish after reading a bad article somewhere else and should have spent more time checking :frowning_face:

Now I need a new reason to argue for my beloved semi-colons :rofl:

Semicolons are great, but ASI can never be removed.