@ai-ecoverse/slicc-kernel 1.36.0 → 1.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/kernel-worker.js +391 -67
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +29 -12
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +394 -70
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +29 -12
- package/dist/process-worker.js.map +2 -2
- package/package.json +1 -1
package/dist/node.js
CHANGED
|
@@ -3249,6 +3249,35 @@ async function scanFilesystems(fs, modules) {
|
|
|
3249
3249
|
}
|
|
3250
3250
|
return found;
|
|
3251
3251
|
}
|
|
3252
|
+
var SUFFIX = /^\.[A-Za-z0-9_+-][A-Za-z0-9._+-]*$/;
|
|
3253
|
+
async function scanBinfmts(fs, modules) {
|
|
3254
|
+
const found = /* @__PURE__ */ new Map();
|
|
3255
|
+
for (const pkg of await packagesIn(fs, modules)) {
|
|
3256
|
+
let manifest;
|
|
3257
|
+
try {
|
|
3258
|
+
manifest = JSON.parse(await fs.readFile(`${pkg}/package.json`));
|
|
3259
|
+
} catch {
|
|
3260
|
+
continue;
|
|
3261
|
+
}
|
|
3262
|
+
const declared = manifest.slicc?.binfmt;
|
|
3263
|
+
if (!declared || typeof declared !== "object") continue;
|
|
3264
|
+
for (const [suffix, command] of Object.entries(declared)) {
|
|
3265
|
+
if (!SUFFIX.test(suffix) || typeof command !== "string" || !NAME.test(command)) continue;
|
|
3266
|
+
if (!found.has(suffix)) found.set(suffix, command);
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
return found;
|
|
3270
|
+
}
|
|
3271
|
+
function binfmtOf(binfmts, path) {
|
|
3272
|
+
const name2 = path.slice(path.lastIndexOf("/") + 1);
|
|
3273
|
+
let best;
|
|
3274
|
+
for (const suffix of binfmts.keys()) {
|
|
3275
|
+
if (name2.length > suffix.length && name2.endsWith(suffix)) {
|
|
3276
|
+
if (best === void 0 || suffix.length > best.length) best = suffix;
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
return best === void 0 ? void 0 : binfmts.get(best);
|
|
3280
|
+
}
|
|
3252
3281
|
|
|
3253
3282
|
// src/fs/commands.ts
|
|
3254
3283
|
var S_IFDIR2 = 16384;
|
|
@@ -3365,13 +3394,193 @@ function withCommandDirs(fs, names) {
|
|
|
3365
3394
|
};
|
|
3366
3395
|
}
|
|
3367
3396
|
|
|
3397
|
+
// src/fs/unlinked.ts
|
|
3398
|
+
var UNLINKED_DIR = ".slicc-unlinked";
|
|
3399
|
+
function webLocks() {
|
|
3400
|
+
return globalThis.navigator?.locks;
|
|
3401
|
+
}
|
|
3402
|
+
var within2 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
3403
|
+
var parentOf3 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
3404
|
+
var lockName = (instance) => `slicc-unlinked:${instance}`;
|
|
3405
|
+
var dirOf = (root) => root === "/" ? `/${UNLINKED_DIR}` : `${root}/${UNLINKED_DIR}`;
|
|
3406
|
+
var PathGate = class {
|
|
3407
|
+
tails = /* @__PURE__ */ new Map();
|
|
3408
|
+
async acquire(path) {
|
|
3409
|
+
const prev = this.tails.get(path) ?? Promise.resolve();
|
|
3410
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
3411
|
+
const tail = prev.then(() => promise);
|
|
3412
|
+
this.tails.set(path, tail);
|
|
3413
|
+
await prev;
|
|
3414
|
+
return () => {
|
|
3415
|
+
resolve();
|
|
3416
|
+
if (this.tails.get(path) === tail) this.tails.delete(path);
|
|
3417
|
+
};
|
|
3418
|
+
}
|
|
3419
|
+
async run(path, op) {
|
|
3420
|
+
const release = await this.acquire(path);
|
|
3421
|
+
try {
|
|
3422
|
+
return await op();
|
|
3423
|
+
} finally {
|
|
3424
|
+
release();
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
};
|
|
3428
|
+
var UnlinkedKeeper = class {
|
|
3429
|
+
fs;
|
|
3430
|
+
holders;
|
|
3431
|
+
rootOf;
|
|
3432
|
+
locks;
|
|
3433
|
+
busy;
|
|
3434
|
+
waiting = /* @__PURE__ */ new Set();
|
|
3435
|
+
instance = crypto.randomUUID();
|
|
3436
|
+
gate = new PathGate();
|
|
3437
|
+
queue = Promise.resolve();
|
|
3438
|
+
count = 0;
|
|
3439
|
+
constructor(fs, holders, rootOf, locks, busy = () => false) {
|
|
3440
|
+
this.fs = fs;
|
|
3441
|
+
this.holders = holders;
|
|
3442
|
+
this.rootOf = rootOf;
|
|
3443
|
+
this.locks = locks;
|
|
3444
|
+
this.busy = busy;
|
|
3445
|
+
void locks?.request(lockName(this.instance), () => new Promise(() => void 0));
|
|
3446
|
+
}
|
|
3447
|
+
serial(op) {
|
|
3448
|
+
const next = this.queue.then(op);
|
|
3449
|
+
this.queue = next.catch(() => void 0);
|
|
3450
|
+
return next;
|
|
3451
|
+
}
|
|
3452
|
+
wrap() {
|
|
3453
|
+
const fs = this.fs;
|
|
3454
|
+
const keeper = this;
|
|
3455
|
+
const visible = (names) => names.filter((name2) => name2 !== UNLINKED_DIR);
|
|
3456
|
+
return {
|
|
3457
|
+
...fs,
|
|
3458
|
+
async rm(path, options) {
|
|
3459
|
+
const target = fs.resolvePath("/", path);
|
|
3460
|
+
const pinned = await keeper.pin(target);
|
|
3461
|
+
if (pinned.moved.has(target)) pinned.commit();
|
|
3462
|
+
else await keeper.settle(pinned, () => fs.rm(path, options));
|
|
3463
|
+
},
|
|
3464
|
+
async rename(from, to) {
|
|
3465
|
+
const pinned = await keeper.pin(fs.resolvePath("/", to));
|
|
3466
|
+
await keeper.settle(pinned, () => fs.rename(from, to));
|
|
3467
|
+
},
|
|
3468
|
+
readdir: async (path) => visible(await fs.readdir(path)),
|
|
3469
|
+
readdirStat: async (path) => (await fs.readdirStat(path)).filter(([name2]) => name2 !== UNLINKED_DIR)
|
|
3470
|
+
};
|
|
3471
|
+
}
|
|
3472
|
+
async settle(pinned, op) {
|
|
3473
|
+
try {
|
|
3474
|
+
await op();
|
|
3475
|
+
} catch (err) {
|
|
3476
|
+
await pinned.rollback();
|
|
3477
|
+
throw err;
|
|
3478
|
+
}
|
|
3479
|
+
pinned.commit();
|
|
3480
|
+
}
|
|
3481
|
+
async pin(target) {
|
|
3482
|
+
const held = /* @__PURE__ */ new Map();
|
|
3483
|
+
for (const holder of this.holders) {
|
|
3484
|
+
if (holder.owns(target)) continue;
|
|
3485
|
+
for (const path of holder.opens.keys()) {
|
|
3486
|
+
if (!within2(path, target) || holder.unlinked.has(path)) continue;
|
|
3487
|
+
held.set(path, [...held.get(path) ?? [], holder]);
|
|
3488
|
+
}
|
|
3489
|
+
}
|
|
3490
|
+
const paths = [...held.keys()].sort();
|
|
3491
|
+
const releases = [];
|
|
3492
|
+
for (const path of paths) releases.push(await this.gate.acquire(path));
|
|
3493
|
+
const hidden = /* @__PURE__ */ new Map();
|
|
3494
|
+
for (const path of paths) {
|
|
3495
|
+
const at = await this.hide(path);
|
|
3496
|
+
if (at !== void 0) hidden.set(path, at);
|
|
3497
|
+
}
|
|
3498
|
+
const done4 = () => {
|
|
3499
|
+
for (const release of releases) release();
|
|
3500
|
+
};
|
|
3501
|
+
return {
|
|
3502
|
+
moved: new Set(hidden.keys()),
|
|
3503
|
+
commit: () => {
|
|
3504
|
+
for (const [path, at] of hidden) {
|
|
3505
|
+
const holders = held.get(path);
|
|
3506
|
+
const file = this.keptFile(at, { refs: holders.length });
|
|
3507
|
+
for (const holder of holders) holder.unlinked.set(path, file);
|
|
3508
|
+
}
|
|
3509
|
+
done4();
|
|
3510
|
+
},
|
|
3511
|
+
rollback: async () => {
|
|
3512
|
+
for (const [path, at] of hidden) {
|
|
3513
|
+
await this.serial(async () => {
|
|
3514
|
+
await Promise.allSettled([this.fs.rename(at, path)]);
|
|
3515
|
+
await this.tidy(parentOf3(at));
|
|
3516
|
+
});
|
|
3517
|
+
}
|
|
3518
|
+
done4();
|
|
3519
|
+
}
|
|
3520
|
+
};
|
|
3521
|
+
}
|
|
3522
|
+
keptFile(hidden, entry) {
|
|
3523
|
+
return {
|
|
3524
|
+
hidden,
|
|
3525
|
+
release: () => {
|
|
3526
|
+
if (--entry.refs === 0) void this.serial(() => this.drop(hidden));
|
|
3527
|
+
}
|
|
3528
|
+
};
|
|
3529
|
+
}
|
|
3530
|
+
hide(path) {
|
|
3531
|
+
return this.serial(async () => {
|
|
3532
|
+
const dir = dirOf(this.rootOf(path));
|
|
3533
|
+
const hidden = `${dir}/${this.instance}.${++this.count}`;
|
|
3534
|
+
try {
|
|
3535
|
+
await this.fs.mkdir(dir, { recursive: true });
|
|
3536
|
+
await this.fs.rename(path, hidden);
|
|
3537
|
+
return hidden;
|
|
3538
|
+
} catch {
|
|
3539
|
+
await this.tidy(dir);
|
|
3540
|
+
return void 0;
|
|
3541
|
+
}
|
|
3542
|
+
});
|
|
3543
|
+
}
|
|
3544
|
+
closed(path) {
|
|
3545
|
+
if (this.waiting.delete(path)) void this.serial(() => this.drop(path));
|
|
3546
|
+
}
|
|
3547
|
+
async drop(hidden) {
|
|
3548
|
+
if (this.busy(hidden)) {
|
|
3549
|
+
this.waiting.add(hidden);
|
|
3550
|
+
return;
|
|
3551
|
+
}
|
|
3552
|
+
await this.fs.rm(hidden).catch(() => void 0);
|
|
3553
|
+
await this.tidy(parentOf3(hidden));
|
|
3554
|
+
}
|
|
3555
|
+
async tidy(dir) {
|
|
3556
|
+
const left = await this.fs.readdir(dir).catch(() => [UNLINKED_DIR]);
|
|
3557
|
+
if (left.length === 0) await this.fs.rm(dir, { recursive: true }).catch(() => void 0);
|
|
3558
|
+
}
|
|
3559
|
+
sweep(root) {
|
|
3560
|
+
const query = this.locks?.query?.bind(this.locks);
|
|
3561
|
+
if (!query) return Promise.resolve();
|
|
3562
|
+
return this.serial(async () => {
|
|
3563
|
+
const dir = dirOf(root);
|
|
3564
|
+
const names = await this.fs.readdir(dir).catch(() => void 0);
|
|
3565
|
+
if (!names) return;
|
|
3566
|
+
const held = new Set(((await query()).held ?? []).map((lock) => lock.name));
|
|
3567
|
+
for (const name2 of names) {
|
|
3568
|
+
const owner = name2.slice(0, name2.lastIndexOf("."));
|
|
3569
|
+
if (owner === this.instance || held.has(lockName(owner))) continue;
|
|
3570
|
+
await this.fs.rm(`${dir}/${name2}`, { recursive: true }).catch(() => void 0);
|
|
3571
|
+
}
|
|
3572
|
+
await this.tidy(dir);
|
|
3573
|
+
});
|
|
3574
|
+
}
|
|
3575
|
+
};
|
|
3576
|
+
|
|
3368
3577
|
// src/fs/watch.ts
|
|
3369
3578
|
var WATCH_BATCH_LIMIT = 1e3;
|
|
3370
3579
|
var under2 = (path, dir) => dir === "/" || path.startsWith(`${dir}/`);
|
|
3371
|
-
var
|
|
3580
|
+
var parentOf4 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
3372
3581
|
function touches(watcher, changed) {
|
|
3373
3582
|
return watcher.paths.some(
|
|
3374
|
-
(watched) => changed === watched || under2(watched, changed) || (watcher.recursive ? under2(changed, watched) :
|
|
3583
|
+
(watched) => changed === watched || under2(watched, changed) || (watcher.recursive ? under2(changed, watched) : parentOf4(changed) === watched)
|
|
3375
3584
|
);
|
|
3376
3585
|
}
|
|
3377
3586
|
var FsWatchers = class {
|
|
@@ -3753,7 +3962,7 @@ function parseSize(text) {
|
|
|
3753
3962
|
if (!match) throw errnoError("EINVAL", `not a size: ${text}`);
|
|
3754
3963
|
return Math.floor(Number(match[1]) * UNITS[match[2].toLowerCase()]);
|
|
3755
3964
|
}
|
|
3756
|
-
var
|
|
3965
|
+
var within3 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
3757
3966
|
var HeldSet = class extends Set {
|
|
3758
3967
|
idle;
|
|
3759
3968
|
constructor(idle) {
|
|
@@ -3766,18 +3975,47 @@ var HeldSet = class extends Set {
|
|
|
3766
3975
|
}
|
|
3767
3976
|
delete(holds) {
|
|
3768
3977
|
const removed = super.delete(holds);
|
|
3769
|
-
for (const path of holds.keys()) this.idle(path);
|
|
3978
|
+
for (const path of /* @__PURE__ */ new Set([...holds.keys(), ...holds.opens.keys()])) this.idle(path);
|
|
3979
|
+
for (const kept of holds.unlinked.values()) kept.release();
|
|
3980
|
+
holds.unlinked.clear();
|
|
3770
3981
|
return removed;
|
|
3771
3982
|
}
|
|
3772
3983
|
};
|
|
3773
3984
|
function heldUnder(held, target) {
|
|
3774
|
-
for (const paths of held) for (const path of paths.keys()) if (
|
|
3985
|
+
for (const paths of held) for (const path of paths.keys()) if (within3(path, target)) return true;
|
|
3775
3986
|
return false;
|
|
3776
3987
|
}
|
|
3777
3988
|
var HeldPaths = class extends Map {
|
|
3778
3989
|
revoked = /* @__PURE__ */ new Set();
|
|
3990
|
+
opens = /* @__PURE__ */ new Map();
|
|
3991
|
+
unlinked = /* @__PURE__ */ new Map();
|
|
3992
|
+
aliases = /* @__PURE__ */ new Map();
|
|
3993
|
+
owning;
|
|
3779
3994
|
onIdle;
|
|
3780
|
-
|
|
3995
|
+
keyOf(path) {
|
|
3996
|
+
return this.aliases.get(path) ?? path;
|
|
3997
|
+
}
|
|
3998
|
+
keptAt(path) {
|
|
3999
|
+
return this.unlinked.get(this.keyOf(path));
|
|
4000
|
+
}
|
|
4001
|
+
holding(path) {
|
|
4002
|
+
return this.opens.has(this.keyOf(path));
|
|
4003
|
+
}
|
|
4004
|
+
hold(path, on, open = false, real) {
|
|
4005
|
+
if (open) {
|
|
4006
|
+
const key = real ?? this.keyOf(path);
|
|
4007
|
+
if (key !== path) this.aliases.set(path, key);
|
|
4008
|
+
const count2 = (this.opens.get(key) ?? 0) + (on ? 1 : -1);
|
|
4009
|
+
if (count2 > 0) this.opens.set(key, count2);
|
|
4010
|
+
else {
|
|
4011
|
+
this.opens.delete(key);
|
|
4012
|
+
this.unlinked.get(key)?.release();
|
|
4013
|
+
this.unlinked.delete(key);
|
|
4014
|
+
for (const [alias, target] of this.aliases) if (target === key) this.aliases.delete(alias);
|
|
4015
|
+
this.onIdle?.(key);
|
|
4016
|
+
}
|
|
4017
|
+
return;
|
|
4018
|
+
}
|
|
3781
4019
|
const count = (this.get(path) ?? 0) + (on ? 1 : -1);
|
|
3782
4020
|
if (count > 0) this.set(path, count);
|
|
3783
4021
|
else {
|
|
@@ -3786,23 +4024,40 @@ var HeldPaths = class extends Map {
|
|
|
3786
4024
|
this.onIdle?.(path);
|
|
3787
4025
|
}
|
|
3788
4026
|
}
|
|
4027
|
+
async own(path, op) {
|
|
4028
|
+
this.owning = path;
|
|
4029
|
+
try {
|
|
4030
|
+
return await op();
|
|
4031
|
+
} finally {
|
|
4032
|
+
this.owning = void 0;
|
|
4033
|
+
}
|
|
4034
|
+
}
|
|
4035
|
+
owns(path) {
|
|
4036
|
+
return this.owning === path;
|
|
4037
|
+
}
|
|
3789
4038
|
revoke(prefix) {
|
|
3790
|
-
for (const path of this.keys()) if (
|
|
4039
|
+
for (const path of this.keys()) if (within3(path, prefix)) this.revoked.add(path);
|
|
3791
4040
|
}
|
|
3792
4041
|
renamed(from, to) {
|
|
3793
4042
|
for (const [path, count] of [...this]) {
|
|
3794
|
-
if (!
|
|
4043
|
+
if (!within3(path, from)) continue;
|
|
3795
4044
|
const moved2 = to + path.slice(from.length);
|
|
3796
4045
|
this.delete(path);
|
|
3797
4046
|
this.set(moved2, (this.get(moved2) ?? 0) + count);
|
|
3798
4047
|
if (this.revoked.delete(path)) this.revoked.add(moved2);
|
|
3799
4048
|
}
|
|
4049
|
+
for (const [path, count] of [...this.opens]) {
|
|
4050
|
+
if (!within3(path, from)) continue;
|
|
4051
|
+
const moved2 = to + path.slice(from.length);
|
|
4052
|
+
this.opens.delete(path);
|
|
4053
|
+
this.opens.set(moved2, (this.opens.get(moved2) ?? 0) + count);
|
|
4054
|
+
}
|
|
3800
4055
|
}
|
|
3801
4056
|
isRevoked(path) {
|
|
3802
4057
|
return this.revoked.has(path);
|
|
3803
4058
|
}
|
|
3804
4059
|
};
|
|
3805
|
-
var
|
|
4060
|
+
var parentOf5 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
3806
4061
|
var readonly = (mount) => mount.caps.readonly === true || mount.options.ro !== void 0;
|
|
3807
4062
|
function statOf(attr, path, mount) {
|
|
3808
4063
|
const mtime = new Date(attr.mtime);
|
|
@@ -3891,7 +4146,7 @@ var MountTable = class {
|
|
|
3891
4146
|
locate(path) {
|
|
3892
4147
|
let best;
|
|
3893
4148
|
for (const mount of this.mounts.values()) {
|
|
3894
|
-
if (
|
|
4149
|
+
if (within3(path, mount.target) && (!best || mount.target.length > best.target.length))
|
|
3895
4150
|
best = mount;
|
|
3896
4151
|
}
|
|
3897
4152
|
if (!best) return void 0;
|
|
@@ -4030,7 +4285,7 @@ var MountTable = class {
|
|
|
4030
4285
|
async commitUnder(prefix) {
|
|
4031
4286
|
const at = normalizePath(prefix);
|
|
4032
4287
|
await Promise.all(
|
|
4033
|
-
[...this.sessions.keys()].filter((p) =>
|
|
4288
|
+
[...this.sessions.keys()].filter((p) => within3(p, at)).map((p) => this.commit(p))
|
|
4034
4289
|
);
|
|
4035
4290
|
}
|
|
4036
4291
|
async commitOverlapping(real, offset, length2) {
|
|
@@ -4064,10 +4319,10 @@ var MountTable = class {
|
|
|
4064
4319
|
this.deps.changed?.(...full);
|
|
4065
4320
|
}
|
|
4066
4321
|
forget(mount, path) {
|
|
4067
|
-
for (const key of [...mount.attrs.keys()]) if (
|
|
4322
|
+
for (const key of [...mount.attrs.keys()]) if (within3(key, path)) mount.attrs.delete(key);
|
|
4068
4323
|
mount.lists.delete(path);
|
|
4069
|
-
mount.lists.delete(
|
|
4070
|
-
for (const key of [...mount.lists.keys()]) if (
|
|
4324
|
+
mount.lists.delete(parentOf5(path));
|
|
4325
|
+
for (const key of [...mount.lists.keys()]) if (within3(key, path)) mount.lists.delete(key);
|
|
4071
4326
|
}
|
|
4072
4327
|
async getattr(mount, path, rel2) {
|
|
4073
4328
|
if (mount.conn.failure) throw mount.conn.failure;
|
|
@@ -4132,7 +4387,7 @@ var MountFs = class {
|
|
|
4132
4387
|
if (attr.kind !== "symlink") return real;
|
|
4133
4388
|
if (hops >= MAX_LINKS4) throw errnoError("ELOOP", path);
|
|
4134
4389
|
const target = await found.mount.conn.call({ op: "readlink", path: found.rel });
|
|
4135
|
-
return this.follow(this.base.resolvePath(
|
|
4390
|
+
return this.follow(this.base.resolvePath(parentOf5(real), target), hops + 1, create);
|
|
4136
4391
|
}
|
|
4137
4392
|
async open(mount, rel2, write) {
|
|
4138
4393
|
return await mount.conn.call({
|
|
@@ -4646,6 +4901,8 @@ async function ranged(fs, path, req) {
|
|
|
4646
4901
|
else await ops.truncate(path, req.length ?? 0);
|
|
4647
4902
|
return done;
|
|
4648
4903
|
}
|
|
4904
|
+
var UNLINKED_OPS = /* @__PURE__ */ new Set(["read", "pread", "pwrite", "truncate"]);
|
|
4905
|
+
var OWN_OPS = /* @__PURE__ */ new Set(["rm", "unlink", "rmdir", "rename"]);
|
|
4649
4906
|
async function dispatchSyncFs(req) {
|
|
4650
4907
|
const entry = resolveSyncFsToken(req.token);
|
|
4651
4908
|
if (!entry) return { ok: false, errno: "EACCES", message: "sync-fs: unknown or revoked token" };
|
|
@@ -4654,11 +4911,22 @@ async function dispatchSyncFs(req) {
|
|
|
4654
4911
|
const path = fs.resolvePath(cwd, req.path);
|
|
4655
4912
|
if (req.op === "statfs") return json2(await entry.statfs?.(path) ?? await storageUsage());
|
|
4656
4913
|
if (req.op === "hold") {
|
|
4657
|
-
|
|
4914
|
+
const [on, open] = [((req.mode ?? 0) & 1) === 1, ((req.mode ?? 0) & 2) === 2];
|
|
4915
|
+
const real = on && open ? await fs.realpath?.(path, true).catch(() => path) : void 0;
|
|
4916
|
+
entry.hold?.(path, on, open, real);
|
|
4658
4917
|
return done;
|
|
4659
4918
|
}
|
|
4660
4919
|
if (entry.revoked?.(path)) return { ok: false, errno: "EIO", message: `${path} was unmounted` };
|
|
4661
|
-
|
|
4920
|
+
if (req.op === "write" && req.mode === 1 || UNLINKED_OPS.has(req.op)) {
|
|
4921
|
+
const serve = async () => {
|
|
4922
|
+
const kept = entry.unlinked?.(path);
|
|
4923
|
+
return run(entry, kept && !await fs.exists(path) ? kept.hidden : path, req);
|
|
4924
|
+
};
|
|
4925
|
+
return await (entry.gate ? entry.gate(path, serve) : serve());
|
|
4926
|
+
}
|
|
4927
|
+
if (!entry.own || !OWN_OPS.has(req.op)) return await run(entry, path, req);
|
|
4928
|
+
const target = req.op === "rename" ? fs.resolvePath(cwd, req.arg2 ?? "") : path;
|
|
4929
|
+
return await entry.own(target, () => run(entry, path, req));
|
|
4662
4930
|
} catch (err) {
|
|
4663
4931
|
return toErrno(err);
|
|
4664
4932
|
}
|
|
@@ -6237,7 +6505,7 @@ function parsePrefix(text) {
|
|
|
6237
6505
|
if (length2 < 0 || length2 > max) return void 0;
|
|
6238
6506
|
return { ...parsed, length: length2 };
|
|
6239
6507
|
}
|
|
6240
|
-
function
|
|
6508
|
+
function within4(prefix, addr) {
|
|
6241
6509
|
if (prefix.v6 !== addr.v6) return false;
|
|
6242
6510
|
const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);
|
|
6243
6511
|
return addr.bits >> shift === prefix.bits >> shift;
|
|
@@ -6277,9 +6545,9 @@ var Routes = class {
|
|
|
6277
6545
|
if (!addr) return "unreachable";
|
|
6278
6546
|
if (addr.v6 && addr.bits === 1n) return "loopback";
|
|
6279
6547
|
if (!addr.v6 && addr.bits >> 24n === 127n) return "loopback";
|
|
6280
|
-
if (RESERVED.some((p) =>
|
|
6548
|
+
if (RESERVED.some((p) => within4(p, addr))) return "reserved";
|
|
6281
6549
|
if (addr.v6 && !this.ipv6) return "unreachable";
|
|
6282
|
-
if (this.exit || this.table.some((p) =>
|
|
6550
|
+
if (this.exit || this.table.some((p) => within4(p, addr))) return "uplink";
|
|
6283
6551
|
return "unreachable";
|
|
6284
6552
|
}
|
|
6285
6553
|
};
|
|
@@ -7248,7 +7516,7 @@ function isMissing(err) {
|
|
|
7248
7516
|
if (err?.code === "ENOENT") return true;
|
|
7249
7517
|
return err instanceof Error && err.message.startsWith("ENOENT");
|
|
7250
7518
|
}
|
|
7251
|
-
function
|
|
7519
|
+
function within5(path, root) {
|
|
7252
7520
|
return path === root || path.startsWith(root.endsWith("/") ? root : `${root}/`);
|
|
7253
7521
|
}
|
|
7254
7522
|
var VfsNode = class {
|
|
@@ -7453,7 +7721,7 @@ var VfsNodes = class {
|
|
|
7453
7721
|
return run2;
|
|
7454
7722
|
}
|
|
7455
7723
|
async entryKey(path) {
|
|
7456
|
-
const parent =
|
|
7724
|
+
const parent = parentOf6(path);
|
|
7457
7725
|
const dir = await this.real(parent, true, () => realDir(this.fs, parent));
|
|
7458
7726
|
return joinName(dir, path.slice(path.lastIndexOf("/") + 1));
|
|
7459
7727
|
}
|
|
@@ -7501,12 +7769,12 @@ var VfsNodes = class {
|
|
|
7501
7769
|
return node;
|
|
7502
7770
|
}
|
|
7503
7771
|
holds(prefix) {
|
|
7504
|
-
for (const path of this.byPath.keys()) if (
|
|
7772
|
+
for (const path of this.byPath.keys()) if (within5(path, prefix)) return true;
|
|
7505
7773
|
return false;
|
|
7506
7774
|
}
|
|
7507
7775
|
writes(prefix) {
|
|
7508
7776
|
for (const [path, node] of this.byPath)
|
|
7509
|
-
if (node.writers > 0 &&
|
|
7777
|
+
if (node.writers > 0 && within5(path, prefix)) return true;
|
|
7510
7778
|
return false;
|
|
7511
7779
|
}
|
|
7512
7780
|
closed(node, writable = false) {
|
|
@@ -7520,24 +7788,24 @@ var VfsNodes = class {
|
|
|
7520
7788
|
this.onClosed?.(node.path);
|
|
7521
7789
|
}
|
|
7522
7790
|
async flush(path) {
|
|
7523
|
-
for (const [p, node] of this.byPath) if (
|
|
7791
|
+
for (const [p, node] of this.byPath) if (within5(p, path)) await node.serial(() => node.flush());
|
|
7524
7792
|
}
|
|
7525
7793
|
async unlinking(path) {
|
|
7526
7794
|
for (const [held, node] of [...this.byPath]) {
|
|
7527
|
-
if (!
|
|
7795
|
+
if (!within5(held, path)) continue;
|
|
7528
7796
|
await node.serial(async () => void await Promise.all([node.keep(), node.limit()]));
|
|
7529
7797
|
}
|
|
7530
7798
|
}
|
|
7531
7799
|
revoke(prefix) {
|
|
7532
7800
|
for (const [path, node] of this.byPath) {
|
|
7533
|
-
if (!
|
|
7801
|
+
if (!within5(path, prefix)) continue;
|
|
7534
7802
|
node.revoke();
|
|
7535
7803
|
this.byPath.delete(path);
|
|
7536
7804
|
}
|
|
7537
7805
|
}
|
|
7538
7806
|
unlinked(path) {
|
|
7539
7807
|
for (const [held, node] of [...this.byPath]) {
|
|
7540
|
-
if (!
|
|
7808
|
+
if (!within5(held, path)) continue;
|
|
7541
7809
|
node.orphaned = true;
|
|
7542
7810
|
this.byPath.delete(held);
|
|
7543
7811
|
}
|
|
@@ -7546,8 +7814,8 @@ var VfsNodes = class {
|
|
|
7546
7814
|
if (from === to) return;
|
|
7547
7815
|
const moved2 = [];
|
|
7548
7816
|
for (const [p, node] of this.byPath) {
|
|
7549
|
-
if (
|
|
7550
|
-
else if (
|
|
7817
|
+
if (within5(p, from)) moved2.push(node);
|
|
7818
|
+
else if (within5(p, to)) {
|
|
7551
7819
|
node.orphaned = true;
|
|
7552
7820
|
this.byPath.delete(p);
|
|
7553
7821
|
}
|
|
@@ -7570,7 +7838,7 @@ async function present(fs, path, follow = false) {
|
|
|
7570
7838
|
}
|
|
7571
7839
|
}
|
|
7572
7840
|
var MAX_LINKS5 = 40;
|
|
7573
|
-
function
|
|
7841
|
+
function parentOf6(path) {
|
|
7574
7842
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
7575
7843
|
}
|
|
7576
7844
|
async function linkOf(fs, path) {
|
|
@@ -7583,7 +7851,7 @@ async function realDir(fs, dir, budget = { hops: 0 }) {
|
|
|
7583
7851
|
const part = queue.shift();
|
|
7584
7852
|
if (part === ".") continue;
|
|
7585
7853
|
if (part === "..") {
|
|
7586
|
-
at =
|
|
7854
|
+
at = parentOf6(at);
|
|
7587
7855
|
continue;
|
|
7588
7856
|
}
|
|
7589
7857
|
const next = at === "/" ? `/${part}` : `${at}/${part}`;
|
|
@@ -7607,7 +7875,7 @@ function joinName(dir, name2) {
|
|
|
7607
7875
|
}
|
|
7608
7876
|
async function realTarget(fs, path) {
|
|
7609
7877
|
const budget = { hops: 0 };
|
|
7610
|
-
let dir = await realDir(fs,
|
|
7878
|
+
let dir = await realDir(fs, parentOf6(path), budget);
|
|
7611
7879
|
let name2 = path.slice(path.lastIndexOf("/") + 1);
|
|
7612
7880
|
for (; ; ) {
|
|
7613
7881
|
const link2 = await linkOf(fs, joinName(dir, name2));
|
|
@@ -7615,13 +7883,13 @@ async function realTarget(fs, path) {
|
|
|
7615
7883
|
if (budget.hops >= MAX_LINKS5) throw fsError("ELOOP", path);
|
|
7616
7884
|
budget.hops++;
|
|
7617
7885
|
const target = link2.startsWith("/") ? link2 : joinName(dir, link2);
|
|
7618
|
-
dir = await realDir(fs,
|
|
7886
|
+
dir = await realDir(fs, parentOf6(target), budget);
|
|
7619
7887
|
name2 = target.slice(target.lastIndexOf("/") + 1);
|
|
7620
7888
|
}
|
|
7621
7889
|
return joinName(dir, name2);
|
|
7622
7890
|
}
|
|
7623
7891
|
async function targetDir(fs, path) {
|
|
7624
|
-
return
|
|
7892
|
+
return parentOf6(await realTarget(fs, path).catch(() => path));
|
|
7625
7893
|
}
|
|
7626
7894
|
async function refuseReadonly(fs, path, flags, opts = {}) {
|
|
7627
7895
|
const writes = (flags & O_ACCMODE) !== 0 || opts.truncate === true;
|
|
@@ -8010,7 +8278,7 @@ var WasmProcess = class {
|
|
|
8010
8278
|
const fd = this.fds.install(heldFile(), 3);
|
|
8011
8279
|
try {
|
|
8012
8280
|
const nodes = this.nodes;
|
|
8013
|
-
const path = req.orphan ? req.path : req.exclusive ? await nodes.entryKey(req.path) : await nodes.targetKey(req.path);
|
|
8281
|
+
const path = req.orphan ? req.path : req.exclusive ? await nodes.entryKey(req.path) : req.create ? await nodes.targetKey(req.path) : await this.keptOr(await nodes.targetKey(req.path));
|
|
8014
8282
|
const open = { ...req, path };
|
|
8015
8283
|
if (req.exclusive) {
|
|
8016
8284
|
await nodes.createExclusive(path);
|
|
@@ -8166,6 +8434,11 @@ var WasmProcess = class {
|
|
|
8166
8434
|
return { ok: true, kind: "json", json: await file.stat() };
|
|
8167
8435
|
}
|
|
8168
8436
|
}
|
|
8437
|
+
keptPath;
|
|
8438
|
+
async keptOr(path) {
|
|
8439
|
+
const kept = this.keptPath?.(path);
|
|
8440
|
+
return kept !== void 0 && !await present(this.options.fs, path, true) ? kept : path;
|
|
8441
|
+
}
|
|
8169
8442
|
async promote(req) {
|
|
8170
8443
|
if (!this.fds.get(req.fd).file.held) throw new KernelError("EBADF");
|
|
8171
8444
|
if (req.share !== void 0) {
|
|
@@ -8173,7 +8446,7 @@ var WasmProcess = class {
|
|
|
8173
8446
|
return;
|
|
8174
8447
|
}
|
|
8175
8448
|
if (req.path === void 0) throw new KernelError("EINVAL");
|
|
8176
|
-
const path = req.orphan ? req.path : await this.nodes.targetKey(req.path);
|
|
8449
|
+
const path = req.orphan ? req.path : await this.keptOr(await this.nodes.targetKey(req.path));
|
|
8177
8450
|
if (!this.fds.get(req.fd).file.held) throw new KernelError("EBADF");
|
|
8178
8451
|
const file = vfsFile(
|
|
8179
8452
|
this.options.fs,
|
|
@@ -8532,6 +8805,19 @@ function inherited(opts) {
|
|
|
8532
8805
|
...opts.umask !== void 0 ? { umask: opts.umask } : {}
|
|
8533
8806
|
};
|
|
8534
8807
|
}
|
|
8808
|
+
function holdingToken(opts, holds) {
|
|
8809
|
+
return mintSyncFsToken({
|
|
8810
|
+
fs: opts.fs,
|
|
8811
|
+
cwd: opts.cwd,
|
|
8812
|
+
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
8813
|
+
hold: (path, on, open, real) => holds.hold(path, on, open, real),
|
|
8814
|
+
unlinked: (path) => holds.keptAt(path),
|
|
8815
|
+
gate: (path, op) => opts.unlinkGate && holds.holding(path) ? opts.unlinkGate.run(holds.keyOf(path), op) : op(),
|
|
8816
|
+
own: (path, op) => holds.own(path, op),
|
|
8817
|
+
revoked: (path) => holds.isRevoked(path),
|
|
8818
|
+
renamed: (from, to) => holds.renamed(from, to)
|
|
8819
|
+
});
|
|
8820
|
+
}
|
|
8535
8821
|
function spawnWasmProcess(opts) {
|
|
8536
8822
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
8537
8823
|
const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
@@ -8576,14 +8862,8 @@ function spawnWasmProcess(opts) {
|
|
|
8576
8862
|
});
|
|
8577
8863
|
const holds = new HeldPaths();
|
|
8578
8864
|
opts.held?.add(holds);
|
|
8579
|
-
const token =
|
|
8580
|
-
|
|
8581
|
-
cwd: opts.cwd,
|
|
8582
|
-
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
8583
|
-
hold: (path, on) => holds.hold(path, on),
|
|
8584
|
-
revoked: (path) => holds.isRevoked(path),
|
|
8585
|
-
renamed: (from, to) => holds.renamed(from, to)
|
|
8586
|
-
});
|
|
8865
|
+
const token = holdingToken(opts, holds);
|
|
8866
|
+
process.keptPath = (path) => holds.keptAt(path)?.hidden;
|
|
8587
8867
|
const worker = opts.createWorker();
|
|
8588
8868
|
const dying = new Dying();
|
|
8589
8869
|
const dispatch2 = (req) => dying.serving(() => isWasmSyscall(req) ? process.syscall(req) : dispatchSyncFs(req));
|
|
@@ -10110,6 +10390,7 @@ var PACKAGE_ROOT = /^(.*\/node_modules\/(?:@[^/]+\/)?[^/]+)\//;
|
|
|
10110
10390
|
var ENV_REFERENCE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
10111
10391
|
var WASM_MAGIC = [0, 97, 115, 109];
|
|
10112
10392
|
var SHEBANG_MAX = 256;
|
|
10393
|
+
var MAX_INTERPRETERS = 4;
|
|
10113
10394
|
var NOT_FOUND = 127;
|
|
10114
10395
|
var DECIDE_MS = 100;
|
|
10115
10396
|
var INIT_PID = 1;
|
|
@@ -10161,6 +10442,17 @@ function targetOf(command) {
|
|
|
10161
10442
|
...command.preopenRoot ? { preopenRoot: true } : {}
|
|
10162
10443
|
};
|
|
10163
10444
|
}
|
|
10445
|
+
function withScriptEnv(target, command) {
|
|
10446
|
+
if (!command) return target;
|
|
10447
|
+
return {
|
|
10448
|
+
...target,
|
|
10449
|
+
env: { ...target.env, ...command.env },
|
|
10450
|
+
unset: [
|
|
10451
|
+
...(target.unset ?? []).filter((key) => !Object.hasOwn(command.env ?? {}, key)),
|
|
10452
|
+
...command.unset ?? []
|
|
10453
|
+
]
|
|
10454
|
+
};
|
|
10455
|
+
}
|
|
10164
10456
|
function childHandle(handle) {
|
|
10165
10457
|
return {
|
|
10166
10458
|
pid: handle.pid,
|
|
@@ -10185,6 +10477,7 @@ var Launcher = class {
|
|
|
10185
10477
|
modulesDir;
|
|
10186
10478
|
env;
|
|
10187
10479
|
catalog;
|
|
10480
|
+
binfmts;
|
|
10188
10481
|
compiled = /* @__PURE__ */ new Map();
|
|
10189
10482
|
processes = /* @__PURE__ */ new Map();
|
|
10190
10483
|
zombies = /* @__PURE__ */ new Set();
|
|
@@ -10219,6 +10512,7 @@ var Launcher = class {
|
|
|
10219
10512
|
deciding = /* @__PURE__ */ new Map();
|
|
10220
10513
|
identities = { asked: 0, timedOut: 0 };
|
|
10221
10514
|
nodes;
|
|
10515
|
+
unlinked;
|
|
10222
10516
|
held = new HeldSet((path) => this.released(path));
|
|
10223
10517
|
processMounts;
|
|
10224
10518
|
booting = new AbortController();
|
|
@@ -10263,9 +10557,18 @@ var Launcher = class {
|
|
|
10263
10557
|
const fs = withCommandDirs(this.base, async () => new Set((await this.commands()).keys()));
|
|
10264
10558
|
this.nodes = new VfsNodes(fs, (path) => this.released(path));
|
|
10265
10559
|
this.openFiles.add(this.nodes);
|
|
10266
|
-
this.
|
|
10560
|
+
this.unlinked = new UnlinkedKeeper(
|
|
10561
|
+
fs,
|
|
10562
|
+
this.held,
|
|
10563
|
+
(path) => this.mountRoot(path),
|
|
10564
|
+
webLocks(),
|
|
10565
|
+
(path) => [...this.openFiles].some((nodes) => nodes.holds(path))
|
|
10566
|
+
);
|
|
10567
|
+
this.fs = keepingOpen(this.unlinked.wrap(), this.nodes);
|
|
10568
|
+
void this.unlinked.sweep("/");
|
|
10267
10569
|
this.watchers.watch([this.modulesDir, this.pnpmHome], { recursive: true }, () => {
|
|
10268
10570
|
this.catalog = void 0;
|
|
10571
|
+
this.binfmts = void 0;
|
|
10269
10572
|
});
|
|
10270
10573
|
}
|
|
10271
10574
|
setRoutes(table) {
|
|
@@ -10275,6 +10578,10 @@ var Launcher = class {
|
|
|
10275
10578
|
this.catalog ??= this.roots().then((roots) => scanCommands(this.base, roots));
|
|
10276
10579
|
return this.catalog;
|
|
10277
10580
|
}
|
|
10581
|
+
interpreters() {
|
|
10582
|
+
this.binfmts ??= this.roots().then((roots) => scanBinfmts(this.base, roots));
|
|
10583
|
+
return this.binfmts;
|
|
10584
|
+
}
|
|
10278
10585
|
async roots() {
|
|
10279
10586
|
return [this.modulesDir, ...await pnpmGlobalRoots(this.base, this.pnpmHome)];
|
|
10280
10587
|
}
|
|
@@ -10320,30 +10627,28 @@ var Launcher = class {
|
|
|
10320
10627
|
const command = (await this.commands()).get(name2);
|
|
10321
10628
|
return command?.script ? command : void 0;
|
|
10322
10629
|
}
|
|
10323
|
-
async interpreted(file, argv, cwd) {
|
|
10630
|
+
async interpreted(file, argv, cwd, depth = 0) {
|
|
10324
10631
|
const command = await this.scriptCommand(file);
|
|
10325
10632
|
const script = command?.script ?? this.fs.resolvePath(cwd, file);
|
|
10326
|
-
const
|
|
10633
|
+
const head = await this.head(script);
|
|
10634
|
+
if (!head) return void 0;
|
|
10635
|
+
const binfmt = isWasm(head) ? void 0 : binfmtOf(await this.interpreters(), script);
|
|
10636
|
+
const words = shebang(head) ?? (binfmt ? [binfmt] : void 0);
|
|
10327
10637
|
if (!words) return void 0;
|
|
10328
10638
|
if (baseName(words[0]) === "env") words.shift();
|
|
10329
10639
|
const [interp, ...rest] = words;
|
|
10330
|
-
const found = interp ? await this.resolve(interp, interp, cwd) : void 0;
|
|
10331
|
-
if (!found) return void 0;
|
|
10332
|
-
const target = command ? {
|
|
10333
|
-
...found,
|
|
10334
|
-
env: { ...found.env, ...command.env },
|
|
10335
|
-
unset: [...found.unset ?? [], ...command.unset ?? []]
|
|
10336
|
-
} : found;
|
|
10337
10640
|
const arg = rest.join(" ");
|
|
10338
|
-
|
|
10339
|
-
|
|
10340
|
-
|
|
10341
|
-
|
|
10342
|
-
|
|
10343
|
-
|
|
10344
|
-
|
|
10345
|
-
|
|
10346
|
-
}
|
|
10641
|
+
const passed = [...arg ? [arg] : [], command ? script : file, ...argv.slice(1)];
|
|
10642
|
+
const found = interp ? await this.resolve(interp, interp, cwd) : void 0;
|
|
10643
|
+
if (!found) {
|
|
10644
|
+
if (!interp || depth >= MAX_INTERPRETERS || !await this.scriptCommand(interp)) {
|
|
10645
|
+
return void 0;
|
|
10646
|
+
}
|
|
10647
|
+
const inner = await this.interpreted(interp, [interp, ...passed], cwd, depth + 1);
|
|
10648
|
+
return inner && { ...inner, target: withScriptEnv(inner.target, command) };
|
|
10649
|
+
}
|
|
10650
|
+
const target = withScriptEnv(found, command);
|
|
10651
|
+
return { target, args: [...target.prefix ?? [], ...passed] };
|
|
10347
10652
|
}
|
|
10348
10653
|
async plan(file, argv, cwd) {
|
|
10349
10654
|
const direct = await this.resolve(file, argv[0] ?? file, cwd);
|
|
@@ -10351,8 +10656,10 @@ var Launcher = class {
|
|
|
10351
10656
|
return this.interpreted(file, argv, cwd);
|
|
10352
10657
|
}
|
|
10353
10658
|
async unrunnable(file, cwd) {
|
|
10354
|
-
const
|
|
10355
|
-
|
|
10659
|
+
const path = this.fs.resolvePath(cwd, file);
|
|
10660
|
+
const head = await this.base.readFileBuffer(path).catch(() => null);
|
|
10661
|
+
if (!head || head[0] === 35 && head[1] === 33) return "ENOENT";
|
|
10662
|
+
return binfmtOf(await this.interpreters(), path) ? "ENOENT" : "ENOEXEC";
|
|
10356
10663
|
}
|
|
10357
10664
|
module(path) {
|
|
10358
10665
|
return this.base.stat(path).then((st) => {
|
|
@@ -10468,6 +10775,7 @@ var Launcher = class {
|
|
|
10468
10775
|
openFiles: this.openFiles,
|
|
10469
10776
|
nodes: this.nodes,
|
|
10470
10777
|
held: this.held,
|
|
10778
|
+
unlinkGate: this.unlinked.gate,
|
|
10471
10779
|
statfs: (path) => this.mounts.statfs(path),
|
|
10472
10780
|
mounts: () => this.mounts.list(),
|
|
10473
10781
|
mount: (call, signal) => this.processMount(pid, call, signal),
|
|
@@ -10625,6 +10933,7 @@ var Launcher = class {
|
|
|
10625
10933
|
}
|
|
10626
10934
|
released(path) {
|
|
10627
10935
|
const at = normalizePath(path);
|
|
10936
|
+
this.unlinked.closed(at);
|
|
10628
10937
|
const open = [...this.openFiles].some((nodes) => nodes.writes(at)) || heldUnder(this.held, at);
|
|
10629
10938
|
if (!open) void this.mounts.commit(at).catch(() => void 0);
|
|
10630
10939
|
}
|
|
@@ -10720,10 +11029,23 @@ var Launcher = class {
|
|
|
10720
11029
|
}
|
|
10721
11030
|
};
|
|
10722
11031
|
}
|
|
10723
|
-
mount(spec) {
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
11032
|
+
async mount(spec) {
|
|
11033
|
+
const fsa = spec.type === "fsa" && !spec.source.startsWith("fsa:");
|
|
11034
|
+
const entry = await this.mounts.mount(
|
|
11035
|
+
fsa ? { ...spec, source: `fsa:${crypto.randomUUID()}` } : spec,
|
|
11036
|
+
this.fs
|
|
11037
|
+
);
|
|
11038
|
+
void this.unlinked.sweep(entry.target);
|
|
11039
|
+
return entry;
|
|
11040
|
+
}
|
|
11041
|
+
mountRoot(path) {
|
|
11042
|
+
let root = "/";
|
|
11043
|
+
for (const { target } of this.mounts.list()) {
|
|
11044
|
+
if (target.length > root.length && (path === target || path.startsWith(`${target}/`))) {
|
|
11045
|
+
root = target;
|
|
11046
|
+
}
|
|
11047
|
+
}
|
|
11048
|
+
return root;
|
|
10727
11049
|
}
|
|
10728
11050
|
async insert(target, handle, source) {
|
|
10729
11051
|
const at = normalizePath(target);
|
|
@@ -10737,6 +11059,7 @@ var Launcher = class {
|
|
|
10737
11059
|
await this.media.put(slot.id, handle);
|
|
10738
11060
|
slot.medium.insert(handle);
|
|
10739
11061
|
slot.served.invalidate(true);
|
|
11062
|
+
void this.unlinked.sweep(at);
|
|
10740
11063
|
}
|
|
10741
11064
|
umount(target, detach = false) {
|
|
10742
11065
|
const at = normalizePath(target);
|
|
@@ -10812,6 +11135,7 @@ var Launcher = class {
|
|
|
10812
11135
|
}
|
|
10813
11136
|
async starting(argv, dir) {
|
|
10814
11137
|
this.catalog = void 0;
|
|
11138
|
+
this.binfmts = void 0;
|
|
10815
11139
|
const cwd = this.fs.resolvePath("/", dir ?? "/");
|
|
10816
11140
|
const [file = ""] = argv;
|
|
10817
11141
|
await this.base.mkdir(cwd, { recursive: true });
|