Skip to content

Commit a29ddb3

Browse files
GeoffreyBoothtargos
authored andcommitted
esm: update loaders warning
PR-URL: nodejs#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 1a2443a commit a29ddb3

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 {
@@ -486,7 +493,7 @@ class CustomizedModuleLoader {
486493
}
487494
}
488495

489-
let emittedExperimentalWarning = false;
496+
let emittedLoaderFlagWarning = false;
490497
/**
491498
* A loader instance is used as the main entry point for loading ES modules. Currently, this is a singleton; there is
492499
* only one used for loading the main module and everything in its dependency graph, though separate instances of this
@@ -502,9 +509,24 @@ function createModuleLoader(useCustomLoadersIfPresent = true) {
502509
!require('internal/modules/esm/utils').isLoaderWorker()) {
503510
const userLoaderPaths = getOptionValue('--experimental-loader');
504511
if (userLoaderPaths.length > 0) {
505-
if (!emittedExperimentalWarning) {
506-
emitExperimentalWarning('Custom ESM Loaders');
507-
emittedExperimentalWarning = true;
512+
if (!emittedLoaderFlagWarning) {
513+
const readableURIEncode = (string) => ArrayPrototypeReduce(
514+
[
515+
[/'/g, '%27'], // We need to URL-encode the single quote as it's the delimiter for the --import flag.
516+
[/%22/g, '"'], // We can decode the double quotes to improve readability.
517+
[/%2F/ig, '/'], // We can decode the slashes to improve readability.
518+
],
519+
(str, { 0: regex, 1: replacement }) => RegExpPrototypeSymbolReplace(hardenRegExp(regex), str, replacement),
520+
encodeURIComponent(string));
521+
process.emitWarning(
522+
'`--experimental-loader` may be removed in the future; instead use `register()`:\n' +
523+
`--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; ${ArrayPrototypeJoin(
524+
ArrayPrototypeMap(userLoaderPaths, (loader) => `register(${readableURIEncode(JSONStringify(loader))}, pathToFileURL("./"))`),
525+
'; ',
526+
)};'`,
527+
'ExperimentalWarning',
528+
);
529+
emittedLoaderFlagWarning = true;
508530
}
509531
customizations = new CustomizedModuleLoader();
510532
}

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

+7-3
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,19 @@ 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
[/specifier resolution/, '--experimental-specifier-resolution=node'],
3135
]
3236
) {
3337
it(`should print for ${experiment.toString().replaceAll('/', '')}`, async () => {
3438
const { code, signal, stderr } = await spawnPromisified(execPath, [
35-
arg,
39+
...args,
3640
'--input-type=module',
3741
'--eval',
3842
`import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`,

0 commit comments

Comments
 (0)