@@ -51,6 +51,7 @@ const {
5151 kErrored,
5252 kSourcePhase,
5353 throwIfPromiseRejected,
54+ setImportMetaResolveInitializer,
5455} = internalBinding ( 'module_wrap' ) ;
5556const {
5657 urlToFilename,
@@ -62,7 +63,8 @@ const {
6263 loadWithHooks : loadWithSyncHooks ,
6364 validateLoadSloppy,
6465} = require ( 'internal/modules/customization_hooks' ) ;
65- let defaultResolve , defaultLoadSync , importMetaInitializer ;
66+
67+ let defaultResolve , defaultLoadSync ;
6668
6769const { tracingChannel } = require ( 'diagnostics_channel' ) ;
6870const onImport = tracingChannel ( 'module.import' ) ;
@@ -183,13 +185,6 @@ class ModuleLoader {
183185 */
184186 translators = getTranslators ( ) ;
185187
186- /**
187- * Truthy to allow the use of `import.meta.resolve`. This is needed
188- * currently because the `Hooks` class does not have `resolveSync`
189- * implemented and `import.meta.resolve` requires it.
190- */
191- allowImportMetaResolve ;
192-
193188 /**
194189 * @see {AsyncLoaderHooks.isForAsyncLoaderHookWorker}
195190 * Shortcut to this.#asyncLoaderHooks.isForAsyncLoaderHookWorker.
@@ -200,9 +195,10 @@ class ModuleLoader {
200195 * Asynchronous loader hooks to pass requests to.
201196 *
202197 * Note that this value _MUST_ be set with `#setAsyncLoaderHooks`
203- * because it needs to copy `#asyncLoaderHooks.allowImportMetaResolve`
204- * to this property and failure to do so will cause undefined
205- * behavior when invoking `import.meta.resolve`.
198+ * because it needs to copy `#asyncLoaderHooks.isForAsyncLoaderHookWorker`
199+ * to this property.
200+ * TODO(joyeecheung): this was a legacy of the previous setup of import.meta.resolve
201+ * configuration; put this information in the environment directly instead.
206202 *
207203 * When the ModuleLoader is created on a loader hook thread, this is
208204 * {@link AsyncLoaderHooksOnLoaderHookWorker}, and its methods directly call out
@@ -234,10 +230,8 @@ class ModuleLoader {
234230 #setAsyncLoaderHooks( asyncLoaderHooks ) {
235231 this . #asyncLoaderHooks = asyncLoaderHooks ;
236232 if ( asyncLoaderHooks ) {
237- this . allowImportMetaResolve = asyncLoaderHooks . allowImportMetaResolve ;
238233 this . isForAsyncLoaderHookWorker = asyncLoaderHooks . isForAsyncLoaderHookWorker ;
239234 } else {
240- this . allowImportMetaResolve = true ;
241235 this . isForAsyncLoaderHookWorker = false ;
242236 }
243237 }
@@ -821,15 +815,6 @@ class ModuleLoader {
821815 }
822816 }
823817
824- importMetaInitialize ( meta , context ) {
825- if ( this . #asyncLoaderHooks) {
826- return this . #asyncLoaderHooks. importMetaInitialize ( meta , context , this ) ;
827- }
828- importMetaInitializer ??= require ( 'internal/modules/esm/initialize_import_meta' ) . initializeImportMeta ;
829- meta = importMetaInitializer ( meta , context , this ) ;
830- return meta ;
831- }
832-
833818 /**
834819 * Block until the async loader hooks have been initialized.
835820 *
@@ -883,8 +868,47 @@ function createModuleLoader(asyncLoaderHooks) {
883868 return new ModuleLoader ( asyncLoaderHooks ) ;
884869}
885870
886- let cascadedLoader ;
871+ let allowImportMetaResolveParentURL ;
872+ /**
873+ * This is only called from the native ImportMetaObjectInitialize function to set up import.meta.resolve
874+ * when import.meta.resolve is accessed for the first time in a module.
875+ * @param {ModuleLoader } loader The cascaded loader to use. Bound when this function gets passed to native land.
876+ * @param {string } moduleURL URL of the module accessing import.meta
877+ * @returns {function(string, URL['href']=): string } The import.meta.resolve function
878+ */
879+ function createImportMetaResolve ( loader , moduleURL ) {
880+ /**
881+ * @param {string } specifier The module specifier to resolve.
882+ * @param {URL['href'] } [parentURL] Optional parent URL to resolve against. Ignored unless
883+ * `--experimental-import-meta-resolve` is enabled.
884+ * @returns {string }
885+ */
886+ return function resolve ( specifier , parentURL ) {
887+ // The second argument is ignored unless --experimental-import-meta-resolve is enabled.
888+ // Even then, if it's not provided, parentURL defaults to the url of the module accessing
889+ // import.meta.resolve.
890+ allowImportMetaResolveParentURL ??= getOptionValue ( '--experimental-import-meta-resolve' ) ;
891+ parentURL = allowImportMetaResolveParentURL ? ( parentURL ?? moduleURL ) : moduleURL ;
892+
893+ let url ;
894+ try {
895+ ( { url } = loader . resolveSync ( parentURL , { specifier, __proto__ : null } ) ) ;
896+ return url ;
897+ } catch ( error ) {
898+ switch ( error ?. code ) {
899+ case 'ERR_UNSUPPORTED_DIR_IMPORT' :
900+ case 'ERR_MODULE_NOT_FOUND' :
901+ ( { url } = error ) ;
902+ if ( url ) {
903+ return url ;
904+ }
905+ }
906+ throw error ;
907+ }
908+ } ;
909+ }
887910
911+ let cascadedLoader ;
888912/**
889913 * This is a singleton ESM loader that integrates the loader hooks, if any.
890914 * It it used by other internal built-ins when they need to load user-land ESM code
@@ -898,7 +922,16 @@ let cascadedLoader;
898922 * @returns {ModuleLoader }
899923 */
900924function getOrInitializeCascadedLoader ( asyncLoaderHooks ) {
901- cascadedLoader ??= createModuleLoader ( asyncLoaderHooks ) ;
925+ if ( ! cascadedLoader ) {
926+ cascadedLoader = createModuleLoader ( asyncLoaderHooks ) ;
927+ // import.meta.resolve is not allowed in the async loader hook worker thread.
928+ // So only set up the import.meta.resolve initializer when we are initializing
929+ // the non-loader-hook-thread cascaded loader. When the native land doesn't see it,
930+ // it knows the loader is running on the loader hook thread.
931+ if ( ! ( asyncLoaderHooks ?. isForAsyncLoaderHookWorker ) ) {
932+ setImportMetaResolveInitializer ( createImportMetaResolve . bind ( null , cascadedLoader ) ) ;
933+ }
934+ }
902935 return cascadedLoader ;
903936}
904937
0 commit comments