module: allow multiple chain
This PR is based on and includes commits from #53200.
Description
This PR introduces the following changes:
- Introduction of the concept of "hooks chain" (see below)
- Addition of a
context
parameters to theinitialize
hook. The context contains the registering thread ID. - Addition of the registering thread ID, and
initialize
's data to thecontext
's properties passed to theresolve
andload
hooks.
How do "hooks chain" work?
Rather than maintaining a single chain of hooks for all threads as it is today, this PR introduces the concept of separate hooks chains.
Each thread has a separate chain registered inside the hooks thread. This chain is either copied from the parent thread when the thread is spawned or created from scratch if the thread is the first one calling module.register
within the application code.
This also covers the case where the process.execArgv
contains --import
or --experimental-loader
. Since the chain copied from the parent already contains the (already initialized) hooks the duplicate register detection will prevent the arguments to be processed again.
Thanks to threadId
and the initialize
's data this PR also covers the case where user want to use a singleton hook shared across threads. All these properties allow the hook to work differently depending on the context. Also, this will ensure that modification made to either parent or children after initialization don't affect other sibling threads.
The only case not covered at the moment from this PR is the one in which the user want a worker thread to start with an empty chain. This is already in theory achievable as we already have the methods to empty a chain, but these methods are not exposed externally. Once we expose those, this case will be covered as well, leaving no other open cases I'm aware of.