diff --git a/doc/api/module.md b/doc/api/module.md index 58092ab1c62a02..4032f0ab89c1d4 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -179,6 +179,9 @@ added: - v20.6.0 - v18.19.0 changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/62518 + description: Runtime experimental warning added. This feature is pending removal. - version: - v23.6.1 - v22.13.1 @@ -193,7 +196,7 @@ changes: description: Add support for WHATWG URL instances. --> -> Stability: 1.1 - Active development +> Stability: 1.0 - Early development * `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/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index 04c374c00cfc3e..52ab0c99d4de0c 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,16 @@ function isCascadedLoaderInitialized() { * }); * ``` */ +const emitRegisterExperimentalWarning = getDeprecationWarningEmitter( + 'ExperimentalWarning', + '`module.register()` is an experimental feature and will be removed in a future version of Node.js. ' + + 'Use `module.registerHooks()` instead.', + undefined, + false, +); + function register(specifier, parentURL = undefined, options) { + emitRegisterExperimentalWarning(); if (parentURL != null && typeof parentURL === 'object' && !isURL(parentURL)) { options = parentURL; parentURL = options.parentURL; diff --git a/test/es-module/test-esm-register-experimental-warning.mjs b/test/es-module/test-esm-register-experimental-warning.mjs new file mode 100644 index 00000000000000..8f19cea8cb1256 --- /dev/null +++ b/test/es-module/test-esm-register-experimental-warning.mjs @@ -0,0 +1,50 @@ +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() experimental warning', { concurrency: !process.env.TEST_PARALLEL }, () => { + it('emits ExperimentalWarning when module.register() is called', async () => { + const { code, stderr } = await spawnPromisified(execPath, [ + '--input-type=module', + '--eval', + `import { register } from 'node:module'; register(${urlToRegisterEscaped});`, + ]); + + const expectedWarning = 'ExperimentalWarning: `module.register()` is an experimental feature and will be ' + + 'removed in a future version of Node.js. Use `module.registerHooks()` instead.'; + assert.ok(stderr.includes(expectedWarning)); + 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('module.register()').length - 1, 1); + assert.strictEqual(code, 0); + }); + + it('does not emit when --no-warnings is set', async () => { + const { code, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--input-type=module', + '--eval', + `import { register } from 'node:module'; register(${urlToRegisterEscaped});`, + ]); + + assert.doesNotMatch(stderr, /ExperimentalWarning/); + assert.strictEqual(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..80e638ad177980 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-warnings', '--no-experimental-require-module', '--import', fixtures.fileURL('es-module-loaders/builtin-named-exports.mjs'),