Skip to content

Commit 3e4bc1b

Browse files
aduh95richardlau
authored andcommitted
module: fix legacy node specifier resolution to resolve "main" field
PR-URL: #38979 Backport-PR-URL: #39497 Fixes: #32103 Fixes: #38739 Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com>
1 parent ddc8dde commit 3e4bc1b

File tree

4 files changed

+27
-6
lines changed

4 files changed

+27
-6
lines changed

lib/internal/modules/esm/resolve.js

+20-6
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const {
3030
Stats,
3131
} = require('fs');
3232
const { getOptionValue } = require('internal/options');
33-
const { sep, relative } = require('path');
33+
const { sep, relative, resolve } = require('path');
3434
const preserveSymlinks = getOptionValue('--preserve-symlinks');
3535
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
3636
const typeFlag = getOptionValue('--input-type');
@@ -160,16 +160,18 @@ function getPackageScopeConfig(resolved) {
160160
return packageConfig;
161161
}
162162

163-
/*
163+
/**
164164
* Legacy CommonJS main resolution:
165165
* 1. let M = pkg_url + (json main field)
166166
* 2. TRY(M, M.js, M.json, M.node)
167167
* 3. TRY(M/index.js, M/index.json, M/index.node)
168168
* 4. TRY(pkg_url/index.js, pkg_url/index.json, pkg_url/index.node)
169169
* 5. NOT_FOUND
170+
* @param {string | URL} url
171+
* @returns {boolean}
170172
*/
171173
function fileExists(url) {
172-
return tryStatSync(fileURLToPath(url)).isFile();
174+
return tryStatSync(url).isFile();
173175
}
174176

175177
function legacyMainResolve(packageJSONUrl, packageConfig, base) {
@@ -236,7 +238,19 @@ function resolveExtensions(search) {
236238
return undefined;
237239
}
238240

239-
function resolveIndex(search) {
241+
function resolveDirectoryEntry(search) {
242+
const dirPath = fileURLToPath(search);
243+
const pkgJsonPath = resolve(dirPath, 'package.json');
244+
if (fileExists(pkgJsonPath)) {
245+
const pkgJson = packageJsonReader.read(pkgJsonPath);
246+
if (pkgJson.containsKeys) {
247+
const { main } = JSONParse(pkgJson.string);
248+
if (main != null) {
249+
const mainUrl = pathToFileURL(resolve(dirPath, main));
250+
return resolveExtensionsWithTryExactName(mainUrl);
251+
}
252+
}
253+
}
240254
return resolveExtensions(new URL('index', search));
241255
}
242256

@@ -252,10 +266,10 @@ function finalizeResolution(resolved, base) {
252266
let file = resolveExtensionsWithTryExactName(resolved);
253267
if (file !== undefined) return file;
254268
if (!StringPrototypeEndsWith(path, '/')) {
255-
file = resolveIndex(new URL(`${resolved}/`));
269+
file = resolveDirectoryEntry(new URL(`${resolved}/`));
256270
if (file !== undefined) return file;
257271
} else {
258-
return resolveIndex(resolved) || resolved;
272+
return resolveDirectoryEntry(resolved) || resolved;
259273
}
260274
throw new ERR_MODULE_NOT_FOUND(
261275
resolved.pathname, fileURLToPath(base), 'module');

test/es-module/test-esm-specifiers-legacy-flag.mjs

+3
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ import assert from 'assert';
66
import commonjs from '../fixtures/es-module-specifiers/package-type-commonjs';
77
// esm index.js
88
import module from '../fixtures/es-module-specifiers/package-type-module';
9+
// Directory entry with main.js
10+
import main from '../fixtures/es-module-specifiers/dir-with-main';
911
// Notice the trailing slash
1012
import success, { explicit, implicit, implicitModule }
1113
from '../fixtures/es-module-specifiers/';
1214

1315
assert.strictEqual(commonjs, 'commonjs');
1416
assert.strictEqual(module, 'module');
17+
assert.strictEqual(main, 'main');
1518
assert.strictEqual(success, 'success');
1619
assert.strictEqual(explicit, 'esm');
1720
assert.strictEqual(implicit, 'cjs');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = 'main';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"main": "./main.js"
3+
}

0 commit comments

Comments
 (0)