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