| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent d519d33 commit 0307e4d
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -101,6 +101,9 @@ const kIsMainSymbol = Symbol('kIsMainSymbol'); | |||
| 101 | 101 | const kIsCachedByESMLoader = Symbol('kIsCachedByESMLoader'); | |
| 102 | 102 | const kRequiredModuleSymbol = Symbol('kRequiredModuleSymbol'); | |
| 103 | 103 | const kIsExecuting = Symbol('kIsExecuting'); | |
| 104 | + | ||
| 105 | + const kFormat = Symbol('kFormat'); | ||
| 106 | + | ||
| 104 | 107 | // Set first due to cycle with ESM loader functions. | |
| 105 | 108 | module.exports = { | |
| 106 | 109 | kModuleSource, | |
@@ -437,9 +440,8 @@ function initializeCJS() { | |||
| 437 | 440 | Module._extensions['.ts'] = loadTS; | |
| 438 | 441 | } | |
| 439 | 442 | if (getOptionValue('--experimental-require-module')) { | |
| 440 | - Module._extensions['.mjs'] = loadESMFromCJS; | ||
| 441 | 443 | if (tsEnabled) { | |
| 442 | - Module._extensions['.mts'] = loadESMFromCJS; | ||
| 444 | + Module._extensions['.mts'] = loadMTS; | ||
| 443 | 445 | } | |
| 444 | 446 | } | |
| 445 | 447 | } | |
@@ -654,8 +656,6 @@ function getDefaultExtensions() { | |||
| 654 | 656 | if (tsEnabled) { | |
| 655 | 657 | // remove .ts and .cts from the default extensions | |
| 656 | 658 | // to avoid extensionless require of .ts and .cts files. | |
| 657 | - // it behaves similarly to how .mjs is handled when --experimental-require-module | ||
| 658 | - // is enabled. | ||
| 659 | 659 | extensions = ArrayPrototypeFilter(extensions, (ext) => | |
| 660 | 660 | (ext !== '.ts' || Module._extensions['.ts'] !== loadTS) && | |
| 661 | 661 | (ext !== '.cts' || Module._extensions['.cts'] !== loadCTS), | |
@@ -668,14 +668,10 @@ function getDefaultExtensions() { | |||
| 668 | 668 | ||
| 669 | 669 | if (tsEnabled) { | |
| 670 | 670 | extensions = ArrayPrototypeFilter(extensions, (ext) => | |
| 671 | - ext !== '.mts' || Module._extensions['.mts'] !== loadESMFromCJS, | ||
| 671 | + ext !== '.mts' || Module._extensions['.mts'] !== loadMTS, | ||
| 672 | 672 | ); | |
| 673 | 673 | } | |
| 674 | - // If the .mjs extension is added by --experimental-require-module, | ||
| 675 | - // remove it from the supported default extensions to maintain | ||
| 676 | - // compatibility. | ||
| 677 | - // TODO(joyeecheung): allow both .mjs and .cjs? | ||
| 678 | - return ArrayPrototypeFilter(extensions, (ext) => ext !== '.mjs' || Module._extensions['.mjs'] !== loadESMFromCJS); | ||
| 674 | + return extensions; | ||
| 679 | 675 | } | |
| 680 | 676 | ||
| 681 | 677 | /** | |
@@ -1284,10 +1280,6 @@ Module.prototype.load = function(filename) { | |||
| 1284 | 1280 | this.paths = Module._nodeModulePaths(path.dirname(filename)); | |
| 1285 | 1281 | ||
| 1286 | 1282 | const extension = findLongestRegisteredExtension(filename); | |
| 1287 | - // allow .mjs to be overridden | ||
| 1288 | - if (StringPrototypeEndsWith(filename, '.mjs') && !Module._extensions['.mjs']) { | ||
| 1289 | - throw new ERR_REQUIRE_ESM(filename, true); | ||
| 1290 | - } | ||
| 1291 | 1283 | ||
| 1292 | 1284 | if (getOptionValue('--experimental-strip-types')) { | |
| 1293 | 1285 | if (StringPrototypeEndsWith(filename, '.mts') && !Module._extensions['.mts']) { | |
@@ -1328,12 +1320,10 @@ let requireModuleWarningMode; | |||
| 1328 | 1320 | * Resolve and evaluate it synchronously as ESM if it's ESM. | |
| 1329 | 1321 | * @param {Module} mod CJS module instance | |
| 1330 | 1322 | * @param {string} filename Absolute path of the file. | |
| 1323 | + * @param {string} format Format of the module. If it had types, this would be what it is after type-stripping. | ||
| 1324 | + * @param {string} source Source the module. If it had types, this would have the type stripped. | ||
| 1331 | 1325 | */ | |
| 1332 | - function loadESMFromCJS(mod, filename) { | ||
| 1333 | - let source = getMaybeCachedSource(mod, filename); | ||
| 1334 | - if (getOptionValue('--experimental-strip-types') && path.extname(filename) === '.mts') { | ||
| 1335 | - source = stripTypeScriptModuleTypes(source, filename); | ||
| 1336 | - } | ||
| 1326 | + function loadESMFromCJS(mod, filename, format, source) { | ||
| 1337 | 1327 | const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader(); | |
| 1338 | 1328 | const isMain = mod[kIsMainSymbol]; | |
| 1339 | 1329 | if (isMain) { | |
@@ -1509,9 +1499,30 @@ function wrapSafe(filename, content, cjsModuleInstance, format) { | |||
| 1509 | 1499 | * `exports`) to the file. Returns exception, if any. | |
| 1510 | 1500 | * @param {string} content The source code of the module | |
| 1511 | 1501 | * @param {string} filename The file path of the module | |
| 1512 | - * @param {'module'|'commonjs'|undefined} format Intended format of the module. | ||
| 1502 | + * @param { | ||
| 1503 | + * 'module'|'commonjs'|'commonjs-typescript'|'module-typescript' | ||
| 1504 | + * } format Intended format of the module. | ||
| 1513 | 1505 | */ | |
| 1514 | 1506 | Module.prototype._compile = function(content, filename, format) { | |
| 1507 | + if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') { | ||
| 1508 | + content = stripTypeScriptModuleTypes(content, filename); | ||
| 1509 | + switch (format) { | ||
| 1510 | + case 'commonjs-typescript': { | ||
| 1511 | + format = 'commonjs'; | ||
| 1512 | + break; | ||
| 1513 | + } | ||
| 1514 | + case 'module-typescript': { | ||
| 1515 | + format = 'module'; | ||
| 1516 | + break; | ||
| 1517 | + } | ||
| 1518 | + // If the format is still unknown i.e. 'typescript', detect it in | ||
| 1519 | + // wrapSafe using the type-stripped source. | ||
| 1520 | + default: | ||
| 1521 | + format = undefined; | ||
| 1522 | + break; | ||
| 1523 | + } | ||
| 1524 | + } | ||
| 1525 | + | ||
| 1515 | 1526 | let redirects; | |
| 1516 | 1527 | ||
| 1517 | 1528 | let compiledWrapper; | |
@@ -1524,9 +1535,7 @@ Module.prototype._compile = function(content, filename, format) { | |||
| 1524 | 1535 | } | |
| 1525 | 1536 | ||
| 1526 | 1537 | if (format === 'module') { | |
| 1527 | - // Pass the source into the .mjs extension handler indirectly through the cache. | ||
| 1528 | - this[kModuleSource] = content; | ||
| 1529 | - loadESMFromCJS(this, filename); | ||
| 1538 | + loadESMFromCJS(this, filename, format, content); | ||
| 1530 | 1539 | return; | |
| 1531 | 1540 | } | |
| 1532 | 1541 | ||
@@ -1554,72 +1563,76 @@ Module.prototype._compile = function(content, filename, format) { | |||
| 1554 | 1563 | ||
| 1555 | 1564 | /** | |
| 1556 | 1565 | * Get the source code of a module, using cached ones if it's cached. | |
| 1566 | + * After this returns, mod[kFormat], mod[kModuleSource] and mod[kURL] will be set. | ||
| 1557 | 1567 | * @param {Module} mod Module instance whose source is potentially already cached. | |
| 1558 | 1568 | * @param {string} filename Absolute path to the file of the module. | |
| 1559 | - * @returns {string} | ||
| 1569 | + * @returns {{source: string, format?: string}} | ||
| 1560 | 1570 | */ | |
| 1561 | - function getMaybeCachedSource(mod, filename) { | ||
| 1562 | - // If already analyzed the source, then it will be cached. | ||
| 1563 | - let content; | ||
| 1564 | - if (mod[kModuleSource] !== undefined) { | ||
| 1565 | - content = mod[kModuleSource]; | ||
| 1571 | + function loadSource(mod, filename, formatFromNode) { | ||
| 1572 | + if (formatFromNode !== undefined) { | ||
| 1573 | + mod[kFormat] = formatFromNode; | ||
| 1574 | + } | ||
| 1575 | + const format = mod[kFormat]; | ||
| 1576 | + | ||
| 1577 | + let source = mod[kModuleSource]; | ||
| 1578 | + if (source !== undefined) { | ||
| 1566 | 1579 | mod[kModuleSource] = undefined; | |
| 1567 | 1580 | } else { | |
| 1568 | 1581 | // TODO(joyeecheung): we can read a buffer instead to speed up | |
| 1569 | 1582 | // compilation. | |
| 1570 | - content = fs.readFileSync(filename, 'utf8'); | ||
| 1583 | + source = fs.readFileSync(filename, 'utf8'); | ||
| 1571 | 1584 | } | |
| 1572 | - return content; | ||
| 1585 | + return { source, format }; | ||
| 1573 | 1586 | } | |
| 1574 | 1587 | ||
| 1588 | + /** | ||
| 1589 | + * Built-in handler for `.mts` files. | ||
| 1590 | + * @param {Module} mod CJS module instance | ||
| 1591 | + * @param {string} filename The file path of the module | ||
| 1592 | + */ | ||
| 1593 | + function loadMTS(mod, filename) { | ||
| 1594 | + const loadResult = loadSource(mod, filename, 'module-typescript'); | ||
| 1595 | + mod._compile(loadResult.source, filename, loadResult.format); | ||
| 1596 | + } | ||
| 1597 | + | ||
| 1598 | + /** | ||
| 1599 | + * Built-in handler for `.cts` files. | ||
| 1600 | + * @param {Module} module CJS module instance | ||
| 1601 | + * @param {string} filename The file path of the module | ||
| 1602 | + */ | ||
| 1603 | + | ||
| 1575 | 1604 | function loadCTS(module, filename) { | |
| 1576 | - const source = getMaybeCachedSource(module, filename); | ||
| 1577 | - const code = stripTypeScriptModuleTypes(source, filename); | ||
| 1578 | - module._compile(code, filename, 'commonjs'); | ||
| 1605 | + const loadResult = loadSource(module, filename, 'commonjs-typescript'); | ||
| 1606 | + module._compile(loadResult.source, filename, loadResult.format); | ||
| 1579 | 1607 | } | |
| 1580 | 1608 | ||
| 1581 | 1609 | /** | |
| 1582 | 1610 | * Built-in handler for `.ts` files. | |
| 1583 | - * @param {Module} module The module to compile | ||
| 1611 | + * @param {Module} module CJS module instance | ||
| 1584 | 1612 | * @param {string} filename The file path of the module | |
| 1585 | 1613 | */ | |
| 1586 | 1614 | function loadTS(module, filename) { | |
| 1587 | - // If already analyzed the source, then it will be cached. | ||
| 1588 | - const source = getMaybeCachedSource(module, filename); | ||
| 1589 | - const content = stripTypeScriptModuleTypes(source, filename); | ||
| 1590 | - let format; | ||
| 1591 | 1615 | const pkg = packageJsonReader.getNearestParentPackageJSON(filename); | |
| 1592 | - // Function require shouldn't be used in ES modules. | ||
| 1593 | - if (pkg?.data.type === 'module') { | ||
| 1594 | - if (getOptionValue('--experimental-require-module')) { | ||
| 1595 | - module._compile(content, filename, 'module'); | ||
| 1596 | - return; | ||
| 1597 | - } | ||
| 1616 | + const typeFromPjson = pkg?.data.type; | ||
| 1598 | 1617 | ||
| 1599 | - const parent = module[kModuleParent]; | ||
| 1600 | - const parentPath = parent?.filename; | ||
| 1601 | - const packageJsonPath = pkg.path; | ||
| 1602 | - const usesEsm = containsModuleSyntax(content, filename); | ||
| 1603 | - const err = new ERR_REQUIRE_ESM(filename, usesEsm, parentPath, | ||
| 1604 | - packageJsonPath); | ||
| 1605 | - // Attempt to reconstruct the parent require frame. | ||
| 1606 | - if (Module._cache[parentPath]) { | ||
| 1607 | - let parentSource; | ||
| 1608 | - try { | ||
| 1609 | - parentSource = stripTypeScriptModuleTypes(fs.readFileSync(parentPath, 'utf8'), parentPath); | ||
| 1610 | - } catch { | ||
| 1611 | - // Continue regardless of error. | ||
| 1612 | - } | ||
| 1613 | - if (parentSource) { | ||
| 1614 | - reconstructErrorStack(err, parentPath, parentSource); | ||
| 1615 | - } | ||
| 1616 | - } | ||
| 1618 | + let format; | ||
| 1619 | + if (typeFromPjson === 'module') { | ||
| 1620 | + format = 'module-typescript'; | ||
| 1621 | + } else if (typeFromPjson === 'commonjs') { | ||
| 1622 | + format = 'commonjs-typescript'; | ||
| 1623 | + } else { | ||
| 1624 | + format = 'typescript'; | ||
| 1625 | + } | ||
| 1626 | + const loadResult = loadSource(module, filename, format); | ||
| 1627 | + | ||
| 1628 | + // Function require shouldn't be used in ES modules when require(esm) is disabled. | ||
| 1629 | + if (typeFromPjson === 'module' && !getOptionValue('--experimental-require-module')) { | ||
| 1630 | + const err = getRequireESMError(module, pkg, loadResult.source, filename); | ||
| 1617 | 1631 | throw err; | |
| 1618 | - } else if (pkg?.data.type === 'commonjs') { | ||
| 1619 | - format = 'commonjs'; | ||
| 1620 | 1632 | } | |
| 1621 | 1633 | ||
| 1622 | - module._compile(content, filename, format); | ||
| 1634 | + module[kFormat] = loadResult.format; | ||
| 1635 | + module._compile(loadResult.source, filename, loadResult.format); | ||
| 1623 | 1636 | }; | |
| 1624 | 1637 | ||
| 1625 | 1638 | function reconstructErrorStack(err, parentPath, parentSource) { | |
@@ -1635,53 +1648,64 @@ function reconstructErrorStack(err, parentPath, parentSource) { | |||
| 1635 | 1648 | } | |
| 1636 | 1649 | } | |
| 1637 | 1650 | ||
| 1651 | + /** | ||
| 1652 | + * Generate the legacy ERR_REQUIRE_ESM for the cases where require(esm) is disabled. | ||
| 1653 | + * @param {Module} mod The module being required. | ||
| 1654 | + * @param {undefined|object} pkg Data of the nearest package.json of the module. | ||
| 1655 | + * @param {string} content Source code of the module. | ||
| 1656 | + * @param {string} filename Filename of the module | ||
| 1657 | + * @returns {Error} | ||
| 1658 | + */ | ||
| 1659 | + function getRequireESMError(mod, pkg, content, filename) { | ||
| 1660 | + // This is an error path because `require` of a `.js` file in a `"type": "module"` scope is not allowed. | ||
| 1661 | + const parent = mod[kModuleParent]; | ||
| 1662 | + const parentPath = parent?.filename; | ||
| 1663 | + const packageJsonPath = pkg?.path; | ||
| 1664 | + const usesEsm = containsModuleSyntax(content, filename); | ||
| 1665 | + const err = new ERR_REQUIRE_ESM(filename, usesEsm, parentPath, | ||
| 1666 | + packageJsonPath); | ||
| 1667 | + // Attempt to reconstruct the parent require frame. | ||
| 1668 | + const parentModule = Module._cache[parentPath]; | ||
| 1669 | + if (parentModule) { | ||
| 1670 | + let parentSource; | ||
| 1671 | + try { | ||
| 1672 | + ({ source: parentSource } = loadSource(parentModule, parentPath)); | ||
| 1673 | + } catch { | ||
| 1674 | + // Continue regardless of error. | ||
| 1675 | + } | ||
| 1676 | + if (parentSource) { | ||
| 1677 | + // TODO(joyeecheung): trim off internal frames from the stack. | ||
| 1678 | + reconstructErrorStack(err, parentPath, parentSource); | ||
| 1679 | + } | ||
| 1680 | + } | ||
| 1681 | + return err; | ||
| 1682 | + } | ||
| 1683 | + | ||
| 1638 | 1684 | /** | |
| 1639 | 1685 | * Built-in handler for `.js` files. | |
| 1640 | 1686 | * @param {Module} module The module to compile | |
| 1641 | 1687 | * @param {string} filename The file path of the module | |
| 1642 | 1688 | */ | |
| 1643 | 1689 | Module._extensions['.js'] = function(module, filename) { | |
| 1644 | - // If already analyzed the source, then it will be cached. | ||
| 1645 | - const content = getMaybeCachedSource(module, filename); | ||
| 1646 | - | ||
| 1647 | - let format; | ||
| 1648 | - if (StringPrototypeEndsWith(filename, '.js')) { | ||
| 1649 | - const pkg = packageJsonReader.getNearestParentPackageJSON(filename); | ||
| 1650 | - // Function require shouldn't be used in ES modules. | ||
| 1651 | - if (pkg?.data.type === 'module') { | ||
| 1652 | - if (getOptionValue('--experimental-require-module')) { | ||
| 1653 | - module._compile(content, filename, 'module'); | ||
| 1654 | - return; | ||
| 1655 | - } | ||
| 1656 | - | ||
| 1657 | - // This is an error path because `require` of a `.js` file in a `"type": "module"` scope is not allowed. | ||
| 1658 | - const parent = module[kModuleParent]; | ||
| 1659 | - const parentPath = parent?.filename; | ||
| 1660 | - const packageJsonPath = pkg.path; | ||
| 1661 | - const usesEsm = containsModuleSyntax(content, filename); | ||
| 1662 | - const err = new ERR_REQUIRE_ESM(filename, usesEsm, parentPath, | ||
| 1663 | - packageJsonPath); | ||
| 1664 | - // Attempt to reconstruct the parent require frame. | ||
| 1665 | - if (Module._cache[parentPath]) { | ||
| 1666 | - let parentSource; | ||
| 1667 | - try { | ||
| 1668 | - parentSource = fs.readFileSync(parentPath, 'utf8'); | ||
| 1669 | - } catch { | ||
| 1670 | - // Continue regardless of error. | ||
| 1671 | - } | ||
| 1672 | - if (parentSource) { | ||
| 1673 | - reconstructErrorStack(err, parentPath, parentSource); | ||
| 1674 | - } | ||
| 1675 | - } | ||
| 1676 | - throw err; | ||
| 1677 | - } else if (pkg?.data.type === 'commonjs') { | ||
| 1678 | - format = 'commonjs'; | ||
| 1679 | - } | ||
| 1680 | - } else if (StringPrototypeEndsWith(filename, '.cjs')) { | ||
| 1690 | + let format, pkg; | ||
| 1691 | + if (StringPrototypeEndsWith(filename, '.cjs')) { | ||
| 1681 | 1692 | format = 'commonjs'; | |
| 1693 | + } else if (StringPrototypeEndsWith(filename, '.mjs')) { | ||
| 1694 | + format = 'module'; | ||
| 1695 | + } else if (StringPrototypeEndsWith(filename, '.js')) { | ||
| 1696 | + pkg = packageJsonReader.getNearestParentPackageJSON(filename); | ||
| 1697 | + const typeFromPjson = pkg?.data.type; | ||
| 1698 | + if (typeFromPjson === 'module' || typeFromPjson === 'commonjs' || !typeFromPjson) { | ||
| 1699 | + format = typeFromPjson; | ||
| 1700 | + } | ||
| 1682 | 1701 | } | |
| 1683 | - | ||
| 1684 | - module._compile(content, filename, format); | ||
| 1702 | + const { source, format: loadedFormat } = loadSource(module, filename, format); | ||
| 1703 | + // Function require shouldn't be used in ES modules when require(esm) is disabled. | ||
| 1704 | + if (loadedFormat === 'module' && !getOptionValue('--experimental-require-module')) { | ||
| 1705 | + const err = getRequireESMError(module, pkg, source, filename); | ||
| 1706 | + throw err; | ||
| 1707 | + } | ||
| 1708 | + module._compile(source, filename, loadedFormat); | ||
| 1685 | 1709 | }; | |
| 1686 | 1710 | ||
| 1687 | 1711 | /** | |
| Back | FazBrowse Home | New Git URL |
0 commit comments