Skip to content

Commit 40dc850

Browse files
committed
module: normalize package map paths
Signed-off-by: dansatch <dansatch98@gmail.com>
1 parent bd2b98f commit 40dc850

6 files changed

Lines changed: 104 additions & 1 deletion

File tree

lib/internal/modules/package_map.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class PackageMap {
105105

106106
let absolutePath;
107107
try {
108-
absolutePath = fileURLToPath(packageURL);
108+
absolutePath = pathResolve(fileURLToPath(packageURL));
109109
} catch (err) {
110110
const error = new ERR_PACKAGE_MAP_INVALID(
111111
this.#configPath,

test/es-module/test-esm-package-map-paths.mjs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ spawnSyncAndAssert(process.execPath, [
2727
trim: true,
2828
});
2929

30+
// Directory-form URLs match package files even when the map is nested below them.
31+
spawnSyncAndAssert(process.execPath, [
32+
'--no-warnings',
33+
'--experimental-package-map',
34+
fixtures.path('package-map/nested-project/map-dir/package-map-parent-url.json'),
35+
'--input-type=module',
36+
'--eval', `import dep from 'dep-a'; console.log(dep);`,
37+
], { cwd: fixtures.path('package-map/nested-project/src') }, {
38+
stdout: /dep-a-value/,
39+
trim: true,
40+
});
41+
3042
// URL fields are decoded as URLs before being converted to paths.
3143
spawnSyncAndAssert(process.execPath, [
3244
'--no-warnings',
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"packages": {
3+
"app": {
4+
"url": "..",
5+
"dependencies": {"dep-a": "dep-a"}
6+
},
7+
"dep-a": {
8+
"url": "../../dep-a/",
9+
"dependencies": {}
10+
}
11+
}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"packages": {
3+
"root": {
4+
"url": "./root/",
5+
"dependencies": {"dep-a": "dep-a"}
6+
},
7+
"dep-a": {
8+
"url": "./dep-a/",
9+
"dependencies": {}
10+
}
11+
}
12+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"packages": {
3+
"root": {
4+
"url": "./root",
5+
"dependencies": {"dep-a": "dep-a"}
6+
},
7+
"dep-a": {
8+
"url": "./dep-a",
9+
"dependencies": {}
10+
},
11+
"dep-a-directory": {
12+
"url": "./dep-a/",
13+
"dependencies": {}
14+
}
15+
}
16+
}

test/parallel/test-require-package-map.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,40 @@ writeFileSync(fileUrlFixturePath, JSON.stringify({
3232
describe('CJS: --experimental-package-map', { concurrency: !process.env.TEST_PARALLEL }, () => {
3333

3434
describe('basic resolution', () => {
35+
it('resolves dependencies from a parent directory URL', () => {
36+
const { status, stdout, stderr } = spawnSync(process.execPath, [
37+
'--no-warnings',
38+
'--experimental-package-map',
39+
fixtures.path('package-map/nested-project/map-dir/package-map-parent-url.json'),
40+
'-e',
41+
`const dep = require('dep-a'); console.log(dep.default);`,
42+
], {
43+
cwd: fixtures.path('package-map/nested-project/src'),
44+
encoding: 'utf8',
45+
});
46+
47+
assert.strictEqual(stderr, '');
48+
assert.match(stdout, /dep-a-value/);
49+
assert.strictEqual(status, 0, stderr);
50+
});
51+
52+
it('resolves packages with directory-form URLs', () => {
53+
const { status, stdout, stderr } = spawnSync(process.execPath, [
54+
'--no-warnings',
55+
'--experimental-package-map',
56+
fixtures.path('package-map/package-map-directory-urls.json'),
57+
'-e',
58+
`const dep = require('dep-a'); console.log(dep.default);`,
59+
], {
60+
cwd: fixtures.path('package-map/root'),
61+
encoding: 'utf8',
62+
});
63+
64+
assert.strictEqual(stderr, '');
65+
assert.match(stdout, /dep-a-value/);
66+
assert.strictEqual(status, 0, stderr);
67+
});
68+
3569
it('resolves require() through package map', () => {
3670
const { status, stdout, stderr } = spawnSync(process.execPath, [
3771
'--no-warnings',
@@ -197,6 +231,23 @@ describe('CJS: --experimental-package-map', { concurrency: !process.env.TEST_PAR
197231
assert.match(stderr, /pkg-b/);
198232
assert.notStrictEqual(status, 0, stderr);
199233
});
234+
235+
it('throws for package URLs differing only by a trailing separator', () => {
236+
const { status, stderr } = spawnSync(process.execPath, [
237+
'--no-warnings',
238+
'--experimental-package-map',
239+
fixtures.path('package-map/package-map-duplicate-directory-path.json'),
240+
'-e',
241+
`require('dep-a');`,
242+
], {
243+
cwd: fixtures.path('package-map/root'),
244+
encoding: 'utf8',
245+
});
246+
247+
assert.match(stderr, /ERR_PACKAGE_MAP_INVALID/);
248+
assert.match(stderr, /dep-a-directory/);
249+
assert.notStrictEqual(status, 0, stderr);
250+
});
200251
});
201252

202253
describe('conditional exports', () => {

0 commit comments

Comments
 (0)