Skip to content

Commit 4e17ffc

Browse files
committed
module: fix legacy node specifier resolution to resolve "main" field
PR-URL: #38979 Fixes: #32103 Fixes: #38739 Reviewed-By: Bradley Farias <[email protected]> Reviewed-By: Guy Bedford <[email protected]>
1 parent 5b3587d commit 4e17ffc

File tree

4 files changed

+27
-6
lines changed

4 files changed

+27
-6
lines changed

lib/internal/modules/esm/resolve.js

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const { getOptionValue } = require('internal/options');
3434
const policy = getOptionValue('--experimental-policy') ?
3535
require('internal/process/policy') :
3636
null;
37-
const { sep, relative } = require('path');
37+
const { sep, relative, resolve } = require('path');
3838
const preserveSymlinks = getOptionValue('--preserve-symlinks');
3939
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
4040
const typeFlag = getOptionValue('--input-type');
@@ -204,16 +204,18 @@ function getPackageScopeConfig(resolved) {
204204
return packageConfig;
205205
}
206206

207-
/*
207+
/**
208208
* Legacy CommonJS main resolution:
209209
* 1. let M = pkg_url + (json main field)
210210
* 2. TRY(M, M.js, M.json, M.node)
211211
* 3. TRY(M/index.js, M/index.json, M/index.node)
212212
* 4. TRY(pkg_url/index.js, pkg_url/index.json, pkg_url/index.node)
213213
* 5. NOT_FOUND
214+
* @param {string | URL} url
215+
* @returns {boolean}
214216
*/
215217
function fileExists(url) {
216-
return tryStatSync(fileURLToPath(url)).isFile();
218+
return statSync(url, { throwIfNoEntry: false })?.isFile() ?? false;
217219
}
218220

219221
function legacyMainResolve(packageJSONUrl, packageConfig, base) {
@@ -272,7 +274,19 @@ function resolveExtensions(search) {
272274
return undefined;
273275
}
274276

275-
function resolveIndex(search) {
277+
function resolveDirectoryEntry(search) {
278+
const dirPath = fileURLToPath(search);
279+
const pkgJsonPath = resolve(dirPath, 'package.json');
280+
if (fileExists(pkgJsonPath)) {
281+
const pkgJson = packageJsonReader.read(pkgJsonPath);
282+
if (pkgJson.containsKeys) {
283+
const { main } = JSONParse(pkgJson.string);
284+
if (main != null) {
285+
const mainUrl = pathToFileURL(resolve(dirPath, main));
286+
return resolveExtensionsWithTryExactName(mainUrl);
287+
}
288+
}
289+
}
276290
return resolveExtensions(new URL('index', search));
277291
}
278292

@@ -288,10 +302,10 @@ function finalizeResolution(resolved, base) {
288302
let file = resolveExtensionsWithTryExactName(resolved);
289303
if (file !== undefined) return file;
290304
if (!StringPrototypeEndsWith(path, '/')) {
291-
file = resolveIndex(new URL(`${resolved}/`));
305+
file = resolveDirectoryEntry(new URL(`${resolved}/`));
292306
if (file !== undefined) return file;
293307
} else {
294-
return resolveIndex(resolved) || resolved;
308+
return resolveDirectoryEntry(resolved) || resolved;
295309
}
296310
throw new ERR_MODULE_NOT_FOUND(
297311
resolved.pathname, fileURLToPath(base), 'module');

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

Lines changed: 3 additions & 0 deletions
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');
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = 'main';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"main": "./main.js"
3+
}

0 commit comments

Comments
 (0)