Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 45e4f82

Browse filesBrowse files
anonriglemire
authored andcommitted
src: move package resolver to c++
Co-authored-by: Daniel Lemire <daniel@lemire.me> PR-URL: #50322 Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
1 parent 0dd53da commit 45e4f82
Copy full SHA for 45e4f82
Expand file treeCollapse file tree

26 files changed

+798
-347
lines changed
Open diff view settings
Collapse file

‎lib/internal/modules/cjs/loader.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/cjs/loader.js
+14-15Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ ObjectDefineProperty(Module, '_readPackage', {
427427
* @param {string} originalPath The specifier passed to `require`
428428
*/
429429
function tryPackage(requestPath, exts, isMain, originalPath) {
430-
const pkg = _readPackage(requestPath).main;
430+
const { main: pkg, pjsonPath } = _readPackage(requestPath);
431431

432432
if (!pkg) {
433433
return tryExtensions(path.resolve(requestPath, 'index'), exts, isMain);
@@ -446,14 +446,13 @@ function tryPackage(requestPath, exts, isMain, originalPath) {
446446
'Please verify that the package.json has a valid "main" entry',
447447
);
448448
err.code = 'MODULE_NOT_FOUND';
449-
err.path = path.resolve(requestPath, 'package.json');
449+
err.path = pjsonPath;
450450
err.requestPath = originalPath;
451451
// TODO(BridgeAR): Add the requireStack as well.
452452
throw err;
453453
} else {
454-
const jsonPath = path.resolve(requestPath, 'package.json');
455454
process.emitWarning(
456-
`Invalid 'main' field in '${jsonPath}' of '${pkg}'. ` +
455+
`Invalid 'main' field in '${pjsonPath}' of '${pkg}'. ` +
457456
'Please either fix that or report it to the module author',
458457
'DeprecationWarning',
459458
'DEP0128',
@@ -539,28 +538,28 @@ function trySelfParentPath(parent) {
539538
function trySelf(parentPath, request) {
540539
if (!parentPath) { return false; }
541540

542-
const { data: pkg, path: pkgPath } = packageJsonReader.readPackageScope(parentPath);
543-
if (!pkg || pkg.exports == null || pkg.name === undefined) {
541+
const pkg = packageJsonReader.getNearestParentPackageJSON(parentPath);
542+
if (pkg?.data.exports === undefined || pkg.data.name === undefined) {
544543
return false;
545544
}
546545

547546
let expansion;
548-
if (request === pkg.name) {
547+
if (request === pkg.data.name) {
549548
expansion = '.';
550-
} else if (StringPrototypeStartsWith(request, `${pkg.name}/`)) {
551-
expansion = '.' + StringPrototypeSlice(request, pkg.name.length);
549+
} else if (StringPrototypeStartsWith(request, `${pkg.data.name}/`)) {
550+
expansion = '.' + StringPrototypeSlice(request, pkg.data.name.length);
552551
} else {
553552
return false;
554553
}
555554

556555
try {
557556
const { packageExportsResolve } = require('internal/modules/esm/resolve');
558557
return finalizeEsmResolution(packageExportsResolve(
559-
pathToFileURL(pkgPath + '/package.json'), expansion, pkg,
560-
pathToFileURL(parentPath), getCjsConditions()), parentPath, pkgPath);
558+
pathToFileURL(pkg.path + '/package.json'), expansion, pkg.data,
559+
pathToFileURL(parentPath), getCjsConditions()), parentPath, pkg.path);
561560
} catch (e) {
562561
if (e.code === 'ERR_MODULE_NOT_FOUND') {
563-
throw createEsmNotFoundErr(request, pkgPath + '/package.json');
562+
throw createEsmNotFoundErr(request, pkg.path + '/package.json');
564563
}
565564
throw e;
566565
}
@@ -1099,7 +1098,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
10991098

11001099
if (request[0] === '#' && (parent?.filename || parent?.id === '<repl>')) {
11011100
const parentPath = parent?.filename ?? process.cwd() + path.sep;
1102-
const pkg = packageJsonReader.readPackageScope(parentPath) || { __proto__: null };
1101+
const pkg = packageJsonReader.getNearestParentPackageJSON(parentPath) || { __proto__: null };
11031102
if (pkg.data?.imports != null) {
11041103
try {
11051104
const { packageImportsResolve } = require('internal/modules/esm/resolve');
@@ -1397,9 +1396,9 @@ Module._extensions['.js'] = function(module, filename) {
13971396
content = fs.readFileSync(filename, 'utf8');
13981397
}
13991398
if (StringPrototypeEndsWith(filename, '.js')) {
1400-
const pkg = packageJsonReader.readPackageScope(filename) || { __proto__: null };
1399+
const pkg = packageJsonReader.getNearestParentPackageJSON(filename);
14011400
// Function require shouldn't be used in ES modules.
1402-
if (pkg.data?.type === 'module') {
1401+
if (pkg?.data.type === 'module') {
14031402
// This is an error path because `require` of a `.js` file in a `"type": "module"` scope is not allowed.
14041403
const parent = moduleParentCache.get(module);
14051404
const parentPath = parent?.filename;
Collapse file

‎lib/internal/modules/esm/get_format.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/get_format.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const {
1919
const experimentalNetworkImports =
2020
getOptionValue('--experimental-network-imports');
2121
const { containsModuleSyntax } = internalBinding('contextify');
22-
const { getPackageType } = require('internal/modules/esm/resolve');
22+
const { getPackageType } = require('internal/modules/esm/package_config');
2323
const { fileURLToPath } = require('internal/url');
2424
const { ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes;
2525

Collapse file

‎lib/internal/modules/esm/module_job.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/module_job.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ class ModuleJob {
228228
const packageConfig =
229229
StringPrototypeStartsWith(this.module.url, 'file://') &&
230230
RegExpPrototypeExec(/\.js(\?[^#]*)?(#.*)?$/, this.module.url) !== null &&
231-
require('internal/modules/esm/resolve')
231+
require('internal/modules/esm/package_config')
232232
.getPackageScopeConfig(this.module.url);
233233
if (packageConfig.type === 'module') {
234234
e.message +=
Collapse file
+22-47Lines changed: 22 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,44 @@
11
'use strict';
22

3-
const {
4-
StringPrototypeEndsWith,
5-
} = primordials;
6-
const { URL, fileURLToPath } = require('internal/url');
7-
const packageJsonReader = require('internal/modules/package_json_reader');
3+
const { ArrayIsArray } = primordials;
4+
const modulesBinding = internalBinding('modules');
5+
const { deserializePackageJSON } = require('internal/modules/package_json_reader');
86

9-
/**
10-
* @typedef {object} PackageConfig
11-
* @property {string} pjsonPath - The path to the package.json file.
12-
* @property {boolean} exists - Whether the package.json file exists.
13-
* @property {'none' | 'commonjs' | 'module'} type - The type of the package.
14-
* @property {string} [name] - The name of the package.
15-
* @property {string} [main] - The main entry point of the package.
16-
* @property {PackageTarget} [exports] - The exports configuration of the package.
17-
* @property {Record<string, string | Record<string, string>>} [imports] - The imports configuration of the package.
18-
*/
19-
/**
20-
* @typedef {string | string[] | Record<string, string | Record<string, string>>} PackageTarget
21-
*/
7+
// TODO(@anonrig): Merge this file with internal/esm/package_json_reader.js
228

239
/**
2410
* Returns the package configuration for the given resolved URL.
2511
* @param {URL | string} resolved - The resolved URL.
26-
* @returns {PackageConfig} - The package configuration.
12+
* @returns {import('typings/internalBinding/modules').PackageConfig} - The package configuration.
2713
*/
2814
function getPackageScopeConfig(resolved) {
29-
let packageJSONUrl = new URL('./package.json', resolved);
30-
while (true) {
31-
const packageJSONPath = packageJSONUrl.pathname;
32-
if (StringPrototypeEndsWith(packageJSONPath, 'node_modules/package.json')) {
33-
break;
34-
}
35-
const packageConfig = packageJsonReader.read(fileURLToPath(packageJSONUrl), {
36-
__proto__: null,
37-
specifier: resolved,
38-
isESM: true,
39-
});
40-
if (packageConfig.exists) {
41-
return packageConfig;
42-
}
43-
44-
const lastPackageJSONUrl = packageJSONUrl;
45-
packageJSONUrl = new URL('../package.json', packageJSONUrl);
15+
const result = modulesBinding.getPackageScopeConfig(`${resolved}`);
4616

47-
// Terminates at root where ../package.json equals ../../package.json
48-
// (can't just check "/package.json" for Windows support).
49-
if (packageJSONUrl.pathname === lastPackageJSONUrl.pathname) {
50-
break;
51-
}
17+
if (ArrayIsArray(result)) {
18+
return deserializePackageJSON(`${resolved}`, result, false /* checkIntegrity */);
5219
}
53-
const packageJSONPath = fileURLToPath(packageJSONUrl);
20+
21+
// This means that the response is a string
22+
// and it is the path to the package.json file
5423
return {
5524
__proto__: null,
56-
pjsonPath: packageJSONPath,
25+
pjsonPath: result,
5726
exists: false,
58-
main: undefined,
59-
name: undefined,
6027
type: 'none',
61-
exports: undefined,
62-
imports: undefined,
6328
};
6429
}
6530

31+
/**
32+
* Returns the package type for a given URL.
33+
* @param {URL} url - The URL to get the package type for.
34+
*/
35+
function getPackageType(url) {
36+
// TODO(@anonrig): Write a C++ function that returns only "type".
37+
return getPackageScopeConfig(url).type;
38+
}
39+
6640

6741
module.exports = {
6842
getPackageScopeConfig,
43+
getPackageType,
6944
};
Collapse file

‎lib/internal/modules/esm/resolve.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/resolve.js
+4-14Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ const legacyMainResolveExtensionsIndexes = {
198198
* 4. TRY(pkg_url/index.js, pkg_url/index.json, pkg_url/index.node)
199199
* 5. NOT_FOUND
200200
* @param {URL} packageJSONUrl
201-
* @param {PackageConfig} packageConfig
201+
* @param {import('typings/internalBinding/modules').PackageConfig} packageConfig
202202
* @param {string | URL | undefined} base
203203
* @returns {URL}
204204
*/
@@ -502,7 +502,7 @@ function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath,
502502
}
503503
return resolveResult;
504504
}
505-
if (lastException === undefined || lastException === null) {
505+
if (lastException == null) {
506506
return lastException;
507507
}
508508
throw lastException;
@@ -575,7 +575,7 @@ function isConditionalExportsMainSugar(exports, packageJSONUrl, base) {
575575
*/
576576
function packageExportsResolve(
577577
packageJSONUrl, packageSubpath, packageConfig, base, conditions) {
578-
let exports = packageConfig.exports;
578+
let { exports } = packageConfig;
579579
if (isConditionalExportsMainSugar(exports, packageJSONUrl, base)) {
580580
exports = { '.': exports };
581581
}
@@ -740,15 +740,6 @@ function packageImportsResolve(name, base, conditions) {
740740
throw importNotDefined(name, packageJSONUrl, base);
741741
}
742742

743-
/**
744-
* Returns the package type for a given URL.
745-
* @param {URL} url - The URL to get the package type for.
746-
*/
747-
function getPackageType(url) {
748-
const packageConfig = getPackageScopeConfig(url);
749-
return packageConfig.type;
750-
}
751-
752743
/**
753744
* Parse a package name from a specifier.
754745
* @param {string} specifier - The import specifier.
@@ -796,6 +787,7 @@ function parsePackageName(specifier, base) {
796787
* @returns {URL} - The resolved URL.
797788
*/
798789
function packageResolve(specifier, base, conditions) {
790+
// TODO(@anonrig): Move this to a C++ function.
799791
if (BuiltinModule.canBeRequiredWithoutScheme(specifier)) {
800792
return new URL('node:' + specifier);
801793
}
@@ -1179,8 +1171,6 @@ module.exports = {
11791171
decorateErrorWithCommonJSHints,
11801172
defaultResolve,
11811173
encodedSepRegEx,
1182-
getPackageScopeConfig,
1183-
getPackageType,
11841174
packageExportsResolve,
11851175
packageImportsResolve,
11861176
throwIfInvalidParentURL,

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.