1'use strict'; 2 3const { 4 ObjectCreate, 5 StringPrototypeEndsWith, 6} = primordials; 7const CJSLoader = require('internal/modules/cjs/loader'); 8const { Module, toRealPath, readPackageScope } = CJSLoader; 9const { getOptionValue } = require('internal/options'); 10const path = require('path'); 11const { 12 handleProcessExit, 13} = require('internal/modules/esm/handle_process_exit'); 14 15function resolveMainPath(main) { 16 // Note extension resolution for the main entry point can be deprecated in a 17 // future major. 18 // Module._findPath is monkey-patchable here. 19 let mainPath = Module._findPath(path.resolve(main), null, true); 20 if (!mainPath) 21 return; 22 23 const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); 24 if (!preserveSymlinksMain) 25 mainPath = toRealPath(mainPath); 26 27 return mainPath; 28} 29 30function shouldUseESMLoader(mainPath) { 31 /** 32 * @type {string[]} userLoaders A list of custom loaders registered by the user 33 * (or an empty list when none have been registered). 34 */ 35 const userLoaders = getOptionValue('--experimental-loader'); 36 /** 37 * @type {string[]} userImports A list of preloaded modules registered by the user 38 * (or an empty list when none have been registered). 39 */ 40 const userImports = getOptionValue('--import'); 41 if (userLoaders.length > 0 || userImports.length > 0) 42 return true; 43 const esModuleSpecifierResolution = 44 getOptionValue('--experimental-specifier-resolution'); 45 if (esModuleSpecifierResolution === 'node') 46 return true; 47 // Determine the module format of the main 48 if (mainPath && StringPrototypeEndsWith(mainPath, '.mjs')) 49 return true; 50 if (!mainPath || StringPrototypeEndsWith(mainPath, '.cjs')) 51 return false; 52 const pkg = readPackageScope(mainPath); 53 return pkg && pkg.data.type === 'module'; 54} 55 56function runMainESM(mainPath) { 57 const { loadESM } = require('internal/process/esm_loader'); 58 const { pathToFileURL } = require('internal/url'); 59 60 handleMainPromise(loadESM((esmLoader) => { 61 const main = path.isAbsolute(mainPath) ? 62 pathToFileURL(mainPath).href : mainPath; 63 return esmLoader.import(main, undefined, ObjectCreate(null)); 64 })); 65} 66 67async function handleMainPromise(promise) { 68 process.on('exit', handleProcessExit); 69 try { 70 return await promise; 71 } finally { 72 process.off('exit', handleProcessExit); 73 } 74} 75 76// For backwards compatibility, we have to run a bunch of 77// monkey-patchable code that belongs to the CJS loader (exposed by 78// `require('module')`) even when the entry point is ESM. 79function executeUserEntryPoint(main = process.argv[1]) { 80 const resolvedMain = resolveMainPath(main); 81 const useESMLoader = shouldUseESMLoader(resolvedMain); 82 if (useESMLoader) { 83 runMainESM(resolvedMain || main); 84 } else { 85 // Module._load is the monkey-patchable CJS module loader. 86 Module._load(main, null, true); 87 } 88} 89 90module.exports = { 91 executeUserEntryPoint, 92 handleMainPromise, 93}; 94