diff --git a/doc/api/module.md b/doc/api/module.md index dc03b50961e680..956b10942ba36e 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -245,6 +245,7 @@ changes: * `deregister()` {Function} Remove the registered hooks so that they are no longer called. Hooks are otherwise retained for the lifetime of the running process. + * `[Symbol.dispose]` {Function} The same as `deregister`. Register [hooks][] that customize Node.js module resolution and loading behavior. See [Customization hooks][]. The returned object can be used to diff --git a/lib/internal/modules/customization_hooks.js b/lib/internal/modules/customization_hooks.js index c2579269ec6396..c3d1970243fd33 100644 --- a/lib/internal/modules/customization_hooks.js +++ b/lib/internal/modules/customization_hooks.js @@ -9,6 +9,7 @@ const { StringPrototypeSlice, StringPrototypeStartsWith, Symbol, + SymbolDispose, } = primordials; const { isAnyArrayBuffer, @@ -83,10 +84,7 @@ class ModuleHooks { ObjectFreeze(this); } - // TODO(joyeecheung): we may want methods that allow disabling/enabling temporarily - // which just sets the item in the array to undefined temporarily. - // TODO(joyeecheung): this can be the [Symbol.dispose] implementation to pair with - // `using` when the explicit resource management proposal is shipped by V8. + /** * Deregister the hook instance. */ @@ -103,6 +101,8 @@ class ModuleHooks { } }; +ModuleHooks.prototype[SymbolDispose] = ModuleHooks.prototype.deregister; + /** * TODO(joyeecheung): taken an optional description? * @param {{ resolve?: ResolveHook, load?: LoadHook }} hooks User-provided hooks diff --git a/test/module-hooks/test-module-hooks-dispose.js b/test/module-hooks/test-module-hooks-dispose.js new file mode 100644 index 00000000000000..2a796d70a50fc2 --- /dev/null +++ b/test/module-hooks/test-module-hooks-dispose.js @@ -0,0 +1,26 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { registerHooks } = require('module'); + +// Test that using syntax works. +{ + // eslint-disable-next-line no-unused-vars + using hook = registerHooks({ + load: common.mustCall((url, context, nextLoad) => { + const result = nextLoad(url, context); + assert.strictEqual(result.source, ''); + return { + source: 'export const hello = "world"', + }; + }), + }); + + const mod = require('../fixtures/empty.js'); + assert.strictEqual(mod.hello, 'world'); +} + +delete require.cache[require.resolve('../fixtures/empty.js')]; +const mod = require('../fixtures/empty.js'); +assert.deepStrictEqual(mod, {});