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