11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  StringPrototypeEndsWith,
51cb0ef41Sopenharmony_ci} = primordials;
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst { getOptionValue } = require('internal/options');
81cb0ef41Sopenharmony_ciconst path = require('path');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci/**
111cb0ef41Sopenharmony_ci * Get the absolute path to the main entry point.
121cb0ef41Sopenharmony_ci * @param {string} main - Entry point path
131cb0ef41Sopenharmony_ci */
141cb0ef41Sopenharmony_cifunction resolveMainPath(main) {
151cb0ef41Sopenharmony_ci  const defaultType = getOptionValue('--experimental-default-type');
161cb0ef41Sopenharmony_ci  /** @type {string} */
171cb0ef41Sopenharmony_ci  let mainPath;
181cb0ef41Sopenharmony_ci  if (defaultType === 'module') {
191cb0ef41Sopenharmony_ci    if (getOptionValue('--preserve-symlinks-main')) { return; }
201cb0ef41Sopenharmony_ci    mainPath = path.resolve(main);
211cb0ef41Sopenharmony_ci  } else {
221cb0ef41Sopenharmony_ci    // Extension searching for the main entry point is supported only in legacy mode.
231cb0ef41Sopenharmony_ci    // Module._findPath is monkey-patchable here.
241cb0ef41Sopenharmony_ci    const { Module } = require('internal/modules/cjs/loader');
251cb0ef41Sopenharmony_ci    mainPath = Module._findPath(path.resolve(main), null, true);
261cb0ef41Sopenharmony_ci  }
271cb0ef41Sopenharmony_ci  if (!mainPath) { return; }
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
301cb0ef41Sopenharmony_ci  if (!preserveSymlinksMain) {
311cb0ef41Sopenharmony_ci    const { toRealPath } = require('internal/modules/helpers');
321cb0ef41Sopenharmony_ci    try {
331cb0ef41Sopenharmony_ci      mainPath = toRealPath(mainPath);
341cb0ef41Sopenharmony_ci    } catch (err) {
351cb0ef41Sopenharmony_ci      if (defaultType === 'module' && err?.code === 'ENOENT') {
361cb0ef41Sopenharmony_ci        const { decorateErrorWithCommonJSHints } = require('internal/modules/esm/resolve');
371cb0ef41Sopenharmony_ci        const { getCWDURL } = require('internal/util');
381cb0ef41Sopenharmony_ci        decorateErrorWithCommonJSHints(err, mainPath, getCWDURL());
391cb0ef41Sopenharmony_ci      }
401cb0ef41Sopenharmony_ci      throw err;
411cb0ef41Sopenharmony_ci    }
421cb0ef41Sopenharmony_ci  }
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  return mainPath;
451cb0ef41Sopenharmony_ci}
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci/**
481cb0ef41Sopenharmony_ci * Determine whether the main entry point should be loaded through the ESM Loader.
491cb0ef41Sopenharmony_ci * @param {string} mainPath - Absolute path to the main entry point
501cb0ef41Sopenharmony_ci */
511cb0ef41Sopenharmony_cifunction shouldUseESMLoader(mainPath) {
521cb0ef41Sopenharmony_ci  if (getOptionValue('--experimental-default-type') === 'module') { return true; }
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  /**
551cb0ef41Sopenharmony_ci   * @type {string[]} userLoaders A list of custom loaders registered by the user
561cb0ef41Sopenharmony_ci   * (or an empty list when none have been registered).
571cb0ef41Sopenharmony_ci   */
581cb0ef41Sopenharmony_ci  const userLoaders = getOptionValue('--experimental-loader');
591cb0ef41Sopenharmony_ci  /**
601cb0ef41Sopenharmony_ci   * @type {string[]} userImports A list of preloaded modules registered by the user
611cb0ef41Sopenharmony_ci   * (or an empty list when none have been registered).
621cb0ef41Sopenharmony_ci   */
631cb0ef41Sopenharmony_ci  const userImports = getOptionValue('--import');
641cb0ef41Sopenharmony_ci  if (userLoaders.length > 0 || userImports.length > 0) {
651cb0ef41Sopenharmony_ci    return true;
661cb0ef41Sopenharmony_ci  }
671cb0ef41Sopenharmony_ci  const esModuleSpecifierResolution =
681cb0ef41Sopenharmony_ci    getOptionValue('--experimental-specifier-resolution');
691cb0ef41Sopenharmony_ci  if (esModuleSpecifierResolution === 'node') {
701cb0ef41Sopenharmony_ci    return true;
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci  // Determine the module format of the entry point.
731cb0ef41Sopenharmony_ci  if (mainPath && StringPrototypeEndsWith(mainPath, '.mjs')) { return true; }
741cb0ef41Sopenharmony_ci  if (!mainPath || StringPrototypeEndsWith(mainPath, '.cjs')) { return false; }
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  const { readPackageScope } = require('internal/modules/package_json_reader');
771cb0ef41Sopenharmony_ci  const pkg = readPackageScope(mainPath);
781cb0ef41Sopenharmony_ci  // No need to guard `pkg` as it can only be an object or `false`.
791cb0ef41Sopenharmony_ci  return pkg.data?.type === 'module' || getOptionValue('--experimental-default-type') === 'module';
801cb0ef41Sopenharmony_ci}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci/**
831cb0ef41Sopenharmony_ci * Run the main entry point through the ESM Loader.
841cb0ef41Sopenharmony_ci * @param {string} mainPath - Absolute path for the main entry point
851cb0ef41Sopenharmony_ci */
861cb0ef41Sopenharmony_cifunction runMainESM(mainPath) {
871cb0ef41Sopenharmony_ci  const { loadESM } = require('internal/process/esm_loader');
881cb0ef41Sopenharmony_ci  const { pathToFileURL } = require('internal/url');
891cb0ef41Sopenharmony_ci  const main = pathToFileURL(mainPath).href;
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  handleMainPromise(loadESM((esmLoader) => {
921cb0ef41Sopenharmony_ci    return esmLoader.import(main, undefined, { __proto__: null });
931cb0ef41Sopenharmony_ci  }));
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci/**
971cb0ef41Sopenharmony_ci * Handle process exit events around the main entry point promise.
981cb0ef41Sopenharmony_ci * @param {Promise} promise - Main entry point promise
991cb0ef41Sopenharmony_ci */
1001cb0ef41Sopenharmony_ciasync function handleMainPromise(promise) {
1011cb0ef41Sopenharmony_ci  const {
1021cb0ef41Sopenharmony_ci    handleProcessExit,
1031cb0ef41Sopenharmony_ci  } = require('internal/modules/esm/handle_process_exit');
1041cb0ef41Sopenharmony_ci  process.on('exit', handleProcessExit);
1051cb0ef41Sopenharmony_ci  try {
1061cb0ef41Sopenharmony_ci    return await promise;
1071cb0ef41Sopenharmony_ci  } finally {
1081cb0ef41Sopenharmony_ci    process.off('exit', handleProcessExit);
1091cb0ef41Sopenharmony_ci  }
1101cb0ef41Sopenharmony_ci}
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci/**
1131cb0ef41Sopenharmony_ci * Parse the CLI main entry point string and run it.
1141cb0ef41Sopenharmony_ci * For backwards compatibility, we have to run a bunch of monkey-patchable code that belongs to the CJS loader (exposed
1151cb0ef41Sopenharmony_ci * by `require('module')`) even when the entry point is ESM.
1161cb0ef41Sopenharmony_ci * This monkey-patchable code is bypassed under `--experimental-default-type=module`.
1171cb0ef41Sopenharmony_ci * Because of backwards compatibility, this function is exposed publicly via `import { runMain } from 'node:module'`.
1181cb0ef41Sopenharmony_ci * @param {string} main - First positional CLI argument, such as `'entry.js'` from `node entry.js`
1191cb0ef41Sopenharmony_ci */
1201cb0ef41Sopenharmony_cifunction executeUserEntryPoint(main = process.argv[1]) {
1211cb0ef41Sopenharmony_ci  const resolvedMain = resolveMainPath(main);
1221cb0ef41Sopenharmony_ci  const useESMLoader = shouldUseESMLoader(resolvedMain);
1231cb0ef41Sopenharmony_ci  if (useESMLoader) {
1241cb0ef41Sopenharmony_ci    runMainESM(resolvedMain || main);
1251cb0ef41Sopenharmony_ci  } else {
1261cb0ef41Sopenharmony_ci    // Module._load is the monkey-patchable CJS module loader.
1271cb0ef41Sopenharmony_ci    const { Module } = require('internal/modules/cjs/loader');
1281cb0ef41Sopenharmony_ci    Module._load(main, null, true);
1291cb0ef41Sopenharmony_ci  }
1301cb0ef41Sopenharmony_ci}
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_cimodule.exports = {
1331cb0ef41Sopenharmony_ci  executeUserEntryPoint,
1341cb0ef41Sopenharmony_ci  handleMainPromise,
1351cb0ef41Sopenharmony_ci};
136