◐ Shell
clean mode source ↗

module: centralize SourceTextModule compilation for builtin loader · nodejs/node@4dae68c

@@ -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');

212223+

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

}

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) {

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

}

218255219256

if (moduleRegistries.has(referrerSymbol)) {

@@ -288,6 +325,29 @@ async function initializeHooks() {

288325

return { __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+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

};