[Bug]: babel crashes when destructuring, after using `for await` inside of async IIFE
See original GitHub issue💻
- Would you like to work on a fix?
How are you using Babel?
Other (Next.js, Gatsby, vue-cli, …)
Input code
Code that reproduces the crash (only happens when targeting older engines like IE 11
:
main();
async function main() {
let is_done = false;
const async_iterable = {
[Symbol.asyncIterator]: () => ({
next: () => {
const promise = Promise.resolve({ value: "luv u", done: is_done });
is_done = true;
return promise;
},
}),
};
(async () => { // IIFE: required for babel to crash
for await (const string of async_iterable) { // for await: required for babel to crash
console.log(string);
}
})();
const [one] = [1]; // array destructuring: required for babel to crash
}
Configuration file name
babel.config.js
Configuration
Not relevant IMO since it also crashes in REPL. Target has to be set to IE 11
.
Current and expected behavior
Current behavior: Property name expected type of string but got null
Expected behavior: Code that prints luv u
to the console when ran.
Environment
- Babel: 7.15.7 (@babel/core 7.15.5)
- Node v16.9.1
- Yarn 3.0.2
- OS: macOS 10.15.7 (19H1323)
Possible solution
Transpile the code correctly instead of crashing
Additional context
I wrote code which was the reproduction code but with many more steps. Wanted to push it to a customer as a quick fix before my next calendar event. Babel crashed. Suck. Deployed only for modern browsers. Bored, offline on a flight I removed code bit for bit for bit for bit until I came up with the reproduction snippet. This is a very weird bug.
Issue Analytics
- State:
- Created 2 years ago
- Comments:11 (6 by maintainers)
Top Results From Across the Web
@babel/plugin-bugfix-safari-id-destructuring-collision ... - Yarn
Fast, reliable, and secure dependency management.
Read more >Destructuring data from async function result or fallback value ...
It seems that you just want await f().catch(() => FALLBACK) . If f() rejects, then you'll substitute the FALLBACK object as the result....
Read more >API - ESBuild
This API call is used by the command-line interface if no input files are provided and the --bundle flag is not present. In...
Read more >Understanding JavaScript's async await - Ponyfoo
Given that await suspends your async function and the await Promise. all expression ultimately resolves into a results array, we can use ......
Read more >CoffeeScript
coffee script into a .js JavaScript file of the same name. -t, --transpile, Pipe the CoffeeScript compiler's output through Babel before saving ...
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 Free
Top 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
I think I have figured it out what’s going wrong here.
The
proposal-async-generator-functions
plugin initiates a sub-traversal from the Program node in order to run beforeasync-to-generators
. In this traversal context, it does not have access to visitors defined by other plugins. It visits the Function nodeasync function main() {}
and addasyncIterators
helper for the for-await statements.The
addHelper
utility does not respect the sub-traversal context, instead it uses the Program node’s context, which is the top level context with visitors defined by all plugins. WhenasyncIterators
helper is inserted beforeasync function main() {}
, the async function’s traversal context is changed to the Program’s context byunshiftContainer
.Now the net effect is: After the async function is visited by
traverse.node
,https://github.com/babel/babel/blob/89cab4311ce6dea0090d5819a721a1269765d6ec/packages/babel-traverse/src/path/context.ts#L88-L97
its context is changed to the Program’s context, in which the
regenerator-transform
registered aFunction:exit
listener to turn all variable declarations to var-statements. The listener is immediately invoked bythis.call("exit")
which eventually brings out the error since at this time, thetransform-destructring
is never run (expected), but neither shouldregenerator-transform
if onlyaddHelper
could respect the sub-traversal context.In my local tests, we have similar issue within
this.call("enter")
andtraverse.node
, too. The traversal context could be changed by the"enter"
listeners, too and they are in current test suites.A conservative fix will be to manually restore context after
this.call("enter")
andtraverse.node
, but it surely impacts performance because most listeners do not change traversal context: except callingunshiftContainer
/pushContainer
on ancestry path in a sub-traversal. And it may break some plugins if they intend to change the path context in the visitor.I will see if it can be fixed in
addHelper
utility, otherwise we may have to trade off performance for correctness here.It fails for me with
and
when running babel via
yarn babel index.js
on