module: centralize SourceTextModule compilation for builtin loader · nodejs/node@4dae68c
@@ -13,12 +13,18 @@ const {
1313},
1414} = internalBinding('util');
1515const {
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');
212223+const { ModuleWrap } = internalBinding('module_wrap');
24+const {
25+ maybeCacheSourceMap,
26+} = require('internal/source_map/source_map_cache');
27+2228const {
2329ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG,
2430ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING,
@@ -167,28 +173,55 @@ function registerModule(referrer, registry) {
167173moduleRegistries.set(idSymbol, registry);
168174}
169175176+/**
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}
183204184205/**
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) {
192225const parentURL = normalizeReferrerURL(referrerName);
193226const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader();
194227return cascadedLoader.import(specifier, parentURL, attributes);
@@ -208,12 +241,16 @@ async function importModuleDynamicallyCallback(referrerSymbol, specifier, attrib
208241// and fall back to the default loader.
209242if (referrerSymbol === vm_dynamic_import_main_context_default) {
210243emitExperimentalWarning('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.
215248if (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}
218255219256if (moduleRegistries.has(referrerSymbol)) {
@@ -288,6 +325,29 @@ async function initializeHooks() {
288325return { __proto__: null, hooks, preloadScripts };
289326}
290327328+/**
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+291351module.exports = {
292352 registerModule,
293353 initializeESM,
@@ -296,4 +356,5 @@ module.exports = {
296356 getConditionsSet,
297357loaderWorkerId: 'internal/modules/esm/worker',
298358 forceDefaultLoader,
359+ compileSourceTextModule,
299360};