@@ -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 = (
@@ -607,6 +550,29 @@ class ESMLoader {
607550 format,
608551 source,
609552 } = loaded ;
553+ let responseURL = loaded . responseURL ;
554+
555+ if ( responseURL === undefined ) {
556+ responseURL = url ;
557+ }
558+
559+ let responseURLObj ;
560+ if ( typeof responseURL === 'string' ) {
561+ try {
562+ responseURLObj = new URL ( responseURL ) ;
563+ } catch {
564+ // responseURLObj not defined will throw in next branch.
565+ }
566+ }
567+
568+ if ( responseURLObj ?. href !== responseURL ) {
569+ throw new ERR_INVALID_RETURN_PROPERTY_VALUE (
570+ 'undefined or a fully resolved URL string' ,
571+ hookErrIdentifier ,
572+ 'responseURL' ,
573+ responseURL ,
574+ ) ;
575+ }
610576
611577 if ( format == null ) {
612578 const dataUrl = RegExpPrototypeExec (
@@ -644,6 +610,7 @@ class ESMLoader {
644610
645611 return {
646612 format,
613+ responseURL,
647614 source,
648615 } ;
649616 }
0 commit comments