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: https://github.com/nodejs/node/pull/60603
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
This commit is contained in:
Joyee Cheung 2025-11-04 01:55:48 +01:00 committed by Node.js GitHub Bot
parent b15070b5ac
commit 1d6a62662c
9 changed files with 242 additions and 219 deletions

View File

@ -58,7 +58,6 @@ const {
let debug = require('internal/util/debuglog').debuglog('async_loader_worker', (fn) => {
debug = fn;
});
let importMetaInitializer;
let importAssertionAlreadyWarned = false;
@ -111,7 +110,6 @@ function defineImportAssertionAlias(context) {
* Interface for classes that implement asynchronous loader hooks that can be attached to the ModuleLoader
* via `ModuleLoader.#setAsyncLoaderHooks()`.
* @typedef {object} AsyncLoaderHooks
* @property {boolean} allowImportMetaResolve Whether to allow the use of `import.meta.resolve`.
* @property {boolean} isForAsyncLoaderHookWorker Whether the instance is running on the loader hook worker thread.
* @property {(url: string, context: object, defaultLoad: Function) => Promise<LoadResult>} load
* Calling the asynchronous `load` hook asynchronously.
@ -163,8 +161,6 @@ class AsyncLoaderHooksOnLoaderHookWorker {
// Cache URLs we've already validated to avoid repeated validation
#validatedUrls = new SafeSet();
allowImportMetaResolve = false;
isForAsyncLoaderHookWorker = true;
/**
@ -480,12 +476,6 @@ class AsyncLoaderHooksOnLoaderHookWorker {
waitForLoaderHookInitialization() {
// No-op
}
importMetaInitialize(meta, context, loader) {
importMetaInitializer ??= require('internal/modules/esm/initialize_import_meta').initializeImportMeta;
meta = importMetaInitializer(meta, context, loader);
return meta;
}
}
ObjectSetPrototypeOf(AsyncLoaderHooksOnLoaderHookWorker.prototype, null);
@ -674,12 +664,6 @@ class AsyncLoaderHookWorker {
return body;
}
}
#importMetaInitializer = require('internal/modules/esm/initialize_import_meta').initializeImportMeta;
importMetaInitialize(meta, context, loader) {
this.#importMetaInitializer(meta, context, loader);
}
}
ObjectSetPrototypeOf(AsyncLoaderHookWorker.prototype, null);
@ -817,8 +801,6 @@ function getAsyncLoaderHookWorker() {
*/
class AsyncLoaderHooksProxiedToLoaderHookWorker {
allowImportMetaResolve = true;
isForAsyncLoaderHookWorker = false;
/**
@ -876,10 +858,6 @@ class AsyncLoaderHooksProxiedToLoaderHookWorker {
return asyncLoaderHookWorker.makeSyncRequest('load', undefined, url, context);
}
importMetaInitialize(meta, context, loader) {
asyncLoaderHookWorker.importMetaInitialize(meta, context, loader);
}
waitForLoaderHookInitialization() {
asyncLoaderHookWorker.waitForWorker();
}

View File

@ -1,83 +0,0 @@
'use strict';
const {
StringPrototypeStartsWith,
} = primordials;
const { getOptionValue } = require('internal/options');
const {
setLazyPathHelpers,
} = internalBinding('modules');
const experimentalImportMetaResolve = getOptionValue('--experimental-import-meta-resolve');
/**
* Generate a function to be used as import.meta.resolve for a particular module.
* @param {string} defaultParentURL The default base to use for resolution
* @param {typeof import('./loader.js').ModuleLoader} loader Reference to the current module loader
* @param {bool} allowParentURL Whether to permit parentURL second argument for contextual resolution
* @returns {(specifier: string) => string} Function to assign to import.meta.resolve
*/
function createImportMetaResolve(defaultParentURL, loader, allowParentURL) {
/**
* @param {string} specifier
* @param {URL['href']} [parentURL] When `--experimental-import-meta-resolve` is specified, a
* second argument can be provided.
* @returns {string}
*/
return function resolve(specifier, parentURL = defaultParentURL) {
let url;
if (!allowParentURL) {
parentURL = defaultParentURL;
}
try {
const request = { specifier, __proto__: null };
({ url } = loader.resolveSync(parentURL, request));
return url;
} catch (error) {
switch (error?.code) {
case 'ERR_UNSUPPORTED_DIR_IMPORT':
case 'ERR_MODULE_NOT_FOUND':
({ url } = error);
if (url) {
return url;
}
}
throw error;
}
};
}
/**
* Create the `import.meta` object for a module.
* @param {object} meta
* @param {{url: string, isMain?: boolean}} context
* @param {typeof import('./loader.js').ModuleLoader} loader Reference to the current module loader
* @returns {{dirname?: string, filename?: string, url: string, resolve?: Function}}
*/
function initializeImportMeta(meta, context, loader) {
const { url, isMain } = context;
// Alphabetical
if (StringPrototypeStartsWith(url, 'file:') === true) {
// dirname
// filename
setLazyPathHelpers(meta, url);
}
meta.main = !!isMain;
if (!loader || loader.allowImportMetaResolve) {
meta.resolve = createImportMetaResolve(url, loader, experimentalImportMetaResolve);
}
meta.url = url;
return meta;
}
module.exports = {
initializeImportMeta,
};

View File

@ -51,6 +51,7 @@ const {
kErrored,
kSourcePhase,
throwIfPromiseRejected,
setImportMetaResolveInitializer,
} = internalBinding('module_wrap');
const {
urlToFilename,
@ -62,7 +63,8 @@ const {
loadWithHooks: loadWithSyncHooks,
validateLoadSloppy,
} = require('internal/modules/customization_hooks');
let defaultResolve, defaultLoadSync, importMetaInitializer;
let defaultResolve, defaultLoadSync;
const { tracingChannel } = require('diagnostics_channel');
const onImport = tracingChannel('module.import');
@ -183,13 +185,6 @@ class ModuleLoader {
*/
translators = getTranslators();
/**
* Truthy to allow the use of `import.meta.resolve`. This is needed
* currently because the `Hooks` class does not have `resolveSync`
* implemented and `import.meta.resolve` requires it.
*/
allowImportMetaResolve;
/**
* @see {AsyncLoaderHooks.isForAsyncLoaderHookWorker}
* Shortcut to this.#asyncLoaderHooks.isForAsyncLoaderHookWorker.
@ -200,9 +195,10 @@ class ModuleLoader {
* Asynchronous loader hooks to pass requests to.
*
* Note that this value _MUST_ be set with `#setAsyncLoaderHooks`
* because it needs to copy `#asyncLoaderHooks.allowImportMetaResolve`
* to this property and failure to do so will cause undefined
* behavior when invoking `import.meta.resolve`.
* because it needs to copy `#asyncLoaderHooks.isForAsyncLoaderHookWorker`
* to this property.
* TODO(joyeecheung): this was a legacy of the previous setup of import.meta.resolve
* configuration; put this information in the environment directly instead.
*
* When the ModuleLoader is created on a loader hook thread, this is
* {@link AsyncLoaderHooksOnLoaderHookWorker}, and its methods directly call out
@ -234,10 +230,8 @@ class ModuleLoader {
#setAsyncLoaderHooks(asyncLoaderHooks) {
this.#asyncLoaderHooks = asyncLoaderHooks;
if (asyncLoaderHooks) {
this.allowImportMetaResolve = asyncLoaderHooks.allowImportMetaResolve;
this.isForAsyncLoaderHookWorker = asyncLoaderHooks.isForAsyncLoaderHookWorker;
} else {
this.allowImportMetaResolve = true;
this.isForAsyncLoaderHookWorker = false;
}
}
@ -821,15 +815,6 @@ class ModuleLoader {
}
}
importMetaInitialize(meta, context) {
if (this.#asyncLoaderHooks) {
return this.#asyncLoaderHooks.importMetaInitialize(meta, context, this);
}
importMetaInitializer ??= require('internal/modules/esm/initialize_import_meta').initializeImportMeta;
meta = importMetaInitializer(meta, context, this);
return meta;
}
/**
* Block until the async loader hooks have been initialized.
*
@ -883,8 +868,47 @@ function createModuleLoader(asyncLoaderHooks) {
return new ModuleLoader(asyncLoaderHooks);
}
let cascadedLoader;
let allowImportMetaResolveParentURL;
/**
* This is only called from the native ImportMetaObjectInitialize function to set up import.meta.resolve
* when import.meta.resolve is accessed for the first time in a module.
* @param {ModuleLoader} loader The cascaded loader to use. Bound when this function gets passed to native land.
* @param {string} moduleURL URL of the module accessing import.meta
* @returns {function(string, URL['href']=): string} The import.meta.resolve function
*/
function createImportMetaResolve(loader, moduleURL) {
/**
* @param {string} specifier The module specifier to resolve.
* @param {URL['href']} [parentURL] Optional parent URL to resolve against. Ignored unless
* `--experimental-import-meta-resolve` is enabled.
* @returns {string}
*/
return function resolve(specifier, parentURL) {
// The second argument is ignored unless --experimental-import-meta-resolve is enabled.
// Even then, if it's not provided, parentURL defaults to the url of the module accessing
// import.meta.resolve.
allowImportMetaResolveParentURL ??= getOptionValue('--experimental-import-meta-resolve');
parentURL = allowImportMetaResolveParentURL ? (parentURL ?? moduleURL) : moduleURL;
let url;
try {
({ url } = loader.resolveSync(parentURL, { specifier, __proto__: null }));
return url;
} catch (error) {
switch (error?.code) {
case 'ERR_UNSUPPORTED_DIR_IMPORT':
case 'ERR_MODULE_NOT_FOUND':
({ url } = error);
if (url) {
return url;
}
}
throw error;
}
};
}
let cascadedLoader;
/**
* This is a singleton ESM loader that integrates the loader hooks, if any.
* It it used by other internal built-ins when they need to load user-land ESM code
@ -898,7 +922,16 @@ let cascadedLoader;
* @returns {ModuleLoader}
*/
function getOrInitializeCascadedLoader(asyncLoaderHooks) {
cascadedLoader ??= createModuleLoader(asyncLoaderHooks);
if (!cascadedLoader) {
cascadedLoader = createModuleLoader(asyncLoaderHooks);
// import.meta.resolve is not allowed in the async loader hook worker thread.
// So only set up the import.meta.resolve initializer when we are initializing
// the non-loader-hook-thread cascaded loader. When the native land doesn't see it,
// it knows the loader is running on the loader hook thread.
if (!(asyncLoaderHooks?.isForAsyncLoaderHookWorker)) {
setImportMetaResolveInitializer(createImportMetaResolve.bind(null, cascadedLoader));
}
}
return cascadedLoader;
}

View File

@ -183,27 +183,14 @@ function registerModule(referrer, registry) {
}
/**
* Proxy the import meta handling to the default loader for source text modules.
* @param {Record<string, string | Function>} meta - The import.meta object to initialize.
* @param {ModuleWrap} wrap - The ModuleWrap of the SourceTextModule where `import.meta` is referenced.
* @returns {object}
*/
function defaultInitializeImportMetaForModule(meta, wrap) {
const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader();
return cascadedLoader.importMetaInitialize(meta, { url: wrap.url, isMain: wrap.isMain });
}
/**
* Defines the `import.meta` object for a given module.
* Initializes the `import.meta` object for a given module. This is only called when the module
* is compiled with custom callbacks. Ordinary user-land source text modules are
* initialized by the native DefaultImportMetaObjectInitializer directly.
* @param {symbol} symbol - Reference to the module.
* @param {Record<string, string | Function>} meta - The import.meta object to initialize.
* @param {ModuleWrap} wrap - The ModuleWrap of the SourceTextModule where `import.meta` is referenced.
*/
function initializeImportMetaObject(symbol, meta, wrap) {
if (symbol === source_text_module_default_hdo) {
defaultInitializeImportMetaForModule(meta, wrap);
return;
}
const data = moduleRegistries.get(symbol);
assert(data, `import.meta registry not found for ${wrap.url}`);
const { initializeImportMeta, callbackReferrer } = data;

View File

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

View File

@ -470,6 +470,7 @@
V(enhance_fatal_stack_before_inspector, v8::Function) \
V(get_source_map_error_source, v8::Function) \
V(host_import_module_dynamically_callback, v8::Function) \
V(host_import_meta_resolve_initializer, v8::Function) \
V(host_initialize_import_meta_object_callback, v8::Function) \
V(http2session_on_altsvc_function, v8::Function) \
V(http2session_on_error_function, v8::Function) \

View File

@ -7,6 +7,7 @@
#include "node_external_reference.h"
#include "node_internals.h"
#include "node_process-inl.h"
#include "node_url.h"
#include "node_watchdog.h"
#include "util-inl.h"
@ -1207,6 +1208,167 @@ void ModuleWrap::SetImportModuleDynamicallyCallback(
ImportModuleDynamicallyWithPhase);
}
void ModuleWrap::SetImportMetaResolveInitializer(
const v8::FunctionCallbackInfo<v8::Value>& args) {
Isolate* isolate = args.GetIsolate();
Realm* realm = Realm::GetCurrent(args);
HandleScope handle_scope(isolate);
CHECK_EQ(args.Length(), 1);
CHECK(args[0]->IsFunction());
Local<Function> initializer = args[0].As<Function>();
realm->set_host_import_meta_resolve_initializer(initializer);
}
static void ImportMetaResolveLazyGetter(
Local<v8::Name> name, const PropertyCallbackInfo<Value>& info) {
Isolate* isolate = info.GetIsolate();
Local<Value> receiver_val = info.This();
if (!receiver_val->IsObject()) {
THROW_ERR_INVALID_INVOCATION(isolate);
return;
}
Local<Object> receiver = receiver_val.As<Object>();
Local<Context> context;
if (!receiver->GetCreationContext().ToLocal(&context)) {
THROW_ERR_INVALID_INVOCATION(isolate);
return;
}
Realm* realm = Realm::GetCurrent(context);
if (realm == nullptr) {
THROW_ERR_INVALID_INVOCATION(isolate);
}
Local<Function> initializer = realm->host_import_meta_resolve_initializer();
if (initializer.IsEmpty()) {
THROW_ERR_INVALID_INVOCATION(isolate);
return;
}
// This should be createImportMetaResolve(). The loader argument is already
// bound at initialization time.
Local<Value> args[] = {info.Data()};
Local<Value> ret;
if (!initializer
->Call(context, Undefined(realm->isolate()), arraysize(args), args)
.ToLocal(&ret)) {
return;
}
info.GetReturnValue().Set(ret);
}
static void PathHelpersLazyGetter(Local<v8::Name> name,
const PropertyCallbackInfo<Value>& info) {
Isolate* isolate = info.GetIsolate();
// This getter has no JavaScript function representation and is not
// invoked in the creation context.
// When this getter is invoked in a vm context, the `Realm::GetCurrent(info)`
// returns a nullptr and retrieve the creation context via `this` object and
// get the creation Realm.
Local<Value> receiver_val = info.This();
if (!receiver_val->IsObject()) {
THROW_ERR_INVALID_INVOCATION(isolate);
return;
}
Local<Object> receiver = receiver_val.As<Object>();
Local<Context> context;
if (!receiver->GetCreationContext().ToLocal(&context)) {
THROW_ERR_INVALID_INVOCATION(isolate);
return;
}
Environment* env = Environment::GetCurrent(context);
node::Utf8Value url(isolate, info.Data());
auto file_url = ada::parse(url.ToStringView());
CHECK(file_url);
auto file_path = url::FileURLToPath(env, *file_url);
CHECK(file_path.has_value());
std::string_view ret_view = file_path.value();
node::Utf8Value utf8name(isolate, name);
auto plain_name = utf8name.ToStringView();
if (plain_name == "dirname") {
#ifdef _WIN32
#define PATH_SEPARATOR '\\'
#else
#define PATH_SEPARATOR '/'
#endif
auto index = ret_view.rfind(PATH_SEPARATOR);
CHECK(index != std::string_view::npos);
ret_view.remove_suffix(ret_view.size() - index);
#undef PATH_SEPARATOR
}
Local<Value> ret;
if (!ToV8Value(context, ret_view, isolate).ToLocal(&ret)) {
return;
}
info.GetReturnValue().Set(ret);
}
static Maybe<void> DefaultImportMetaObjectInitializer(Realm* realm,
Local<Object> wrap,
Local<Object> meta) {
Local<Context> context = realm->context();
Isolate* isolate = realm->isolate();
Environment* env = realm->env();
Local<Value> url;
if (!wrap->Get(context, env->url_string()).ToLocal(&url)) {
return Nothing<void>();
}
// N.B.: Order is important to keep keys in alphabetical order.
Utf8Value url_utf8(isolate, url);
if (url_utf8.ToStringView().starts_with("file:")) {
// Set a lazy getter of import.meta.dirname
if (meta->SetLazyDataProperty(
context, env->dirname_string(), PathHelpersLazyGetter, url)
.IsNothing()) {
return Nothing<void>();
}
// Set a lazy getter of import.meta.filename
if (meta->SetLazyDataProperty(
context, env->filename_string(), PathHelpersLazyGetter, url)
.IsNothing()) {
return Nothing<void>();
}
}
// Set import.meta.main = moduleWrap.isMain
Local<Value> is_main;
if (!wrap->Get(context, FIXED_ONE_BYTE_STRING(isolate, "isMain"))
.ToLocal(&is_main)) {
return Nothing<void>();
}
if (meta->Set(context,
FIXED_ONE_BYTE_STRING(isolate, "main"),
Boolean::New(isolate, is_main->IsTrue()))
.IsEmpty()) {
return Nothing<void>();
}
// Set a lazy getter of import.meta.resolve - only if the initializer is set,
// which is only the case when run on a non-loader-hook thread.
Local<Function> import_meta_resolve_initializer =
realm->host_import_meta_resolve_initializer();
if (!import_meta_resolve_initializer.IsEmpty() &&
meta->SetLazyDataProperty(context,
FIXED_ONE_BYTE_STRING(isolate, "resolve"),
ImportMetaResolveLazyGetter,
url)
.IsNothing()) {
return Nothing<void>();
}
// Set import.meta.url = moduleWrap.url
if (meta->Set(context, env->url_string(), url).IsEmpty()) {
return Nothing<void>();
}
return JustVoid();
}
void ModuleWrap::HostInitializeImportMetaObjectCallback(
Local<Context> context, Local<Module> module, Local<Object> meta) {
Environment* env = Environment::GetCurrent(context);
@ -1232,8 +1394,19 @@ void ModuleWrap::HostInitializeImportMetaObjectCallback(
return;
}
DCHECK(id->IsSymbol());
// Use the default initializer for source text modules without custom
// callbacks.
if (id == env->source_text_module_default_hdo()) {
USE(DefaultImportMetaObjectInitializer(realm, wrap, meta));
return;
}
// For modules that have custom callbacks, call into JS land
// to look up the callback from the registry.
Local<Value> args[] = {id, meta, wrap};
TryCatchScope try_catch(env);
USE(callback->Call(
context, Undefined(realm->isolate()), arraysize(args), args));
if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
@ -1452,6 +1625,10 @@ void ModuleWrap::CreatePerIsolateProperties(IsolateData* isolate_data,
target,
"setInitializeImportMetaObjectCallback",
SetInitializeImportMetaObjectCallback);
SetMethod(isolate,
target,
"setImportMetaResolveInitializer",
SetImportMetaResolveInitializer);
SetMethod(isolate,
target,
"createRequiredModuleFacade",
@ -1505,6 +1682,7 @@ void ModuleWrap::RegisterExternalReferences(
registry->Register(SetImportModuleDynamicallyCallback);
registry->Register(SetInitializeImportMetaObjectCallback);
registry->Register(SetImportMetaResolveInitializer);
registry->Register(ThrowIfPromiseRejected);
}
} // namespace loader

View File

@ -182,6 +182,8 @@ class ModuleWrap : public BaseObject {
static void SetImportModuleDynamicallyCallback(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetImportMetaResolveInitializer(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetInitializeImportMetaObjectCallback(
const v8::FunctionCallbackInfo<v8::Value>& args);
static v8::MaybeLocal<v8::Value> SyntheticModuleEvaluationStepsCallback(

View File

@ -35,7 +35,6 @@ using v8::Null;
using v8::Object;
using v8::ObjectTemplate;
using v8::Primitive;
using v8::PropertyCallbackInfo;
using v8::String;
using v8::Undefined;
using v8::Value;
@ -549,76 +548,6 @@ void GetCompileCacheEntry(const FunctionCallbackInfo<Value>& args) {
isolate, v8::Null(isolate), names.data(), values.data(), names.size()));
}
static void PathHelpersLazyGetter(Local<v8::Name> name,
const PropertyCallbackInfo<Value>& info) {
Isolate* isolate = info.GetIsolate();
// This getter has no JavaScript function representation and is not
// invoked in the creation context.
// When this getter is invoked in a vm context, the `Realm::GetCurrent(info)`
// returns a nullptr and retrieve the creation context via `this` object and
// get the creation Realm.
Local<Value> receiver_val = info.This();
if (!receiver_val->IsObject()) {
THROW_ERR_INVALID_INVOCATION(isolate);
return;
}
Local<Object> receiver = receiver_val.As<Object>();
Local<Context> context;
if (!receiver->GetCreationContext().ToLocal(&context)) {
THROW_ERR_INVALID_INVOCATION(isolate);
return;
}
Environment* env = Environment::GetCurrent(context);
node::Utf8Value url(isolate, info.Data());
auto file_url = ada::parse(url.ToStringView());
CHECK(file_url);
auto file_path = url::FileURLToPath(env, *file_url);
CHECK(file_path.has_value());
std::string_view ret_view = file_path.value();
node::Utf8Value utf8name(isolate, name);
auto plain_name = utf8name.ToStringView();
if (plain_name == "dirname") {
#ifdef _WIN32
#define PATH_SEPARATOR '\\'
#else
#define PATH_SEPARATOR '/'
#endif
auto index = ret_view.rfind(PATH_SEPARATOR);
CHECK(index != std::string_view::npos);
ret_view.remove_suffix(ret_view.size() - index);
#undef PATH_SEPARATOR
}
Local<Value> ret;
if (!ToV8Value(context, ret_view, isolate).ToLocal(&ret)) {
return;
}
info.GetReturnValue().Set(ret);
}
void InitImportMetaPathHelpers(const FunctionCallbackInfo<Value>& args) {
// target, url, shouldSetDirnameAndFilename, resolve
CHECK_GE(args.Length(), 2);
CHECK(args[0]->IsObject());
CHECK(args[1]->IsString());
Isolate* isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
Environment* env = Environment::GetCurrent(context);
auto target = args[0].As<Object>();
// N.B.: Order is important to keep keys in alphabetical order.
if (target
->SetLazyDataProperty(
context, env->dirname_string(), PathHelpersLazyGetter, args[1])
.IsNothing() ||
target
->SetLazyDataProperty(
context, env->filename_string(), PathHelpersLazyGetter, args[1])
.IsNothing())
return;
}
void SaveCompileCacheEntry(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
@ -648,7 +577,6 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
SetMethod(isolate, target, "flushCompileCache", FlushCompileCache);
SetMethod(isolate, target, "getCompileCacheEntry", GetCompileCacheEntry);
SetMethod(isolate, target, "saveCompileCacheEntry", SaveCompileCacheEntry);
SetMethod(isolate, target, "setLazyPathHelpers", InitImportMetaPathHelpers);
}
void BindingData::CreatePerContextProperties(Local<Object> target,
@ -703,7 +631,6 @@ void BindingData::RegisterExternalReferences(
registry->Register(FlushCompileCache);
registry->Register(GetCompileCacheEntry);
registry->Register(SaveCompileCacheEntry);
registry->Register(InitImportMetaPathHelpers);
}
} // namespace modules