From 14a929b0b08eaea7bb78cf6aa9cbb883c016f3fe Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Mon, 28 Mar 2022 23:43:15 +0200 Subject: [PATCH] esm: emit experimental warnings in common place PR-URL: https://github.com/nodejs/node/pull/42314 Reviewed-By: Antoine du Hamel Reviewed-By: Geoffrey Booth --- lib/internal/modules/esm/loader.js | 24 ++++++++++++++ lib/internal/modules/esm/resolve.js | 8 ----- lib/internal/process/esm_loader.js | 3 -- .../test-esm-experimental-warnings.mjs | 32 +++++++++++++++++++ ...est-esm-specifiers-legacy-flag-warning.mjs | 24 -------------- 5 files changed, 56 insertions(+), 35 deletions(-) create mode 100644 test/es-module/test-esm-experimental-warnings.mjs delete mode 100644 test/es-module/test-esm-specifiers-legacy-flag-warning.mjs diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index 16b832527f7c64..0dccfebbd4f37f 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -31,6 +31,7 @@ const { ERR_UNKNOWN_MODULE_FORMAT } = require('internal/errors').codes; const { pathToFileURL, isURLInstance, URL } = require('internal/url'); +const { emitExperimentalWarning } = require('internal/util'); const { isAnyArrayBuffer, isArrayBufferView, @@ -53,6 +54,13 @@ const { fetchModule, } = require('internal/modules/esm/fetch_module'); + +/** + * Prevent the specifier resolution warning from being printed twice + */ +let emittedSpecifierResolutionWarning = false; + + /** * An ESMLoader instance is used as the main entry point for loading ES modules. * Currently, this is a singleton -- there is only one used for loading @@ -107,6 +115,22 @@ class ESMLoader { */ translators = translators; + constructor() { + if (getOptionValue('--experimental-loader')) { + emitExperimentalWarning('Custom ESM Loaders'); + } + if (getOptionValue('--experimental-network-imports')) { + emitExperimentalWarning('Network Imports'); + } + if (getOptionValue('--experimental-specifier-resolution') === 'node' && !emittedSpecifierResolutionWarning) { + process.emitWarning( + 'The Node.js specifier resolution flag is experimental. It could change or be removed at any time.', + 'ExperimentalWarning' + ); + emittedSpecifierResolutionWarning = true; + } + } + static pluckHooks({ globalPreload, resolve, diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js index 3576f75f0a40a6..ad720fc2bbc123 100644 --- a/lib/internal/modules/esm/resolve.js +++ b/lib/internal/modules/esm/resolve.js @@ -387,7 +387,6 @@ function resolveDirectoryEntry(search) { } const encodedSepRegEx = /%2F|%5C/i; -let experimentalSpecifierResolutionWarned = false; /** * @param {URL} resolved * @param {string | URL | undefined} base @@ -402,13 +401,6 @@ function finalizeResolution(resolved, base, preserveSymlinks) { let path = fileURLToPath(resolved); if (getOptionValue('--experimental-specifier-resolution') === 'node') { - if (!experimentalSpecifierResolutionWarned) { - process.emitWarning( - 'The Node.js specifier resolution flag is experimental. It could change or be removed at any time.', - 'ExperimentalWarning'); - experimentalSpecifierResolutionWarned = true; - } - let file = resolveExtensionsWithTryExactName(resolved); // Directory diff --git a/lib/internal/process/esm_loader.js b/lib/internal/process/esm_loader.js index 73385a85b4e106..20021134ce40f3 100644 --- a/lib/internal/process/esm_loader.js +++ b/lib/internal/process/esm_loader.js @@ -55,9 +55,6 @@ async function initializeLoader() { if (!customLoaders.length) return; - const { emitExperimentalWarning } = require('internal/util'); - emitExperimentalWarning('--experimental-loader'); - let cwd; try { cwd = process.cwd() + '/'; diff --git a/test/es-module/test-esm-experimental-warnings.mjs b/test/es-module/test-esm-experimental-warnings.mjs new file mode 100644 index 00000000000000..bf92b158e485eb --- /dev/null +++ b/test/es-module/test-esm-experimental-warnings.mjs @@ -0,0 +1,32 @@ +import { mustCall } from '../common/index.mjs'; +import { fileURL } from '../common/fixtures.mjs'; +import { match, strictEqual } from 'assert'; +import { spawn } from 'child_process'; +import { execPath } from 'process'; + +// Verify experimental warnings are printed +for ( + const [experiment, arg] of [ + [/Custom ESM Loaders/, `--experimental-loader=${fileURL('es-module-loaders', 'hooks-custom.mjs')}`], + [/Network Imports/, '--experimental-network-imports'], + [/specifier resolution/, '--experimental-specifier-resolution=node'], + ] +) { + const input = `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`; + const child = spawn(execPath, [ + arg, + '--input-type=module', + '--eval', + input, + ]); + + let stderr = ''; + child.stderr.setEncoding('utf8'); + child.stderr.on('data', (data) => { stderr += data; }); + child.on('close', mustCall((code, signal) => { + strictEqual(code, 0); + strictEqual(signal, null); + match(stderr, /ExperimentalWarning/); + match(stderr, experiment); + })); +} diff --git a/test/es-module/test-esm-specifiers-legacy-flag-warning.mjs b/test/es-module/test-esm-specifiers-legacy-flag-warning.mjs deleted file mode 100644 index 244499a3e02093..00000000000000 --- a/test/es-module/test-esm-specifiers-legacy-flag-warning.mjs +++ /dev/null @@ -1,24 +0,0 @@ -import { mustCall } from '../common/index.mjs'; -import { fileURL } from '../common/fixtures.mjs'; -import { match, strictEqual } from 'assert'; -import { spawn } from 'child_process'; -import { execPath } from 'process'; - -// Verify experimental warning is printed -const child = spawn(execPath, [ - '--experimental-specifier-resolution=node', - '--input-type=module', - '--eval', - `import ${JSON.stringify(fileURL('es-module-specifiers', 'package-type-module'))}`, -]); - -let stderr = ''; -child.stderr.setEncoding('utf8'); -child.stderr.on('data', (data) => { - stderr += data; -}); -child.on('close', mustCall((code, signal) => { - strictEqual(code, 0); - strictEqual(signal, null); - match(stderr, /ExperimentalWarning: The Node\.js specifier resolution flag is experimental/); -}));