Skip to content

Commit f91b4e2

Browse files
esm: update loaders warning
PR-URL: #49633 Reviewed-By: Jacob Smith <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Guy Bedford <[email protected]>
1 parent 7517c9f commit f91b4e2

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

lib/internal/modules/esm/loader.js

+26-4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,16 @@
44
require('internal/modules/cjs/loader');
55

66
const {
7+
ArrayPrototypeJoin,
8+
ArrayPrototypeMap,
9+
ArrayPrototypeReduce,
710
FunctionPrototypeCall,
11+
JSONStringify,
812
ObjectSetPrototypeOf,
13+
RegExpPrototypeSymbolReplace,
914
SafeWeakMap,
15+
encodeURIComponent,
16+
hardenRegExp,
1017
} = primordials;
1118

1219
const {
@@ -511,7 +518,7 @@ class CustomizedModuleLoader {
511518
}
512519
}
513520

514-
let emittedExperimentalWarning = false;
521+
let emittedLoaderFlagWarning = false;
515522
/**
516523
* A loader instance is used as the main entry point for loading ES modules. Currently, this is a singleton; there is
517524
* only one used for loading the main module and everything in its dependency graph, though separate instances of this
@@ -527,9 +534,24 @@ function createModuleLoader(useCustomLoadersIfPresent = true) {
527534
!require('internal/modules/esm/utils').isLoaderWorker()) {
528535
const userLoaderPaths = getOptionValue('--experimental-loader');
529536
if (userLoaderPaths.length > 0) {
530-
if (!emittedExperimentalWarning) {
531-
emitExperimentalWarning('Custom ESM Loaders');
532-
emittedExperimentalWarning = true;
537+
if (!emittedLoaderFlagWarning) {
538+
const readableURIEncode = (string) => ArrayPrototypeReduce(
539+
[
540+
[/'/g, '%27'], // We need to URL-encode the single quote as it's the delimiter for the --import flag.
541+
[/%22/g, '"'], // We can decode the double quotes to improve readability.
542+
[/%2F/ig, '/'], // We can decode the slashes to improve readability.
543+
],
544+
(str, { 0: regex, 1: replacement }) => RegExpPrototypeSymbolReplace(hardenRegExp(regex), str, replacement),
545+
encodeURIComponent(string));
546+
process.emitWarning(
547+
'`--experimental-loader` may be removed in the future; instead use `register()`:\n' +
548+
`--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; ${ArrayPrototypeJoin(
549+
ArrayPrototypeMap(userLoaderPaths, (loader) => `register(${readableURIEncode(JSONStringify(loader))}, pathToFileURL("./"))`),
550+
'; ',
551+
)};'`,
552+
'ExperimentalWarning',
553+
);
554+
emittedLoaderFlagWarning = true;
533555
}
534556
customizations = new CustomizedModuleLoader();
535557
}

test/es-module/test-esm-experimental-warnings.mjs

+7-3
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,18 @@ describe('ESM: warn for obsolete hooks provided', { concurrency: true }, () => {
2424

2525
describe('experimental warnings for enabled experimental feature', () => {
2626
for (
27-
const [experiment, arg] of [
28-
[/Custom ESM Loaders/, `--experimental-loader=${fileURL('es-module-loaders', 'hooks-custom.mjs')}`],
27+
const [experiment, ...args] of [
28+
[
29+
/`--experimental-loader` may be removed in the future/,
30+
'--experimental-loader',
31+
fileURL('es-module-loaders', 'hooks-custom.mjs'),
32+
],
2933
[/Network Imports/, '--experimental-network-imports'],
3034
]
3135
) {
3236
it(`should print for ${experiment.toString().replaceAll('/', '')}`, async () => {
3337
const { code, signal, stderr } = await spawnPromisified(execPath, [
34-
arg,
38+
...args,
3539
'--input-type=module',
3640
'--eval',
3741
`import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`,

0 commit comments

Comments
 (0)