Suggestion: Getting a handle on ASI usage

# Claus Reinke (14 years ago)

Background assumptions:

Fixing ASI, as desirable as that may be, is not going to
happen soon. Neither is the transition going to be quick 
if/when a better alternative emerges, as existing ASI usage
patterns need to be supported. 

However, these usage patterns are currently not clearly 
identified - there seem to be multiple schools of ASI usage, 
with different needs and intentions, and implementations 
cannot guess intentions.

Idea:

Start by giving javascript programmers the ability to declare
their intentions wrt ASI usage. That way, future attempts at
ASI improvements will have a better handle on what they
need to preserve, and what they can change. 

Even without ASI changes, such declarations will allow 
implementations to give better warnings (no need to guess 
user intentions), helping to avoid current ASI pitfalls.

Suggestion (outline; syntax and details up for discussion):

Introduce a language pragma for ASI, accompanied by
warning pragmas (a "language pragma" indicates use of a
language feature, as a modular alternative to language
versions; a "warning pragma" indicates use of an
implementation option). 

Lacking a javascript standard for pragmas, this suggestion 
follows the "use strict" example (string expression statements 
with function or script scope):

Language pragma:

    "ASI:on"; // to indicate maximal use of ASI

    "ASI:off"; // to indicate minimal use of ASI

Warning pragmas:

    "ASI:warn-insert:[on/off]"; 
        // warn about unexpected semicolon insertion

    "ASI:warn-no-insert:[on/off]";
        // warn about missing semicolons

    (examples of "unexpected"/"missing" are given below)
    
Implied warnings:

    The default for ASI warnings is "off" (no warnings).
    Use of "ASI:on" shall imply "ASI:warn-no-insert:on".
    Use of "ASI:off" shall imply "ASI:warn-insert:on".
    Implied warnings can be reset by explicit warning
    pragmas.

Phase 1: (the current suggestion; as soon as possible)

    Implementations supporting ASI pragmas must run code 
    *with or without* ASI pragmas as before, but must provide
    checks and warnings (on a side channel, such as an error 
    console) for code *with* ASI pragmas.

Phase 2: (depending on implementer/programmer buy-in
                 to phase 1; probably not anytime soon)

    Implementations supporting ASI pragmas must run code 
    *without* ASI pragmas as before, but could treat ASI 
    warnings for code *with* ASI pragmas as errors. 

    One could also start to issue deprecation warnings for 
    code without ASI pragmas, encouraging transition to
    ASI usage pattern documentation, and one could evaluate 
    ASI usage patterns, as declared by use of ASI pragmas in 
    real-world code. 

    Warning-free code with ASI pragmas should both offer 
    good test-cases for any ASI modifications and document
    programmer intentions for any transition support tools.

Observations and clarifications:

As far as I can tell from the previous ASI thread, there are several groups with opinions about ASI, including (but not limited to):

A those who avoid semicolons, relying on ASI to fill them in B those who avoid ASI, writing out all semicolons explicitly C those who expect newlines to imply semicolons, with mixed results, because that isn't the way ASI works

These groups have different problems with ASI, even assuming that both A and B know and understand how ASI works:

A have to insert semicolons where ASI does not kick in B have to be wary of ASI inserting unwanted semicolons C tend to find ASI confusing

As long as we don't have a better solution, it seems that warning about the unexpected/unwanted might improve understanding and user experience of ASI as it stands. This should also prepare the ground for any ASI improvements/replacements.

Currently, implementations cannot issue warnings - they are handling ASI as specified and they cannot guess whether or not that matches programmer intentions; however, once programmers declare their ASI usage pattern (maximal/minimal), there are two well-known trouble spots that can trigger warnings.

Both of these trouble spots are related to newlines (either the programmer expects a newline to insert a semicolon, but ASI does not apply, or the programmer expects no inserted semicolons, but ASI is triggered by a newline):

(a) warn if two consecutive statement lines of equal indentation are not separated by explicit or inserted semicolon (b) warn if restricted production or error correction insert semicolon at a newline that is followed by extra indent

For warnings to be useful, it must be possible for coders to avoid them on a case-by-case basis, without disabling the warning entirely - this is here supported based on the idea of indentation (only used for controlling these warnings):

a can be silenced by having the next line indented further, to indicate continuation of statement on previous line b can be silenced by having the next line indented equally, to indicate start of new statement

The choice of indentation for warning control is intentional, as it will offer feedback on whether a significant whitespace approach to semicolon insertion would work for Javascript developers, without going all the way towards introducing such a change (although ASI already is whitespace-dependent, via newlines).

Warning (a) should be included in "ASI:warn-no-insert", warning (b) should be included in "ASI:warn-insert". It might be possible to include warnings for other pitfalls, if they can be identified and silenced unambiguously.

The warnings should be opt-in (by pragma), and on a side channel (like HTML/CSS parser errors), visible to developers and interested users, but not to viewers only interested in content. Group A will want to use "ASI:on", and get some help with missing semicolons, group B will want to use "ASI:off", and get some help with unwanted semicolons, group C might be helped by using both warnings.

Does this sound useful to all parties? Claus

// examples

function restricted_production() { "ASI:off"; return //; "hi"; // warn here, provided this line is indented }

function newline_no_asi() { "ASI:on"; var x = ["hi"] //; [1]; // warn here, unless this line is indented return x; }

function newline_error_asi() { "ASI:warn-insert"; var a = "hi"+ "ho"; var b = "hi" //; "ho"; // warn here, provided this line is indented return a==="hiho" && b==="hi"; }

log( restricted_production() || "newline in restricted production inserts semicolon" ); log( newline_no_asi() || "newline alone does not insert semicolon" ); log( newline_error_asi() && "newline followed by error inserts semicolon" )

/*

  • suggestions:
    • warn if inserted semicolon is followed by indented line
    • warn if non-indented line is not preceded by implicit or explicit semicolon */