Skip to content

Commit 5dc5643

Browse files
committed
Adds a test for symlinks in the package map ancestors
1 parent 105d77f commit 5dc5643

File tree

4 files changed

+60
-6
lines changed

4 files changed

+60
-6
lines changed

doc/api/packages.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -966,8 +966,8 @@ This feature is useful for:
966966
packages without symlinks or hoisting complexities.
967967
* **Dependency isolation**: Prevent packages from accessing undeclared
968968
dependencies (phantom dependencies).
969-
* **Multiple versions**: Allow different packages to depend on different
970-
versions of the same dependency.
969+
* **Low filesystem coupling**: The package resolution algorithm runs without
970+
inspecting the filesystem, relying instead on static data tables.
971971

972972
### Configuration file format
973973

lib/internal/modules/package_map.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ function loadPackageMap(configPath) {
217217
throw new ERR_PACKAGE_MAP_INVALID(configPath, err.message);
218218
}
219219

220+
// Resolve symlinks so that stored paths match the realpath'd module paths
221+
// that Node.js uses during resolution.
222+
configPath = fs.realpathSync(configPath);
223+
220224
let data;
221225
try {
222226
data = JSONParse(content);

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { spawnPromisified } from '../common/index.mjs';
1+
import { canCreateSymLink, spawnPromisified } from '../common/index.mjs';
22
import * as fixtures from '../common/fixtures.mjs';
33
import tmpdir from '../common/tmpdir.js';
44
import assert from 'node:assert';
5-
import { writeFileSync } from 'node:fs';
5+
import { symlinkSync, writeFileSync } from 'node:fs';
6+
import path from 'node:path';
67
import { execPath } from 'node:process';
78
import { describe, it } from 'node:test';
89
import { pathToFileURL } from 'node:url';
@@ -375,4 +376,28 @@ describe('ESM: --experimental-package-map', () => {
375376
assert.notStrictEqual(code, 0, stderr);
376377
});
377378
});
379+
380+
// =========== Symlink in Ancestor ===========
381+
382+
describe('symlink in ancestor of package map', {
383+
skip: !canCreateSymLink() && 'insufficient privileges for symlinks',
384+
}, () => {
385+
const symlinkDir = tmpdir.resolve('symlinked-package-map-esm');
386+
symlinkSync(fixtures.path('package-map'), symlinkDir, 'dir');
387+
388+
it('resolves through a symlinked ancestor directory', async () => {
389+
const symlinkMapPath = path.join(symlinkDir, 'package-map.json');
390+
const { code, stdout, stderr } = await spawnPromisified(execPath, [
391+
'--no-warnings',
392+
'--experimental-package-map', symlinkMapPath,
393+
'--input-type=module',
394+
'--eval',
395+
`import dep from 'dep-a'; console.log(dep);`,
396+
], { cwd: fixtures.path('package-map/root') });
397+
398+
assert.strictEqual(stderr, '');
399+
assert.match(stdout, /dep-a-value/);
400+
assert.strictEqual(code, 0, stderr);
401+
});
402+
});
378403
});

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
'use strict';
22

3-
require('../common');
3+
const common = require('../common');
44
const fixtures = require('../common/fixtures');
55
const assert = require('node:assert');
66
const { spawnSync } = require('node:child_process');
7-
const { writeFileSync } = require('node:fs');
7+
const { symlinkSync, writeFileSync } = require('node:fs');
8+
const path = require('node:path');
89
const { describe, it } = require('node:test');
910
const { pathToFileURL } = require('node:url');
1011
const tmpdir = require('../common/tmpdir');
@@ -335,4 +336,28 @@ describe('CJS: --experimental-package-map', { concurrency: !process.env.TEST_PAR
335336
assert.notStrictEqual(status, 0);
336337
});
337338
});
339+
340+
describe('symlink in ancestor of package map', {
341+
skip: !common.canCreateSymLink() && 'insufficient privileges for symlinks',
342+
}, () => {
343+
const symlinkDir = tmpdir.resolve('symlinked-package-map-cjs');
344+
symlinkSync(fixtures.path('package-map'), symlinkDir, 'dir');
345+
346+
it('resolves through a symlinked ancestor directory', () => {
347+
const symlinkMapPath = path.join(symlinkDir, 'package-map.json');
348+
const { status, stdout, stderr } = spawnSync(process.execPath, [
349+
'--no-warnings',
350+
'--experimental-package-map', symlinkMapPath,
351+
'-e',
352+
`const dep = require('dep-a'); console.log(dep.default);`,
353+
], {
354+
cwd: fixtures.path('package-map/root'),
355+
encoding: 'utf8',
356+
});
357+
358+
assert.strictEqual(stderr, '');
359+
assert.match(stdout, /dep-a-value/);
360+
assert.strictEqual(status, 0, stderr);
361+
});
362+
});
338363
});

0 commit comments

Comments
 (0)