GeezerVison is showing github.com — esm: fix support for `URL` instances in `register` · nodejs/node@47193a3
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/module.md +8-4Lines changed: 8 additions & 4 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -82,14 +82,18 @@ isBuiltin('wss'); // false | 82 | 82 |
| 83 | 83 | <!-- YAML | 84 | 84 | 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. | 85 | 89 | --> | 86 | 90 |
| 87 | 91 | > Stability: 1.1 - Active development | 88 | 92 |
| 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 | 93 | 97 | URL, such as `import.meta.url`, you can pass that URL here. **Default:** | 94 | 98 | `'data:'` | 95 | 99 | * `options` {Object} | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/loader.js +7-7Lines changed: 7 additions & 7 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -13,7 +13,7 @@ const { | 13 | 13 | ERR_UNKNOWN_MODULE_FORMAT, | 14 | 14 | } = require('internal/errors').codes; | 15 | 15 | const { getOptionValue } = require('internal/options'); | 16 | | -const { pathToFileURL } = require('internal/url'); | | 16 | +const { pathToFileURL, isURL } = require('internal/url'); | 17 | 17 | const { emitExperimentalWarning } = require('internal/util'); | 18 | 18 | const { | 19 | 19 | getDefaultConditions, | @@ -329,7 +329,7 @@ class ModuleLoader { | 329 | 329 | // eslint-disable-next-line no-use-before-define | 330 | 330 | this.setCustomizations(new CustomizedModuleLoader()); | 331 | 331 | } | 332 | | - return this.#customizations.register(specifier, parentURL, data, transferList); | | 332 | + return this.#customizations.register(`${specifier}`, `${parentURL}`, data, transferList); | 333 | 333 | } | 334 | 334 |
| 335 | 335 | /** | @@ -529,11 +529,11 @@ function getHooksProxy() { | 529 | 529 |
| 530 | 530 | /** | 531 | 531 | * 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 | 534 | 534 | * `specifier` is absolute. Same as `options.parentUrl`, just inline | 535 | 535 | * @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` | 537 | 537 | * @param {any} [options.data] Arbitrary data passed to the loader's `initialize` hook | 538 | 538 | * @param {any[]} [options.transferList] Objects in `data` that are changing ownership | 539 | 539 | * @returns {void} We want to reserve the return value for potential future extension of the API. | @@ -558,12 +558,12 @@ function getHooksProxy() { | 558 | 558 | */ | 559 | 559 | function register(specifier, parentURL = undefined, options) { | 560 | 560 | const moduleLoader = require('internal/process/esm_loader').esmLoader; | 561 | | - if (parentURL != null && typeof parentURL === 'object') { | | 561 | + if (parentURL != null && typeof parentURL === 'object' && !isURL(parentURL)) { | 562 | 562 | options = parentURL; | 563 | 563 | parentURL = options.parentURL; | 564 | 564 | } | 565 | 565 | moduleLoader.register( | 566 | | - `${specifier}`, | | 566 | + specifier, | 567 | 567 | parentURL ?? 'data:', | 568 | 568 | options?.data, | 569 | 569 | options?.transferList, | |
Collapse file Copy file name to clipboardExpand all lines: test/es-module/test-esm-loader-hooks.mjs +31Lines changed: 31 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -455,6 +455,37 @@ describe('Loader hooks', { concurrency: true }, () => { | 455 | 455 | assert.strictEqual(signal, null); | 456 | 456 | }); | 457 | 457 |
| | 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 | + | 458 | 489 | it('should have `register` work with cjs', async () => { | 459 | 490 | const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ | 460 | 491 | '--no-warnings', | |
|