Description
Version
v21.6.1
Platform
Darwin mbpll.local 23.1.0 Darwin Kernel Version 23.1.0: Mon Oct 9 21:28:12 PDT 2023; root:xnu-10002.41.9~6/RELEASE_ARM64_T8103 arm64
Subsystem
module
What steps will reproduce the bug?
Chaining hooks via multiple register
calls: https://gist.github.com/yklcs/9b4182e365aead6bad32e637621fd6fb
How often does it reproduce? Is there a required condition?
No response
What is the expected behavior? Why is that the expected behavior?
Loader hooks should get executed in registration order (FIFO). This is the behavior consistent with documentation:
The chaining section for node:module
states:
In this example, the registered hooks will form chains. If both
first.mjs
andsecond.mjs
define aresolve
hook, both will be called, in the order they were registered. The same applies to all the other hooks.
The hooks section for node:module
states:
Hooks are part of a chain, even if that chain consists of only one custom (user-provided) hook and the default hook, which is always present. Hook functions nest: each one must always return a plain object, and chaining happens as a result of each function calling
next<hookName>()
, which is a reference to the subsequent loader's hook.
loader 1 initialize
loader 2 initialize
loader 3 initialize
loader 1 resolve
loader 2 resolve
loader 3 resolve
loader 1 load
loader 2 load
loader 3 load
What do you see instead?
Recursive calls to next<hookName>
are executed in LIFO order, with the first calls happening in FIFO order:
loader 1 initialize
loader 1 resolve
loader 1 load
loader 2 initialize
loader 2 resolve
loader 1 resolve
loader 2 load
loader 1 load
loader 3 initialize
loader 3 resolve
loader 2 resolve
loader 1 resolve
loader 3 load
loader 2 load
loader 1 load
This appears to be incorrect because:
1. The same hook is executed multiple times (n^2 behavior)
2. The dependency chain between hooks is broken. For example, if we tried to import by chaining https-loader
and typescript-loader
(as is the intended use case for chaining hooks), https-loader
must run before typescript-loader
. However, the current behavior gives us the following loading order:
https-loader load
typescript-loader load
https-loader load
Or, when chained in reverse:
typescript-loader load
https-loader load
typescript-loader load
Where neither version can function as intended.
Additional information
No response