| 
3 | 3 | const {  | 
4 | 4 |   ArrayPrototypeMap,  | 
5 | 5 |   ArrayPrototypePush,  | 
6 |  | -  Boolean,  | 
7 | 6 |   FunctionPrototypeCall,  | 
8 | 7 |   JSONParse,  | 
9 | 8 |   ObjectKeys,  | 
@@ -52,6 +51,7 @@ let debug = require('internal/util/debuglog').debuglog('esm', (fn) => {  | 
52 | 51 | });  | 
53 | 52 | const { emitExperimentalWarning, kEmptyObject, setOwnProperty, isWindows } = require('internal/util');  | 
54 | 53 | const {  | 
 | 54 | +  ERR_INVALID_RETURN_PROPERTY_VALUE,  | 
55 | 55 |   ERR_UNKNOWN_BUILTIN_MODULE,  | 
56 | 56 | } = require('internal/errors').codes;  | 
57 | 57 | const { maybeCacheSourceMap } = require('internal/source_map/source_map_cache');  | 
@@ -185,7 +185,7 @@ function createCJSModuleWrap(url, source, isMain, format, loadCJS = loadCJSModul  | 
185 | 185 |   // In case the source was not provided by the `load` step, we need fetch it now.  | 
186 | 186 |   source = stringify(source ?? getSource(new URL(url)).source);  | 
187 | 187 | 
 
  | 
188 |  | -  const { exportNames, module } = cjsPreparseModuleExports(filename, source, isMain, format);  | 
 | 188 | +  const { exportNames, module } = cjsPreparseModuleExports(filename, source, format);  | 
189 | 189 |   cjsCache.set(url, module);  | 
190 | 190 | 
 
  | 
191 | 191 |   const wrapperNames = [...exportNames, 'module.exports'];  | 
@@ -229,6 +229,47 @@ function createCJSModuleWrap(url, source, isMain, format, loadCJS = loadCJSModul  | 
229 | 229 |   }, module);  | 
230 | 230 | }  | 
231 | 231 | 
 
  | 
 | 232 | +/**  | 
 | 233 | + * Creates a ModuleWrap object for a CommonJS module without source texts.  | 
 | 234 | + * @param {string} url - The URL of the module.  | 
 | 235 | + * @param {boolean} isMain - Whether the module is the main module.  | 
 | 236 | + * @returns {ModuleWrap} The ModuleWrap object for the CommonJS module.  | 
 | 237 | + */  | 
 | 238 | +function createCJSNoSourceModuleWrap(url, isMain) {  | 
 | 239 | +  debug(`Translating CJSModule without source ${url}`);  | 
 | 240 | + | 
 | 241 | +  const filename = urlToFilename(url);  | 
 | 242 | + | 
 | 243 | +  const module = cjsEmplaceModuleCacheEntry(filename);  | 
 | 244 | +  cjsCache.set(url, module);  | 
 | 245 | + | 
 | 246 | +  if (isMain) {  | 
 | 247 | +    setOwnProperty(process, 'mainModule', module);  | 
 | 248 | +  }  | 
 | 249 | + | 
 | 250 | +  // Addon export names are not known until the addon is loaded.  | 
 | 251 | +  const exportNames = ['default', 'module.exports'];  | 
 | 252 | +  return new ModuleWrap(url, undefined, exportNames, function evaluationCallback() {  | 
 | 253 | +    debug(`Loading CJSModule ${url}`);  | 
 | 254 | + | 
 | 255 | +    if (!module.loaded) {  | 
 | 256 | +      wrapModuleLoad(filename, null, isMain);  | 
 | 257 | +    }  | 
 | 258 | + | 
 | 259 | +    /** @type {import('./loader').ModuleExports} */  | 
 | 260 | +    let exports;  | 
 | 261 | +    if (module[kModuleExport] !== undefined) {  | 
 | 262 | +      exports = module[kModuleExport];  | 
 | 263 | +      module[kModuleExport] = undefined;  | 
 | 264 | +    } else {  | 
 | 265 | +      ({ exports } = module);  | 
 | 266 | +    }  | 
 | 267 | + | 
 | 268 | +    this.setExport('default', exports);  | 
 | 269 | +    this.setExport('module.exports', exports);  | 
 | 270 | +  }, module);  | 
 | 271 | +}  | 
 | 272 | + | 
