Skip to content

Commit d9a800e

Browse files
aduh95ruyadorno
authored andcommitted
esm: fix emit deprecation on legacy main resolve
PR-URL: #48664 Refs: #48325 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
1 parent e2688c8 commit d9a800e

File tree

2 files changed

+134
-12
lines changed

2 files changed

+134
-12
lines changed

lib/internal/modules/esm/resolve.js

+13-12
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ function emitInvalidSegmentDeprecation(target, request, match, pjsonUrl, interna
118118
* @param {URL} url
119119
* @param {URL} packageJSONUrl
120120
* @param {string | URL | undefined} base
121-
* @param {string} main
121+
* @param {string} [main]
122122
* @returns {void}
123123
*/
124124
function emitLegacyIndexDeprecation(url, packageJSONUrl, base, main) {
@@ -128,17 +128,7 @@ function emitLegacyIndexDeprecation(url, packageJSONUrl, base, main) {
128128
const path = fileURLToPath(url);
129129
const pkgPath = fileURLToPath(new URL('.', packageJSONUrl));
130130
const basePath = fileURLToPath(base);
131-
if (main)
132-
process.emitWarning(
133-
`Package ${pkgPath} has a "main" field set to ${JSONStringify(main)}, ` +
134-
`excluding the full filename and extension to the resolved file at "${
135-
StringPrototypeSlice(path, pkgPath.length)}", imported from ${
136-
basePath}.\n Automatic extension resolution of the "main" field is ` +
137-
'deprecated for ES modules.',
138-
'DeprecationWarning',
139-
'DEP0151',
140-
);
141-
else
131+
if (!main) {
142132
process.emitWarning(
143133
`No "main" or "exports" field defined in the package.json for ${pkgPath
144134
} resolving the main entry point "${
@@ -147,6 +137,17 @@ function emitLegacyIndexDeprecation(url, packageJSONUrl, base, main) {
147137
'DeprecationWarning',
148138
'DEP0151',
149139
);
140+
} else if (resolve(pkgPath, main) !== path) {
141+
process.emitWarning(
142+
`Package ${pkgPath} has a "main" field set to "${main}", ` +
143+
`excluding the full filename and extension to the resolved file at "${
144+
StringPrototypeSlice(path, pkgPath.length)}", imported from ${
145+
basePath}.\n Automatic extension resolution of the "main" field is ` +
146+
'deprecated for ES modules.',
147+
'DeprecationWarning',
148+
'DEP0151',
149+
);
150+
}
150151
}
151152

152153
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { spawnPromisified } from '../common/index.mjs';
2+
import * as tmpdir from '../common/tmpdir.js';
3+
4+
import assert from 'node:assert';
5+
import { mkdir, writeFile } from 'node:fs/promises';
6+
import * as path from 'node:path';
7+
import { execPath } from 'node:process';
8+
import { describe, it, before } from 'node:test';
9+
10+
describe('ESM in main field', { concurrency: true }, () => {
11+
before(() => tmpdir.refresh());
12+
13+
it('should handle fully-specified relative path without any warning', async () => {
14+
const cwd = path.join(tmpdir.path, Math.random().toString());
15+
const pkgPath = path.join(cwd, './node_modules/pkg/');
16+
await mkdir(pkgPath, { recursive: true });
17+
await writeFile(path.join(pkgPath, './index.js'), 'console.log("Hello World!")');
18+
await writeFile(path.join(pkgPath, './package.json'), JSON.stringify({
19+
main: './index.js',
20+
type: 'module',
21+
}));
22+
const { code, stdout, stderr } = await spawnPromisified(execPath, [
23+
'--input-type=module',
24+
'--eval', 'import "pkg"',
25+
], { cwd });
26+
27+
assert.strictEqual(stderr, '');
28+
assert.match(stdout, /^Hello World!\r?\n$/);
29+
assert.strictEqual(code, 0);
30+
});
31+
it('should handle fully-specified absolute path without any warning', async () => {
32+
const cwd = path.join(tmpdir.path, Math.random().toString());
33+
const pkgPath = path.join(cwd, './node_modules/pkg/');
34+
await mkdir(pkgPath, { recursive: true });
35+
await writeFile(path.join(pkgPath, './index.js'), 'console.log("Hello World!")');
36+
await writeFile(path.join(pkgPath, './package.json'), JSON.stringify({
37+
main: path.join(pkgPath, './index.js'),
38+
type: 'module',
39+
}));
40+
const { code, stdout, stderr } = await spawnPromisified(execPath, [
41+
'--input-type=module',
42+
'--eval', 'import "pkg"',
43+
], { cwd });
44+
45+
assert.strictEqual(stderr, '');
46+
assert.match(stdout, /^Hello World!\r?\n$/);
47+
assert.strictEqual(code, 0);
48+
});
49+
50+
it('should emit warning when "main" and "exports" are missing', async () => {
51+
const cwd = path.join(tmpdir.path, Math.random().toString());
52+
const pkgPath = path.join(cwd, './node_modules/pkg/');
53+
await mkdir(pkgPath, { recursive: true });
54+
await writeFile(path.join(pkgPath, './index.js'), 'console.log("Hello World!")');
55+
await writeFile(path.join(pkgPath, './package.json'), JSON.stringify({
56+
type: 'module',
57+
}));
58+
const { code, stdout, stderr } = await spawnPromisified(execPath, [
59+
'--input-type=module',
60+
'--eval', 'import "pkg"',
61+
], { cwd });
62+
63+
assert.match(stderr, /\[DEP0151\]/);
64+
assert.match(stdout, /^Hello World!\r?\n$/);
65+
assert.strictEqual(code, 0);
66+
});
67+
it('should emit warning when "main" is falsy', async () => {
68+
const cwd = path.join(tmpdir.path, Math.random().toString());
69+
const pkgPath = path.join(cwd, './node_modules/pkg/');
70+
await mkdir(pkgPath, { recursive: true });
71+
await writeFile(path.join(pkgPath, './index.js'), 'console.log("Hello World!")');
72+
await writeFile(path.join(pkgPath, './package.json'), JSON.stringify({
73+
type: 'module',
74+
main: '',
75+
}));
76+
const { code, stdout, stderr } = await spawnPromisified(execPath, [
77+
'--input-type=module',
78+
'--eval', 'import "pkg"',
79+
], { cwd });
80+
81+
assert.match(stderr, /\[DEP0151\]/);
82+
assert.match(stdout, /^Hello World!\r?\n$/);
83+
assert.strictEqual(code, 0);
84+
});
85+
it('should emit warning when "main" is a relative path without extension', async () => {
86+
const cwd = path.join(tmpdir.path, Math.random().toString());
87+
const pkgPath = path.join(cwd, './node_modules/pkg/');
88+
await mkdir(pkgPath, { recursive: true });
89+
await writeFile(path.join(pkgPath, './index.js'), 'console.log("Hello World!")');
90+
await writeFile(path.join(pkgPath, './package.json'), JSON.stringify({
91+
main: 'index',
92+
type: 'module',
93+
}));
94+
const { code, stdout, stderr } = await spawnPromisified(execPath, [
95+
'--input-type=module',
96+
'--eval', 'import "pkg"',
97+
], { cwd });
98+
99+
assert.match(stderr, /\[DEP0151\]/);
100+
assert.match(stdout, /^Hello World!\r?\n$/);
101+
assert.strictEqual(code, 0);
102+
});
103+
it('should emit warning when "main" is an absolute path without extension', async () => {
104+
const cwd = path.join(tmpdir.path, Math.random().toString());
105+
const pkgPath = path.join(cwd, './node_modules/pkg/');
106+
await mkdir(pkgPath, { recursive: true });
107+
await writeFile(path.join(pkgPath, './index.js'), 'console.log("Hello World!")');
108+
await writeFile(path.join(pkgPath, './package.json'), JSON.stringify({
109+
main: pkgPath + 'index',
110+
type: 'module',
111+
}));
112+
const { code, stdout, stderr } = await spawnPromisified(execPath, [
113+
'--input-type=module',
114+
'--eval', 'import "pkg"',
115+
], { cwd });
116+
117+
assert.match(stderr, /\[DEP0151\]/);
118+
assert.match(stdout, /^Hello World!\r?\n$/);
119+
assert.strictEqual(code, 0);
120+
});
121+
});

0 commit comments

Comments
 (0)