Description
Version
19.8.0
Platform
Microsoft Windows NT 10.0.19045.0 x64
Subsystem
esm
What steps will reproduce the bug?
Issue occurs when chaining 3 or more loaders
loader-a.mjs
export function resolve(id, parent, next) { console.log('loader-a', id); return next(id, parent); }
loader-b.mjs
export function resolve(id, parent, next) { console.log('loader-b', id); return next(id, parent); }
loader-c.mjs
export function resolve(id, parent, next) { console.log('loader-c', id); return next(id, parent); }
$ node --loader ./loader-a.mjs --loader ./loader-b.mjs --loader ./loader-c.mjs a.mjs
How often does it reproduce? Is there a required condition?
No response
What is the expected behavior? Why is that the expected behavior?
The above node
run would output
loader-a ./loader-b.mjs
loader-b ./loader-c.mjs
loader-a ./loader-c.mjs
loader-c <cwd>/a.mjs
loader-b <cwd>/a.mjs
loader-a <cwd>/a.mjs
In other words, each loader would be chained to resolve subsequent loaders as per #43772 and docs:
When hooks are used they apply to each subsequent loader [...]
What do you see instead?
loader-a ./loader-b.mjs
loader-b ./loader-c.mjs
loader-c <cwd>/a.mjs
loader-b <cwd>/a.mjs
loader-a <cwd>/a.mjs
Only the immediately preceding loader is used to load a loader
Additional information
This regression was introduced in #45869, first released in v19.8.0
The feature in question is implemented by added loaded loaders to the internal ESM loader by calling ESMLoader#addCustomLoaders
in a loop
node/lib/internal/process/esm_loader.js
Lines 46 to 58 in 4221dce
Before the regression, ESMLoader#addCustomLoaders
mutates this.#hooks
, thus multiple calls to it will add to the internal loader chain
node/lib/internal/modules/esm/loader.js
Lines 317 to 359 in 00a428e
In #45869, ESMLoader#addCustomLoaders
was changed to (re-)instantiating a Hooks
object, making multiple calls to it overwriting this.#hooks
node/lib/internal/modules/esm/loader.js
Lines 108 to 111 in 4221dce