@@ -17,14 +17,12 @@ const {
1717 RegExpPrototypeExec,
1818 SafeArrayIterator,
1919 SafeWeakMap,
20- StringPrototypeStartsWith,
2120 globalThis,
2221} = primordials ;
2322const { MessageChannel } = require ( 'internal/worker/io' ) ;
2423
2524const {
2625 ERR_LOADER_CHAIN_INCOMPLETE ,
27- ERR_INTERNAL_ASSERTION ,
2826 ERR_INVALID_ARG_TYPE ,
2927 ERR_INVALID_ARG_VALUE ,
3028 ERR_INVALID_RETURN_PROPERTY_VALUE ,
@@ -55,11 +53,6 @@ const { defaultLoad } = require('internal/modules/esm/load');
5553const { translators } = require (
5654 'internal/modules/esm/translators' ) ;
5755const { getOptionValue } = require ( 'internal/options' ) ;
58- const {
59- fetchModule,
60- inFetchCache,
61- } = require ( 'internal/modules/esm/fetch_module' ) ;
62-
6356
6457/**
6558 * @typedef {object } ExportedHooks
@@ -306,9 +299,7 @@ class ESMLoader {
306299 const module = new ModuleWrap ( url , undefined , source , 0 , 0 ) ;
307300 callbackMap . set ( module , {
308301 importModuleDynamically : ( specifier , { url } , importAssertions ) => {
309- return this . import ( specifier ,
310- this . getBaseURL ( url ) ,
311- importAssertions ) ;
302+ return this . import ( specifier , url , importAssertions ) ;
312303 }
313304 } ) ;
314305
@@ -324,55 +315,6 @@ class ESMLoader {
324315 } ;
325316 }
326317
327- /**
328- * Returns the url to use for the resolution of a given cache key url
329- * These are not guaranteed to be the same.
330- *
331- * In WHATWG HTTP spec for ESM the cache key is the non-I/O bound
332- * synchronous resolution using only string operations
333- * ~= resolveImportMap(new URL(specifier, importerHREF))
334- *
335- * The url used for subsequent resolution is the response URL after
336- * all redirects have been resolved.
337- *
338- * https://example.com/foo redirecting to https://example.com/bar
339- * would have a cache key of https://example.com/foo and baseURL
340- * of https://example.com/bar
341- *
342- * ! MUST BE SYNCHRONOUS for import.meta initialization
343- * ! MUST BE CALLED AFTER receiving the url body due to I/O
344- * @param {URL['href'] } url
345- * @returns {string|Promise<URL['href']> }
346- */
347- getBaseURL ( url ) {
348- if ( getOptionValue ( '--experimental-network-imports' ) && (
349- StringPrototypeStartsWith ( url , 'http:' ) ||
350- StringPrototypeStartsWith ( url , 'https:' )
351- ) ) {
352- // When using network-imports, the request & response have already settled
353- // so they are in fetchModule's cache, in which case, fetchModule returns
354- // immediately and synchronously
355- // Unless a custom loader bypassed the fetch cache, in which case we just
356- // use the original url
357- if ( inFetchCache ( url ) ) {
358- const module = fetchModule ( new URL ( url ) , { parentURL : url } ) ;
359- if ( typeof module ?. resolvedHREF === 'string' ) {
360- return module . resolvedHREF ;
361- }
362- // Internal error
363- throw new ERR_INTERNAL_ASSERTION (
364- `Base url for module ${ url } not loaded.`
365- ) ;
366- } else {
367- // A custom loader was used instead of network-imports.
368- // Adding support for a response URL resolve return in custom loaders is
369- // pending.
370- return url ;
371- }
372- }
373- return url ;
374- }
375-
376318 /**
377319 * Get a (possibly still pending) module job from the cache,
378320 * or create one and return its Promise.
@@ -431,6 +373,7 @@ class ESMLoader {
431373 const moduleProvider = async ( url , isMain ) => {
432374 const {
433375 format : finalFormat ,
376+ responseURL,
434377 source,
435378 } = await this . load ( url , {
436379 format,
@@ -440,10 +383,10 @@ class ESMLoader {
440383 const translator = translators . get ( finalFormat ) ;
441384
442385 if ( ! translator ) {
443- throw new ERR_UNKNOWN_MODULE_FORMAT ( finalFormat , url ) ;
386+ throw new ERR_UNKNOWN_MODULE_FORMAT ( finalFormat , responseURL ) ;
444387 }
445388
446- return FunctionPrototypeCall ( translator , this , url , source , isMain ) ;
389+ return FunctionPrototypeCall ( translator , this , responseURL , source , isMain ) ;
447390 } ;
448391
449392 const inspectBrk = (
@@ -523,7 +466,7 @@ class ESMLoader {
523466 * hooks starts at the top and each call to `nextLoad()` moves down 1 step
524467 * until it reaches the bottom or short-circuits.
525468 *
526- * @param {URL['href'] } url The URL/path of the module to be loaded
469+ * @param {string } url The URL/path of the module to be loaded
527470 * @param {object } context Metadata about the module
528471 * @returns {{ format: ModuleFormat, source: ModuleSource } }
529472 */
@@ -607,6 +550,36 @@ class ESMLoader {
607550 format,
608551 source,
609552 } = loaded ;
553+ let responseURL = loaded . responseURL ;
554+
555+ if ( responseURL === undefined ) {
556+ responseURL = url ;
557+ }
558+
559+ if ( typeof responseURL !== 'string' ) {
560+ throw new ERR_INVALID_RETURN_PROPERTY_VALUE (
561+ 'undefined or a string' ,
562+ hookErrIdentifier ,
563+ 'responseURL' ,
564+ responseURL ,
565+ ) ;
566+ }
567+
568+ let responseURLObj ;
569+ try {
570+ responseURLObj = new URL ( responseURL ) ;
571+ } catch {
572+ // Continue regardless of error.
573+ }
574+
575+ if ( responseURLObj . href !== responseURL ) {
576+ throw new ERR_INVALID_RETURN_PROPERTY_VALUE (
577+ 'a value URL string' ,
578+ hookErrIdentifier ,
579+ 'responseURL' ,
580+ responseURL ,
581+ ) ;
582+ }
610583
611584 if ( format == null ) {
612585 const dataUrl = RegExpPrototypeExec (
@@ -644,6 +617,7 @@ class ESMLoader {
644617
645618 return {
646619 format,
620+ responseURL,
647621 source,
648622 } ;
649623 }
0 commit comments