Skip to content

Commit 7f1c83e

Browse files
meixgsxa
authored andcommitted
loader: fix esm resolve for symlink file
Fix: #42195 PR-URL: #42197Fixes: #42195 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
1 parent 05c3ff5 commit 7f1c83e

2 files changed

Lines changed: 55 additions & 9 deletions

File tree

‎lib/internal/modules/esm/resolve.js‎

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -374,18 +374,24 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
374374
resolved.pathname,'must not include encoded "/" or "\\" characters',
375375
fileURLToPath(base));
376376

377-
constpath=fileURLToPath(resolved);
377+
letpath=fileURLToPath(resolved);
378378
if(getOptionValue('--experimental-specifier-resolution')==='node'){
379379
letfile=resolveExtensionsWithTryExactName(resolved);
380-
if(file!==undefined)returnfile;
381-
if(!StringPrototypeEndsWith(path,'/')){
382-
file=resolveDirectoryEntry(newURL(`${resolved}/`));
383-
if(file!==undefined)returnfile;
384-
}else{
385-
returnresolveDirectoryEntry(resolved)||resolved;
380+
381+
// Directory
382+
if(file===undefined){
383+
file=StringPrototypeEndsWith(path,'/') ?
384+
(resolveDirectoryEntry(resolved)||resolved) : resolveDirectoryEntry(newURL(`${resolved}/`));
385+
386+
if(file===resolved)returnfile;
387+
388+
if(file===undefined){
389+
thrownewERR_MODULE_NOT_FOUND(
390+
resolved.pathname,fileURLToPath(base),'module');
391+
}
386392
}
387-
thrownewERR_MODULE_NOT_FOUND(
388-
resolved.pathname,fileURLToPath(base),'module');
393+
394+
path=file;
389395
}
390396

391397
conststats=tryStatSync(StringPrototypeEndsWith(path,'/') ?
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import*ascommonfrom'../common/index.mjs';
2+
importpathfrom'path';
3+
importfsfrom'fs/promises';
4+
importtmpdirfrom'../common/tmpdir.js';
5+
import{spawn}from'child_process';
6+
importassertfrom'assert';
7+
8+
tmpdir.refresh();
9+
consttmpDir=tmpdir.path;
10+
11+
// Create the following file structure:
12+
// ├── index.mjs
13+
// ├── subfolder
14+
// │ ├── index.mjs
15+
// │ └── node_modules
16+
// │ └── package-a
17+
// │ └── index.mjs
18+
// └── symlink.mjs -> ./subfolder/index.mjs
19+
constentry=path.join(tmpDir,'index.mjs');
20+
constsymlink=path.join(tmpDir,'symlink.mjs');
21+
constreal=path.join(tmpDir,'subfolder','index.mjs');
22+
constpackageDir=path.join(tmpDir,'subfolder','node_modules','package-a');
23+
constpackageEntry=path.join(packageDir,'index.mjs');
24+
try{
25+
awaitfs.symlink(real,symlink);
26+
}catch(err){
27+
if(err.code!=='EPERM')throwerr;
28+
common.skip('insufficient privileges for symlinks');
29+
}
30+
awaitfs.mkdir(packageDir,{recursive: true});
31+
awaitPromise.all([
32+
fs.writeFile(entry,'import "./symlink.mjs";'),
33+
fs.writeFile(real,'export { a } from "package-a/index.mjs"'),
34+
fs.writeFile(packageEntry,'export const a = 1;'),
35+
]);
36+
37+
spawn(process.execPath,['--experimental-specifier-resolution=node',entry],
38+
{stdio: 'inherit'}).on('exit',common.mustCall((code)=>{
39+
assert.strictEqual(code,0);
40+
}));

0 commit comments

Comments
 (0)