-4

Today while I was coding realized destructuring assignment will not work correctly when write immediately after close brace of object defining without semicolon. May you re-create this bug from your end and report if you see the same results.
My node version is 12.16.2
Also I report this bug on Github for V8 engine and Nodejs

https://github.com/v8/v8.dev/issues/482#issue-711046361

https://github.com/nodejs/nodejs.org/issues/3411#issue-711047377

Close brace of object defining without semicolon

let a,b,c
a={x:1} //<~~~without semicolon
[b, c] = [1, 2]
console.log(b)
console.log(c)

above code will return

undefined
undefined

Close brace of object defining with semicolon

let a,b,c
a={x:1}; //<~~~with semicolon
[b, c] = [1, 2]
console.log(b)
console.log(c)

above code will return

1
2

Close brace of if statement

let a,b,c
if(1===1){
  a = 1
} //<~~~without semicolon
[b, c] = [1, 2]
console.log(b)
console.log(c)

above code will return

1
2

2 Answers2

0

First off, the correct place to report a V8 bug is crbug.com/v8/new. StackOverflow is not the right venue for bug reports.

Secondly, this is not a bug; it is JavaScript's "Automatic Semicolon Insertion" working as specified. You can read the specification here. What it boils down to is that a = {x:1}[b, c] = [1, 2] is valid JavaScript (nonsensical maybe, but valid syntax), so no semicolon is inserted automatically.

The best way to avoid falling into this and similar traps is to always write explicit semicolons. Or you can prefer the visual cleanliness of semicolon-free code, but then you'll have to familiarize yourself with the rules of ASI, and know in which cases semicolons are required.

EDIT: Since you asked below what a = {x:1}[b, c] = [1, 2] does, here's an explanation:

Firstly, you can chain assignments, like x = y = z = 0;, so one effect of this expression is that the variable a will point at the array [1, 2] afterwards. Looking at the middle term {x:1}[b, c], the first half of that is, of course, an object literal. The second half is an index expression to access a property of this object. As a simplified version, consider: {x:1}["x"] would return 1. (Note: if you evaluate this in e.g. the console, you'll have to wrap the object literal into (), i.e. ({x:1})["x"], because the {} will otherwise be interpreted as a block instead of a literal. One of the many traps of JavaScript...) Now the specific index expression here is b, c, which is a comma-separated sequence of expressions, similar to how you could write for (x = 0, y = 0; ...; ...) {...}. So the b part is evaluated for side effects; since it's just a reference to a variable, that doesn't do anything, but you could e.g. write console.log(b) there and then it would do something. c is then the overall result value of the sequence; in your example it's an uninitialized variable so its value is undefined, which in the context of an index expression is converted to the string "undefined".

Putting it all together, here's what happens, in order:

  1. [1, 2] is evaluated and creates a two-element array. Let's call this array A, just for descriptive purposes.
  2. {x:1} is evaluated and creates an object with an x property. Let's call this object O, again just for descriptive purposes.
  3. b is evaluated (to undefined), and the result of the evaluation is discarded.
  4. c is evaluated (to undefined), converted to the string "undefined", and used to store A as a property on O, as in O["undefined"] = A, or as if you had written {x:1, undefined:[1, 2]}.
  5. Since nothing refers to O, it becomes unreachable and eligible for garbage collection. You can't see that step (4) happened to it.
  6. A will be assigned to a.

In summary, a = {x:1}[b, c] = [1, 2] is certainly a weird line of code to write, but it would be a bug if a JavaScript engine decided for you "I'm sure you meant something else, let me give you the behavior that I think you wanted". As long as you write valid JavaScript, the engine has to evaluate it exactly by the rules of the JavaScript language.

jmrk
  • 34,271
  • 7
  • 59
  • 74
  • Oh, turns out the actual order is a bit different: `[b, c]` is evaluated before `[1, 2]`. Doesn't change anything in this example though, and arguably the order I used above is a little simple to follow for understanding what's happening. – jmrk Sep 29 '20 at 19:18
  • Your description about **how the expression `a = {x:1}[b, c] = [1, 2]` will compile** is correct and I'm agree with you on it, but you completely missing the main question. first, note that my example expression was written in two separate lines, if you check [link](https://tc39.es/ecma262/#sec-automatic-semicolon-insertion), one of main rules is **The offending token is separated from the previous token by at least one LineTerminator** then we expect that Javascript interpreter convert two line expression into `a = {x:1};[b, c] = [1, 2]` instead of mixed them into one expression in one line. – Siroos Sheikhi Sep 29 '20 at 21:21
  • It seems JavaScript interpreter ASI will miss inserting semicolon after `a = {x:1}` expression because it immediately followed by an open bracket in the next line and the open brackets interpreted as an index for the object literal on the previous line, Anyhow this is incorrect behavior. in my opinion this is not important that the problem is because of V8 implementation or JavaScript rules because its doesn't matter how interpreter works or compiler compile the code from view of developer. developer need to write and run the code correctly in semicolon-free JavaScript programming language. – Siroos Sheikhi Sep 29 '20 at 21:43
  • 1
    Note the beginning of the sentence in the spec: **When, as the source text is parsed from left to right, a token is encountered that is not allowed by any production of the grammar, ...**. In other words: a semicolon is only inserted if without the semicolon, there would be a syntax error. What you quoted is an additional restriction: semicolons can only be automatically inserted at the end of a line (never in the middle of a line). – jmrk Sep 29 '20 at 22:46
-2

Yes I know this is ASI behavior of Javascript interpreter but it is not acceptable and from my view this is a bug that should be fix.
This is not logical and also absolutely unacceptable that a programming language offer semicolon-free syntax and leave programmers with unwanted and incorrect behaviors and traps.
We programmers have learned that every programming expressions is a "syntactic entity with an absolute unique result" not a trap.
We develop software, not playing Jumanji game that programming languages decide to place traps for us.
Yes below syntax is valid and please as a programmer carefully read below code:

a = {x:1}[b, c] = [1, 2]

What do you expect from running this code? I expect Javascript set "{x:1}" into "a" variable and "1", "2" into "b" and "c" variables.
At the end I can not understand why should interpreter makes this mistake?

a = {x:1}

In this line interpreter see the object which has been started with open brace and finished with close brace correctly, then ASI can insert semicolon after close brace and don't mix it up with the next expression

[b, c] = [1, 2]

If I'm wrong please correct me.

  • 1
    There are many things that are weird about JavaScript, but an engine implementing the language by the rules of the language's specification is not a bug, on the contrary: if V8 did anything different, then *that* would be a bug. – jmrk Sep 29 '20 at 18:49
  • I've amended my answer with a detailed explanation of what `a = {x:1}[b, c] = [1, 2]` does and why. – jmrk Sep 29 '20 at 19:11