So, given these three ES modules below, what output do you expect to get when you run node one.js
?
one.js:
import { two } from './two.js';
await two();
export function one() {
console.log('one');
}
two.js:
export async function two() {
console.log('two');
const { three } = await import('./three.js');
three();
}
three.js:
import { one } from './one.js';
export function three() {
console.log('three');
one();
}
Following through the calls, you’d expect to get:
two
three
one
But instead you get just the following output:
two
And node exits with exit code 13, which means “Unfinished Top-Level Await: await
was used outside of a function in the top-level code, but the passed Promise
never resolved.” There are no messages reported to the console, which is very disconcerting!
It turns out that the await import()
causes this, because of the circular dependency introduced in module three.js, back to one.js. Now, if there is no async involved, then this circular dependency just works; that is, instead of using import('./three.js')
you use import { three } from './three.js'
:
two
three
one
Not sure yet how to move forward with this. Tested in Node 20.9.0 and 18.14.1. Should I be raising it as a bug? It’s certainly not a documented behaviour that I’ve been able to find (node documentation, mdn documentation).