Execution order

I apologize for the obvious question, but the spec is a bit difficult for me to read and understand on this particular case. I am wondering in what order a hypothetical bit of code like this should execute:

const { [g()]: x } = f();

Should g or f be called first? Out in the wild, it seems that Chrome, Node, Edge, and Babel all agree that f should be called first, then g. TypeScript, on the other hand, (and thus ts-node) thinks that g should be called first, then f. My personal feeling is that I think it makes more sense to call g, then f, just based on how the program looks. So, who is right? What does the spec have to say about which order this code should execute in?

Given that this is destructuring, and that the pattern on the LHS isn't even necessary unless f() is non-nullish, I'd assume f would be called first, and then g.

As for the spec, it seems to me like https://tc39.es/ecma262/#sec-assignment-operators-runtime-semantics-evaluation step 3 evaluates the RHS first, and then step 5 evaluates the LHS - but I might be reading the wrong thing.

const { [g()]: x } = f();
is what the spec calls a LexicalDeclaration. Evaluation of these is specified in clause 13.3.1.4. For this code, it boils down to evaluating
{ [g()]: x } = f()
which in this context is an instance of the production

LexicalBinding : BindingPattern Initializer

which is handled in the last block of that clause. There, step 1 evaluates the Initializer, and step 4 performs BindingInitialization of the BindingPattern, in which the ComputedProperty [g()] would be evaluated. So f() should be evaluated before g().

1 Like