232 | 273 | translators.set('commonjs-sync', function requireCommonJS(url, source, isMain) {  | 
233 | 274 |   initCJSParseSync();  | 
234 | 275 | 
 
  | 
@@ -280,26 +321,38 @@ translators.set('commonjs', function commonjsStrategy(url, source, isMain) {  | 
280 | 321 |   return createCJSModuleWrap(url, source, isMain, 'commonjs', cjsLoader);  | 
281 | 322 | });  | 
282 | 323 | 
 
  | 
 | 324 | +/**  | 
 | 325 | + * Get or create an entry in the CJS module cache for the given filename.  | 
 | 326 | + * @param {string} filename CJS module filename  | 
 | 327 | + * @returns {CJSModule} the cached CJS module entry  | 
 | 328 | + */  | 
 | 329 | +function cjsEmplaceModuleCacheEntry(filename, exportNames) {  | 
 | 330 | +  // TODO: Do we want to keep hitting the user mutable CJS loader here?  | 
 | 331 | +  let cjsMod = CJSModule._cache[filename];  | 
 | 332 | +  if (cjsMod) {  | 
 | 333 | +    return cjsMod;  | 
 | 334 | +  }  | 
 | 335 | + | 
 | 336 | +  cjsMod = new CJSModule(filename);  | 
 | 337 | +  cjsMod.filename = filename;  | 
 | 338 | +  cjsMod.paths = CJSModule._nodeModulePaths(cjsMod.path);  | 
 | 339 | +  cjsMod[kIsCachedByESMLoader] = true;  | 
 | 340 | +  CJSModule._cache[filename] = cjsMod;  | 
 | 341 | + | 
 | 342 | +  return cjsMod;  | 
 | 343 | +}  | 
 | 344 | + | 
283 | 345 | /**  | 
284 | 346 |  * Pre-parses a CommonJS module's exports and re-exports.  | 
285 | 347 |  * @param {string} filename - The filename of the module.  | 
286 | 348 |  * @param {string} [source] - The source code of the module.  | 
287 |  | - * @param {boolean} isMain - Whether it is pre-parsing for the entry point.  | 
288 |  | - * @param {string} format  | 
 | 349 | + * @param {string} [format]  | 
289 | 350 |  */  | 
290 |  | -function cjsPreparseModuleExports(filename, source, isMain, format) {  | 
291 |  | -  let module = CJSModule._cache[filename];  | 
292 |  | -  if (module && module[kModuleExportNames] !== undefined) {  | 
 | 351 | +function cjsPreparseModuleExports(filename, source, format) {  | 
 | 352 | +  const module = cjsEmplaceModuleCacheEntry(filename);  | 
 | 353 | +  if (module[kModuleExportNames] !== undefined) {  | 
293 | 354 |     return { module, exportNames: module[kModuleExportNames] };  | 
294 | 355 |   }  | 
295 |  | -  const loaded = Boolean(module);  | 
296 |  | -  if (!loaded) {  | 
297 |  | -    module = new CJSModule(filename);  | 
298 |  | -    module.filename = filename;  | 
299 |  | -    module.paths = CJSModule._nodeModulePaths(module.path);  | 
300 |  | -    module[kIsCachedByESMLoader] = true;  | 
301 |  | -    CJSModule._cache[filename] = module;  | 
302 |  | -  }  | 
303 | 356 | 
 
  | 
304 | 357 |   if (source === undefined) {  | 
305 | 358 |     ({ source } = loadSourceForCJSWithHooks(module, filename, format));  | 
@@ -340,7 +393,7 @@ function cjsPreparseModuleExports(filename, source, isMain, format) {  | 
340 | 393 | 
 
  | 
341 | 394 |       if (format === 'commonjs' ||  | 
342 | 395 |         (!BuiltinModule.normalizeRequirableId(resolved) && findLongestRegisteredExtension(resolved) === '.js')) {  | 
343 |  | -        const { exportNames: reexportNames } = cjsPreparseModuleExports(resolved, undefined, false, format);  | 
 | 396 | +        const { exportNames: reexportNames } = cjsPreparseModuleExports(resolved, undefined, format);  | 
344 | 397 |         for (const name of reexportNames) {  | 
345 | 398 |           exportNames.add(name);  | 
346 | 399 |         }  | 
@@ -462,6 +515,25 @@ translators.set('wasm', async function(url, source) {  | 
462 | 515 |   }).module;  | 
463 | 516 | });  | 
464 | 517 | 
 
  | 
 | 518 | +// Strategy for loading a addon  | 
 | 519 | +translators.set('addon', function translateAddon(url, source, isMain) {  | 
 | 520 | +  emitExperimentalWarning('Importing addons');  | 
 | 521 | + | 
 | 522 | +  // The addon must be loaded from file system with dlopen. Assert  | 
 | 523 | +  // the source is null.  | 
 | 524 | +  if (source !== null) {  | 
 | 525 | +    throw new ERR_INVALID_RETURN_PROPERTY_VALUE(  | 
 | 526 | +      'null',  | 
 | 527 | +      'load',  | 
 | 528 | +      'source',  | 
 | 529 | +      source);  | 
 | 530 | +  }  | 
 | 531 | + | 
 | 532 | +  debug(`Translating addon ${url}`);  | 
 | 533 | + | 
 | 534 | +  return createCJSNoSourceModuleWrap(url, isMain);  | 
 | 535 | +});  | 
 | 536 | + | 
465 | 537 | // Strategy for loading a commonjs TypeScript module  | 
466 | 538 | translators.set('commonjs-typescript', function(url, source) {  | 
467 | 539 |   emitExperimentalWarning('Type Stripping');  | 
 | 
0 commit comments