11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  RegExpPrototypeExec,
51cb0ef41Sopenharmony_ci  ObjectPrototypeHasOwnProperty,
61cb0ef41Sopenharmony_ci  PromisePrototypeThen,
71cb0ef41Sopenharmony_ci  PromiseResolve,
81cb0ef41Sopenharmony_ci  StringPrototypeIncludes,
91cb0ef41Sopenharmony_ci  StringPrototypeCharCodeAt,
101cb0ef41Sopenharmony_ci  StringPrototypeSlice,
111cb0ef41Sopenharmony_ci} = primordials;
121cb0ef41Sopenharmony_ciconst { getOptionValue } = require('internal/options');
131cb0ef41Sopenharmony_ciconst {
141cb0ef41Sopenharmony_ci  extensionFormatMap,
151cb0ef41Sopenharmony_ci  getFormatOfExtensionlessFile,
161cb0ef41Sopenharmony_ci  getLegacyExtensionFormat,
171cb0ef41Sopenharmony_ci  mimeToFormat,
181cb0ef41Sopenharmony_ci} = require('internal/modules/esm/formats');
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciconst experimentalNetworkImports =
211cb0ef41Sopenharmony_ci  getOptionValue('--experimental-network-imports');
221cb0ef41Sopenharmony_ciconst experimentalSpecifierResolution =
231cb0ef41Sopenharmony_ci  getOptionValue('--experimental-specifier-resolution');
241cb0ef41Sopenharmony_ciconst defaultTypeFlag = getOptionValue('--experimental-default-type');
251cb0ef41Sopenharmony_ci// The next line is where we flip the default to ES modules someday.
261cb0ef41Sopenharmony_ciconst defaultType = defaultTypeFlag === 'module' ? 'module' : 'commonjs';
271cb0ef41Sopenharmony_ciconst { getPackageType } = require('internal/modules/esm/resolve');
281cb0ef41Sopenharmony_ciconst { fileURLToPath } = require('internal/url');
291cb0ef41Sopenharmony_ciconst { ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes;
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ciconst protocolHandlers = {
321cb0ef41Sopenharmony_ci  '__proto__': null,
331cb0ef41Sopenharmony_ci  'data:': getDataProtocolModuleFormat,
341cb0ef41Sopenharmony_ci  'file:': getFileProtocolModuleFormat,
351cb0ef41Sopenharmony_ci  'http:': getHttpProtocolModuleFormat,
361cb0ef41Sopenharmony_ci  'https:': getHttpProtocolModuleFormat,
371cb0ef41Sopenharmony_ci  'node:'() { return 'builtin'; },
381cb0ef41Sopenharmony_ci};
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci/**
411cb0ef41Sopenharmony_ci * @param {URL} parsed
421cb0ef41Sopenharmony_ci * @returns {string | null}
431cb0ef41Sopenharmony_ci */
441cb0ef41Sopenharmony_cifunction getDataProtocolModuleFormat(parsed) {
451cb0ef41Sopenharmony_ci  const { 1: mime } = RegExpPrototypeExec(
461cb0ef41Sopenharmony_ci    /^([^/]+\/[^;,]+)(?:[^,]*?)(;base64)?,/,
471cb0ef41Sopenharmony_ci    parsed.pathname,
481cb0ef41Sopenharmony_ci  ) || [ null, null, null ];
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  return mimeToFormat(mime);
511cb0ef41Sopenharmony_ci}
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ciconst DOT_CODE = 46;
541cb0ef41Sopenharmony_ciconst SLASH_CODE = 47;
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci/**
571cb0ef41Sopenharmony_ci * Returns the file extension from a URL. Should give similar result to
581cb0ef41Sopenharmony_ci * `require('node:path').extname(require('node:url').fileURLToPath(url))`
591cb0ef41Sopenharmony_ci * when used with a `file:` URL.
601cb0ef41Sopenharmony_ci * @param {URL} url
611cb0ef41Sopenharmony_ci * @returns {string}
621cb0ef41Sopenharmony_ci */
631cb0ef41Sopenharmony_cifunction extname(url) {
641cb0ef41Sopenharmony_ci  const { pathname } = url;
651cb0ef41Sopenharmony_ci  for (let i = pathname.length - 1; i > 0; i--) {
661cb0ef41Sopenharmony_ci    switch (StringPrototypeCharCodeAt(pathname, i)) {
671cb0ef41Sopenharmony_ci      case SLASH_CODE:
681cb0ef41Sopenharmony_ci        return '';
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci      case DOT_CODE:
711cb0ef41Sopenharmony_ci        return StringPrototypeCharCodeAt(pathname, i - 1) === SLASH_CODE ? '' : StringPrototypeSlice(pathname, i);
721cb0ef41Sopenharmony_ci    }
731cb0ef41Sopenharmony_ci  }
741cb0ef41Sopenharmony_ci  return '';
751cb0ef41Sopenharmony_ci}
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci/**
781cb0ef41Sopenharmony_ci * Determine whether the given file URL is under a `node_modules` folder.
791cb0ef41Sopenharmony_ci * This function assumes that the input has already been verified to be a `file:` URL,
801cb0ef41Sopenharmony_ci * and is a file rather than a folder.
811cb0ef41Sopenharmony_ci * @param {URL} url
821cb0ef41Sopenharmony_ci */
831cb0ef41Sopenharmony_cifunction underNodeModules(url) {
841cb0ef41Sopenharmony_ci  if (url.protocol !== 'file:') { return false; } // We determine module types for other protocols based on MIME header
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  return StringPrototypeIncludes(url.pathname, '/node_modules/');
871cb0ef41Sopenharmony_ci}
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci/**
901cb0ef41Sopenharmony_ci * @param {URL} url
911cb0ef41Sopenharmony_ci * @param {{parentURL: string}} context
921cb0ef41Sopenharmony_ci * @param {boolean} ignoreErrors
931cb0ef41Sopenharmony_ci * @returns {string}
941cb0ef41Sopenharmony_ci */
951cb0ef41Sopenharmony_cifunction getFileProtocolModuleFormat(url, context, ignoreErrors) {
961cb0ef41Sopenharmony_ci  const ext = extname(url);
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  if (ext === '.js') {
991cb0ef41Sopenharmony_ci    const packageType = getPackageType(url);
1001cb0ef41Sopenharmony_ci    if (packageType !== 'none') {
1011cb0ef41Sopenharmony_ci      return packageType;
1021cb0ef41Sopenharmony_ci    }
1031cb0ef41Sopenharmony_ci    // The controlling `package.json` file has no `type` field.
1041cb0ef41Sopenharmony_ci    if (defaultType === 'module') {
1051cb0ef41Sopenharmony_ci      // An exception to the type flag making ESM the default everywhere is that package scopes under `node_modules`
1061cb0ef41Sopenharmony_ci      // should retain the assumption that a lack of a `type` field means CommonJS.
1071cb0ef41Sopenharmony_ci      return underNodeModules(url) ? 'commonjs' : 'module';
1081cb0ef41Sopenharmony_ci    }
1091cb0ef41Sopenharmony_ci    return 'commonjs';
1101cb0ef41Sopenharmony_ci  }
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  if (ext === '') {
1131cb0ef41Sopenharmony_ci    const packageType = getPackageType(url);
1141cb0ef41Sopenharmony_ci    if (defaultType === 'commonjs') { // Legacy behavior
1151cb0ef41Sopenharmony_ci      if (packageType === 'none' || packageType === 'commonjs') {
1161cb0ef41Sopenharmony_ci        return 'commonjs';
1171cb0ef41Sopenharmony_ci      } // Else packageType === 'module'
1181cb0ef41Sopenharmony_ci      return getFormatOfExtensionlessFile(url);
1191cb0ef41Sopenharmony_ci    } // Else defaultType === 'module'
1201cb0ef41Sopenharmony_ci    if (underNodeModules(url)) { // Exception for package scopes under `node_modules`
1211cb0ef41Sopenharmony_ci      return packageType === 'module' ? getFormatOfExtensionlessFile(url) : 'commonjs';
1221cb0ef41Sopenharmony_ci    }
1231cb0ef41Sopenharmony_ci    if (packageType === 'none' || packageType === 'module') {
1241cb0ef41Sopenharmony_ci      return getFormatOfExtensionlessFile(url);
1251cb0ef41Sopenharmony_ci    } // Else packageType === 'commonjs'
1261cb0ef41Sopenharmony_ci    return 'commonjs';
1271cb0ef41Sopenharmony_ci  }
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci  const format = extensionFormatMap[ext];
1301cb0ef41Sopenharmony_ci  if (format) { return format; }
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  if (experimentalSpecifierResolution !== 'node') {
1331cb0ef41Sopenharmony_ci    // Explicit undefined return indicates load hook should rerun format check
1341cb0ef41Sopenharmony_ci    if (ignoreErrors) { return undefined; }
1351cb0ef41Sopenharmony_ci    const filepath = fileURLToPath(url);
1361cb0ef41Sopenharmony_ci    throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath);
1371cb0ef41Sopenharmony_ci  }
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci  return getLegacyExtensionFormat(ext) ?? null;
1401cb0ef41Sopenharmony_ci}
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci/**
1431cb0ef41Sopenharmony_ci * @param {URL} url
1441cb0ef41Sopenharmony_ci * @param {{parentURL: string}} context
1451cb0ef41Sopenharmony_ci * @returns {Promise<string> | undefined} only works when enabled
1461cb0ef41Sopenharmony_ci */
1471cb0ef41Sopenharmony_cifunction getHttpProtocolModuleFormat(url, context) {
1481cb0ef41Sopenharmony_ci  if (experimentalNetworkImports) {
1491cb0ef41Sopenharmony_ci    const { fetchModule } = require('internal/modules/esm/fetch_module');
1501cb0ef41Sopenharmony_ci    return PromisePrototypeThen(
1511cb0ef41Sopenharmony_ci      PromiseResolve(fetchModule(url, context)),
1521cb0ef41Sopenharmony_ci      (entry) => {
1531cb0ef41Sopenharmony_ci        return mimeToFormat(entry.headers['content-type']);
1541cb0ef41Sopenharmony_ci      },
1551cb0ef41Sopenharmony_ci    );
1561cb0ef41Sopenharmony_ci  }
1571cb0ef41Sopenharmony_ci}
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci/**
1601cb0ef41Sopenharmony_ci * @param {URL} url
1611cb0ef41Sopenharmony_ci * @param {{parentURL: string}} context
1621cb0ef41Sopenharmony_ci * @returns {Promise<string> | string | undefined} only works when enabled
1631cb0ef41Sopenharmony_ci */
1641cb0ef41Sopenharmony_cifunction defaultGetFormatWithoutErrors(url, context) {
1651cb0ef41Sopenharmony_ci  const protocol = url.protocol;
1661cb0ef41Sopenharmony_ci  if (!ObjectPrototypeHasOwnProperty(protocolHandlers, protocol)) {
1671cb0ef41Sopenharmony_ci    return null;
1681cb0ef41Sopenharmony_ci  }
1691cb0ef41Sopenharmony_ci  return protocolHandlers[protocol](url, context, true);
1701cb0ef41Sopenharmony_ci}
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci/**
1731cb0ef41Sopenharmony_ci * @param {URL} url
1741cb0ef41Sopenharmony_ci * @param {{parentURL: string}} context
1751cb0ef41Sopenharmony_ci * @returns {Promise<string> | string | undefined} only works when enabled
1761cb0ef41Sopenharmony_ci */
1771cb0ef41Sopenharmony_cifunction defaultGetFormat(url, context) {
1781cb0ef41Sopenharmony_ci  const protocol = url.protocol;
1791cb0ef41Sopenharmony_ci  if (!ObjectPrototypeHasOwnProperty(protocolHandlers, protocol)) {
1801cb0ef41Sopenharmony_ci    return null;
1811cb0ef41Sopenharmony_ci  }
1821cb0ef41Sopenharmony_ci  return protocolHandlers[protocol](url, context, false);
1831cb0ef41Sopenharmony_ci}
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_cimodule.exports = {
1861cb0ef41Sopenharmony_ci  defaultGetFormat,
1871cb0ef41Sopenharmony_ci  defaultGetFormatWithoutErrors,
1881cb0ef41Sopenharmony_ci  extensionFormatMap,
1891cb0ef41Sopenharmony_ci  extname,
1901cb0ef41Sopenharmony_ci};
191