summaryrefslogtreecommitdiff
path: root/lib/internal/modules
diff options
context:
space:
mode:
authorBradley Farias <bfarias@godaddy.com>2019-09-30 14:55:59 -0500
committerBeth Griggs <Bethany.Griggs@uk.ibm.com>2020-02-06 02:48:52 +0000
commit02c4d27007f04c729f603aabb0f764a1d8fbf809 (patch)
tree63d2db84a321a193d66f576de83ce49add54d1a0 /lib/internal/modules
parenta5d2b66bdc6e164247d331ea406ca619a7d2fd01 (diff)
downloadnode-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.js67
-rw-r--r--lib/internal/modules/esm/loader.js11
-rw-r--r--lib/internal/modules/esm/module_job.js8
-rw-r--r--lib/internal/modules/esm/module_map.js3
-rw-r--r--lib/internal/modules/esm/translators.js8
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