When returning an anonymous object from a function, a parse error results if the opening brace is not on the same line as the return statement; this is sensitivity to whitespace unecmascriptlike.
In the two functions below functionA() is fine, but functionB() results in "Uncaught SyntaxError: Unexpected token ':'"
It is written in the specification that a line terminator is not allowed after a return, but this strangely enforces a particular brace style for return statements that does not match what is allowed elsewhere, for example assignments.
// OK
functionA()
{
return {
propertyA: true,
propertyB: true
};
}
// Not OK
function functionB()
{
return
{
propertyA: true,
propertyB: true
};
}
// OK
var myobject =
{
propertyA: true,
propertyB: true
};
Putting brace-style religions aside ... if you look at the examples above, do you agree that it is inconsistent that a line terminator is allowed in the other scenarios, but not when returning an object-literal?
Yes, ASI is very inconsistent in terms of intuition, which is also why the recommended style is to use semicolons (and a linter that checks them for you). However, such things can’t ever be changed or they’d break websites.
Where in the examples above did I not use semicolons?
Can you give a concrete example where allowing a line-terminator between the return keyword and an object literal would not be backwards compatible?
Yes, I'm aware of OTBS/1TBS, it is just one style of many, hardly the 'one true' one. Regardless, ECMAscript does not require or enforce that one particular style. However, in this scenario, where a line-terminator is not accepted between a return and an opening brace of an object-literal, the language specification is (unusually) opinionated about style.
What I am raising for discussion, is this correctable inconsistency/opinionatedness in the language specification.
I am fairly certain that the grammar/specification could be updated to allow a line-terminator between the return keyword and an object literal while maintaining backwards compatibility with all existing programs. I am raising this question to the forum to understand if this is or is not the case.
All it would take is a program where that pattern appears, and code that expects the function to return undefined, and that program depends on that pattern. I expect it wouldn't take too long to find such code on github, let alone on npm, and I doubt browsers would have the risk appetite for such a change anyways.
The language almost never has breaking changes; virtually all changes are additive. Breaking changes are only possible if they're web compatible, and something as fundamental as this is almost certainly not.
Maybe not, but there are possibly programs that have an unreachable empty block after a return statement. While improbably it's valid syntax, and you can't change the meaning of valid syntax.
function functionB()
{
return
{
// unreachable block
};
}
I think this example is important too because it explains the SyntaxError in the original code. That error isn't so much about an object literal not being allowed after a return statement. Its that in that context, the brackets are being seen as a code block rather than an object literal. As a code block there's an error given the use of the comma operator between two labeled statements. Removing the comma would make the syntax valid (though the function would still return undefined).
// OK
function functionB()
{
return
{
propertyA: true
propertyB: true
};
}
Out of context there's no distinction between a literal with a single property and a code block with a single labeled statement.
// either an object literal or a block with a labeled statement
{
propertyA: true
}
Future proposals may be adding other hurdles for those who like to put the opening curly bracket on a new line. Pattern matching, for example, wishes to invent a new "match" syntax, but since "match" isn't a reserved keyword, they have to be a bit tricky about it. The current plans are as follows:
// Today this would be a syntax error.
// Because of this, they can add meaning to this syntax without
// breaking old code. A.k.a. this is what pattern-matching will likely look like.
match (val) {
...
}
// This is valid syntax today (we're calling a "match" function, then we have a block of code).
// Because of this, pattern-matching can't use this syntax space.
// This will always need to mean the same thing.
match (val)
{
...
}
In other words, as currently planned, for pattern-matching to work you must put the opening curly bracket on the same line as the "match". In general, if they ever want to invent a new control structure-like thing, and want to use a keyword for it that isn't currently reserved, this is how they'd have to do it - either that or do some ugly stuff with the new syntax.
Ideally, it wouldn't be this way and everyone could choose to place the curly brackets wherever they want, but that's just not the reality.