Skip to content

Commit 47193a3

Browse files
aduh95targos
authored andcommitted
esm: fix support for URL instances in register
PR-URL: #49655 Backport-PR-URL: #50669 Reviewed-By: Geoffrey Booth <[email protected]> Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 51ced0f commit 47193a3

File tree

3 files changed

+46
-11
lines changed

3 files changed

+46
-11
lines changed

doc/api/module.md

+8-4
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,18 @@ isBuiltin('wss'); // false
8282
8383
<!-- YAML
8484
added: REPLACEME
85+
changes:
86+
- version: REPLACEME
87+
pr-url: https://github.com./nodejs/node/pull/49655
88+
description: Add support for WHATWG URL instances.
8589
-->
8690
8791
> Stability: 1.1 - Active development
8892
89-
* `specifier` {string} Customization hooks to be registered; this should be the
90-
same string that would be passed to `import()`, except that if it is relative,
91-
it is resolved relative to `parentURL`.
92-
* `parentURL` {string} If you want to resolve `specifier` relative to a base
93+
* `specifier` {string|URL} Customization hooks to be registered; this should be
94+
the same string that would be passed to `import()`, except that if it is
95+
relative, it is resolved relative to `parentURL`.
96+
* `parentURL` {string|URL} If you want to resolve `specifier` relative to a base
9397
URL, such as `import.meta.url`, you can pass that URL here. **Default:**
9498
`'data:'`
9599
* `options` {Object}

lib/internal/modules/esm/loader.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const {
1313
ERR_UNKNOWN_MODULE_FORMAT,
1414
} = require('internal/errors').codes;
1515
const { getOptionValue } = require('internal/options');
16-
const { pathToFileURL } = require('internal/url');
16+
const { pathToFileURL, isURL } = require('internal/url');
1717
const { emitExperimentalWarning } = require('internal/util');
1818
const {
1919
getDefaultConditions,
@@ -329,7 +329,7 @@ class ModuleLoader {
329329
// eslint-disable-next-line no-use-before-define
330330
this.setCustomizations(new CustomizedModuleLoader());
331331
}
332-
return this.#customizations.register(specifier, parentURL, data, transferList);
332+
return this.#customizations.register(`${specifier}`, `${parentURL}`, data, transferList);
333333
}
334334

335335
/**
@@ -529,11 +529,11 @@ function getHooksProxy() {
529529

530530
/**
531531
* Register a single loader programmatically.
532-
* @param {string} specifier
533-
* @param {string} [parentURL] Base to use when resolving `specifier`; optional if
532+
* @param {string|import('url').URL} specifier
533+
* @param {string|import('url').URL} [parentURL] Base to use when resolving `specifier`; optional if
534534
* `specifier` is absolute. Same as `options.parentUrl`, just inline
535535
* @param {object} [options] Additional options to apply, described below.
536-
* @param {string} [options.parentURL] Base to use when resolving `specifier`
536+
* @param {string|import('url').URL} [options.parentURL] Base to use when resolving `specifier`
537537
* @param {any} [options.data] Arbitrary data passed to the loader's `initialize` hook
538538
* @param {any[]} [options.transferList] Objects in `data` that are changing ownership
539539
* @returns {void} We want to reserve the return value for potential future extension of the API.
@@ -558,12 +558,12 @@ function getHooksProxy() {
558558
*/
559559
function register(specifier, parentURL = undefined, options) {
560560
const moduleLoader = require('internal/process/esm_loader').esmLoader;
561-
if (parentURL != null && typeof parentURL === 'object') {
561+
if (parentURL != null && typeof parentURL === 'object' && !isURL(parentURL)) {
562562
options = parentURL;
563563
parentURL = options.parentURL;
564564
}
565565
moduleLoader.register(
566-
`${specifier}`,
566+
specifier,
567567
parentURL ?? 'data:',
568568
options?.data,
569569
options?.transferList,

test/es-module/test-esm-loader-hooks.mjs

+31
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,37 @@ describe('Loader hooks', { concurrency: true }, () => {
455455
assert.strictEqual(signal, null);
456456
});
457457

458+
it('should have `register` accept URL objects as `parentURL`', async () => {
459+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
460+
'--no-warnings',
461+
'--import',
462+
`data:text/javascript,${encodeURIComponent(
463+
'import{ register } from "node:module";' +
464+
'import { pathToFileURL } from "node:url";' +
465+
'register("./hooks-initialize.mjs", pathToFileURL("./"));'
466+
)}`,
467+
'--input-type=module',
468+
'--eval',
469+
`
470+
import {register} from 'node:module';
471+
register(
472+
${JSON.stringify(fixtures.fileURL('es-module-loaders/loader-load-foo-or-42.mjs'))},
473+
new URL('data:'),
474+
);
475+
476+
import('node:os').then((result) => {
477+
console.log(JSON.stringify(result));
478+
});
479+
`,
480+
], { cwd: fixtures.fileURL('es-module-loaders/') });
481+
482+
assert.strictEqual(stderr, '');
483+
assert.deepStrictEqual(stdout.split('\n').sort(), ['hooks initialize 1', '{"default":"foo"}', ''].sort());
484+
485+
assert.strictEqual(code, 0);
486+
assert.strictEqual(signal, null);
487+
});
488+
458489
it('should have `register` work with cjs', async () => {
459490
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
460491
'--no-warnings',

0 commit comments

Comments
 (0)