Skip to content

Commit 43a8d3e

Browse files
per4ukrichardlau
authored andcommitted
module: fix --preserve-symlinks-main
Fixes resolving main module when the `argv[1]` was pointing to a symlink without its file extension. PR-URL: #51312 Fixes: #41000 Reviewed-By: Antoine du Hamel <[email protected]>
1 parent 5235aaf commit 43a8d3e

File tree

2 files changed

+49
-30
lines changed

2 files changed

+49
-30
lines changed

lib/internal/modules/cjs/loader.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -470,15 +470,15 @@ function tryPackage(requestPath, exts, isMain, originalPath) {
470470
}
471471

472472
/**
473-
* Check if the file exists and is not a directory if using `--preserve-symlinks` and `isMain` is false, keep symlinks
474-
* intact, otherwise resolve to the absolute realpath.
473+
* Check if the file exists and is not a directory if using `--preserve-symlinks` and `isMain` is false or
474+
* `--preserve-symlinks-main` and `isMain` is true , keep symlinks intact, otherwise resolve to the absolute realpath.
475475
* @param {string} requestPath The path to the file to load.
476476
* @param {boolean} isMain Whether the file is the main module.
477477
*/
478478
function tryFile(requestPath, isMain) {
479479
const rc = _stat(requestPath);
480480
if (rc !== 0) { return; }
481-
if (getOptionValue('--preserve-symlinks') && !isMain) {
481+
if (getOptionValue(isMain ? '--preserve-symlinks-main' : '--preserve-symlinks')) {
482482
return path.resolve(requestPath);
483483
}
484484
return toRealPath(requestPath);
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
'use strict';
22

3-
const common = require('../common');
4-
const { spawn } = require('child_process');
5-
const assert = require('assert');
6-
const path = require('path');
7-
const fs = require('fs');
8-
3+
const { spawnPromisified, skip } = require('../common');
94
const tmpdir = require('../common/tmpdir');
5+
6+
// Invoke the main file via a symlink. In this case --preserve-symlinks-main
7+
// dictates that it'll resolve relative imports in the main file relative to
8+
// the symlink, and not relative to the symlink target; the file structure set
9+
// up below requires this to not crash when loading ./submodule_link.js
10+
11+
const assert = require('node:assert');
12+
const fs = require('node:fs');
13+
const path = require('node:path');
14+
const { execPath } = require('node:process');
15+
const { describe, it } = require('node:test');
16+
1017
tmpdir.refresh();
1118
const tmpDir = tmpdir.path;
1219

1320
fs.mkdirSync(path.join(tmpDir, 'nested'));
1421
fs.mkdirSync(path.join(tmpDir, 'nested2'));
1522

1623
const entry = path.join(tmpDir, 'nested', 'entry.js');
17-
const entry_link_absolute_path = path.join(tmpDir, 'link.js');
24+
const entry_link_absolute_path = path.join(tmpDir, 'index.js');
1825
const submodule = path.join(tmpDir, 'nested2', 'submodule.js');
1926
const submodule_link_absolute_path = path.join(tmpDir, 'submodule_link.js');
2027

@@ -31,27 +38,39 @@ try {
3138
fs.symlinkSync(submodule, submodule_link_absolute_path);
3239
} catch (err) {
3340
if (err.code !== 'EPERM') throw err;
34-
common.skip('insufficient privileges for symlinks');
41+
skip('insufficient privileges for symlinks');
3542
}
3643

37-
function doTest(flags, done) {
38-
// Invoke the main file via a symlink. In this case --preserve-symlinks-main
39-
// dictates that it'll resolve relative imports in the main file relative to
40-
// the symlink, and not relative to the symlink target; the file structure set
41-
// up above requires this to not crash when loading ./submodule_link.js
42-
spawn(process.execPath, [
43-
'--preserve-symlinks',
44-
'--preserve-symlinks-main',
45-
entry_link_absolute_path,
46-
], { stdio: 'inherit' })
47-
.on('exit', (code) => {
48-
assert.strictEqual(code, 0);
49-
done();
50-
});
51-
}
44+
describe('Invoke the main file via a symlink.', { concurrency: true }, () => {
45+
it('should resolve relative imports in the main file', async () => {
46+
const { code } = await spawnPromisified(execPath, [
47+
'--preserve-symlinks',
48+
'--preserve-symlinks-main',
49+
entry_link_absolute_path,
50+
]);
51+
52+
assert.strictEqual(code, 0);
53+
});
54+
55+
it('should resolve relative imports in the main file when file extension is omitted', async () => {
56+
const entry_link_absolute_path_without_ext = path.join(tmpDir, 'index');
57+
58+
const { code } = await spawnPromisified(execPath, [
59+
'--preserve-symlinks',
60+
'--preserve-symlinks-main',
61+
entry_link_absolute_path_without_ext,
62+
]);
63+
64+
assert.strictEqual(code, 0);
65+
});
66+
67+
it('should resolve relative imports in the main file when filename(index.js) is omitted', async () => {
68+
const { code } = await spawnPromisified(execPath, [
69+
'--preserve-symlinks',
70+
'--preserve-symlinks-main',
71+
tmpDir,
72+
]);
5273

53-
// First test the commonjs module loader
54-
doTest([], () => {
55-
// Now test the new loader
56-
doTest([], () => {});
74+
assert.strictEqual(code, 0);
75+
});
5776
});

0 commit comments

Comments
 (0)