Description
TypeScript Version: Nightly
Search Terms: side effect ordering destructuring transform lowering spread rest binding pattern
Code
I recently implemented object rest properties for esbuild, a new TypeScript transpiler. When doing this I noticed several bugs with TypeScript's destructuring transform.
These bugs were identified by a fuzzer for JavaScript destructuring that I wrote while developing the transform code for esbuild. The fuzzer generates random test cases and compares the execution of the transpiled code with the execution of the original JavaScript. You can see example output from the fuzzer here.
This issue is for tracking bugs where expressions with side effects are accidentally reordered. There may be more than one individual bug in this class of bugs, and the fuzzer could be a good tool for finding them all.
Here's an example ordering issue:
let trace = []
let order = n => trace.push(n)
let [{ [order(1)]: x } = order(0)] = []
console.log(trace)
Expected behavior:
This should always print [0, 1]
. Default values must always be evaluated before computed property keys.
Actual behavior:
The TypeScript transpiler generates code that correctly prints [0, 1]
when targeting ES6 and above but generates code that incorrectly prints [1, 0]
when targeting ES5 and below.
Playground Link: link
Related Issues:
This ordering issue can also come up when targeting ES6, although the reproduction is a little more complicated:
let trace = []
let order = n => trace.push(n)
let { [order(0)]: { [order(2)]: y } = order(1), ...z } = {}
console.log(trace)
This prints [0, 1, 2]
when run natively and prints [0, 2, 1]
when transpiled with TypeScript targeting ES6.
Another ordering bug was mentioned in #39181:
var [{ ...a }, b = a] = [{ x: 1 }]
console.log(b.x === 1) // true
This should print true
but crashes with Uncaught TypeError: Cannot read property 'x' of undefined
when transpiled with TypeScript targeting ES6.
As I mentioned above, there may also be more ordering bugs like this depending on if these all have the same root cause or not. Hopefully the fuzzer will be a useful tool for getting to the bottom of these bugs.