Skip to content

Commit a6140f1

Browse files
GeoffreyBoothruyadorno
authored andcommitted
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 ff81bfb commit a6140f1

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 {
@@ -498,7 +505,7 @@ class CustomizedModuleLoader {
498505
}
499506
}
500507

501-
let emittedExperimentalWarning = false;
508+
let emittedLoaderFlagWarning = false;
502509
/**
503510
* A loader instance is used as the main entry point for loading ES modules. Currently, this is a singleton; there is
504511
* only one used for loading the main module and everything in its dependency graph, though separate instances of this
@@ -514,9 +521,24 @@ function createModuleLoader(useCustomLoadersIfPresent = true) {
514521
!require('internal/modules/esm/utils').isLoaderWorker()) {
515522
const userLoaderPaths = getOptionValue('--experimental-loader');
516523
if (userLoaderPaths.length > 0) {
517-
if (!emittedExperimentalWarning) {
518-
emitExperimentalWarning('Custom ESM Loaders');
519-
emittedExperimentalWarning = true;
524+
if (!emittedLoaderFlagWarning) {
525+
const readableURIEncode = (string) => ArrayPrototypeReduce(
526+
[
527+
[/'/g, '%27'], // We need to URL-encode the single quote as it's the delimiter for the --import flag.
528+
[/%22/g, '"'], // We can decode the double quotes to improve readability.
529+
[/%2F/ig, '/'], // We can decode the slashes to improve readability.
530+
],
531+
(str, { 0: regex, 1: replacement }) => RegExpPrototypeSymbolReplace(hardenRegExp(regex), str, replacement),
532+
encodeURIComponent(string));
533+
process.emitWarning(
534+
'`--experimental-loader` may be removed in the future; instead use `register()`:\n' +
535+
`--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; ${ArrayPrototypeJoin(
536+
ArrayPrototypeMap(userLoaderPaths, (loader) => `register(${readableURIEncode(JSONStringify(loader))}, pathToFileURL("./"))`),
537+
'; ',
538+
)};'`,
539+
'ExperimentalWarning',
540+
);
541+
emittedLoaderFlagWarning = true;
520542
}
521543
customizations = new CustomizedModuleLoader();
522544
}

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)