Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions prelude/sea-vfs-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,10 @@ class SEAProvider extends MemoryProvider {
this._manifest = seaManifest;
this._fileCache = new Map();

// Precompute whether the manifest has any symlinks.
// If a project has no symlinks, there is also no need to resolve them.
this._hasSymlinks = Object.keys(seaManifest.symlinks).length > 0;

// Pick the per-file decompressor once at construction time. Absent or 0 =
// uncompressed archive (backward compat with pre-#250 SEA binaries). The
// shared helper raises a uniformly-worded error when the host Node.js is
Expand Down Expand Up @@ -337,15 +341,26 @@ class SEAProvider extends MemoryProvider {
}

_resolveSymlink(p) {
// Fast path: the vast majority of lookups (~30K per startup on large
// projects) are not symlinks. A single object-has-key check avoids
// entering the loop and the i++/target fetch overhead for the common
// case.
// Fast path: if the manifest has no symlinks, skip the loop entirely.
if (!this._hasSymlinks) return p;
var symlinks = this._manifest.symlinks;
if (symlinks[p] === undefined) return p;
var original = p;
for (var i = 0; i < MAX_SYMLINK_DEPTH; i++) {
// First check the full path, then walk up the directory tree to find a symlink.
var target = symlinks[p];
if (!target) {
var parentIdx = p.lastIndexOf('/');
while (parentIdx > 0) {
var parent = p.slice(0, parentIdx);
target = symlinks[parent];
if (target) {
// Resolve the symlink and append the remainder of the original path.
target = target + p.slice(parentIdx);
break;
}
parentIdx = parent.lastIndexOf('/');
}
}
if (!target) return p;
p = target;
}
Expand Down
5 changes: 5 additions & 0 deletions test/test-99-#295/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';

const log = require('./lib/log');

log(42);
1 change: 1 addition & 0 deletions test/test-99-#295/lib
31 changes: 31 additions & 0 deletions test/test-99-#295/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env node

'use strict';

const assert = require('assert');
const utils = require('../utils.js');

// Enhanced SEA requires Node.js >= 22
if (utils.getNodeMajorVersion() < 22) {
return;
}

assert(__dirname === process.cwd());

// test symlinks on unix only // TODO junction
if (process.platform === 'win32') return;

const input = './package.json';
const testName = 'test-99-#295';

const newcomers = utils.seaHostOutputs(testName);

const before = utils.filesBefore(newcomers);

utils.runSeaHostOnly(input, testName);

const expectedOutput = '42\n';

utils.assertSeaOutput(testName, expectedOutput);

utils.filesAfter(before, newcomers, { tolerateWindowsEbusy: true });
6 changes: 6 additions & 0 deletions test/test-99-#295/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "test-99-#295",
"version": "1.0.0",
"main": "index.js",
"bin": "index.js"
}
3 changes: 3 additions & 0 deletions test/test-99-#295/reallib/log.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict';

module.exports = console.log;