• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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