All files / lib/internal/modules run_main.js

100% Statements 86/86
96.67% Branches 29/30
100% Functions 6/6
100% Lines 86/86

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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