GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — module: centralize SourceTextModule compilation for builtin loader · nodejs/node@4dae68c

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • lib/internal
    • modules/esm
      • create_dynamic_module.js
      • loader.js
      • translators.js
      • utils.js
    • vm
      • module.js
  • src
    • env_properties.h
    • module_wrap.cc
Expand file treeCollapse file tree
Open diff view settings
Collapse file

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

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/create_dynamic_module.js
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ ${ArrayPrototypeJoin(ArrayPrototypeMap(imports, createImport), '\n')}
5555
${ArrayPrototypeJoin(ArrayPrototypeMap(exports, createExport), '\n')}
5656
import.meta.done();
5757
`;
58-
const { ModuleWrap } = internalBinding('module_wrap');
59-
const m = new ModuleWrap(`${url}`, undefined, source, 0, 0);
58+
const { registerModule, compileSourceTextModule } = require('internal/modules/esm/utils');
59+
const m = compileSourceTextModule(`${url}`, source);
6060

6161
const readyfns = new SafeSet();
6262
/** @type {DynamicModuleReflect} */
@@ -68,7 +68,6 @@ import.meta.done();
6868
if (imports.length) {
6969
reflect.imports = { __proto__: null };
7070
}
71-
const { registerModule } = require('internal/modules/esm/utils');
7271
registerModule(m, {
7372
__proto__: null,
7473
initializeImportMeta: (meta, wrap) => {
Collapse file

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

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/loader.js
+3-31Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,10 @@ const { getOptionValue } = require('internal/options');
2525
const { isURL, pathToFileURL, URL } = require('internal/url');
2626
const { emitExperimentalWarning, kEmptyObject } = require('internal/util');
2727
const {
28-
registerModule,
28+
compileSourceTextModule,
2929
getDefaultConditions,
3030
} = require('internal/modules/esm/utils');
3131
const { kImplicitAssertType } = require('internal/modules/esm/assert');
32-
const {
33-
maybeCacheSourceMap,
34-
} = require('internal/source_map/source_map_cache');
3532
const { canParse } = internalBinding('url');
3633
const { ModuleWrap } = internalBinding('module_wrap');
3734
let defaultResolve, defaultLoad, defaultLoadSync, importMetaInitializer;
@@ -193,16 +190,7 @@ class ModuleLoader {
193190

194191
async eval(source, url) {
195192
const evalInstance = (url) => {
196-
const module = new ModuleWrap(url, undefined, source, 0, 0);
197-
registerModule(module, {
198-
__proto__: null,
199-
initializeImportMeta: (meta, wrap) => this.importMetaInitialize(meta, { url }),
200-
importModuleDynamically: (specifier, { url }, importAttributes) => {
201-
return this.import(specifier, url, importAttributes);
202-
},
203-
});
204-
205-
return module;
193+
return compileSourceTextModule(url, source, this);
206194
};
207195
const { ModuleJob } = require('internal/modules/esm/module_job');
208196
const job = new ModuleJob(
@@ -273,26 +261,10 @@ class ModuleLoader {
273261
if (job !== undefined) {
274262
return job.module.getNamespaceSync();
275263
}
276-
277264
// TODO(joyeecheung): refactor this so that we pre-parse in C++ and hit the
278265
// cache here, or use a carrier object to carry the compiled module script
279266
// into the constructor to ensure cache hit.
280-
const wrap = new ModuleWrap(url, undefined, source, 0, 0);
281-
// Cache the source map for the module if present.
282-
if (wrap.sourceMapURL) {
283-
maybeCacheSourceMap(url, source, null, false, undefined, wrap.sourceMapURL);
284-
}
285-
const { registerModule } = require('internal/modules/esm/utils');
286-
// TODO(joyeecheung): refactor so that the default options are shared across
287-
// the built-in loaders.
288-
registerModule(wrap, {
289-
__proto__: null,
290-
initializeImportMeta: (meta, wrap) => this.importMetaInitialize(meta, { url }),
291-
importModuleDynamically: (specifier, wrap, importAttributes) => {
292-
return this.import(specifier, url, importAttributes);
293-
},
294-
});
295-
267+
const wrap = compileSourceTextModule(url, source, this);
296268
const inspectBrk = (isMain && getOptionValue('--inspect-brk'));
297269

298270
const { ModuleJobSync } = require('internal/modules/esm/module_job');
Collapse file

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

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/translators.js
+2-24Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -156,35 +156,13 @@ function errPath(url) {
156156
return url;
157157
}
158158

159-
/**
160-
* Dynamically imports a module using the ESM loader.
161-
* @param {string} specifier - The module specifier to import.
162-
* @param {object} options - An object containing options for the import.
163-
* @param {string} options.url - The URL of the module requesting the import.
164-
* @param {Record<string, string>} [attributes] - An object containing attributes for the import.
165-
* @returns {Promise<import('internal/modules/esm/loader.js').ModuleExports>} The imported module.
166-
*/
167-
async function importModuleDynamically(specifier, { url }, attributes) {
168-
const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader();
169-
return cascadedLoader.import(specifier, url, attributes);
170-
}
171-
172159
// Strategy for loading a standard JavaScript module.
173160
translators.set('module', function moduleStrategy(url, source, isMain) {
174161
assertBufferSource(source, true, 'load');
175162
source = stringify(source);
176163
debug(`Translating StandardModule ${url}`);
177-
const module = new ModuleWrap(url, undefined, source, 0, 0);
178-
// Cache the source map for the module if present.
179-
if (module.sourceMapURL) {
180-
maybeCacheSourceMap(url, source, null, false, undefined, module.sourceMapURL);
181-
}
182-
const { registerModule } = require('internal/modules/esm/utils');
183-
registerModule(module, {
184-
__proto__: null,
185-
initializeImportMeta: (meta, wrap) => this.importMetaInitialize(meta, { url }),
186-
importModuleDynamically,
187-
});
164+
const { compileSourceTextModule } = require('internal/modules/esm/utils');
165+
const module = compileSourceTextModule(url, source, this);
188166
return module;
189167
});
190168

Collapse file

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

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/utils.js
+71-10Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,18 @@ const {
1313
},
1414
} = internalBinding('util');
1515
const {
16+
source_text_module_default_hdo,
1617
vm_dynamic_import_default_internal,
1718
vm_dynamic_import_main_context_default,
1819
vm_dynamic_import_missing_flag,
1920
vm_dynamic_import_no_callback,
2021
} = internalBinding('symbols');
2122

23+
const { ModuleWrap } = internalBinding('module_wrap');
24+
const {
25+
maybeCacheSourceMap,
26+
} = require('internal/source_map/source_map_cache');
27+
2228
const {
2329
ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG,
2430
ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING,
@@ -167,28 +173,55 @@ function registerModule(referrer, registry) {
167173
moduleRegistries.set(idSymbol, registry);
168174
}
169175

176+
/**
177+
* Proxy the import meta handling to the default loader for source text modules.
178+
* @param {Record<string, string | Function>} meta - The import.meta object to initialize.
179+
* @param {ModuleWrap} wrap - The ModuleWrap of the SourceTextModule where `import.meta` is referenced.
180+
*/
181+
function defaultInitializeImportMetaForModule(meta, wrap) {
182+
const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader();
183+
return cascadedLoader.importMetaInitialize(meta, { url: wrap.url });
184+
}
185+
170186
/**
171187
* Defines the `import.meta` object for a given module.
172188
* @param {symbol} symbol - Reference to the module.
173189
* @param {Record<string, string | Function>} meta - The import.meta object to initialize.
190+
* @param {ModuleWrap} wrap - The ModuleWrap of the SourceTextModule where `import.meta` is referenced.
174191
*/
175-
function initializeImportMetaObject(symbol, meta) {
176-
if (moduleRegistries.has(symbol)) {
177-
const { initializeImportMeta, callbackReferrer } = moduleRegistries.get(symbol);
178-
if (initializeImportMeta !== undefined) {
179-
meta = initializeImportMeta(meta, callbackReferrer);
180-
}
192+
function initializeImportMetaObject(symbol, meta, wrap) {
193+
if (symbol === source_text_module_default_hdo) {
194+
defaultInitializeImportMetaForModule(meta, wrap);
195+
return;
196+
}
197+
const data = moduleRegistries.get(symbol);
198+
assert(data, `import.meta registry not found for ${wrap.url}`);
199+
const { initializeImportMeta, callbackReferrer } = data;
200+
if (initializeImportMeta !== undefined) {
201+
meta = initializeImportMeta(meta, callbackReferrer);
181202
}
182203
}
183204

184205
/**
185-
* Proxy the dynamic import to the default loader.
206+
* Proxy the dynamic import handling to the default loader for source text modules.
207+
* @param {string} specifier - The module specifier string.
208+
* @param {Record<string, string>} attributes - The import attributes object.
209+
* @param {string|null|undefined} referrerName - name of the referrer.
210+
* @returns {Promise<import('internal/modules/esm/loader.js').ModuleExports>} - The imported module object.
211+
*/
212+
function defaultImportModuleDynamicallyForModule(specifier, attributes, referrerName) {
213+
const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader();
214+
return cascadedLoader.import(specifier, referrerName, attributes);
215+
}
216+
217+
/**
218+
* Proxy the dynamic import to the default loader for classic scripts.
186219
* @param {string} specifier - The module specifier string.
187220
* @param {Record<string, string>} attributes - The import attributes object.
188221
* @param {string|null|undefined} referrerName - name of the referrer.
189222
* @returns {Promise<import('internal/modules/esm/loader.js').ModuleExports>} - The imported module object.
190223
*/
191-
function defaultImportModuleDynamically(specifier, attributes, referrerName) {
224+
function defaultImportModuleDynamicallyForScript(specifier, attributes, referrerName) {
192225
const parentURL = normalizeReferrerURL(referrerName);
193226
const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader();
194227
return cascadedLoader.import(specifier, parentURL, attributes);
@@ -208,12 +241,16 @@ async function importModuleDynamicallyCallback(referrerSymbol, specifier, attrib
208241
// and fall back to the default loader.
209242
if (referrerSymbol === vm_dynamic_import_main_context_default) {
210243
emitExperimentalWarning('vm.USE_MAIN_CONTEXT_DEFAULT_LOADER');
211-
return defaultImportModuleDynamically(specifier, attributes, referrerName);
244+
return defaultImportModuleDynamicallyForScript(specifier, attributes, referrerName);
212245
}
213246
// For script compiled internally that should use the default loader to handle dynamic
214247
// import, proxy the request to the default loader without the warning.
215248
if (referrerSymbol === vm_dynamic_import_default_internal) {
216-
return defaultImportModuleDynamically(specifier, attributes, referrerName);
249+
return defaultImportModuleDynamicallyForScript(specifier, attributes, referrerName);
250+
}
251+
// For SourceTextModules compiled internally, proxy the request to the default loader.
252+
if (referrerSymbol === source_text_module_default_hdo) {
253+
return defaultImportModuleDynamicallyForModule(specifier, attributes, referrerName);
217254
}
218255

219256
if (moduleRegistries.has(referrerSymbol)) {
@@ -288,6 +325,29 @@ async function initializeHooks() {
288325
return { __proto__: null, hooks, preloadScripts };
289326
}
290327

328+
/**
329+
* Compile a SourceTextModule for the built-in ESM loader. Register it for default
330+
* source map and import.meta and dynamic import() handling if cascadedLoader is provided.
331+
* @param {string} url URL of the module.
332+
* @param {string} source Source code of the module.
333+
* @param {typeof import('./loader.js').ModuleLoader|undefined} cascadedLoader If provided,
334+
* register the module for default handling.
335+
* @returns {ModuleWrap}
336+
*/
337+
function compileSourceTextModule(url, source, cascadedLoader) {
338+
const hostDefinedOption = cascadedLoader ? source_text_module_default_hdo : undefined;
339+
const wrap = new ModuleWrap(url, undefined, source, 0, 0, hostDefinedOption);
340+
341+
if (!cascadedLoader) {
342+
return wrap;
343+
}
344+
// Cache the source map for the module if present.
345+
if (wrap.sourceMapURL) {
346+
maybeCacheSourceMap(url, source, null, false, undefined, wrap.sourceMapURL);
347+
}
348+
return wrap;
349+
}
350+
291351
module.exports = {
292352
registerModule,
293353
initializeESM,
@@ -296,4 +356,5 @@ module.exports = {
296356
getConditionsSet,
297357
loaderWorkerId: 'internal/modules/esm/worker',
298358
forceDefaultLoader,
359+
compileSourceTextModule,
299360
};
Collapse file

‎lib/internal/vm/module.js‎

Copy file name to clipboardExpand all lines: lib/internal/vm/module.js
+5-6Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,19 +131,18 @@ class Module {
131131
importModuleDynamicallyWrap(options.importModuleDynamically) :
132132
undefined,
133133
};
134+
// This will take precedence over the referrer as the object being
135+
// passed into the callbacks.
136+
registry.callbackReferrer = this;
137+
const { registerModule } = require('internal/modules/esm/utils');
138+
registerModule(this[kWrap], registry);
134139
} else {
135140
assert(syntheticEvaluationSteps);
136141
this[kWrap] = new ModuleWrap(identifier, context,
137142
syntheticExportNames,
138143
syntheticEvaluationSteps);
139144
}
140145

141-
// This will take precedence over the referrer as the object being
142-
// passed into the callbacks.
143-
registry.callbackReferrer = this;
144-
const { registerModule } = require('internal/modules/esm/utils');
145-
registerModule(this[kWrap], registry);
146-
147146
this[kContext] = context;
148147
}
149148

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
@@ -45,6 +45,7 @@
4545
V(onpskexchange_symbol, "onpskexchange") \
4646
V(resource_symbol, "resource_symbol") \
4747
V(trigger_async_id_symbol, "trigger_async_id_symbol") \
48+
V(source_text_module_default_hdo, "source_text_module_default_hdo") \
4849
V(vm_dynamic_import_default_internal, "vm_dynamic_import_default_internal") \
4950
V(vm_dynamic_import_main_context_default, \
5051
"vm_dynamic_import_main_context_default") \
Collapse file

‎src/module_wrap.cc‎

Copy file name to clipboardExpand all lines: src/module_wrap.cc
+25-17Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,10 @@ ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
102102
return nullptr;
103103
}
104104

105-
// new ModuleWrap(url, context, source, lineOffset, columnOffset)
106-
// new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
105+
// new ModuleWrap(url, context, source, lineOffset, columnOffset, cachedData)
106+
// new ModuleWrap(url, context, source, lineOffset, columOffset,
107+
// hostDefinedOption) new ModuleWrap(url, context, exportNames,
108+
// syntheticExecutionFunction)
107109
void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
108110
CHECK(args.IsConstructCall());
109111
CHECK_GE(args.Length(), 3);
@@ -132,22 +134,36 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
132134
int column_offset = 0;
133135

134136
bool synthetic = args[2]->IsArray();
137+
138+
Local<PrimitiveArray> host_defined_options =
139+
PrimitiveArray::New(isolate, HostDefinedOptions::kLength);
140+
Local<Symbol> id_symbol;
135141
if (synthetic) {
136142
// new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
137143
CHECK(args[3]->IsFunction());
138144
} else {
139145
// new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
146+
// new ModuleWrap(url, context, source, lineOffset, columOffset,
147+
// hostDefinedOption)
140148
CHECK(args[2]->IsString());
141149
CHECK(args[3]->IsNumber());
142150
line_offset = args[3].As<Int32>()->Value();
143151
CHECK(args[4]->IsNumber());
144152
column_offset = args[4].As<Int32>()->Value();
145-
}
153+
if (args[5]->IsSymbol()) {
154+
id_symbol = args[5].As<Symbol>();
155+
} else {
156+
id_symbol = Symbol::New(isolate, url);
157+
}
158+
host_defined_options->Set(isolate, HostDefinedOptions::kID, id_symbol);
146159

147-
Local<PrimitiveArray> host_defined_options =
148-
PrimitiveArray::New(isolate, HostDefinedOptions::kLength);
149-
Local<Symbol> id_symbol = Symbol::New(isolate, url);
150-
host_defined_options->Set(isolate, HostDefinedOptions::kID, id_symbol);
160+
if (that->SetPrivate(context,
161+
realm->isolate_data()->host_defined_option_symbol(),
162+
id_symbol)
163+
.IsNothing()) {
164+
return;
165+
}
166+
}
151167

152168
ShouldNotAbortOnUncaughtScope no_abort_scope(realm->env());
153169
TryCatchScope try_catch(realm->env());
@@ -173,8 +189,7 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
173189
SyntheticModuleEvaluationStepsCallback);
174190
} else {
175191
ScriptCompiler::CachedData* cached_data = nullptr;
176-
if (!args[5]->IsUndefined()) {
177-
CHECK(args[5]->IsArrayBufferView());
192+
if (args[5]->IsArrayBufferView()) {
178193
Local<ArrayBufferView> cached_data_buf = args[5].As<ArrayBufferView>();
179194
uint8_t* data =
180195
static_cast<uint8_t*>(cached_data_buf->Buffer()->Data());
@@ -237,13 +252,6 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
237252
return;
238253
}
239254

240-
if (that->SetPrivate(context,
241-
realm->isolate_data()->host_defined_option_symbol(),
242-
id_symbol)
243-
.IsNothing()) {
244-
return;
245-
}
246-
247255
// Use the extras object as an object whose GetCreationContext() will be the
248256
// original `context`, since the `Context` itself strictly speaking cannot
249257
// be stored in an internal field.
@@ -837,7 +845,7 @@ void ModuleWrap::HostInitializeImportMetaObjectCallback(
837845
return;
838846
}
839847
DCHECK(id->IsSymbol());
840-
Local<Value> args[] = {id, meta};
848+
Local<Value> args[] = {id, meta, wrap};
841849
TryCatchScope try_catch(env);
842850
USE(callback->Call(
843851
context, Undefined(realm->isolate()), arraysize(args), args));

0 commit comments

Comments
0 (0)
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.