Destructuring doesn't work with await expression
See original GitHub issueJSC_CANNOT_CONVERT: This code cannot be converted from ES6. Undecomposable expression at line 3 character 18
const [first] = await Promise.all(['first', 'second']);
^
This doesn’t work (link):
async function run() {
const [first] = await Promise.all(['first', 'second']);
return first;
}
run().then(first => console.log(first));
This works (link):
async function run() {
const array = await Promise.all(['first', 'second']);
const [first] = array;
return first;
}
run().then(first => console.log(first));
Probably related: #2330
Issue Analytics
- State:
- Created 6 years ago
- Comments:7 (5 by maintainers)
Top Results From Across the Web
Does desctructuring assignment not work the same with async ...
As demonstrated in the live code snippet below, the answer is yes. Destructuring assignments work on the results of awaited function calls ...
Read more >Destructuring assignment - JavaScript - MDN Web Docs
The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from ...
Read more >ES2015 Destructuring & More - Medium
ES2015 Destructuring doesn't have to be scary, and in this post we'll go in-depth as to how it works, the various patterns you...
Read more >Tricks with JavaScript Destructuring - DigitalOcean
If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the...
Read more >Destructuring Assignment | Advanced JavaScript
We must be careful when destructuring arrays to make sure that we don't ... the desired default value in the left-hand side of...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Sorry it’s taken so long to address this - was sort of hoping somebody else would pick it up.
There are three transpilations happening here: async-await, destructuring, and then finally generators (in that order). After async-await and destructuring, we end up with:
In order to transpile this, the RHS needs to be decomposed - specifically, I believe the
$jscomp.makeIterator(...)
expression needs to be “moved” to a separate variable that can be called after the yield returns. According toExpressionDecomposer
1, the condition for this is as followsIt looks like the issue is maybe (2), though I’m a little shaky on the exact details here. The expression
$jscomp.makeIterator
can be affected by side-effects, and there’s no guarantee that there are no side effects while yielding. To further investigate, I simplified the expression quite a bit:This code still fails to transpile with the same error. (It’s worth nothing that
$jscomp.makeIterator
isn’t actually declared as@const
- not sure if this matters, or if the compiler can infer that it is effectively const; either way, I did it withx.makeIterator
and still got the error, so maybe it’s irrelevant). If I changemakeIterator
to a simple function, rather than a qualified name, then it works fine, presumably because it was the GETPROP that “can be affected by side effects”.I don’t understand why the compiler doesn’t recognize that this is never reassigned, and therefore is actually not affected. And I think we still have some significant issues with generator transpilation, since (as far as I can tell) other transpilers seem to be more permissive here - maybe this should be a suppressible warning, rather than an error? In any case, it seems like a quick fix would be to change how destructuring is rewritten, to save
$jscomp.makeIterator
into a temporary variable in a separate statement (or possible the root of the function) before calling it. That would at least fix this unfortunate interaction.In this particular case it is safe to ignore the warning. In general, you should pay attention to the warning if you are accessing a constructor or class off of an aliased namespace, or aliasing a constructor.
Here’s a snippet of the generated code that’s triggering the warning (source):
The compiler is warning you that
JSCompiler_temp_const = $jscomp;
may be unsafe.In this case, it’s actually safe. The only usage of
JSCompiler_temp_const
is to accessJSCompiler_temp_const.makeIterator
, and the compiler will not unsafely flatten$jscomp.makeIterator
because it is not an enum or constructor.Note: I might have missed a few edge cases since the property flattening logic is generally confusing. I filed https://github.com/google/closure-compiler/issues/3428 to avoid false positives like this one.