diff options
author | Bradley Farias <bfarias@godaddy.com> | 2019-09-30 14:55:59 -0500 |
---|---|---|
committer | Beth Griggs <Bethany.Griggs@uk.ibm.com> | 2020-02-06 02:48:52 +0000 |
commit | 02c4d27007f04c729f603aabb0f764a1d8fbf809 (patch) | |
tree | 63d2db84a321a193d66f576de83ce49add54d1a0 /lib/internal/modules | |
parent | a5d2b66bdc6e164247d331ea406ca619a7d2fd01 (diff) | |
download | node-new-02c4d27007f04c729f603aabb0f764a1d8fbf809.tar.gz |
module: refactor modules bootstrap
PR-URL: https://github.com/nodejs/node/pull/29937
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Diffstat (limited to 'lib/internal/modules')
-rw-r--r-- | lib/internal/modules/cjs/loader.js | 67 | ||||
-rw-r--r-- | lib/internal/modules/esm/loader.js | 11 | ||||
-rw-r--r-- | lib/internal/modules/esm/module_job.js | 8 | ||||
-rw-r--r-- | lib/internal/modules/esm/module_map.js | 3 | ||||
-rw-r--r-- | lib/internal/modules/esm/translators.js | 8 |
5 files changed, 57 insertions, 40 deletions
diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 106d85107d..75300ae942 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -70,9 +70,14 @@ const { ERR_REQUIRE_ESM } = require('internal/errors').codes; const { validateString } = require('internal/validators'); +const { + resolveMainPath, + shouldUseESMLoader, + runMainESM +} = require('internal/bootstrap/pre_execution'); const pendingDeprecation = getOptionValue('--pending-deprecation'); -module.exports = { wrapSafe, Module }; +module.exports = { wrapSafe, Module, toRealPath, readPackageScope }; let asyncESM, ModuleJob, ModuleWrap, kInstantiated; @@ -898,6 +903,10 @@ Module.prototype.load = function(filename) { this.paths = Module._nodeModulePaths(path.dirname(filename)); const extension = findLongestRegisteredExtension(filename); + // allow .mjs to be overridden + if (filename.endsWith('.mjs') && !Module._extensions['.mjs']) { + throw new ERR_REQUIRE_ESM(filename); + } Module._extensions[extension](this, filename); this.loaded = true; @@ -911,14 +920,19 @@ Module.prototype.load = function(filename) { if (module !== undefined && module.module !== undefined) { if (module.module.getStatus() >= kInstantiated) module.module.setExport('default', exports); - } else { // preemptively cache + } else { + // Preemptively cache + // We use a function to defer promise creation for async hooks. ESMLoader.moduleMap.set( url, - new ModuleJob(ESMLoader, url, () => + // Module job creation will start promises. + // We make it a function to lazily trigger those promises + // for async hooks compatibility. + () => new ModuleJob(ESMLoader, url, () => new ModuleWrap(url, undefined, ['default'], function() { this.setExport('default', exports); }) - ) + , false /* isMain */, false /* inspectBrk */) ); } } @@ -947,7 +961,7 @@ Module.prototype.require = function(id) { let resolvedArgv; let hasPausedEntry = false; -function wrapSafe(filename, content) { +function wrapSafe(filename, content, cjsModuleInstance) { if (patched) { const wrapper = Module.wrap(content); return vm.runInThisContext(wrapper, { @@ -955,7 +969,7 @@ function wrapSafe(filename, content) { lineOffset: 0, displayErrors: true, importModuleDynamically: experimentalModules ? async (specifier) => { - const loader = await asyncESM.loaderPromise; + const loader = asyncESM.ESMLoader; return loader.import(specifier, normalizeReferrerURL(filename)); } : undefined, }); @@ -981,9 +995,8 @@ function wrapSafe(filename, content) { ] ); } catch (err) { - if (experimentalModules) { + if (experimentalModules && process.mainModule === cjsModuleInstance) enrichCJSError(err); - } throw err; } @@ -991,7 +1004,7 @@ function wrapSafe(filename, content) { const { callbackMap } = internalBinding('module_wrap'); callbackMap.set(compiled.cacheKey, { importModuleDynamically: async (specifier) => { - const loader = await asyncESM.loaderPromise; + const loader = asyncESM.ESMLoader; return loader.import(specifier, normalizeReferrerURL(filename)); } }); @@ -1014,7 +1027,7 @@ Module.prototype._compile = function(content, filename) { } maybeCacheSourceMap(filename, content, this); - const compiledWrapper = wrapSafe(filename, content); + const compiledWrapper = wrapSafe(filename, content, this); var inspectorWrapper = null; if (getOptionValue('--inspect-brk') && process._eval == null) { @@ -1070,7 +1083,11 @@ Module._extensions['.js'] = function(module, filename) { 'files in that package scope as ES modules.\nInstead rename ' + `${basename} to end in .cjs, change the requiring code to use ` + 'import(), or remove "type": "module" from ' + - `${path.resolve(pkg.path, 'package.json')}.` + `${path.resolve(pkg.path, 'package.json')}.`, + undefined, + undefined, + undefined, + true ); warnRequireESM = false; } @@ -1113,26 +1130,16 @@ Module._extensions['.node'] = function(module, filename) { return process.dlopen(module, path.toNamespacedPath(filename)); }; -Module._extensions['.mjs'] = function(module, filename) { - throw new ERR_REQUIRE_ESM(filename); -}; - // Bootstrap main module. -Module.runMain = function() { - // Load the main module--the command line argument. - if (experimentalModules) { - asyncESM.loaderPromise.then((loader) => { - return loader.import(pathToFileURL(process.argv[1]).href); - }) - .catch((e) => { - internalBinding('errors').triggerUncaughtException( - e, - true /* fromPromise */ - ); - }); - return; +Module.runMain = function(main = process.argv[1]) { + const resolvedMain = resolveMainPath(main); + const useESMLoader = shouldUseESMLoader(resolvedMain); + module.exports.asyncRunMain = useESMLoader; + if (useESMLoader) { + runMainESM(resolvedMain || main); + } else { + Module._load(main, null, true); } - Module._load(process.argv[1], null, true); }; function createRequireFromPath(filename) { @@ -1238,7 +1245,7 @@ Module.Module = Module; // We have to load the esm things after module.exports! if (experimentalModules) { - asyncESM = require('internal/process/esm_loader'); ModuleJob = require('internal/modules/esm/module_job'); + asyncESM = require('internal/process/esm_loader'); ({ ModuleWrap, kInstantiated } = internalBinding('module_wrap')); } diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index a62529e9b3..875fb97f91 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -22,6 +22,7 @@ const createDynamicModule = require( 'internal/modules/esm/create_dynamic_module'); const { translators } = require('internal/modules/esm/translators'); const { ModuleWrap } = internalBinding('module_wrap'); +const { getOptionValue } = require('internal/options'); const debug = require('internal/util/debuglog').debuglog('esm'); @@ -118,7 +119,7 @@ class Loader { url = pathToFileURL(`${process.cwd()}/[eval${++this.evalIndex}]`).href ) { const evalInstance = (url) => new ModuleWrap(url, undefined, source, 0, 0); - const job = new ModuleJob(this, url, evalInstance, false); + const job = new ModuleJob(this, url, evalInstance, false, false); this.moduleMap.set(url, job); const { module, result } = await job.run(); return { @@ -146,6 +147,9 @@ class Loader { async getModuleJob(specifier, parentURL) { const { url, format } = await this.resolve(specifier, parentURL); let job = this.moduleMap.get(url); + // CommonJS will set functions for lazy job evaluation. + if (typeof job === 'function') + this.moduleMap.set(url, job = job()); if (job !== undefined) return job; @@ -169,7 +173,10 @@ class Loader { loaderInstance = translators.get(format); } - job = new ModuleJob(this, url, loaderInstance, parentURL === undefined); + const inspectBrk = parentURL === undefined && + format === 'module' && getOptionValue('--inspect-brk'); + job = new ModuleJob(this, url, loaderInstance, parentURL === undefined, + inspectBrk); this.moduleMap.set(url, job); return job; } diff --git a/lib/internal/modules/esm/module_job.js b/lib/internal/modules/esm/module_job.js index ef11e2ec83..df1edc3810 100644 --- a/lib/internal/modules/esm/module_job.js +++ b/lib/internal/modules/esm/module_job.js @@ -9,7 +9,6 @@ const { const { ModuleWrap } = internalBinding('module_wrap'); const { decorateErrorStack } = require('internal/util'); -const { getOptionValue } = require('internal/options'); const assert = require('internal/assert'); const resolvedPromise = SafePromise.resolve(); @@ -22,9 +21,10 @@ let hasPausedEntry = false; class ModuleJob { // `loader` is the Loader instance used for loading dependencies. // `moduleProvider` is a function - constructor(loader, url, moduleProvider, isMain) { + constructor(loader, url, moduleProvider, isMain, inspectBrk) { this.loader = loader; this.isMain = isMain; + this.inspectBrk = inspectBrk; // This is a Promise<{ module, reflect }>, whose fields will be copied // onto `this` by `link()` below once it has been resolved. @@ -83,12 +83,12 @@ class ModuleJob { }; await addJobsToDependencyGraph(this); try { - if (!hasPausedEntry && this.isMain && getOptionValue('--inspect-brk')) { + if (!hasPausedEntry && this.inspectBrk) { hasPausedEntry = true; const initWrapper = internalBinding('inspector').callAndPauseOnStart; initWrapper(this.module.instantiate, this.module); } else { - this.module.instantiate(); + this.module.instantiate(true); } } catch (e) { decorateErrorStack(e); diff --git a/lib/internal/modules/esm/module_map.js b/lib/internal/modules/esm/module_map.js index 01521fb788..41adc0079a 100644 --- a/lib/internal/modules/esm/module_map.js +++ b/lib/internal/modules/esm/module_map.js @@ -16,7 +16,8 @@ class ModuleMap extends SafeMap { } set(url, job) { validateString(url, 'url'); - if (job instanceof ModuleJob !== true) { + if (job instanceof ModuleJob !== true && + typeof job !== 'function') { throw new ERR_INVALID_ARG_TYPE('job', 'ModuleJob', job); } debug(`Storing ${url} in ModuleMap`); diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js index 18ccfb35e8..34a9a140dd 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -23,7 +23,6 @@ const fs = require('fs'); const { fileURLToPath, URL } = require('url'); const { debuglog } = require('internal/util/debuglog'); const { promisify } = require('internal/util'); -const esmLoader = require('internal/process/esm_loader'); const { ERR_INVALID_URL, ERR_INVALID_URL_SCHEME, @@ -69,9 +68,12 @@ function initializeImportMeta(meta, { url }) { meta.url = url; } +let esmLoader; async function importModuleDynamically(specifier, { url }) { - const loader = await esmLoader.loaderPromise; - return loader.import(specifier, url); + if (!esmLoader) { + esmLoader = require('internal/process/esm_loader'); + } + return esmLoader.ESMLoader.import(specifier, url); } // Strategy for loading a standard JavaScript module |