Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e9b68e6

Browse filesBrowse files
joyeecheungaduh95
authored andcommitted
src: move import.meta initializer to native land
When the source text module is compiled without custom callbacks, instead of calling into JS land from the per-isolate import.meta initializer and then back to C++ land to set up lazy data properties, just do the initialization all in C++ land. Only import.meta.resolve initialization will call back into JS land to generate a closure that call the cascaded loader for resolution. In addition, simplify the loader structure by merging allowImportMetaResolve into isForAsyncLoaderHookWorker - the two are essentially equivalent, as import.meta.resolve is only allowed in a non-loader-hook worker thread's loader. PR-URL: #60603 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
1 parent d64795b commit e9b68e6
Copy full SHA for e9b68e6

File tree

Expand file treeCollapse file tree

9 files changed

+242
-219
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

9 files changed

+242
-219
lines changed
Open diff view settings
Collapse file

‎lib/internal/modules/esm/hooks.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/hooks.js
-22Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ const {
5858
let debug = require('internal/util/debuglog').debuglog('async_loader_worker', (fn) => {
5959
debug = fn;
6060
});
61-
let importMetaInitializer;
6261

6362
let importAssertionAlreadyWarned = false;
6463

@@ -111,7 +110,6 @@ function defineImportAssertionAlias(context) {
111110
* Interface for classes that implement asynchronous loader hooks that can be attached to the ModuleLoader
112111
* via `ModuleLoader.#setAsyncLoaderHooks()`.
113112
* @typedef {object} AsyncLoaderHooks
114-
* @property {boolean} allowImportMetaResolve Whether to allow the use of `import.meta.resolve`.
115113
* @property {boolean} isForAsyncLoaderHookWorker Whether the instance is running on the loader hook worker thread.
116114
* @property {(url: string, context: object, defaultLoad: Function) => Promise<LoadResult>} load
117115
* Calling the asynchronous `load` hook asynchronously.
@@ -163,8 +161,6 @@ class AsyncLoaderHooksOnLoaderHookWorker {
163161
// Cache URLs we've already validated to avoid repeated validation
164162
#validatedUrls = new SafeSet();
165163

166-
allowImportMetaResolve = false;
167-
168164
isForAsyncLoaderHookWorker = true;
169165

170166
/**
@@ -480,12 +476,6 @@ class AsyncLoaderHooksOnLoaderHookWorker {
480476
waitForLoaderHookInitialization() {
481477
// No-op
482478
}
483-
484-
importMetaInitialize(meta, context, loader) {
485-
importMetaInitializer ??= require('internal/modules/esm/initialize_import_meta').initializeImportMeta;
486-
meta = importMetaInitializer(meta, context, loader);
487-
return meta;
488-
}
489479
}
490480
ObjectSetPrototypeOf(AsyncLoaderHooksOnLoaderHookWorker.prototype, null);
491481

@@ -674,12 +664,6 @@ class AsyncLoaderHookWorker {
674664
return body;
675665
}
676666
}
677-
678-
#importMetaInitializer = require('internal/modules/esm/initialize_import_meta').initializeImportMeta;
679-
680-
importMetaInitialize(meta, context, loader) {
681-
this.#importMetaInitializer(meta, context, loader);
682-
}
683667
}
684668
ObjectSetPrototypeOf(AsyncLoaderHookWorker.prototype, null);
685669

@@ -817,8 +801,6 @@ function getAsyncLoaderHookWorker() {
817801
*/
818802
class AsyncLoaderHooksProxiedToLoaderHookWorker {
819803

820-
allowImportMetaResolve = true;
821-
822804
isForAsyncLoaderHookWorker = false;
823805

824806
/**
@@ -876,10 +858,6 @@ class AsyncLoaderHooksProxiedToLoaderHookWorker {
876858
return asyncLoaderHookWorker.makeSyncRequest('load', undefined, url, context);
877859
}
878860

879-
importMetaInitialize(meta, context, loader) {
880-
asyncLoaderHookWorker.importMetaInitialize(meta, context, loader);
881-
}
882-
883861
waitForLoaderHookInitialization() {
884862
asyncLoaderHookWorker.waitForWorker();
885863
}
Collapse file

‎lib/internal/modules/esm/initialize_import_meta.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/initialize_import_meta.js
-83Lines changed: 0 additions & 83 deletions
This file was deleted.
Collapse file

‎lib/internal/modules/esm/loader.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/loader.js
+57-24Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const {
5151
kErrored,
5252
kSourcePhase,
5353
throwIfPromiseRejected,
54+
setImportMetaResolveInitializer,
5455
} = internalBinding('module_wrap');
5556
const {
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

6769
const { tracingChannel } = require('diagnostics_channel');
6870
const 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
*/
900924
function 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

Collapse file

‎lib/internal/modules/esm/utils.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/utils.js
+3-16Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -183,27 +183,14 @@ function registerModule(referrer, registry) {
183183
}
184184

185185
/**
186-
* Proxy the import meta handling to the default loader for source text modules.
187-
* @param {Record<string, string | Function>} meta - The import.meta object to initialize.
188-
* @param {ModuleWrap} wrap - The ModuleWrap of the SourceTextModule where `import.meta` is referenced.
189-
* @returns {object}
190-
*/
191-
function defaultInitializeImportMetaForModule(meta, wrap) {
192-
const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader();
193-
return cascadedLoader.importMetaInitialize(meta, { url: wrap.url, isMain: wrap.isMain });
194-
}
195-
196-
/**
197-
* Defines the `import.meta` object for a given module.
186+
* Initializes the `import.meta` object for a given module. This is only called when the module
187+
* is compiled with custom callbacks. Ordinary user-land source text modules are
188+
* initialized by the native DefaultImportMetaObjectInitializer directly.
198189
* @param {symbol} symbol - Reference to the module.
199190
* @param {Record<string, string | Function>} meta - The import.meta object to initialize.
200191
* @param {ModuleWrap} wrap - The ModuleWrap of the SourceTextModule where `import.meta` is referenced.
201192
*/
202193
function initializeImportMetaObject(symbol, meta, wrap) {
203-
if (symbol === source_text_module_default_hdo) {
204-
defaultInitializeImportMetaForModule(meta, wrap);
205-
return;
206-
}
207194
const data = moduleRegistries.get(symbol);
208195
assert(data, `import.meta registry not found for ${wrap.url}`);
209196
const { initializeImportMeta, callbackReferrer } = data;
Collapse file

‎lib/internal/modules/package_json_reader.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/package_json_reader.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ function findPackageJSON(specifier, base = 'data:') {
350350

351351
try {
352352
// TODO(@JakobJingleheimer): Detect whether findPackageJSON is being used within a loader
353-
// (possibly piggyback on `allowImportMetaResolve`)
353+
// (possibly piggyback on `isForAsyncLoaderHookWorker` from the loader?) and if so:
354354
// - When inside, use the default resolve
355355
// - (I think it's impossible to use the chain because of re-entry & a deadlock from atomics).
356356
// - When outside, use cascadedLoader.resolveSync (not implemented yet, but the pieces exist).
Collapse file

‎src/env_properties.h‎

Copy file name to clipboardExpand all lines: src/env_properties.h
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@
470470
V(enhance_fatal_stack_before_inspector, v8::Function) \
471471
V(get_source_map_error_source, v8::Function) \
472472
V(host_import_module_dynamically_callback, v8::Function) \
473+
V(host_import_meta_resolve_initializer, v8::Function) \
473474
V(host_initialize_import_meta_object_callback, v8::Function) \
474475
V(http2session_on_altsvc_function, v8::Function) \
475476
V(http2session_on_error_function, v8::Function) \

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.