@@ -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 }
@@ -822,15 +816,6 @@ class ModuleLoader {
822816 }
823817 }
824818
825- importMetaInitialize ( meta , context ) {
826- if ( this . #asyncLoaderHooks) {
827- return this . #asyncLoaderHooks. importMetaInitialize ( meta , context , this ) ;
828- }
829- importMetaInitializer ??= require ( 'internal/modules/esm/initialize_import_meta' ) . initializeImportMeta ;
830- meta = importMetaInitializer ( meta , context , this ) ;
831- return meta ;
832- }
833-
834819 /**
835820 * Block until the async loader hooks have been initialized.
836821 *
@@ -884,8 +869,47 @@ function createModuleLoader(asyncLoaderHooks) {
884869 return new ModuleLoader ( asyncLoaderHooks ) ;
885870}
886871
887- let cascadedLoader ;
872+ let allowImportMetaResolveParentURL ;
873+ /**
874+ * This is only called from the native ImportMetaObjectInitialize function to set up import.meta.resolve
875+ * when import.meta.resolve is accessed for the first time in a module.
876+ * @param {ModuleLoader } loader The cascaded loader to use. Bound when this function gets passed to native land.
877+ * @param {string } moduleURL URL of the module accessing import.meta
878+ * @returns {function(string, URL['href']=): string } The import.meta.resolve function
879+ */
880+ function createImportMetaResolve ( loader , moduleURL ) {
881+ /**
882+ * @param {string } specifier The module specifier to resolve.
883+ * @param {URL['href'] } [parentURL] Optional parent URL to resolve against. Ignored unless
884+ * `--experimental-import-meta-resolve` is enabled.
885+ * @returns {string }
886+ */
887+ return function resolve ( specifier , parentURL ) {
888+ // The second argument is ignored unless --experimental-import-meta-resolve is enabled.
889+ // Even then, if it's not provided, parentURL defaults to the url of the module accessing
890+ // import.meta.resolve.
891+ allowImportMetaResolveParentURL ??= getOptionValue ( '--experimental-import-meta-resolve' ) ;
892+ parentURL = allowImportMetaResolveParentURL ? ( parentURL ?? moduleURL ) : moduleURL ;
893+
894+ let url ;
895+ try {
896+ ( { url } = loader . resolveSync ( parentURL , { specifier, __proto__ : null } ) ) ;
897+ return url ;
898+ } catch ( error ) {
899+ switch ( error ?. code ) {
900+ case 'ERR_UNSUPPORTED_DIR_IMPORT' :
901+ case 'ERR_MODULE_NOT_FOUND' :
902+ ( { url } = error ) ;
903+ if ( url ) {
904+ return url ;
905+ }
906+ }
907+ throw error ;
908+ }
909+ } ;
910+ }
888911
912+ let cascadedLoader ;
889913/**
890914 * This is a singleton ESM loader that integrates the loader hooks, if any.
891915 * It it used by other internal built-ins when they need to load user-land ESM code
@@ -899,7 +923,16 @@ let cascadedLoader;
899923 * @returns {ModuleLoader }
900924 */
901925function getOrInitializeCascadedLoader ( asyncLoaderHooks ) {
902- cascadedLoader ??= createModuleLoader ( asyncLoaderHooks ) ;
926+ if ( ! cascadedLoader ) {
927+ cascadedLoader = createModuleLoader ( asyncLoaderHooks ) ;
928+ // import.meta.resolve is not allowed in the async loader hook worker thread.
929+ // So only set up the import.meta.resolve initializer when we are initializing
930+ // the non-loader-hook-thread cascaded loader. When the native land doesn't see it,
931+ // it knows the loader is running on the loader hook thread.
932+ if ( ! ( asyncLoaderHooks ?. isForAsyncLoaderHookWorker ) ) {
933+ setImportMetaResolveInitializer ( createImportMetaResolve . bind ( null , cascadedLoader ) ) ;
934+ }
935+ }
903936 return cascadedLoader ;
904937}
905938
0 commit comments