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:
Antoine du Hamel 2020-11-07 11:08:09 +01:00 committed by Node.js GitHub Bot
parent a8b9ede3c1
commit 2c77fe192e
3 changed files with 83 additions and 54 deletions

View File

@ -1,11 +1,16 @@
'use strict'; 'use strict';
const { const {
ArrayPrototypeForEach,
ArrayPrototypeJoin, ArrayPrototypeJoin,
ObjectDefineProperty, ObjectDefineProperty,
ObjectPrototypeHasOwnProperty, ObjectPrototypeHasOwnProperty,
SafeMap, SafeMap,
SafeSet, SafeSet,
StringPrototypeCharCodeAt,
StringPrototypeIncludes,
StringPrototypeSlice,
StringPrototypeStartsWith,
} = primordials; } = primordials;
const { const {
ERR_MANIFEST_DEPENDENCY_MISSING, ERR_MANIFEST_DEPENDENCY_MISSING,
@ -15,8 +20,7 @@ const { NativeModule } = require('internal/bootstrap/loaders');
const { validateString } = require('internal/validators'); const { validateString } = require('internal/validators');
const path = require('path'); const path = require('path');
const { pathToFileURL, fileURLToPath } = require('internal/url'); const { pathToFileURL, fileURLToPath, URL } = require('internal/url');
const { URL } = require('url');
const { getOptionValue } = require('internal/options'); const { getOptionValue } = require('internal/options');
const userConditions = getOptionValue('--conditions'); const userConditions = getOptionValue('--conditions');
@ -119,8 +123,8 @@ function makeRequireFunction(mod, redirects) {
* translates it to FEFF, the UTF-16 BOM. * translates it to FEFF, the UTF-16 BOM.
*/ */
function stripBOM(content) { function stripBOM(content) {
if (content.charCodeAt(0) === 0xFEFF) { if (StringPrototypeCharCodeAt(content) === 0xFEFF) {
content = content.slice(1); content = StringPrototypeSlice(content, 1);
} }
return content; return content;
} }
@ -128,11 +132,11 @@ function stripBOM(content) {
function addBuiltinLibsToObject(object) { function addBuiltinLibsToObject(object) {
// Make built-in modules available directly (loaded lazily). // Make built-in modules available directly (loaded lazily).
const { builtinModules } = require('internal/modules/cjs/loader').Module; 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., // Neither add underscored modules, nor ones that contain slashes (e.g.,
// 'fs/promises') or ones that are already defined. // 'fs/promises') or ones that are already defined.
if (name.startsWith('_') || if (StringPrototypeStartsWith(name, '_') ||
name.includes('/') || StringPrototypeIncludes(name, '/') ||
ObjectPrototypeHasOwnProperty(object, name)) { ObjectPrototypeHasOwnProperty(object, name)) {
return; return;
} }

View File

@ -23,10 +23,17 @@
const { const {
ArrayIsArray, ArrayIsArray,
ArrayPrototypeConcat,
ArrayPrototypeFilter,
ArrayPrototypeIncludes,
ArrayPrototypeIndexOf,
ArrayPrototypeJoin, ArrayPrototypeJoin,
ArrayPrototypePush,
ArrayPrototypeSlice,
ArrayPrototypeSplice,
Boolean,
Error, Error,
JSONParse, JSONParse,
Map,
ObjectCreate, ObjectCreate,
ObjectDefineProperty, ObjectDefineProperty,
ObjectFreeze, ObjectFreeze,
@ -36,16 +43,20 @@ const {
ObjectPrototype, ObjectPrototype,
ObjectPrototypeHasOwnProperty, ObjectPrototypeHasOwnProperty,
ObjectSetPrototypeOf, ObjectSetPrototypeOf,
ReflectApply,
ReflectSet, ReflectSet,
RegExpPrototypeTest, RegExpPrototypeTest,
SafeMap, SafeMap,
SafeWeakMap, SafeWeakMap,
String, String,
StringPrototypeCharAt,
StringPrototypeCharCodeAt,
StringPrototypeEndsWith, StringPrototypeEndsWith,
StringPrototypeLastIndexOf, StringPrototypeLastIndexOf,
StringPrototypeIndexOf, StringPrototypeIndexOf,
StringPrototypeMatch, StringPrototypeMatch,
StringPrototypeSlice, StringPrototypeSlice,
StringPrototypeSplit,
StringPrototypeStartsWith, StringPrototypeStartsWith,
} = primordials; } = primordials;
@ -142,8 +153,8 @@ function stat(filename) {
function updateChildren(parent, child, scan) { function updateChildren(parent, child, scan) {
const children = parent && parent.children; const children = parent && parent.children;
if (children && !(scan && children.includes(child))) if (children && !(scan && ArrayPrototypeIncludes(children, child)))
children.push(child); ArrayPrototypePush(children, child);
} }
const moduleParentCache = new SafeWeakMap(); const moduleParentCache = new SafeWeakMap();
@ -161,7 +172,7 @@ function Module(id = '', parent) {
const builtinModules = []; const builtinModules = [];
for (const [id, mod] of NativeModule.map) { for (const [id, mod] of NativeModule.map) {
if (mod.canBeRequiredByUsers) { 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, // In order to minimize unnecessary lstat() calls,
// this cache is a list of known-real paths. // this cache is a list of known-real paths.
// Set to an empty Map to reset. // 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 // Check if the file exists and is not a directory
// if using --preserve-symlinks and isMain is false, // if using --preserve-symlinks and isMain is false,
@ -389,10 +400,10 @@ function findLongestRegisteredExtension(filename) {
let currentExtension; let currentExtension;
let index; let index;
let startIndex = 0; let startIndex = 0;
while ((index = name.indexOf('.', startIndex)) !== -1) { while ((index = StringPrototypeIndexOf(name, '.', startIndex)) !== -1) {
startIndex = index + 1; startIndex = index + 1;
if (index === 0) continue; // Skip dotfiles like .gitignore if (index === 0) continue; // Skip dotfiles like .gitignore
currentExtension = name.slice(index); currentExtension = StringPrototypeSlice(name, index);
if (Module._extensions[currentExtension]) return currentExtension; if (Module._extensions[currentExtension]) return currentExtension;
} }
return '.js'; return '.js';
@ -473,15 +484,15 @@ Module._findPath = function(request, paths, isMain) {
return false; return false;
} }
const cacheKey = request + '\x00' + const cacheKey = request + '\x00' + ArrayPrototypeJoin(paths, '\x00');
(paths.length === 1 ? paths[0] : paths.join('\x00'));
const entry = Module._pathCache[cacheKey]; const entry = Module._pathCache[cacheKey];
if (entry) if (entry)
return entry; return entry;
let exts; let exts;
let trailingSlash = request.length > 0 && let trailingSlash = request.length > 0 &&
request.charCodeAt(request.length - 1) === CHAR_FORWARD_SLASH; StringPrototypeCharCodeAt(request, request.length - 1) ===
CHAR_FORWARD_SLASH;
if (!trailingSlash) { if (!trailingSlash) {
trailingSlash = RegExpPrototypeTest(trailingSlashRegex, request); trailingSlash = RegExpPrototypeTest(trailingSlashRegex, request);
} }
@ -564,13 +575,14 @@ if (isWindows) {
// return root node_modules when path is 'D:\\'. // return root node_modules when path is 'D:\\'.
// path.resolve will make sure from.length >=3 in Windows. // path.resolve will make sure from.length >=3 in Windows.
if (from.charCodeAt(from.length - 1) === CHAR_BACKWARD_SLASH && if (StringPrototypeCharCodeAt(from, from.length - 1) ===
from.charCodeAt(from.length - 2) === CHAR_COLON) CHAR_BACKWARD_SLASH &&
StringPrototypeCharCodeAt(from, from.length - 2) === CHAR_COLON)
return [from + 'node_modules']; return [from + 'node_modules'];
const paths = []; const paths = [];
for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) { 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 // The path segment separator check ('\' and '/') was used to get
// node_modules path for every path segment. // node_modules path for every path segment.
// Use colon as an extra condition since we can get node_modules // Use colon as an extra condition since we can get node_modules
@ -580,7 +592,10 @@ if (isWindows) {
code === CHAR_FORWARD_SLASH || code === CHAR_FORWARD_SLASH ||
code === CHAR_COLON) { code === CHAR_COLON) {
if (p !== nmLen) if (p !== nmLen)
paths.push(from.slice(0, last) + '\\node_modules'); ArrayPrototypePush(
paths,
StringPrototypeSlice(from, 0, last) + '\\node_modules'
);
last = i; last = i;
p = 0; p = 0;
} else if (p !== -1) { } else if (p !== -1) {
@ -609,10 +624,13 @@ if (isWindows) {
// that works on both Windows and Posix is non-trivial. // that works on both Windows and Posix is non-trivial.
const paths = []; const paths = [];
for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) { 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 (code === CHAR_FORWARD_SLASH) {
if (p !== nmLen) if (p !== nmLen)
paths.push(from.slice(0, last) + '/node_modules'); ArrayPrototypePush(
paths,
StringPrototypeSlice(from, 0, last) + '/node_modules'
);
last = i; last = i;
p = 0; p = 0;
} else if (p !== -1) { } else if (p !== -1) {
@ -625,7 +643,7 @@ if (isWindows) {
} }
// Append /node_modules to handle root paths. // Append /node_modules to handle root paths.
paths.push('/node_modules'); ArrayPrototypePush(paths, '/node_modules');
return paths; return paths;
}; };
@ -638,15 +656,15 @@ Module._resolveLookupPaths = function(request, parent) {
} }
// Check for node modules paths. // Check for node modules paths.
if (request.charAt(0) !== '.' || if (StringPrototypeCharAt(request, 0) !== '.' ||
(request.length > 1 && (request.length > 1 &&
request.charAt(1) !== '.' && StringPrototypeCharAt(request, 1) !== '.' &&
request.charAt(1) !== '/' && StringPrototypeCharAt(request, 1) !== '/' &&
(!isWindows || request.charAt(1) !== '\\'))) { (!isWindows || StringPrototypeCharAt(request, 1) !== '\\'))) {
let paths = modulePaths; let paths = modulePaths;
if (parent != null && parent.paths && parent.paths.length) { 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); debug('looking for %j in %j', request, paths);
@ -796,9 +814,9 @@ Module._load = function(request, parent, isMain) {
delete relativeResolveCache[relResolveCacheIdentifier]; delete relativeResolveCache[relResolveCacheIdentifier];
const children = parent && parent.children; const children = parent && parent.children;
if (ArrayIsArray(children)) { if (ArrayIsArray(children)) {
const index = children.indexOf(module); const index = ArrayPrototypeIndexOf(children, module);
if (index !== -1) { 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 (typeof options === 'object' && options !== null) {
if (ArrayIsArray(options.paths)) { if (ArrayIsArray(options.paths)) {
const isRelative = request.startsWith('./') || const isRelative = StringPrototypeStartsWith(request, './') ||
request.startsWith('../') || StringPrototypeStartsWith(request, '../') ||
((isWindows && request.startsWith('.\\')) || ((isWindows && StringPrototypeStartsWith(request, '.\\')) ||
request.startsWith('..\\')); StringPrototypeStartsWith(request, '..\\'));
if (isRelative) { if (isRelative) {
paths = options.paths; paths = options.paths;
@ -840,8 +858,8 @@ Module._resolveFilename = function(request, parent, isMain, options) {
const lookupPaths = Module._resolveLookupPaths(request, fakeParent); const lookupPaths = Module._resolveLookupPaths(request, fakeParent);
for (let j = 0; j < lookupPaths.length; j++) { for (let j = 0; j < lookupPaths.length; j++) {
if (!paths.includes(lookupPaths[j])) if (!ArrayPrototypeIncludes(paths, lookupPaths[j]))
paths.push(lookupPaths[j]); ArrayPrototypePush(paths, lookupPaths[j]);
} }
} }
} }
@ -890,11 +908,12 @@ Module._resolveFilename = function(request, parent, isMain, options) {
for (let cursor = parent; for (let cursor = parent;
cursor; cursor;
cursor = moduleParentCache.get(cursor)) { cursor = moduleParentCache.get(cursor)) {
requireStack.push(cursor.filename || cursor.id); ArrayPrototypePush(requireStack, cursor.filename || cursor.id);
} }
let message = `Cannot find module '${request}'`; let message = `Cannot find module '${request}'`;
if (requireStack.length > 0) { 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 // eslint-disable-next-line no-restricted-syntax
const err = new Error(message); const err = new Error(message);
@ -905,7 +924,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
function finalizeEsmResolution(match, request, parentPath, pkgPath) { function finalizeEsmResolution(match, request, parentPath, pkgPath) {
const { resolved, exact } = match; const { resolved, exact } = match;
if (StringPrototypeMatch(resolved, encodedSepRegEx)) if (RegExpPrototypeTest(encodedSepRegEx, resolved))
throw new ERR_INVALID_MODULE_SPECIFIER( throw new ERR_INVALID_MODULE_SPECIFIER(
resolved, 'must not include encoded "/" or "\\" characters', parentPath); resolved, 'must not include encoded "/" or "\\" characters', parentPath);
const filename = fileURLToPath(resolved); const filename = fileURLToPath(resolved);
@ -942,9 +961,9 @@ Module.prototype.load = function(filename) {
const extension = findLongestRegisteredExtension(filename); const extension = findLongestRegisteredExtension(filename);
// allow .mjs to be overridden // 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); throw new ERR_REQUIRE_ESM(filename);
}
Module._extensions[extension](this, filename); Module._extensions[extension](this, filename);
this.loaded = true; this.loaded = true;
@ -1075,13 +1094,13 @@ Module.prototype._compile = function(content, filename) {
const exports = this.exports; const exports = this.exports;
const thisValue = exports; const thisValue = exports;
const module = this; const module = this;
if (requireDepth === 0) statCache = new Map(); if (requireDepth === 0) statCache = new SafeMap();
if (inspectorWrapper) { if (inspectorWrapper) {
result = inspectorWrapper(compiledWrapper, thisValue, exports, result = inspectorWrapper(compiledWrapper, thisValue, exports,
require, module, filename, dirname); require, module, filename, dirname);
} else { } else {
result = compiledWrapper.call(thisValue, exports, require, module, result = ReflectApply(compiledWrapper, thisValue,
filename, dirname); [exports, require, module, filename, dirname]);
} }
hasLoadedAnyUserCJSModule = true; hasLoadedAnyUserCJSModule = true;
if (requireDepth === 0) statCache = null; if (requireDepth === 0) statCache = null;
@ -1090,7 +1109,7 @@ Module.prototype._compile = function(content, filename) {
// Native extension for .js // Native extension for .js
Module._extensions['.js'] = function(module, filename) { Module._extensions['.js'] = function(module, filename) {
if (filename.endsWith('.js')) { if (StringPrototypeEndsWith(filename, '.js')) {
const pkg = readPackageScope(filename); const pkg = readPackageScope(filename);
// Function require shouldn't be used in ES modules. // Function require shouldn't be used in ES modules.
if (pkg && pkg.data && pkg.data.type === 'module') { if (pkg && pkg.data && pkg.data.type === 'module') {
@ -1145,7 +1164,8 @@ Module._extensions['.node'] = function(module, filename) {
function createRequireFromPath(filename) { function createRequireFromPath(filename) {
// Allow a directory to be passed as the filename // Allow a directory to be passed as the filename
const trailingSlash = const trailingSlash =
filename.endsWith('/') || (isWindows && filename.endsWith('\\')); StringPrototypeEndsWith(filename, '/') ||
(isWindows && StringPrototypeEndsWith(filename, '\\'));
const proxyPath = trailingSlash ? const proxyPath = trailingSlash ?
path.join(filename, 'noop.js') : path.join(filename, 'noop.js') :
@ -1207,15 +1227,16 @@ Module._initPaths = function() {
} }
if (nodePath) { if (nodePath) {
paths = nodePath.split(path.delimiter).filter(function pathsFilterCB(path) { paths = ArrayPrototypeConcat(ArrayPrototypeFilter(
return !!path; StringPrototypeSplit(nodePath, path.delimiter),
}).concat(paths); Boolean
), paths);
} }
modulePaths = paths; modulePaths = paths;
// Clone as a shallow copy, for introspection. // Clone as a shallow copy, for introspection.
Module.globalPaths = modulePaths.slice(0); Module.globalPaths = ArrayPrototypeSlice(modulePaths);
}; };
Module._preloadModules = function(requests) { Module._preloadModules = function(requests) {

View File

@ -1,5 +1,9 @@
'use strict'; 'use strict';
const {
PromisePrototypeFinally,
StringPrototypeEndsWith,
} = primordials;
const CJSLoader = require('internal/modules/cjs/loader'); const CJSLoader = require('internal/modules/cjs/loader');
const { Module, toRealPath, readPackageScope } = CJSLoader; const { Module, toRealPath, readPackageScope } = CJSLoader;
const { getOptionValue } = require('internal/options'); const { getOptionValue } = require('internal/options');
@ -29,9 +33,9 @@ function shouldUseESMLoader(mainPath) {
if (esModuleSpecifierResolution === 'node') if (esModuleSpecifierResolution === 'node')
return true; return true;
// Determine the module format of the main // Determine the module format of the main
if (mainPath && mainPath.endsWith('.mjs')) if (mainPath && StringPrototypeEndsWith(mainPath, '.mjs'))
return true; return true;
if (!mainPath || mainPath.endsWith('.cjs')) if (!mainPath || StringPrototypeEndsWith(mainPath, '.cjs'))
return false; return false;
const pkg = readPackageScope(mainPath); const pkg = readPackageScope(mainPath);
return pkg && pkg.data.type === 'module'; return pkg && pkg.data.type === 'module';
@ -56,7 +60,7 @@ function handleMainPromise(promise) {
process.exitCode = 13; process.exitCode = 13;
} }
process.on('exit', handler); 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 // For backwards compatibility, we have to run a bunch of