| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -905,13 +905,13 @@ _isMain_ is **true** when resolving the Node.js application entry point. | |||
| 905 | 905 | > 1. Throw a _Module Not Found_ error. | |
| 906 | 906 | > 1. If _pjson.exports_ is not **null** or **undefined**, then | |
| 907 | 907 | > 1. If _pjson.exports_ is a String or Array, then | |
| 908 | - > 1. Return _PACKAGE_EXPORTS_TARGET_RESOLVE(packageURL, pjson.exports, | ||
| 909 | - > "")_. | ||
| 908 | + > 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, | ||
| 909 | + > _pjson.exports_, "")_. | ||
| 910 | 910 | > 1. If _pjson.exports is an Object, then | |
| 911 | 911 | > 1. If _pjson.exports_ contains a _"."_ property, then | |
| 912 | 912 | > 1. Let _mainExport_ be the _"."_ property in _pjson.exports_. | |
| 913 | - > 1. Return _PACKAGE_EXPORTS_TARGET_RESOLVE(packageURL, mainExport, | ||
| 914 | - > "")_. | ||
| 913 | + > 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, | ||
| 914 | + > _mainExport_, "")_. | ||
| 915 | 915 | > 1. If _pjson.main_ is a String, then | |
| 916 | 916 | > 1. Let _resolvedMain_ be the URL resolution of _packageURL_, "/", and | |
| 917 | 917 | > _pjson.main_. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -221,7 +221,10 @@ NativeModule.prototype.compileForPublicLoader = function(needToSyncExports) { | |||
| 221 | 221 | this.compile(); | |
| 222 | 222 | if (needToSyncExports) { | |
| 223 | 223 | if (!this.exportKeys) { | |
| 224 | - this.exportKeys = Object.keys(this.exports); | ||
| 224 | + // When using --expose-internals, we do not want to reflect the named | ||
| 225 | + // exports from core modules as this can trigger unnecessary getters. | ||
| 226 | + const internal = this.id.startsWith('internal/'); | ||
| 227 | + this.exportKeys = internal ? [] : Object.keys(this.exports); | ||
| 225 | 228 | } | |
| 226 | 229 | this.getESMFacade(); | |
| 227 | 230 | this.syncExports(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,6 +5,7 @@ const { Object, SafeWeakMap } = primordials; | |||
| 5 | 5 | const { getOptionValue } = require('internal/options'); | |
| 6 | 6 | const { Buffer } = require('buffer'); | |
| 7 | 7 | const { ERR_MANIFEST_ASSERT_INTEGRITY } = require('internal/errors').codes; | |
| 8 | + const path = require('path'); | ||
| 8 | 9 | ||
| 9 | 10 | function prepareMainThreadExecution(expandArgv1 = false) { | |
| 10 | 11 | // Patch the process object with legacy properties and normalizations | |
@@ -404,7 +405,6 @@ function initializeESMLoader() { | |||
| 404 | 405 | 'The ESM module loader is experimental.', | |
| 405 | 406 | 'ExperimentalWarning', undefined); | |
| 406 | 407 | } | |
| 407 | - | ||
| 408 | 408 | const { | |
| 409 | 409 | setImportModuleDynamicallyCallback, | |
| 410 | 410 | setInitializeImportMetaObjectCallback | |
@@ -414,14 +414,6 @@ function initializeESMLoader() { | |||
| 414 | 414 | // track of for different ESM modules. | |
| 415 | 415 | setInitializeImportMetaObjectCallback(esm.initializeImportMetaObject); | |
| 416 | 416 | setImportModuleDynamicallyCallback(esm.importModuleDynamicallyCallback); | |
| 417 | - const userLoader = getOptionValue('--experimental-loader'); | ||
| 418 | - // If --experimental-loader is specified, create a loader with user hooks. | ||
| 419 | - // Otherwise create the default loader. | ||
| 420 | - if (userLoader) { | ||
| 421 | - const { emitExperimentalWarning } = require('internal/util'); | ||
| 422 | - emitExperimentalWarning('--experimental-loader'); | ||
| 423 | - } | ||
| 424 | - esm.initializeLoader(process.cwd(), userLoader); | ||
| 425 | 417 | } | |
| 426 | 418 | } | |
| 427 | 419 | ||
@@ -446,11 +438,70 @@ function loadPreloadModules() { | |||
| 446 | 438 | } | |
| 447 | 439 | } | |
| 448 | 440 | ||
| 441 | + function resolveMainPath(main) { | ||
| 442 | + const { toRealPath, Module: CJSModule } = | ||
| 443 | + require('internal/modules/cjs/loader'); | ||
| 444 | + | ||
| 445 | + // Note extension resolution for the main entry point can be deprecated in a | ||
| 446 | + // future major. | ||
| 447 | + let mainPath = CJSModule._findPath(path.resolve(main), null, true); | ||
| 448 | + if (!mainPath) | ||
| 449 | + return; | ||
| 450 | + | ||
| 451 | + const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); | ||
| 452 | + if (!preserveSymlinksMain) | ||
| 453 | + mainPath = toRealPath(mainPath); | ||
| 454 | + | ||
| 455 | + return mainPath; | ||
| 456 | + } | ||
| 457 | + | ||
| 458 | + function shouldUseESMLoader(mainPath) { | ||
| 459 | + const experimentalModules = getOptionValue('--experimental-modules'); | ||
| 460 | + if (!experimentalModules) | ||
| 461 | + return false; | ||
| 462 | + const userLoader = getOptionValue('--experimental-loader'); | ||
| 463 | + if (userLoader) | ||
| 464 | + return true; | ||
| 465 | + // Determine the module format of the main | ||
| 466 | + if (mainPath && mainPath.endsWith('.mjs')) | ||
| 467 | + return true; | ||
| 468 | + if (!mainPath || mainPath.endsWith('.cjs')) | ||
| 469 | + return false; | ||
| 470 | + const { readPackageScope } = require('internal/modules/cjs/loader'); | ||
| 471 | + const pkg = readPackageScope(mainPath); | ||
| 472 | + return pkg && pkg.data.type === 'module'; | ||
| 473 | + } | ||
| 474 | + | ||
| 475 | + function runMainESM(mainPath) { | ||
| 476 | + const esmLoader = require('internal/process/esm_loader'); | ||
| 477 | + const { pathToFileURL } = require('internal/url'); | ||
| 478 | + const { hasUncaughtExceptionCaptureCallback } = | ||
| 479 | + require('internal/process/execution'); | ||
| 480 | + return esmLoader.initializeLoader().then(() => { | ||
| 481 | + const main = path.isAbsolute(mainPath) ? | ||
| 482 | + pathToFileURL(mainPath).href : mainPath; | ||
| 483 | + return esmLoader.ESMLoader.import(main).catch((e) => { | ||
| 484 | + if (hasUncaughtExceptionCaptureCallback()) { | ||
| 485 | + process._fatalException(e); | ||
| 486 | + return; | ||
| 487 | + } | ||
| 488 | + internalBinding('errors').triggerUncaughtException( | ||
| 489 | + e, | ||
| 490 | + true /* fromPromise */ | ||
| 491 | + ); | ||
| 492 | + }); | ||
| 493 | + }); | ||
| 494 | + } | ||
| 495 | + | ||
| 496 | + | ||
| 449 | 497 | module.exports = { | |
| 450 | 498 | patchProcessObject, | |
| 499 | + resolveMainPath, | ||
| 500 | + runMainESM, | ||
| 451 | 501 | setupCoverageHooks, | |
| 452 | 502 | setupWarningHandler, | |
| 453 | 503 | setupDebugEnv, | |
| 504 | + shouldUseESMLoader, | ||
| 454 | 505 | prepareMainThreadExecution, | |
| 455 | 506 | initializeDeprecations, | |
| 456 | 507 | initializeESMLoader, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,8 +10,7 @@ const CJSModule = require('internal/modules/cjs/loader').Module; | |||
| 10 | 10 | ||
| 11 | 11 | markBootstrapComplete(); | |
| 12 | 12 | ||
| 13 | - // Note: this actually tries to run the module as a ESM first if | ||
| 14 | - // --experimental-modules is on. | ||
| 15 | - // TODO(joyeecheung): can we move that logic to here? Note that this | ||
| 16 | - // is an undocumented method available via `require('module').runMain` | ||
| 17 | - CJSModule.runMain(); | ||
| 13 | + // Note: this loads the module through the ESM loader if | ||
| 14 | + // --experimental-loader is provided or --experimental-modules is on | ||
| 15 | + // and the module is determined to be an ES module | ||
| 16 | + CJSModule.runMain(process.argv[1]); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -135,8 +135,9 @@ port.on('message', (message) => { | |||
| 135 | 135 | const { evalScript } = require('internal/process/execution'); | |
| 136 | 136 | evalScript('[worker eval]', filename); | |
| 137 | 137 | } else { | |
| 138 | - process.argv[1] = filename; // script filename | ||
| 139 | - require('module').runMain(); | ||
| 138 | + // script filename | ||
| 139 | + const CJSModule = require('internal/modules/cjs/loader').Module; | ||
| 140 | + CJSModule.runMain(process.argv[1] = filename); | ||
| 140 | 141 | } | |
| 141 | 142 | } else if (message.type === STDIO_PAYLOAD) { | |
| 142 | 143 | const { stream, chunk, encoding } = message; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -70,9 +70,14 @@ const { | |||
| 70 | 70 | ERR_REQUIRE_ESM | |
| 71 | 71 | } = require('internal/errors').codes; | |
| 72 | 72 | const { validateString } = require('internal/validators'); | |
| 73 | + const { | ||
| 74 | + resolveMainPath, | ||
| 75 | + shouldUseESMLoader, | ||
| 76 | + runMainESM | ||
| 77 | + } = require('internal/bootstrap/pre_execution'); | ||
| 73 | 78 | const pendingDeprecation = getOptionValue('--pending-deprecation'); | |
| 74 | 79 | ||
| 75 | - module.exports = { wrapSafe, Module }; | ||
| 80 | + module.exports = { wrapSafe, Module, toRealPath, readPackageScope }; | ||
| 76 | 81 | ||
| 77 | 82 | let asyncESM, ModuleJob, ModuleWrap, kInstantiated; | |
| 78 | 83 | ||
@@ -898,6 +903,10 @@ Module.prototype.load = function(filename) { | |||
| 898 | 903 | this.paths = Module._nodeModulePaths(path.dirname(filename)); | |
| 899 | 904 | ||
| 900 | 905 | const extension = findLongestRegisteredExtension(filename); | |
| 906 | + // allow .mjs to be overridden | ||
| 907 | + if (filename.endsWith('.mjs') && !Module._extensions['.mjs']) { | ||
| 908 | + throw new ERR_REQUIRE_ESM(filename); | ||
| 909 | + } | ||
| 901 | 910 | Module._extensions[extension](this, filename); | |
| 902 | 911 | this.loaded = true; | |
| 903 | 912 | ||
@@ -911,14 +920,19 @@ Module.prototype.load = function(filename) { | |||
| 911 | 920 | if (module !== undefined && module.module !== undefined) { | |
| 912 | 921 | if (module.module.getStatus() >= kInstantiated) | |
| 913 | 922 | module.module.setExport('default', exports); | |
| 914 | - } else { // preemptively cache | ||
| 923 | + } else { | ||
| 924 | + // Preemptively cache | ||
| 925 | + // We use a function to defer promise creation for async hooks. | ||
| 915 | 926 | ESMLoader.moduleMap.set( | |
| 916 | 927 | url, | |
| 917 | - new ModuleJob(ESMLoader, url, () => | ||
| 928 | + // Module job creation will start promises. | ||
| 929 | + // We make it a function to lazily trigger those promises | ||
| 930 | + // for async hooks compatibility. | ||
| 931 | + () => new ModuleJob(ESMLoader, url, () => | ||
| 918 | 932 | new ModuleWrap(url, undefined, ['default'], function() { | |
| 919 | 933 | this.setExport('default', exports); | |
| 920 | 934 | }) | |
| 921 | - ) | ||
| 935 | + , false /* isMain */, false /* inspectBrk */) | ||
| 922 | 936 | ); | |
| 923 | 937 | } | |
| 924 | 938 | } | |
@@ -947,15 +961,15 @@ Module.prototype.require = function(id) { | |||
| 947 | 961 | let resolvedArgv; | |
| 948 | 962 | let hasPausedEntry = false; | |
| 949 | 963 | ||
| 950 | - function wrapSafe(filename, content) { | ||
| 964 | + function wrapSafe(filename, content, cjsModuleInstance) { | ||
| 951 | 965 | if (patched) { | |
| 952 | 966 | const wrapper = Module.wrap(content); | |
| 953 | 967 | return vm.runInThisContext(wrapper, { | |
| 954 | 968 | filename, | |
| 955 | 969 | lineOffset: 0, | |
| 956 | 970 | displayErrors: true, | |
| 957 | 971 | importModuleDynamically: experimentalModules ? async (specifier) => { | |
| 958 | - const loader = await asyncESM.loaderPromise; | ||
| 972 | + const loader = asyncESM.ESMLoader; | ||
| 959 | 973 | return loader.import(specifier, normalizeReferrerURL(filename)); | |
| 960 | 974 | } : undefined, | |
| 961 | 975 | }); | |
@@ -981,17 +995,16 @@ function wrapSafe(filename, content) { | |||
| 981 | 995 | ] | |
| 982 | 996 | ); | |
| 983 | 997 | } catch (err) { | |
| 984 | - if (experimentalModules) { | ||
| 998 | + if (experimentalModules && process.mainModule === cjsModuleInstance) | ||
| 985 | 999 | enrichCJSError(err); | |
| 986 | - } | ||
| 987 | 1000 | throw err; | |
| 988 | 1001 | } | |
| 989 | 1002 | ||
| 990 | 1003 | if (experimentalModules) { | |
| 991 | 1004 | const { callbackMap } = internalBinding('module_wrap'); | |
| 992 | 1005 | callbackMap.set(compiled.cacheKey, { | |
| 993 | 1006 | importModuleDynamically: async (specifier) => { | |
| 994 | - const loader = await asyncESM.loaderPromise; | ||
| 1007 | + const loader = asyncESM.ESMLoader; | ||
| 995 | 1008 | return loader.import(specifier, normalizeReferrerURL(filename)); | |
| 996 | 1009 | } | |
| 997 | 1010 | }); | |
@@ -1014,7 +1027,7 @@ Module.prototype._compile = function(content, filename) { | |||
| 1014 | 1027 | } | |
| 1015 | 1028 | ||
| 1016 | 1029 | maybeCacheSourceMap(filename, content, this); | |
| 1017 | - const compiledWrapper = wrapSafe(filename, content); | ||
| 1030 | + const compiledWrapper = wrapSafe(filename, content, this); | ||
| 1018 | 1031 | ||
| 1019 | 1032 | var inspectorWrapper = null; | |
| 1020 | 1033 | if (getOptionValue('--inspect-brk') && process._eval == null) { | |
@@ -1070,7 +1083,11 @@ Module._extensions['.js'] = function(module, filename) { | |||
| 1070 | 1083 | 'files in that package scope as ES modules.\nInstead rename ' + | |
| 1071 | 1084 | `${basename} to end in .cjs, change the requiring code to use ` + | |
| 1072 | 1085 | 'import(), or remove "type": "module" from ' + | |
| 1073 | - `${path.resolve(pkg.path, 'package.json')}.` | ||
| 1086 | + `${path.resolve(pkg.path, 'package.json')}.`, | ||
| 1087 | + undefined, | ||
| 1088 | + undefined, | ||
| 1089 | + undefined, | ||
| 1090 | + true | ||
| 1074 | 1091 | ); | |
| 1075 | 1092 | warnRequireESM = false; | |
| 1076 | 1093 | } | |
@@ -1113,26 +1130,16 @@ Module._extensions['.node'] = function(module, filename) { | |||
| 1113 | 1130 | return process.dlopen(module, path.toNamespacedPath(filename)); | |
| 1114 | 1131 | }; | |
| 1115 | 1132 | ||
| 1116 | - Module._extensions['.mjs'] = function(module, filename) { | ||
| 1117 | - throw new ERR_REQUIRE_ESM(filename); | ||
| 1118 | - }; | ||
| 1119 | - | ||
| 1120 | 1133 | // Bootstrap main module. | |
| 1121 | - Module.runMain = function() { | ||
| 1122 | - // Load the main module--the command line argument. | ||
| 1123 | - if (experimentalModules) { | ||
| 1124 | - asyncESM.loaderPromise.then((loader) => { | ||
| 1125 | - return loader.import(pathToFileURL(process.argv[1]).href); | ||
| 1126 | - }) | ||
| 1127 | - .catch((e) => { | ||
| 1128 | - internalBinding('errors').triggerUncaughtException( | ||
| 1129 | - e, | ||
| 1130 | - true /* fromPromise */ | ||
| 1131 | - ); | ||
| 1132 | - }); | ||
| 1133 | - return; | ||
| 1134 | + Module.runMain = function(main = process.argv[1]) { | ||
| 1135 | + const resolvedMain = resolveMainPath(main); | ||
| 1136 | + const useESMLoader = shouldUseESMLoader(resolvedMain); | ||
| 1137 | + module.exports.asyncRunMain = useESMLoader; | ||
| 1138 | + if (useESMLoader) { | ||
| 1139 | + runMainESM(resolvedMain || main); | ||
| 1140 | + } else { | ||
| 1141 | + Module._load(main, null, true); | ||
| 1134 | 1142 | } | |
| 1135 | - Module._load(process.argv[1], null, true); | ||
| 1136 | 1143 | }; | |
| 1137 | 1144 | ||
| 1138 | 1145 | function createRequireFromPath(filename) { | |
@@ -1238,7 +1245,7 @@ Module.Module = Module; | |||
| 1238 | 1245 | ||
| 1239 | 1246 | // We have to load the esm things after module.exports! | |
| 1240 | 1247 | if (experimentalModules) { | |
| 1241 | - asyncESM = require('internal/process/esm_loader'); | ||
| 1242 | 1248 | ModuleJob = require('internal/modules/esm/module_job'); | |
| 1249 | + asyncESM = require('internal/process/esm_loader'); | ||
| 1243 | 1250 | ({ ModuleWrap, kInstantiated } = internalBinding('module_wrap')); | |
| 1244 | 1251 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -22,6 +22,7 @@ const createDynamicModule = require( | |||
| 22 | 22 | 'internal/modules/esm/create_dynamic_module'); | |
| 23 | 23 | const { translators } = require('internal/modules/esm/translators'); | |
| 24 | 24 | const { ModuleWrap } = internalBinding('module_wrap'); | |
| 25 | + const { getOptionValue } = require('internal/options'); | ||
| 25 | 26 | ||
| 26 | 27 | const debug = require('internal/util/debuglog').debuglog('esm'); | |
| 27 | 28 | ||
@@ -118,7 +119,7 @@ class Loader { | |||
| 118 | 119 | url = pathToFileURL(`${process.cwd()}/[eval${++this.evalIndex}]`).href | |
| 119 | 120 | ) { | |
| 120 | 121 | const evalInstance = (url) => new ModuleWrap(url, undefined, source, 0, 0); | |
| 121 | - const job = new ModuleJob(this, url, evalInstance, false); | ||
| 122 | + const job = new ModuleJob(this, url, evalInstance, false, false); | ||
| 122 | 123 | this.moduleMap.set(url, job); | |
| 123 | 124 | const { module, result } = await job.run(); | |
| 124 | 125 | return { | |
@@ -146,6 +147,9 @@ class Loader { | |||
| 146 | 147 | async getModuleJob(specifier, parentURL) { | |
| 147 | 148 | const { url, format } = await this.resolve(specifier, parentURL); | |
| 148 | 149 | let job = this.moduleMap.get(url); | |
| 150 | + // CommonJS will set functions for lazy job evaluation. | ||
| 151 | + if (typeof job === 'function') | ||
| 152 | + this.moduleMap.set(url, job = job()); | ||
| 149 | 153 | if (job !== undefined) | |
| 150 | 154 | return job; | |
| 151 | 155 | ||
@@ -169,7 +173,10 @@ class Loader { | |||
| 169 | 173 | loaderInstance = translators.get(format); | |
| 170 | 174 | } | |
| 171 | 175 | ||
| 172 | - job = new ModuleJob(this, url, loaderInstance, parentURL === undefined); | ||
| 176 | + const inspectBrk = parentURL === undefined && | ||
| 177 | + format === 'module' && getOptionValue('--inspect-brk'); | ||
| 178 | + job = new ModuleJob(this, url, loaderInstance, parentURL === undefined, | ||
| 179 | + inspectBrk); | ||
| 173 | 180 | this.moduleMap.set(url, job); | |
| 174 | 181 | return job; | |
| 175 | 182 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -9,7 +9,6 @@ const { | |||
| 9 | 9 | const { ModuleWrap } = internalBinding('module_wrap'); | |
| 10 | 10 | ||
| 11 | 11 | const { decorateErrorStack } = require('internal/util'); | |
| 12 | - const { getOptionValue } = require('internal/options'); | ||
| 13 | 12 | const assert = require('internal/assert'); | |
| 14 | 13 | const resolvedPromise = SafePromise.resolve(); | |
| 15 | 14 | ||
@@ -22,9 +21,10 @@ let hasPausedEntry = false; | |||
| 22 | 21 | class ModuleJob { | |
| 23 | 22 | // `loader` is the Loader instance used for loading dependencies. | |
| 24 | 23 | // `moduleProvider` is a function | |
| 25 | - constructor(loader, url, moduleProvider, isMain) { | ||
| 24 | + constructor(loader, url, moduleProvider, isMain, inspectBrk) { | ||
| 26 | 25 | this.loader = loader; | |
| 27 | 26 | this.isMain = isMain; | |
| 27 | + this.inspectBrk = inspectBrk; | ||
| 28 | 28 | ||
| 29 | 29 | // This is a Promise<{ module, reflect }>, whose fields will be copied | |
| 30 | 30 | // onto `this` by `link()` below once it has been resolved. | |
@@ -83,12 +83,12 @@ class ModuleJob { | |||
| 83 | 83 | }; | |
| 84 | 84 | await addJobsToDependencyGraph(this); | |
| 85 | 85 | try { | |
| 86 | - if (!hasPausedEntry && this.isMain && getOptionValue('--inspect-brk')) { | ||
| 86 | + if (!hasPausedEntry && this.inspectBrk) { | ||
| 87 | 87 | hasPausedEntry = true; | |
| 88 | 88 | const initWrapper = internalBinding('inspector').callAndPauseOnStart; | |
| 89 | 89 | initWrapper(this.module.instantiate, this.module); | |
| 90 | 90 | } else { | |
| 91 | - this.module.instantiate(); | ||
| 91 | + this.module.instantiate(true); | ||
| 92 | 92 | } | |
| 93 | 93 | } catch (e) { | |
| 94 | 94 | decorateErrorStack(e); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,7 +16,8 @@ class ModuleMap extends SafeMap { | |||
| 16 | 16 | } | |
| 17 | 17 | set(url, job) { | |
| 18 | 18 | validateString(url, 'url'); | |
| 19 | - if (job instanceof ModuleJob !== true) { | ||
| 19 | + if (job instanceof ModuleJob !== true && | ||
| 20 | + typeof job !== 'function') { | ||
| 20 | 21 | throw new ERR_INVALID_ARG_TYPE('job', 'ModuleJob', job); | |
| 21 | 22 | } | |
| 22 | 23 | debug(`Storing ${url} in ModuleMap`); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments