@@ -235,9 +235,14 @@ changes:
235235* ` options` {Object}
236236 * ` load` {Function|undefined} See [load hook][]. **Default:** ` undefined` .
237237 * ` resolve` {Function|undefined} See [resolve hook][]. **Default:** ` undefined` .
238+ * Returns: {Object} An object with the following property:
239+ * ` deregister()` {Function} Remove the registered hooks so that they are no
240+ longer called. Hooks are otherwise retained for the lifetime of the running
241+ process.
238242
239243Register [hooks][] that customize Node.js module resolution and loading behavior.
240- See [Customization hooks][].
244+ See [Customization hooks][]. The returned object can be used to
245+ [deregister the hooks][deregistration of synchronous customization hooks].
241246
242247### ` module.stripTypeScriptTypes(code[, options])`
243248
@@ -764,6 +769,63 @@ hook to signal that the chain is intentionally ending at your hook.
764769If a hook should be applied when loading other hook modules, the other hook
765770modules should be loaded after the hook is registered.
766771
772+ #### Deregistration of synchronous customization hooks
773+
774+ The object returned by ` registerHooks ()` has a ` deregister ()` method that can be
775+ used to remove the hooks from the chain. Once ` deregister ()` is called, the hooks
776+ will no longer be invoked during module resolution or loading.
777+
778+ This is currently only available for synchronous hooks registered via ` registerHooks ()` , not for asynchronous
779+ hooks registered via ` module .register ()` .
780+
781+ ` ` ` mjs
782+ import { registerHooks } from ' node:module' ;
783+
784+ const hooks = registerHooks ({
785+ resolve (specifier , context , nextResolve ) {
786+ console .log (' resolve hook called for' , specifier);
787+ return nextResolve (specifier, context);
788+ },
789+ load (url , context , nextLoad ) {
790+ return nextLoad (url, context);
791+ },
792+ });
793+
794+ // At this point, the hooks are active and will be called for
795+ // any subsequent import() or require() calls.
796+ await import (' ./my-module.mjs' );
797+
798+ // Later, remove the hooks from the chain.
799+ hooks .deregister ();
800+
801+ // Subsequent loads will no longer trigger the hooks.
802+ await import (' ./another-module.mjs' );
803+ ` ` `
804+
805+ ` ` ` cjs
806+ const { registerHooks } = require (' node:module' );
807+
808+ const hooks = registerHooks ({
809+ resolve (specifier , context , nextResolve ) {
810+ console .log (' resolve hook called for' , specifier);
811+ return nextResolve (specifier, context);
812+ },
813+ load (url , context , nextLoad ) {
814+ return nextLoad (url, context);
815+ },
816+ });
817+
818+ // At this point, the hooks are active and will be called for
819+ // any subsequent require() calls.
820+ require (' ./my-module.cjs' );
821+
822+ // Later, remove the hooks from the chain.
823+ hooks .deregister ();
824+
825+ // Subsequent loads will no longer trigger the hooks.
826+ require (' ./another-module.cjs' );
827+ ` ` `
828+
767829#### Hook functions accepted by ` module .registerHooks ()`
768830
769831<!-- YAML
@@ -1995,6 +2057,7 @@ returned object contains the following keys:
19952057[asynchronous ` resolve` hook]: #asynchronous-resolvespecifier-context-nextresolve
19962058[asynchronous hook functions]: #asynchronous-hooks-accepted-by-moduleregister
19972059[caveats of asynchronous customization hooks]: #caveats-of-asynchronous-customization-hooks
2060+ [deregistration of synchronous customization hooks]: #deregistration-of-synchronous-customization-hooks
19982061[hooks]: #customization-hooks
19992062[load hook]: #synchronous-loadurl-context-nextload
20002063[module compile cache]: #module-compile-cache
0 commit comments