module: refactor to use more primordials
PR-URL: https://github.com/nodejs/node/pull/36024 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
parent
a8b9ede3c1
commit
2c77fe192e
@ -1,11 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
ArrayPrototypeForEach,
|
||||
ArrayPrototypeJoin,
|
||||
ObjectDefineProperty,
|
||||
ObjectPrototypeHasOwnProperty,
|
||||
SafeMap,
|
||||
SafeSet,
|
||||
StringPrototypeCharCodeAt,
|
||||
StringPrototypeIncludes,
|
||||
StringPrototypeSlice,
|
||||
StringPrototypeStartsWith,
|
||||
} = primordials;
|
||||
const {
|
||||
ERR_MANIFEST_DEPENDENCY_MISSING,
|
||||
@ -15,8 +20,7 @@ const { NativeModule } = require('internal/bootstrap/loaders');
|
||||
|
||||
const { validateString } = require('internal/validators');
|
||||
const path = require('path');
|
||||
const { pathToFileURL, fileURLToPath } = require('internal/url');
|
||||
const { URL } = require('url');
|
||||
const { pathToFileURL, fileURLToPath, URL } = require('internal/url');
|
||||
|
||||
const { getOptionValue } = require('internal/options');
|
||||
const userConditions = getOptionValue('--conditions');
|
||||
@ -119,8 +123,8 @@ function makeRequireFunction(mod, redirects) {
|
||||
* translates it to FEFF, the UTF-16 BOM.
|
||||
*/
|
||||
function stripBOM(content) {
|
||||
if (content.charCodeAt(0) === 0xFEFF) {
|
||||
content = content.slice(1);
|
||||
if (StringPrototypeCharCodeAt(content) === 0xFEFF) {
|
||||
content = StringPrototypeSlice(content, 1);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
@ -128,11 +132,11 @@ function stripBOM(content) {
|
||||
function addBuiltinLibsToObject(object) {
|
||||
// Make built-in modules available directly (loaded lazily).
|
||||
const { builtinModules } = require('internal/modules/cjs/loader').Module;
|
||||
builtinModules.forEach((name) => {
|
||||
ArrayPrototypeForEach(builtinModules, (name) => {
|
||||
// Neither add underscored modules, nor ones that contain slashes (e.g.,
|
||||
// 'fs/promises') or ones that are already defined.
|
||||
if (name.startsWith('_') ||
|
||||
name.includes('/') ||
|
||||
if (StringPrototypeStartsWith(name, '_') ||
|
||||
StringPrototypeIncludes(name, '/') ||
|
||||
ObjectPrototypeHasOwnProperty(object, name)) {
|
||||
return;
|
||||
}
|
||||
|
@ -23,10 +23,17 @@
|
||||
|
||||
const {
|
||||
ArrayIsArray,
|
||||
ArrayPrototypeConcat,
|
||||
ArrayPrototypeFilter,
|
||||
ArrayPrototypeIncludes,
|
||||
ArrayPrototypeIndexOf,
|
||||
ArrayPrototypeJoin,
|
||||
ArrayPrototypePush,
|
||||
ArrayPrototypeSlice,
|
||||
ArrayPrototypeSplice,
|
||||
Boolean,
|
||||
Error,
|
||||
JSONParse,
|
||||
Map,
|
||||
ObjectCreate,
|
||||
ObjectDefineProperty,
|
||||
ObjectFreeze,
|
||||
@ -36,16 +43,20 @@ const {
|
||||
ObjectPrototype,
|
||||
ObjectPrototypeHasOwnProperty,
|
||||
ObjectSetPrototypeOf,
|
||||
ReflectApply,
|
||||
ReflectSet,
|
||||
RegExpPrototypeTest,
|
||||
SafeMap,
|
||||
SafeWeakMap,
|
||||
String,
|
||||
StringPrototypeCharAt,
|
||||
StringPrototypeCharCodeAt,
|
||||
StringPrototypeEndsWith,
|
||||
StringPrototypeLastIndexOf,
|
||||
StringPrototypeIndexOf,
|
||||
StringPrototypeMatch,
|
||||
StringPrototypeSlice,
|
||||
StringPrototypeSplit,
|
||||
StringPrototypeStartsWith,
|
||||
} = primordials;
|
||||
|
||||
@ -142,8 +153,8 @@ function stat(filename) {
|
||||
|
||||
function updateChildren(parent, child, scan) {
|
||||
const children = parent && parent.children;
|
||||
if (children && !(scan && children.includes(child)))
|
||||
children.push(child);
|
||||
if (children && !(scan && ArrayPrototypeIncludes(children, child)))
|
||||
ArrayPrototypePush(children, child);
|
||||
}
|
||||
|
||||
const moduleParentCache = new SafeWeakMap();
|
||||
@ -161,7 +172,7 @@ function Module(id = '', parent) {
|
||||
const builtinModules = [];
|
||||
for (const [id, mod] of NativeModule.map) {
|
||||
if (mod.canBeRequiredByUsers) {
|
||||
builtinModules.push(id);
|
||||
ArrayPrototypePush(builtinModules, id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,7 +360,7 @@ function tryPackage(requestPath, exts, isMain, originalPath) {
|
||||
// In order to minimize unnecessary lstat() calls,
|
||||
// this cache is a list of known-real paths.
|
||||
// Set to an empty Map to reset.
|
||||
const realpathCache = new Map();
|
||||
const realpathCache = new SafeMap();
|
||||
|
||||
// Check if the file exists and is not a directory
|
||||
// if using --preserve-symlinks and isMain is false,
|
||||
@ -389,10 +400,10 @@ function findLongestRegisteredExtension(filename) {
|
||||
let currentExtension;
|
||||
let index;
|
||||
let startIndex = 0;
|
||||
while ((index = name.indexOf('.', startIndex)) !== -1) {
|
||||
while ((index = StringPrototypeIndexOf(name, '.', startIndex)) !== -1) {
|
||||
startIndex = index + 1;
|
||||
if (index === 0) continue; // Skip dotfiles like .gitignore
|
||||
currentExtension = name.slice(index);
|
||||
currentExtension = StringPrototypeSlice(name, index);
|
||||
if (Module._extensions[currentExtension]) return currentExtension;
|
||||
}
|
||||
return '.js';
|
||||
@ -473,15 +484,15 @@ Module._findPath = function(request, paths, isMain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const cacheKey = request + '\x00' +
|
||||
(paths.length === 1 ? paths[0] : paths.join('\x00'));
|
||||
const cacheKey = request + '\x00' + ArrayPrototypeJoin(paths, '\x00');
|
||||
const entry = Module._pathCache[cacheKey];
|
||||
if (entry)
|
||||
return entry;
|
||||
|
||||
let exts;
|
||||
let trailingSlash = request.length > 0 &&
|
||||
request.charCodeAt(request.length - 1) === CHAR_FORWARD_SLASH;
|
||||
StringPrototypeCharCodeAt(request, request.length - 1) ===
|
||||
CHAR_FORWARD_SLASH;
|
||||
if (!trailingSlash) {
|
||||
trailingSlash = RegExpPrototypeTest(trailingSlashRegex, request);
|
||||
}
|
||||
@ -564,13 +575,14 @@ if (isWindows) {
|
||||
|
||||
// return root node_modules when path is 'D:\\'.
|
||||
// path.resolve will make sure from.length >=3 in Windows.
|
||||
if (from.charCodeAt(from.length - 1) === CHAR_BACKWARD_SLASH &&
|
||||
from.charCodeAt(from.length - 2) === CHAR_COLON)
|
||||
if (StringPrototypeCharCodeAt(from, from.length - 1) ===
|
||||
CHAR_BACKWARD_SLASH &&
|
||||
StringPrototypeCharCodeAt(from, from.length - 2) === CHAR_COLON)
|
||||
return [from + 'node_modules'];
|
||||
|
||||
const paths = [];
|
||||
for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) {
|
||||
const code = from.charCodeAt(i);
|
||||
const code = StringPrototypeCharCodeAt(from, i);
|
||||
// The path segment separator check ('\' and '/') was used to get
|
||||
// node_modules path for every path segment.
|
||||
// Use colon as an extra condition since we can get node_modules
|
||||
@ -580,7 +592,10 @@ if (isWindows) {
|
||||
code === CHAR_FORWARD_SLASH ||
|
||||
code === CHAR_COLON) {
|
||||
if (p !== nmLen)
|
||||
paths.push(from.slice(0, last) + '\\node_modules');
|
||||
ArrayPrototypePush(
|
||||
paths,
|
||||
StringPrototypeSlice(from, 0, last) + '\\node_modules'
|
||||
);
|
||||
last = i;
|
||||
p = 0;
|
||||
} else if (p !== -1) {
|
||||
@ -609,10 +624,13 @@ if (isWindows) {
|
||||
// that works on both Windows and Posix is non-trivial.
|
||||
const paths = [];
|
||||
for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) {
|
||||
const code = from.charCodeAt(i);
|
||||
const code = StringPrototypeCharCodeAt(from, i);
|
||||
if (code === CHAR_FORWARD_SLASH) {
|
||||
if (p !== nmLen)
|
||||
paths.push(from.slice(0, last) + '/node_modules');
|
||||
ArrayPrototypePush(
|
||||
paths,
|
||||
StringPrototypeSlice(from, 0, last) + '/node_modules'
|
||||
);
|
||||
last = i;
|
||||
p = 0;
|
||||
} else if (p !== -1) {
|
||||
@ -625,7 +643,7 @@ if (isWindows) {
|
||||
}
|
||||
|
||||
// Append /node_modules to handle root paths.
|
||||
paths.push('/node_modules');
|
||||
ArrayPrototypePush(paths, '/node_modules');
|
||||
|
||||
return paths;
|
||||
};
|
||||
@ -638,15 +656,15 @@ Module._resolveLookupPaths = function(request, parent) {
|
||||
}
|
||||
|
||||
// Check for node modules paths.
|
||||
if (request.charAt(0) !== '.' ||
|
||||
if (StringPrototypeCharAt(request, 0) !== '.' ||
|
||||
(request.length > 1 &&
|
||||
request.charAt(1) !== '.' &&
|
||||
request.charAt(1) !== '/' &&
|
||||
(!isWindows || request.charAt(1) !== '\\'))) {
|
||||
StringPrototypeCharAt(request, 1) !== '.' &&
|
||||
StringPrototypeCharAt(request, 1) !== '/' &&
|
||||
(!isWindows || StringPrototypeCharAt(request, 1) !== '\\'))) {
|
||||
|
||||
let paths = modulePaths;
|
||||
if (parent != null && parent.paths && parent.paths.length) {
|
||||
paths = parent.paths.concat(paths);
|
||||
paths = ArrayPrototypeConcat(parent.paths, paths);
|
||||
}
|
||||
|
||||
debug('looking for %j in %j', request, paths);
|
||||
@ -796,9 +814,9 @@ Module._load = function(request, parent, isMain) {
|
||||
delete relativeResolveCache[relResolveCacheIdentifier];
|
||||
const children = parent && parent.children;
|
||||
if (ArrayIsArray(children)) {
|
||||
const index = children.indexOf(module);
|
||||
const index = ArrayPrototypeIndexOf(children, module);
|
||||
if (index !== -1) {
|
||||
children.splice(index, 1);
|
||||
ArrayPrototypeSplice(children, index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -822,10 +840,10 @@ Module._resolveFilename = function(request, parent, isMain, options) {
|
||||
|
||||
if (typeof options === 'object' && options !== null) {
|
||||
if (ArrayIsArray(options.paths)) {
|
||||
const isRelative = request.startsWith('./') ||
|
||||
request.startsWith('../') ||
|
||||
((isWindows && request.startsWith('.\\')) ||
|
||||
request.startsWith('..\\'));
|
||||
const isRelative = StringPrototypeStartsWith(request, './') ||
|
||||
StringPrototypeStartsWith(request, '../') ||
|
||||
((isWindows && StringPrototypeStartsWith(request, '.\\')) ||
|
||||
StringPrototypeStartsWith(request, '..\\'));
|
||||
|
||||
if (isRelative) {
|
||||
paths = options.paths;
|
||||
@ -840,8 +858,8 @@ Module._resolveFilename = function(request, parent, isMain, options) {
|
||||
const lookupPaths = Module._resolveLookupPaths(request, fakeParent);
|
||||
|
||||
for (let j = 0; j < lookupPaths.length; j++) {
|
||||
if (!paths.includes(lookupPaths[j]))
|
||||
paths.push(lookupPaths[j]);
|
||||
if (!ArrayPrototypeIncludes(paths, lookupPaths[j]))
|
||||
ArrayPrototypePush(paths, lookupPaths[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -890,11 +908,12 @@ Module._resolveFilename = function(request, parent, isMain, options) {
|
||||
for (let cursor = parent;
|
||||
cursor;
|
||||
cursor = moduleParentCache.get(cursor)) {
|
||||
requireStack.push(cursor.filename || cursor.id);
|
||||
ArrayPrototypePush(requireStack, cursor.filename || cursor.id);
|
||||
}
|
||||
let message = `Cannot find module '${request}'`;
|
||||
if (requireStack.length > 0) {
|
||||
message = message + '\nRequire stack:\n- ' + requireStack.join('\n- ');
|
||||
message = message + '\nRequire stack:\n- ' +
|
||||
ArrayPrototypeJoin(requireStack, '\n- ');
|
||||
}
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const err = new Error(message);
|
||||
@ -905,7 +924,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
|
||||
|
||||
function finalizeEsmResolution(match, request, parentPath, pkgPath) {
|
||||
const { resolved, exact } = match;
|
||||
if (StringPrototypeMatch(resolved, encodedSepRegEx))
|
||||
if (RegExpPrototypeTest(encodedSepRegEx, resolved))
|
||||
throw new ERR_INVALID_MODULE_SPECIFIER(
|
||||
resolved, 'must not include encoded "/" or "\\" characters', parentPath);
|
||||
const filename = fileURLToPath(resolved);
|
||||
@ -942,9 +961,9 @@ Module.prototype.load = function(filename) {
|
||||
|
||||
const extension = findLongestRegisteredExtension(filename);
|
||||
// allow .mjs to be overridden
|
||||
if (filename.endsWith('.mjs') && !Module._extensions['.mjs']) {
|
||||
if (StringPrototypeEndsWith(filename, '.mjs') && !Module._extensions['.mjs'])
|
||||
throw new ERR_REQUIRE_ESM(filename);
|
||||
}
|
||||
|
||||
Module._extensions[extension](this, filename);
|
||||
this.loaded = true;
|
||||
|
||||
@ -1075,13 +1094,13 @@ Module.prototype._compile = function(content, filename) {
|
||||
const exports = this.exports;
|
||||
const thisValue = exports;
|
||||
const module = this;
|
||||
if (requireDepth === 0) statCache = new Map();
|
||||
if (requireDepth === 0) statCache = new SafeMap();
|
||||
if (inspectorWrapper) {
|
||||
result = inspectorWrapper(compiledWrapper, thisValue, exports,
|
||||
require, module, filename, dirname);
|
||||
} else {
|
||||
result = compiledWrapper.call(thisValue, exports, require, module,
|
||||
filename, dirname);
|
||||
result = ReflectApply(compiledWrapper, thisValue,
|
||||
[exports, require, module, filename, dirname]);
|
||||
}
|
||||
hasLoadedAnyUserCJSModule = true;
|
||||
if (requireDepth === 0) statCache = null;
|
||||
@ -1090,7 +1109,7 @@ Module.prototype._compile = function(content, filename) {
|
||||
|
||||
// Native extension for .js
|
||||
Module._extensions['.js'] = function(module, filename) {
|
||||
if (filename.endsWith('.js')) {
|
||||
if (StringPrototypeEndsWith(filename, '.js')) {
|
||||
const pkg = readPackageScope(filename);
|
||||
// Function require shouldn't be used in ES modules.
|
||||
if (pkg && pkg.data && pkg.data.type === 'module') {
|
||||
@ -1145,7 +1164,8 @@ Module._extensions['.node'] = function(module, filename) {
|
||||
function createRequireFromPath(filename) {
|
||||
// Allow a directory to be passed as the filename
|
||||
const trailingSlash =
|
||||
filename.endsWith('/') || (isWindows && filename.endsWith('\\'));
|
||||
StringPrototypeEndsWith(filename, '/') ||
|
||||
(isWindows && StringPrototypeEndsWith(filename, '\\'));
|
||||
|
||||
const proxyPath = trailingSlash ?
|
||||
path.join(filename, 'noop.js') :
|
||||
@ -1207,15 +1227,16 @@ Module._initPaths = function() {
|
||||
}
|
||||
|
||||
if (nodePath) {
|
||||
paths = nodePath.split(path.delimiter).filter(function pathsFilterCB(path) {
|
||||
return !!path;
|
||||
}).concat(paths);
|
||||
paths = ArrayPrototypeConcat(ArrayPrototypeFilter(
|
||||
StringPrototypeSplit(nodePath, path.delimiter),
|
||||
Boolean
|
||||
), paths);
|
||||
}
|
||||
|
||||
modulePaths = paths;
|
||||
|
||||
// Clone as a shallow copy, for introspection.
|
||||
Module.globalPaths = modulePaths.slice(0);
|
||||
Module.globalPaths = ArrayPrototypeSlice(modulePaths);
|
||||
};
|
||||
|
||||
Module._preloadModules = function(requests) {
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
PromisePrototypeFinally,
|
||||
StringPrototypeEndsWith,
|
||||
} = primordials;
|
||||
const CJSLoader = require('internal/modules/cjs/loader');
|
||||
const { Module, toRealPath, readPackageScope } = CJSLoader;
|
||||
const { getOptionValue } = require('internal/options');
|
||||
@ -29,9 +33,9 @@ function shouldUseESMLoader(mainPath) {
|
||||
if (esModuleSpecifierResolution === 'node')
|
||||
return true;
|
||||
// Determine the module format of the main
|
||||
if (mainPath && mainPath.endsWith('.mjs'))
|
||||
if (mainPath && StringPrototypeEndsWith(mainPath, '.mjs'))
|
||||
return true;
|
||||
if (!mainPath || mainPath.endsWith('.cjs'))
|
||||
if (!mainPath || StringPrototypeEndsWith(mainPath, '.cjs'))
|
||||
return false;
|
||||
const pkg = readPackageScope(mainPath);
|
||||
return pkg && pkg.data.type === 'module';
|
||||
@ -56,7 +60,7 @@ function handleMainPromise(promise) {
|
||||
process.exitCode = 13;
|
||||
}
|
||||
process.on('exit', handler);
|
||||
return promise.finally(() => process.off('exit', handler));
|
||||
return PromisePrototypeFinally(promise, () => process.off('exit', handler));
|
||||
}
|
||||
|
||||
// For backwards compatibility, we have to run a bunch of
|
||||
|
Loading…
x
Reference in New Issue
Block a user