From d153a031458b987a030d1e794e35df99fa7c45e9 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Sun, 22 Mar 2026 10:46:49 -0700 Subject: [PATCH 1/2] module: doc-deprecate module.register() (DEP0205) --- doc/api/deprecations.md | 16 ++++++++++++++++ doc/api/module.md | 7 ++++++- test/doctool/test-doc-api-json.mjs | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index baeabb78505c1b..2bebfcb3cb0d17 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -4517,6 +4517,20 @@ Type: Documentation-only Passing a non-extractable [`CryptoKey`][] to [`KeyObject.from()`][] is deprecated and will throw an error in a future version. +### DEP0205: `module.register()` + + + +Type: Documentation-only + +[`module.register()`][] is deprecated. Use [`module.registerHooks()`][] +instead. + [DEP0142]: #dep0142-repl_builtinlibs [NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf [RFC 6066]: https://tools.ietf.org/html/rfc6066#section-3 @@ -4621,6 +4635,8 @@ deprecated and will throw an error in a future version. [`message.trailersDistinct`]: http.md#messagetrailersdistinct [`message.trailers`]: http.md#messagetrailers [`module.createRequire()`]: module.md#modulecreaterequirefilename +[`module.register()`]: module.md#moduleregisterspecifier-parenturl-options +[`module.registerHooks()`]: module.md#moduleregisterhooksoptions [`os.networkInterfaces()`]: os.md#osnetworkinterfaces [`os.tmpdir()`]: os.md#ostmpdir [`process.env`]: process.md#processenv diff --git a/doc/api/module.md b/doc/api/module.md index 58092ab1c62a02..465749f28731c0 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -178,7 +178,12 @@ isBuiltin('wss'); // false added: - v20.6.0 - v18.19.0 +deprecated: REPLACEME changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/62395 + description: Documentation-only deprecation (DEP0205). Use + `module.registerHooks()` instead. - version: - v23.6.1 - v22.13.1 @@ -193,7 +198,7 @@ changes: description: Add support for WHATWG URL instances. --> -> Stability: 1.1 - Active development +> Stability: 0 - Deprecated: Use [`module.registerHooks()`][] instead. * `specifier` {string|URL} Customization hooks to be registered; this should be the same string that would be passed to `import()`, except that if it is diff --git a/test/doctool/test-doc-api-json.mjs b/test/doctool/test-doc-api-json.mjs index 91b3dea4fc47f3..66302d3605c24b 100644 --- a/test/doctool/test-doc-api-json.mjs +++ b/test/doctool/test-doc-api-json.mjs @@ -159,5 +159,5 @@ for await (const dirent of await fs.opendir(new URL('../../out/doc/api/', import assert.partialDeepStrictEqual(allExpectedKeys, findAllKeys(json)); } -assert.strictEqual(numberOfDeprecatedSections, 44); // Increase this number every time a new API is deprecated. +assert.strictEqual(numberOfDeprecatedSections, 45); // Increase this number every time a new API is deprecated. assert.strictEqual(numberOfRemovedAPIs, 46); // Increase this number every time a section is marked as removed. From 1a082545ba7da0bf32f68ed283d33a6210b31c63 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Sun, 22 Mar 2026 10:49:09 -0700 Subject: [PATCH 2/2] module: runtime-deprecate module.register() (DEP0205) --- doc/api/deprecations.md | 5 +- doc/api/module.md | 3 + lib/internal/modules/esm/loader.js | 13 +++- .../test-esm-register-deprecation.mjs | 60 +++++++++++++++++++ ...ync-loader-hooks-use-hooks-require-esm.mjs | 1 + 5 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 test/es-module/test-esm-register-deprecation.mjs diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 2bebfcb3cb0d17..78fe66716089f5 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -4521,12 +4521,15 @@ deprecated and will throw an error in a future version. -Type: Documentation-only +Type: Runtime [`module.register()`][] is deprecated. Use [`module.registerHooks()`][] instead. diff --git a/doc/api/module.md b/doc/api/module.md index 465749f28731c0..e0f1abad62d03e 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -180,6 +180,9 @@ added: - v18.19.0 deprecated: REPLACEME changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/62401 + description: Runtime deprecation (DEP0205). - version: REPLACEME pr-url: https://github.com/nodejs/node/pull/62395 description: Documentation-only deprecation (DEP0205). Use diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index 04c374c00cfc3e..4ff5af2b118456 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -31,7 +31,10 @@ const { } = require('internal/errors').codes; const { getOptionValue } = require('internal/options'); const { isURL, pathToFileURL } = require('internal/url'); -const { kEmptyObject } = require('internal/util'); +const { + getDeprecationWarningEmitter, + kEmptyObject, +} = require('internal/util'); const { compileSourceTextModule, SourceTextModuleTypes: { kUser }, @@ -955,7 +958,15 @@ function isCascadedLoaderInitialized() { * }); * ``` */ +const emitRegisterDeprecation = getDeprecationWarningEmitter( + 'DEP0205', + '`module.register()` is deprecated. Use `module.registerHooks()` instead.', + undefined, + false, +); + function register(specifier, parentURL = undefined, options) { + emitRegisterDeprecation(); if (parentURL != null && typeof parentURL === 'object' && !isURL(parentURL)) { options = parentURL; parentURL = options.parentURL; diff --git a/test/es-module/test-esm-register-deprecation.mjs b/test/es-module/test-esm-register-deprecation.mjs new file mode 100644 index 00000000000000..171e5971a091fe --- /dev/null +++ b/test/es-module/test-esm-register-deprecation.mjs @@ -0,0 +1,60 @@ +import { spawnPromisified } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; + +import assert from 'node:assert'; +import { execPath } from 'node:process'; +import { describe, it } from 'node:test'; + +const urlToRegister = fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'); +const urlToRegisterEscaped = JSON.stringify(urlToRegister.href); + + +describe('module.register() deprecation (DEP0205)', { concurrency: !process.env.TEST_PARALLEL }, () => { + it('emits DEP0205 when module.register() is called', async () => { + const { code, stderr } = await spawnPromisified(execPath, [ + '--input-type=module', + '--eval', + `import { register } from 'node:module'; register(${urlToRegisterEscaped});`, + ]); + + assert.match(stderr, /\[DEP0205\]/); + assert.strictEqual(code, 0); + }); + + it('only emits the warning once per process', async () => { + const { code, stderr } = await spawnPromisified(execPath, [ + '--input-type=module', + '--eval', + `import { register } from 'node:module'; + register(${urlToRegisterEscaped}); + register(${urlToRegisterEscaped});`, + ]); + + assert.strictEqual(stderr.split('[DEP0205]').length - 1, 1); + assert.strictEqual(code, 0); + }); + + it('does not emit when --no-deprecation is set', async () => { + const { code, stderr } = await spawnPromisified(execPath, [ + '--no-deprecation', + '--input-type=module', + '--eval', + `import { register } from 'node:module'; register(${urlToRegisterEscaped});`, + ]); + + assert.doesNotMatch(stderr, /DEP0205/); + assert.strictEqual(code, 0); + }); + + it('throws when --throw-deprecation is set', async () => { + const { code, stderr } = await spawnPromisified(execPath, [ + '--throw-deprecation', + '--input-type=module', + '--eval', + `import { register } from 'node:module'; register(${urlToRegisterEscaped});`, + ]); + + assert.match(stderr, /DEP0205/); + assert.notStrictEqual(code, 0); + }); +}); diff --git a/test/module-hooks/test-async-loader-hooks-use-hooks-require-esm.mjs b/test/module-hooks/test-async-loader-hooks-use-hooks-require-esm.mjs index a86b0607246fa9..1eee6a6014aa15 100644 --- a/test/module-hooks/test-async-loader-hooks-use-hooks-require-esm.mjs +++ b/test/module-hooks/test-async-loader-hooks-use-hooks-require-esm.mjs @@ -7,6 +7,7 @@ import { spawnSyncAndAssert } from '../common/child_process.js'; spawnSyncAndAssert( execPath, [ + '--no-deprecation', '--no-experimental-require-module', '--import', fixtures.fileURL('es-module-loaders/builtin-named-exports.mjs'),