@ai-ecoverse/slicc-kernel 1.167.4 → 1.168.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 +24 -1
- package/dist/index.js.map +1 -1
- package/dist/kernel-worker.js +332 -87
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js +61 -2
- package/dist/meta.js.map +3 -3
- package/dist/node-process-worker.cjs +3 -1
- package/dist/node-process-worker.cjs.map +2 -2
- package/dist/node-process-worker.js +3 -1
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +486 -241
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +3 -1
- package/dist/process-worker.js.map +2 -2
- package/dist/types/fs/opfs.d.ts +1 -0
- package/dist/types/fs/remote.d.ts +1 -0
- package/dist/types/fs/types.d.ts +2 -0
- package/dist/types/kernel/package-swaps.d.ts +25 -0
- package/dist/types/kernel/proc-info.d.ts +6 -0
- package/dist/types/kernel/replacing.d.ts +18 -0
- package/dist/types/launcher.d.ts +9 -0
- package/dist/types/meta.d.ts +4 -0
- package/package.json +3 -3
package/dist/kernel-worker.js
CHANGED
|
@@ -1753,9 +1753,11 @@ var OpfsFs = class {
|
|
|
1753
1753
|
this.channel.onmessage = ({ data }) => {
|
|
1754
1754
|
const { paths, trees, outside } = noticeOf(data);
|
|
1755
1755
|
for (const path of [...paths, ...trees]) this.forget(normalizePath(path));
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1756
|
+
if (!outside) remote?.emit({ paths, trees });
|
|
1757
|
+
else
|
|
1758
|
+
void this.noticed(paths.map(normalizePath), Date.now()).finally(
|
|
1759
|
+
() => remote?.emit({ paths, trees, outside: true })
|
|
1760
|
+
);
|
|
1759
1761
|
};
|
|
1760
1762
|
this.channel.unref?.();
|
|
1761
1763
|
}
|
|
@@ -2121,6 +2123,9 @@ var OpfsFs = class {
|
|
|
2121
2123
|
this.exact--;
|
|
2122
2124
|
}
|
|
2123
2125
|
}
|
|
2126
|
+
refresh(trees) {
|
|
2127
|
+
for (const tree2 of trees) this.forget(normalizePath(tree2));
|
|
2128
|
+
}
|
|
2124
2129
|
forget(path) {
|
|
2125
2130
|
this.changes++;
|
|
2126
2131
|
this.dirs.deleteTree(path);
|
|
@@ -3077,15 +3082,15 @@ var OpfsFs = class {
|
|
|
3077
3082
|
const hooks = {};
|
|
3078
3083
|
const staging = swap ? `.${name2}.${crypto.randomUUID()}` : name2;
|
|
3079
3084
|
const copying = sourceStat.isDirectory && !movable(source.handle);
|
|
3080
|
-
const
|
|
3085
|
+
const staged2 = resolvePath(parent.path, staging);
|
|
3081
3086
|
const place = async () => {
|
|
3082
3087
|
this.forget(destination);
|
|
3083
3088
|
const copies = /* @__PURE__ */ new Map();
|
|
3084
3089
|
const root = { ino: inodeOf(source.path), ...moving };
|
|
3085
3090
|
const owned4 = lock ? { lock } : {};
|
|
3086
3091
|
hooks.notify?.();
|
|
3087
|
-
const first = copying ? await this.intend({ from: source.path, to:
|
|
3088
|
-
const second = copying && swap ? await this.intend({ from:
|
|
3092
|
+
const first = copying ? await this.intend({ from: source.path, to: staged2, root, ...owned4 }) : void 0;
|
|
3093
|
+
const second = copying && swap ? await this.intend({ from: staged2, to: destination, replace: true, root, ...owned4 }) : void 0;
|
|
3089
3094
|
await hooks.started?.().catch(async (err) => {
|
|
3090
3095
|
for (const intent of [first, second]) {
|
|
3091
3096
|
if (intent) await this.meta.update(intent, () => void 0);
|
|
@@ -3096,11 +3101,11 @@ var OpfsFs = class {
|
|
|
3096
3101
|
targetStat !== null,
|
|
3097
3102
|
() => this.place(source.handle, dir, staging, copies)
|
|
3098
3103
|
).catch(async (err) => {
|
|
3099
|
-
if (first) await this.rollBack(
|
|
3104
|
+
if (first) await this.rollBack(staged2, source.path, [first, second]);
|
|
3100
3105
|
throw err;
|
|
3101
3106
|
});
|
|
3102
3107
|
if (swap) await this.rm(destination, { recursive: true });
|
|
3103
|
-
if (second) await this.intend({ from:
|
|
3108
|
+
if (second) await this.intend({ from: staged2, to: destination, root, ...owned4 }, second);
|
|
3104
3109
|
await this.meta.move(source.path, destination, carry, left);
|
|
3105
3110
|
this.movePending(source.path, destination);
|
|
3106
3111
|
if (!moved2) {
|
|
@@ -7598,14 +7603,14 @@ var UserDb = class {
|
|
|
7598
7603
|
this.fs = fs;
|
|
7599
7604
|
this.owners = owners;
|
|
7600
7605
|
}
|
|
7601
|
-
async stampHome(row,
|
|
7606
|
+
async stampHome(row, shared2, homeMode) {
|
|
7602
7607
|
const home = this.fs.resolvePath("/", row.home);
|
|
7603
7608
|
if (!this.owners || !this.fs.chown || !HOME_DIR.test(home)) return;
|
|
7604
7609
|
if (!await this.realDir(home)) return;
|
|
7605
|
-
const gid =
|
|
7610
|
+
const gid = shared2?.gid ?? row.gid;
|
|
7606
7611
|
await this.fs.chown(home, { uid: row.uid, gid, follow: false, kind: "adopt" });
|
|
7607
7612
|
const scoop = row.name.startsWith("scoop-");
|
|
7608
|
-
await this.fs.chmod(home, homeMode ?? (
|
|
7613
|
+
await this.fs.chmod(home, homeMode ?? (shared2 ? 1512 : scoop ? 488 : 448));
|
|
7609
7614
|
const pnpm = `${home}/.local/share/pnpm`;
|
|
7610
7615
|
if (await this.realDir(pnpm)) await this.fs.chmod(pnpm, scoop ? 488 : 448);
|
|
7611
7616
|
}
|
|
@@ -7642,9 +7647,9 @@ var UserDb = class {
|
|
|
7642
7647
|
const [passwd, group] = await this.texts();
|
|
7643
7648
|
return { passwd: parsePasswd(passwd), group: parseGroup(group) };
|
|
7644
7649
|
}
|
|
7645
|
-
async provision(row, umask,
|
|
7646
|
-
const dirs = 511 & ~umask | (
|
|
7647
|
-
const gid =
|
|
7650
|
+
async provision(row, umask, shared2) {
|
|
7651
|
+
const dirs = 511 & ~umask | (shared2 ? 1024 : 0);
|
|
7652
|
+
const gid = shared2?.gid ?? row.gid;
|
|
7648
7653
|
const owner = this.owners ? { uid: row.uid, gid } : void 0;
|
|
7649
7654
|
const made2 = owner ? { recursive: true, owner: { ...owner, mode: dirs, parents: dirs } } : { recursive: true };
|
|
7650
7655
|
const pnpm = `${row.home}/.local/share/pnpm`;
|
|
@@ -7748,7 +7753,7 @@ var UserDb = class {
|
|
|
7748
7753
|
const users = parsed(passwd);
|
|
7749
7754
|
const groups = parsed(group);
|
|
7750
7755
|
const found = users.find((r) => r.name === name2);
|
|
7751
|
-
const
|
|
7756
|
+
const shared2 = homeGroupOf(groups, options.homeGroup);
|
|
7752
7757
|
const homeMode = homeModeOf(options.homeMode);
|
|
7753
7758
|
if (found) {
|
|
7754
7759
|
const more = groupsOf(groups, options.groups ?? []);
|
|
@@ -7756,8 +7761,8 @@ var UserDb = class {
|
|
|
7756
7761
|
throw fsError("EINVAL", `a user is no member of its own group ${name2}`);
|
|
7757
7762
|
}
|
|
7758
7763
|
if (found.uid >= FIRST_UID && found.uid <= LAST_UID) {
|
|
7759
|
-
await this.provision(found, this.umaskFor(options),
|
|
7760
|
-
await this.stampHome(found,
|
|
7764
|
+
await this.provision(found, this.umaskFor(options), shared2);
|
|
7765
|
+
await this.stampHome(found, shared2, homeMode);
|
|
7761
7766
|
}
|
|
7762
7767
|
if (joined(name2, more)) await this.fs.writeFile(GROUP, formatGroup(group));
|
|
7763
7768
|
remember();
|
|
@@ -7774,8 +7779,8 @@ var UserDb = class {
|
|
|
7774
7779
|
const fresh3 = !await this.fs.exists(home);
|
|
7775
7780
|
await this.fs.mkdir(home, { recursive: true });
|
|
7776
7781
|
try {
|
|
7777
|
-
await this.provision(row, this.umaskFor(options),
|
|
7778
|
-
await this.stampHome(row,
|
|
7782
|
+
await this.provision(row, this.umaskFor(options), shared2);
|
|
7783
|
+
await this.stampHome(row, shared2, homeMode);
|
|
7779
7784
|
await this.fs.mkdir("/etc", { recursive: true });
|
|
7780
7785
|
await this.commit(formatPasswd(passwd), formatGroup(group));
|
|
7781
7786
|
} catch (err) {
|
|
@@ -7824,19 +7829,19 @@ var UserDb = class {
|
|
|
7824
7829
|
);
|
|
7825
7830
|
for (const r of parsed(keptGroups)) r.members = r.members.filter((m) => m !== name2);
|
|
7826
7831
|
const home = this.fs.resolvePath("/", row.home);
|
|
7827
|
-
const
|
|
7832
|
+
const shared2 = parsed(passwd).some(
|
|
7828
7833
|
(r) => r !== row && this.fs.resolvePath("/", r.home) === home
|
|
7829
7834
|
);
|
|
7830
|
-
const removeHome = !options.keepHome && !
|
|
7831
|
-
const
|
|
7835
|
+
const removeHome = !options.keepHome && !shared2 && HOME_DIR.test(home) && await this.fs.exists(home);
|
|
7836
|
+
const staged2 = `/home/.${name2}.removed-${Date.now()}`;
|
|
7832
7837
|
await this.commit(
|
|
7833
7838
|
formatPasswd(passwd.filter((r) => r !== row)),
|
|
7834
7839
|
formatGroup(keptGroups),
|
|
7835
|
-
removeHome ? () => this.fs.rename(home,
|
|
7840
|
+
removeHome ? () => this.fs.rename(home, staged2) : void 0
|
|
7836
7841
|
);
|
|
7837
7842
|
this.umasks.delete(name2);
|
|
7838
7843
|
if (removeHome)
|
|
7839
|
-
await this.fs.rm(
|
|
7844
|
+
await this.fs.rm(staged2, { recursive: true, force: true }).catch(() => void 0);
|
|
7840
7845
|
return true;
|
|
7841
7846
|
});
|
|
7842
7847
|
}
|
|
@@ -8492,7 +8497,7 @@ function satisfies(version, range2) {
|
|
|
8492
8497
|
}
|
|
8493
8498
|
|
|
8494
8499
|
// src/version.ts
|
|
8495
|
-
var KERNEL_VERSION = true ? "1.
|
|
8500
|
+
var KERNEL_VERSION = true ? "1.168.1" : "0.0.0-dev";
|
|
8496
8501
|
var OS_RELEASE = "6.0.0-slicc";
|
|
8497
8502
|
function procVersion() {
|
|
8498
8503
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -8575,8 +8580,8 @@ function abiOf(raw2, fallback) {
|
|
|
8575
8580
|
const abi = raw2 ?? fallback;
|
|
8576
8581
|
return abi === "emscripten" || abi === "wasi" || abi === "js" ? abi : void 0;
|
|
8577
8582
|
}
|
|
8578
|
-
function commandOf(pkg, name2, raw2, packageAbi,
|
|
8579
|
-
const withEnv = envFields({ ...
|
|
8583
|
+
function commandOf(pkg, name2, raw2, packageAbi, shared2) {
|
|
8584
|
+
const withEnv = envFields({ ...shared2, ...envOf(pkg, raw2.env) });
|
|
8580
8585
|
const script = inside(pkg, raw2.script);
|
|
8581
8586
|
if (script) {
|
|
8582
8587
|
return { name: name2, abi: packageAbi, glue: script, wasm: script, argv0: name2, script, ...withEnv };
|
|
@@ -8626,13 +8631,13 @@ function commandsOf(pkg, manifest) {
|
|
|
8626
8631
|
const packageAbi = abiOf(slicc.abi, "emscripten");
|
|
8627
8632
|
const entries = slicc.commands;
|
|
8628
8633
|
if (!packageAbi || !entries || typeof entries !== "object") return [];
|
|
8629
|
-
const
|
|
8634
|
+
const shared2 = envOf(pkg, slicc.env);
|
|
8630
8635
|
const out = [];
|
|
8631
8636
|
for (const [name2, raw2] of Object.entries(entries)) {
|
|
8632
8637
|
if (!commandName(name2) || !raw2 || typeof raw2 !== "object") {
|
|
8633
8638
|
continue;
|
|
8634
8639
|
}
|
|
8635
|
-
const command = commandOf(pkg, name2, raw2, packageAbi,
|
|
8640
|
+
const command = commandOf(pkg, name2, raw2, packageAbi, shared2);
|
|
8636
8641
|
if (command) out.push(command);
|
|
8637
8642
|
}
|
|
8638
8643
|
return out;
|
|
@@ -9793,8 +9798,8 @@ var UnlinkedKeeper = class {
|
|
|
9793
9798
|
void peers.ask(tab, { kept: { items: [], paths } }, PEER_RM_MS);
|
|
9794
9799
|
throw fsError("EBUSY", `${target}: open in another tab that did not answer`);
|
|
9795
9800
|
}
|
|
9796
|
-
const { whole, sends, shared } = await this.setAside(target, asked);
|
|
9797
|
-
return { whole, undoing: (op) => this.undoing(op, peers, sends, heard,
|
|
9801
|
+
const { whole, sends, shared: shared2 } = await this.setAside(target, asked);
|
|
9802
|
+
return { whole, undoing: (op) => this.undoing(op, peers, sends, heard, shared2) };
|
|
9798
9803
|
}
|
|
9799
9804
|
async setAside(target, asked) {
|
|
9800
9805
|
const mine = this.heldWithin(target);
|
|
@@ -9802,25 +9807,25 @@ var UnlinkedKeeper = class {
|
|
|
9802
9807
|
for (const { holders } of asked)
|
|
9803
9808
|
for (const { path } of holders) tabsOf.set(path, (tabsOf.get(path) ?? 0) + 1);
|
|
9804
9809
|
const done5 = /* @__PURE__ */ new Map();
|
|
9805
|
-
const
|
|
9810
|
+
const shared2 = [];
|
|
9806
9811
|
const sends = [];
|
|
9807
9812
|
for (const { tab, holders, paths } of asked) {
|
|
9808
9813
|
const items = [];
|
|
9809
9814
|
for (const holder of holders) {
|
|
9810
9815
|
if (!done5.has(holder.path)) {
|
|
9811
9816
|
const many = mine.has(holder.path) || (tabsOf.get(holder.path) ?? 0) > 1;
|
|
9812
|
-
done5.set(holder.path, await this.asideOne(holder, many, mine,
|
|
9817
|
+
done5.set(holder.path, await this.asideOne(holder, many, mine, shared2));
|
|
9813
9818
|
}
|
|
9814
9819
|
items.push({ path: holder.path, hidden: done5.get(holder.path), fid: holder.fid });
|
|
9815
9820
|
}
|
|
9816
9821
|
sends.push({ tab, items, paths });
|
|
9817
9822
|
}
|
|
9818
|
-
return { whole: done5.get(target) !== void 0, sends, shared };
|
|
9823
|
+
return { whole: done5.get(target) !== void 0, sends, shared: shared2 };
|
|
9819
9824
|
}
|
|
9820
|
-
async asideOne(holder, many, mine,
|
|
9825
|
+
async asideOne(holder, many, mine, shared2) {
|
|
9821
9826
|
if (!many) return this.asideFor(holder.path, holder.instance);
|
|
9822
9827
|
const one = await this.sharedAside(holder.path, mine);
|
|
9823
|
-
if (one)
|
|
9828
|
+
if (one) shared2.push(one);
|
|
9824
9829
|
return one?.hidden;
|
|
9825
9830
|
}
|
|
9826
9831
|
async sharedAside(path, mine) {
|
|
@@ -9865,16 +9870,16 @@ var UnlinkedKeeper = class {
|
|
|
9865
9870
|
sharedLocks() {
|
|
9866
9871
|
return this.locks;
|
|
9867
9872
|
}
|
|
9868
|
-
async undoing(op, peers, sends, heard,
|
|
9873
|
+
async undoing(op, peers, sends, heard, shared2 = []) {
|
|
9869
9874
|
let failed3;
|
|
9870
9875
|
let out;
|
|
9871
9876
|
try {
|
|
9872
9877
|
out = await op();
|
|
9873
9878
|
} catch (err) {
|
|
9874
9879
|
failed3 = err ?? new Error("failed");
|
|
9875
|
-
await this.rollBackAsides(sends,
|
|
9880
|
+
await this.rollBackAsides(sends, shared2);
|
|
9876
9881
|
}
|
|
9877
|
-
const hiddenShared = new Set(
|
|
9882
|
+
const hiddenShared = new Set(shared2.map((one) => one.hidden));
|
|
9878
9883
|
const answers2 = sends.map(({ tab, items, paths }) => {
|
|
9879
9884
|
const keeps = items.some((item) => item.hidden && hiddenShared.has(item.hidden));
|
|
9880
9885
|
return {
|
|
@@ -9885,7 +9890,7 @@ var UnlinkedKeeper = class {
|
|
|
9885
9890
|
await Promise.all(
|
|
9886
9891
|
answers2.map(({ told }, i) => heard[i] ? Promise.race([told, delay(PEER_RM_MS)]) : void 0)
|
|
9887
9892
|
);
|
|
9888
|
-
for (const one of
|
|
9893
|
+
for (const one of shared2) {
|
|
9889
9894
|
const waits = answers2.filter(
|
|
9890
9895
|
({ keeps }, i) => keeps && sends[i]?.items.some((item) => item.hidden === one.hidden)
|
|
9891
9896
|
);
|
|
@@ -9895,7 +9900,7 @@ var UnlinkedKeeper = class {
|
|
|
9895
9900
|
if (failed3 !== void 0) throw failed3;
|
|
9896
9901
|
return out;
|
|
9897
9902
|
}
|
|
9898
|
-
async rollBackAsides(sends,
|
|
9903
|
+
async rollBackAsides(sends, shared2) {
|
|
9899
9904
|
const back = /* @__PURE__ */ new Map();
|
|
9900
9905
|
for (const item of sends.flatMap((send2) => send2.items)) {
|
|
9901
9906
|
const { hidden, path } = item;
|
|
@@ -9903,7 +9908,7 @@ var UnlinkedKeeper = class {
|
|
|
9903
9908
|
if (!back.has(hidden)) back.set(hidden, await this.moveBack(hidden, path));
|
|
9904
9909
|
if (back.get(hidden)) item.hidden = void 0;
|
|
9905
9910
|
}
|
|
9906
|
-
for (const { hidden, path, local: local2, file } of
|
|
9911
|
+
for (const { hidden, path, local: local2, file } of shared2) {
|
|
9907
9912
|
if (!back.get(hidden) || !file) continue;
|
|
9908
9913
|
for (const holder of local2) {
|
|
9909
9914
|
holder.unkeep(path, file);
|
|
@@ -13144,8 +13149,8 @@ var CwdTable = class {
|
|
|
13144
13149
|
this.inodeOf = inodeOf2;
|
|
13145
13150
|
}
|
|
13146
13151
|
async hold(path, from) {
|
|
13147
|
-
const
|
|
13148
|
-
if (
|
|
13152
|
+
const shared2 = from === void 0 ? void 0 : this.held.get(from);
|
|
13153
|
+
if (shared2 && shared2.path === path) return this.share(from);
|
|
13149
13154
|
const ino = await this.inodeOf(path).catch(() => void 0);
|
|
13150
13155
|
const slot2 = this.free.pop() ?? (this.next < UNTRACKED ? this.next++ : UNTRACKED);
|
|
13151
13156
|
if (slot2 === UNTRACKED) return slot2;
|
|
@@ -16294,6 +16299,8 @@ var SYS_TREE = {
|
|
|
16294
16299
|
slicc_opfs_ops: (listing) => `${listing.opfsOps ?? 0}
|
|
16295
16300
|
`,
|
|
16296
16301
|
slicc_cwd_checks: (listing) => `${listing.cwdChecks ?? 0}
|
|
16302
|
+
`,
|
|
16303
|
+
slicc_package_swaps: ({ swaps }) => `${swaps?.swaps ?? 0} ${(swaps?.longestMs ?? 0).toFixed(1)} ${swaps?.waits ?? 0} ${(swaps?.waitedMs ?? 0).toFixed(1)}
|
|
16297
16304
|
`,
|
|
16298
16305
|
slicc_rename_ack_busy: (listing) => `${listing.renameAcks?.busy ?? 0}
|
|
16299
16306
|
`,
|
|
@@ -17509,13 +17516,13 @@ async function flock(req, ctx) {
|
|
|
17509
17516
|
if (!FLOCK_KINDS.has(req.kind)) throw new KernelError("EINVAL");
|
|
17510
17517
|
const { key, owner } = await flockOf(req.fd);
|
|
17511
17518
|
const granted2 = req.kind !== "unlock";
|
|
17512
|
-
const
|
|
17513
|
-
if (
|
|
17519
|
+
const shared2 = locks.shared?.() === true;
|
|
17520
|
+
if (shared2 && !granted2) await ctx.settle?.(req.fd, false);
|
|
17514
17521
|
if (req.kind !== "unlock" && req.wait)
|
|
17515
17522
|
await locks.flocks.wait(key, owner, req.kind, ctx.blocking);
|
|
17516
17523
|
else if (!await locks.flocks.set(key, owner, req.kind)) throw new KernelError("EAGAIN");
|
|
17517
|
-
if (
|
|
17518
|
-
return
|
|
17524
|
+
if (shared2 && granted2) await grantedAcross(ctx, req.fd);
|
|
17525
|
+
return shared2 ? json3(true) : done3;
|
|
17519
17526
|
}
|
|
17520
17527
|
async function grantedAcross(ctx, fd) {
|
|
17521
17528
|
ctx.locks?.fresh?.();
|
|
@@ -17543,15 +17550,15 @@ async function recordLock2(req, ctx) {
|
|
|
17543
17550
|
return json3({ kind: held.kind, pid: held.owner, start: held.start, len });
|
|
17544
17551
|
}
|
|
17545
17552
|
const granted2 = req.kind !== "unlock";
|
|
17546
|
-
const
|
|
17547
|
-
const fd =
|
|
17553
|
+
const shared2 = locks.shared?.() === true;
|
|
17554
|
+
const fd = shared2 ? req.fd : void 0;
|
|
17548
17555
|
if (!granted2 && fd !== void 0) await ctx.settle?.(fd, false);
|
|
17549
17556
|
if (req.kind !== "unlock" && req.wait)
|
|
17550
17557
|
await locks.wait(key, owner, req.kind, range2, ctx.blocking);
|
|
17551
17558
|
else if (!await locks.set(key, owner, req.kind, range2.start, range2.end))
|
|
17552
17559
|
throw new KernelError("EAGAIN");
|
|
17553
|
-
if (granted2 &&
|
|
17554
|
-
return
|
|
17560
|
+
if (granted2 && shared2) await grantedAcross(ctx, fd);
|
|
17561
|
+
return shared2 ? json3(true) : done3;
|
|
17555
17562
|
}
|
|
17556
17563
|
|
|
17557
17564
|
// src/kernel/net/loopback-transport.ts
|
|
@@ -23791,9 +23798,9 @@ function pausing(signal) {
|
|
|
23791
23798
|
return { pausedAt, select };
|
|
23792
23799
|
}
|
|
23793
23800
|
async function serveSecure(proc, socket, req) {
|
|
23794
|
-
const
|
|
23795
|
-
if (req.listener && !
|
|
23796
|
-
const server =
|
|
23801
|
+
const shared2 = req.listener?.serving;
|
|
23802
|
+
if (req.listener && !shared2) throw new KernelError("EINVAL", "the listener has no tls");
|
|
23803
|
+
const server = shared2 ?? await serverOf(proc, req);
|
|
23797
23804
|
const { engine, leaf, alpn, store, flags: flags2 } = server;
|
|
23798
23805
|
const limit = handshakeSignal(proc, server.timeoutMs);
|
|
23799
23806
|
const { pausedAt, select } = pausing(limit.signal);
|
|
@@ -23807,12 +23814,12 @@ async function serveSecure(proc, socket, req) {
|
|
|
23807
23814
|
(flags2 & TLS_KEYLOG) !== 0
|
|
23808
23815
|
),
|
|
23809
23816
|
limit.signal,
|
|
23810
|
-
(reason) => !
|
|
23817
|
+
(reason) => !shared2 && reason === timedOut
|
|
23811
23818
|
).finally(() => {
|
|
23812
23819
|
limit.done();
|
|
23813
23820
|
selections.delete(socket);
|
|
23814
23821
|
socket.pending = void 0;
|
|
23815
|
-
if (!
|
|
23822
|
+
if (!shared2) server.release();
|
|
23816
23823
|
});
|
|
23817
23824
|
run2.catch(() => void 0);
|
|
23818
23825
|
const first = await Promise.race([run2, pausedAt.then((pause2) => ({ pause: pause2 }))]);
|
|
@@ -29010,6 +29017,105 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
29010
29017
|
};
|
|
29011
29018
|
}
|
|
29012
29019
|
|
|
29020
|
+
// src/kernel/package-swaps.ts
|
|
29021
|
+
var SWAP_GAP_MS = 2e3;
|
|
29022
|
+
var STAGES = ["_tmp_", "_pacquet-stage_"];
|
|
29023
|
+
function staged(source, target) {
|
|
29024
|
+
if (parentOf4(source) !== parentOf4(target)) return false;
|
|
29025
|
+
const name2 = target.slice(target.lastIndexOf("/") + 1);
|
|
29026
|
+
const from = source.slice(source.lastIndexOf("/") + 1);
|
|
29027
|
+
return from.startsWith(`.${name2}-`) || STAGES.some((stage) => from.startsWith(`${name2}${stage}`));
|
|
29028
|
+
}
|
|
29029
|
+
var PackageSwaps = class {
|
|
29030
|
+
gaps = /* @__PURE__ */ new Map();
|
|
29031
|
+
isRoot;
|
|
29032
|
+
hold;
|
|
29033
|
+
closed;
|
|
29034
|
+
gapMs;
|
|
29035
|
+
tally = { swaps: 0, longestMs: 0, waits: 0, waitedMs: 0 };
|
|
29036
|
+
constructor(isRoot, hold, closed, gapMs = SWAP_GAP_MS) {
|
|
29037
|
+
this.isRoot = isRoot;
|
|
29038
|
+
this.hold = hold;
|
|
29039
|
+
this.closed = closed;
|
|
29040
|
+
this.gapMs = gapMs;
|
|
29041
|
+
}
|
|
29042
|
+
counts() {
|
|
29043
|
+
return { ...this.tally };
|
|
29044
|
+
}
|
|
29045
|
+
settled() {
|
|
29046
|
+
if (this.gaps.size === 0) return Promise.resolve();
|
|
29047
|
+
const started = performance.now();
|
|
29048
|
+
this.tally.waits++;
|
|
29049
|
+
return Promise.all([...this.gaps.values()].map((gap) => gap.settled)).then(() => {
|
|
29050
|
+
this.tally.waitedMs += performance.now() - started;
|
|
29051
|
+
});
|
|
29052
|
+
}
|
|
29053
|
+
wrap(fs) {
|
|
29054
|
+
return { ...fs, rename: (from, to) => this.rename(fs, from, to) };
|
|
29055
|
+
}
|
|
29056
|
+
async rename(fs, from, to) {
|
|
29057
|
+
const source = fs.resolvePath("/", from);
|
|
29058
|
+
const target = fs.resolvePath("/", to);
|
|
29059
|
+
const gap = this.gaps.get(target);
|
|
29060
|
+
if (gap) return this.land(gap, target, () => fs.rename(from, to));
|
|
29061
|
+
if (source === target || this.gaps.has(source) || staged(source, target) || !this.isRoot(source)) {
|
|
29062
|
+
return fs.rename(from, to);
|
|
29063
|
+
}
|
|
29064
|
+
const release = await this.hold(source);
|
|
29065
|
+
let kept = false;
|
|
29066
|
+
try {
|
|
29067
|
+
await fs.rename(from, to);
|
|
29068
|
+
kept = await fs.stat(`${target}/package.json`).then(
|
|
29069
|
+
(st) => st.isFile,
|
|
29070
|
+
() => false
|
|
29071
|
+
);
|
|
29072
|
+
if (kept) this.open(source, release);
|
|
29073
|
+
} finally {
|
|
29074
|
+
if (!kept) release();
|
|
29075
|
+
}
|
|
29076
|
+
}
|
|
29077
|
+
open(root, release) {
|
|
29078
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
29079
|
+
const gap = {
|
|
29080
|
+
release,
|
|
29081
|
+
done: () => resolve2(),
|
|
29082
|
+
settled: promise,
|
|
29083
|
+
timer: void 0,
|
|
29084
|
+
landing: 0,
|
|
29085
|
+
opened: performance.now()
|
|
29086
|
+
};
|
|
29087
|
+
this.gaps.set(root, gap);
|
|
29088
|
+
this.tally.swaps++;
|
|
29089
|
+
this.arm(root, gap);
|
|
29090
|
+
}
|
|
29091
|
+
arm(root, gap) {
|
|
29092
|
+
const timer = setTimeout(() => this.close(root, gap), this.gapMs);
|
|
29093
|
+
timer.unref?.();
|
|
29094
|
+
gap.timer = timer;
|
|
29095
|
+
}
|
|
29096
|
+
close(root, gap) {
|
|
29097
|
+
if (this.gaps.get(root) !== gap) return;
|
|
29098
|
+
clearTimeout(gap.timer);
|
|
29099
|
+
this.gaps.delete(root);
|
|
29100
|
+
this.tally.longestMs = Math.max(this.tally.longestMs, performance.now() - gap.opened);
|
|
29101
|
+
this.closed();
|
|
29102
|
+
gap.done();
|
|
29103
|
+
gap.release();
|
|
29104
|
+
}
|
|
29105
|
+
async land(gap, root, run2) {
|
|
29106
|
+
gap.landing++;
|
|
29107
|
+
clearTimeout(gap.timer);
|
|
29108
|
+
try {
|
|
29109
|
+
await run2();
|
|
29110
|
+
} catch (err) {
|
|
29111
|
+
gap.landing--;
|
|
29112
|
+
if (gap.landing === 0 && this.gaps.get(root) === gap) this.arm(root, gap);
|
|
29113
|
+
throw err;
|
|
29114
|
+
}
|
|
29115
|
+
this.close(root, gap);
|
|
29116
|
+
}
|
|
29117
|
+
};
|
|
29118
|
+
|
|
29013
29119
|
// src/kernel/rename-log.ts
|
|
29014
29120
|
var RENAME_LOG_SIZE = 4096;
|
|
29015
29121
|
function within9(path, root) {
|
|
@@ -29047,6 +29153,51 @@ var RenameLog = class {
|
|
|
29047
29153
|
}
|
|
29048
29154
|
};
|
|
29049
29155
|
|
|
29156
|
+
// src/kernel/replacing.ts
|
|
29157
|
+
var REPLACING_LOCK = "slicc-kernel-replacing:v1:";
|
|
29158
|
+
function replacingLocks(scope = globalThis) {
|
|
29159
|
+
const locks = scope.navigator?.locks;
|
|
29160
|
+
return typeof locks?.request === "function" ? locks : void 0;
|
|
29161
|
+
}
|
|
29162
|
+
function replacingLock(metadata, root) {
|
|
29163
|
+
return `${REPLACING_LOCK}${metadata}:${root}`;
|
|
29164
|
+
}
|
|
29165
|
+
function shared(locks, names2, run2, waited) {
|
|
29166
|
+
const [name2, ...rest2] = names2;
|
|
29167
|
+
if (name2 === void 0) return run2(waited);
|
|
29168
|
+
const next3 = (after) => shared(locks, rest2, run2, after);
|
|
29169
|
+
return locks.request(
|
|
29170
|
+
name2,
|
|
29171
|
+
{ mode: "shared", ifAvailable: true },
|
|
29172
|
+
(lock) => lock ? next3(waited) : locks.request(name2, { mode: "shared" }, () => next3(true))
|
|
29173
|
+
);
|
|
29174
|
+
}
|
|
29175
|
+
var PackageLocks = class {
|
|
29176
|
+
locks;
|
|
29177
|
+
metadata;
|
|
29178
|
+
constructor(metadata, locks = replacingLocks()) {
|
|
29179
|
+
this.metadata = metadata;
|
|
29180
|
+
this.locks = locks;
|
|
29181
|
+
}
|
|
29182
|
+
loading(roots, run2) {
|
|
29183
|
+
if (!this.locks || roots.length === 0) return run2(false);
|
|
29184
|
+
const names2 = roots.map((root) => replacingLock(this.metadata, root));
|
|
29185
|
+
return shared(this.locks, names2, run2, false);
|
|
29186
|
+
}
|
|
29187
|
+
holding(root) {
|
|
29188
|
+
const { locks } = this;
|
|
29189
|
+
if (!locks) return Promise.resolve(() => {
|
|
29190
|
+
});
|
|
29191
|
+
const { promise: held, resolve: release } = Promise.withResolvers();
|
|
29192
|
+
return new Promise((granted2, failed3) => {
|
|
29193
|
+
locks.request(replacingLock(this.metadata, root), { mode: "exclusive" }, () => {
|
|
29194
|
+
granted2(() => release());
|
|
29195
|
+
return held;
|
|
29196
|
+
}).catch(failed3);
|
|
29197
|
+
});
|
|
29198
|
+
}
|
|
29199
|
+
};
|
|
29200
|
+
|
|
29050
29201
|
// src/kernel/settling.ts
|
|
29051
29202
|
var SETUP_OPS = /* @__PURE__ */ new Set([
|
|
29052
29203
|
"proc-list",
|
|
@@ -31297,6 +31448,7 @@ var COMMAND2 = /^\/(?:usr\/)?bin\/([^/]+)$/;
|
|
|
31297
31448
|
var SHIM_MARKER = /^\/\/ pnpm-wasm-shim=(\{.*\})$/gm;
|
|
31298
31449
|
var SHIM_MAX = 64 * 1024;
|
|
31299
31450
|
var PACKAGE_ROOT = /^(.*\/node_modules\/(?:@[^/]+\/)?[^/]+)\//;
|
|
31451
|
+
var NODE_MODULES = /\/node_modules(?:\/|$)/;
|
|
31300
31452
|
var ENV_REFERENCE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
31301
31453
|
var WASM_MAGIC = [0, 97, 115, 109];
|
|
31302
31454
|
var SHEBANG_MAX = 256;
|
|
@@ -31364,6 +31516,21 @@ function packageRootOf(path, roots) {
|
|
|
31364
31516
|
}
|
|
31365
31517
|
return void 0;
|
|
31366
31518
|
}
|
|
31519
|
+
function planFiles(planned) {
|
|
31520
|
+
const { target } = planned;
|
|
31521
|
+
const files = [
|
|
31522
|
+
target.glue,
|
|
31523
|
+
target.wasm,
|
|
31524
|
+
target.imports,
|
|
31525
|
+
target.copy,
|
|
31526
|
+
...(target.variants ?? []).map((variant) => variant.wasm),
|
|
31527
|
+
...planned.sources ?? []
|
|
31528
|
+
];
|
|
31529
|
+
return files.filter((file) => file !== void 0);
|
|
31530
|
+
}
|
|
31531
|
+
function sameList(a, b) {
|
|
31532
|
+
return a.length === b.length && a.every((item, i) => item === b[i]);
|
|
31533
|
+
}
|
|
31367
31534
|
function modulePath(glue) {
|
|
31368
31535
|
return glue.endsWith(".js") ? `${glue.slice(0, -3)}.wasm` : `${glue}.wasm`;
|
|
31369
31536
|
}
|
|
@@ -31537,6 +31704,12 @@ var Launcher = class {
|
|
|
31537
31704
|
sudoer;
|
|
31538
31705
|
jobs = new JobTable();
|
|
31539
31706
|
locks;
|
|
31707
|
+
packageLocks;
|
|
31708
|
+
swaps = new PackageSwaps(
|
|
31709
|
+
(path) => this.packageRootIs(path),
|
|
31710
|
+
(root) => this.packageLocks.holding(root),
|
|
31711
|
+
() => this.resetCatalogs()
|
|
31712
|
+
);
|
|
31540
31713
|
fifos = new FifoTable();
|
|
31541
31714
|
memories;
|
|
31542
31715
|
sems = new SemTable();
|
|
@@ -31609,6 +31782,7 @@ var Launcher = class {
|
|
|
31609
31782
|
this.memories = memoriesOf(options.wasmMemories);
|
|
31610
31783
|
this.rootFs = options.fs;
|
|
31611
31784
|
this.locks = kernelLocks(options.fs.rootName, this.flushingPeers(options.fs));
|
|
31785
|
+
this.packageLocks = new PackageLocks(options.packageLocks ?? META_DB);
|
|
31612
31786
|
this.dac = this.usersMode === "off" ? void 0 : new Dac(this.usersMode, options.onDenial);
|
|
31613
31787
|
if (this.dac) this.wireDac(this.dac);
|
|
31614
31788
|
this.clipboard = new ClipboardBroker(
|
|
@@ -31702,15 +31876,7 @@ var Launcher = class {
|
|
|
31702
31876
|
this.nodes.keepsOnDisk = true;
|
|
31703
31877
|
this.openFiles.add(this.nodes);
|
|
31704
31878
|
options.fs.onPeer?.(() => this.flushOpen());
|
|
31705
|
-
options.fs.remoteChanges?.((change) =>
|
|
31706
|
-
this.held.doubt(change.paths, change.moved?.to);
|
|
31707
|
-
if (change.moved) this.moved(change.moved.from, change.moved.to);
|
|
31708
|
-
this.changes.flush();
|
|
31709
|
-
this.cwds.touched(change.paths, change.trees);
|
|
31710
|
-
this.rewritten(change.paths, change.trees);
|
|
31711
|
-
this.watchers.heard(change.content ? "change" : "rename", change.paths);
|
|
31712
|
-
this.watchers.heard("rename", change.trees ?? []);
|
|
31713
|
-
});
|
|
31879
|
+
options.fs.remoteChanges?.((change) => this.remoteChanged(change));
|
|
31714
31880
|
const holders = [this.held, this.openFiles];
|
|
31715
31881
|
options.fs.heldBy?.(
|
|
31716
31882
|
(dir) => holders.flatMap((set3) => [...set3].flatMap((holder) => [...holder.held()])).filter((p) => p.startsWith(`${dir}/`) && this.mounts.locate(p) === void 0)
|
|
@@ -31834,7 +32000,7 @@ var Launcher = class {
|
|
|
31834
32000
|
commands(scope = "") {
|
|
31835
32001
|
let found = this.catalogs.get(scope);
|
|
31836
32002
|
if (!found) {
|
|
31837
|
-
found = this.trustedAppended().then(async (appended2) => {
|
|
32003
|
+
found = this.swaps.settled().then(() => this.trustedAppended()).then(async (appended2) => {
|
|
31838
32004
|
const tiers = await this.tiers(scope, appended2);
|
|
31839
32005
|
const refused3 = [];
|
|
31840
32006
|
const commands = await scanCommands(
|
|
@@ -31920,6 +32086,26 @@ var Launcher = class {
|
|
|
31920
32086
|
}
|
|
31921
32087
|
return trusted;
|
|
31922
32088
|
}
|
|
32089
|
+
remoteChanged(change) {
|
|
32090
|
+
this.held.doubt(change.paths, change.moved?.to);
|
|
32091
|
+
if (change.moved) this.moved(change.moved.from, change.moved.to);
|
|
32092
|
+
this.changes.flush();
|
|
32093
|
+
this.cwds.touched(change.paths, change.trees);
|
|
32094
|
+
this.rewritten(change.paths, change.trees);
|
|
32095
|
+
this.watchers.heard(change.content ? "change" : "rename", change.paths);
|
|
32096
|
+
this.watchers.heard("rename", change.trees ?? []);
|
|
32097
|
+
if (change.outside && this.catalogChanged([...change.paths, ...change.trees ?? []])) {
|
|
32098
|
+
this.resetCatalogs();
|
|
32099
|
+
}
|
|
32100
|
+
}
|
|
32101
|
+
catalogChanged(paths) {
|
|
32102
|
+
const roots = [this.modulesDir, this.pnpmHome, ...this.appended].map(normalizePath);
|
|
32103
|
+
return paths.map(normalizePath).some(
|
|
32104
|
+
(at) => at === "/" || NODE_MODULES.test(at) || roots.some(
|
|
32105
|
+
(root) => at === root || at.startsWith(`${root}/`) || root.startsWith(`${at}/`)
|
|
32106
|
+
)
|
|
32107
|
+
);
|
|
32108
|
+
}
|
|
31923
32109
|
resetCatalogs() {
|
|
31924
32110
|
this.catalogs.clear();
|
|
31925
32111
|
this.ownCatalogs.clear();
|
|
@@ -32320,7 +32506,11 @@ var Launcher = class {
|
|
|
32320
32506
|
secrets.push({ name: name2, value: value2, placeholder });
|
|
32321
32507
|
}
|
|
32322
32508
|
const scrub = scrubberOf(secrets);
|
|
32323
|
-
|
|
32509
|
+
const recheck = async (next3) => {
|
|
32510
|
+
const same3 = sameList(planFiles(next3), planFiles(planned)) && sameList(await this.interpreterChain(next3, booked.cwd, scope), interpreters) && (this.usersMode === "enforce" && await this.trustedFiles(next3, req.file, booked.cwd, scope)) === trusted;
|
|
32511
|
+
if (!same3) throw new SpawnError("EACCES");
|
|
32512
|
+
};
|
|
32513
|
+
return { env, pid, cwd: booked.cwd, ...scrub ? { scrub } : {}, recheck };
|
|
32324
32514
|
}
|
|
32325
32515
|
async interpreterChain(planned, cwd, scope) {
|
|
32326
32516
|
const out = [];
|
|
@@ -32605,25 +32795,16 @@ var Launcher = class {
|
|
|
32605
32795
|
async launch(asked, req) {
|
|
32606
32796
|
const cwd = await physicalPathAsync(this.base, req.cwd);
|
|
32607
32797
|
const seen = { ...req.env, HOSTNAME: this.hostname, cwd };
|
|
32608
|
-
const env = { ...expandDefaults(asked.target.env, seen), ...req.env };
|
|
32609
|
-
for (const key of asked.target.unset ?? []) delete env[key];
|
|
32610
|
-
delete env[TICKET_ENV];
|
|
32611
|
-
const own = env.HOSTNAME;
|
|
32612
|
-
if (asked.target.abi === "wasi") env.HOSTNAME = this.hostname;
|
|
32613
|
-
const planned = chosen2(asked, env);
|
|
32614
|
-
const { target, args } = planned;
|
|
32615
|
-
let program;
|
|
32616
|
-
let exeId;
|
|
32617
32798
|
await this.pnpmReady();
|
|
32799
|
+
let loaded;
|
|
32618
32800
|
try {
|
|
32619
|
-
|
|
32620
|
-
if (this.integrity) await this.checkedSources(planned, caller);
|
|
32621
|
-
[program, exeId] = await this.loaded(target, env, caller);
|
|
32622
|
-
if (readsEtcHostname(program)) setOrDrop(env, "HOSTNAME", own);
|
|
32801
|
+
loaded = await this.loadedUnder(asked, (planned2) => this.loadPlanned(planned2, req, seen));
|
|
32623
32802
|
} catch (err) {
|
|
32624
32803
|
await req.fds.closeAll();
|
|
32625
32804
|
throw err;
|
|
32626
32805
|
}
|
|
32806
|
+
const { planned, env, program, exeId } = loaded;
|
|
32807
|
+
const { target, args } = planned;
|
|
32627
32808
|
const done5 = this.heldUrl(program);
|
|
32628
32809
|
try {
|
|
32629
32810
|
const cwdSlot = await this.cwds.hold(cwd, req.cwdFrom);
|
|
@@ -32651,6 +32832,59 @@ var Launcher = class {
|
|
|
32651
32832
|
throw err;
|
|
32652
32833
|
}
|
|
32653
32834
|
}
|
|
32835
|
+
async loadPlanned(asked, req, seen) {
|
|
32836
|
+
const env = { ...expandDefaults(asked.target.env, seen), ...req.env };
|
|
32837
|
+
for (const key of asked.target.unset ?? []) delete env[key];
|
|
32838
|
+
delete env[TICKET_ENV];
|
|
32839
|
+
const own = env.HOSTNAME;
|
|
32840
|
+
if (asked.target.abi === "wasi") env.HOSTNAME = this.hostname;
|
|
32841
|
+
const planned = chosen2(asked, env);
|
|
32842
|
+
const caller = { pid: req.ppid ?? 0, uid: req.cred.euid, tag: req.tags?.[0] };
|
|
32843
|
+
if (this.integrity) await this.checkedSources(planned, caller);
|
|
32844
|
+
const [program, exeId] = await this.loaded(planned.target, env, caller);
|
|
32845
|
+
if (readsEtcHostname(program)) setOrDrop(env, "HOSTNAME", own);
|
|
32846
|
+
return { planned, env, program, exeId };
|
|
32847
|
+
}
|
|
32848
|
+
packageRootIs(path) {
|
|
32849
|
+
const at = normalizePath(path);
|
|
32850
|
+
const within10 = `${at}/`;
|
|
32851
|
+
const roots = [this.modulesDir, ...this.appended];
|
|
32852
|
+
const root = PACKAGE_ROOT.exec(within10)?.[1] ?? packageRootOf(within10, roots);
|
|
32853
|
+
return root === at;
|
|
32854
|
+
}
|
|
32855
|
+
packageRoots(planned) {
|
|
32856
|
+
const packages2 = [this.modulesDir, ...this.appended];
|
|
32857
|
+
const roots = /* @__PURE__ */ new Set();
|
|
32858
|
+
for (const file of planFiles(planned)) {
|
|
32859
|
+
if (!file.startsWith("/")) continue;
|
|
32860
|
+
const at = normalizePath(file);
|
|
32861
|
+
const root = PACKAGE_ROOT.exec(at)?.[1] ?? packageRootOf(at, packages2);
|
|
32862
|
+
if (root !== void 0 && root !== at) roots.add(root);
|
|
32863
|
+
}
|
|
32864
|
+
return [...roots].sort();
|
|
32865
|
+
}
|
|
32866
|
+
async loadedUnder(asked, load) {
|
|
32867
|
+
const { replan, recheck } = asked;
|
|
32868
|
+
let planned = asked;
|
|
32869
|
+
let roots = this.packageRoots(planned);
|
|
32870
|
+
let stale = false;
|
|
32871
|
+
for (; ; ) {
|
|
32872
|
+
const held = roots;
|
|
32873
|
+
const done5 = await this.packageLocks.loading(held, async (waited) => {
|
|
32874
|
+
if (!waited && !stale) return { value: await load(planned) };
|
|
32875
|
+
this.rootFs.refresh?.(held);
|
|
32876
|
+
this.resetCatalogs();
|
|
32877
|
+
if (replan) planned = await replan() ?? planned;
|
|
32878
|
+
await recheck?.(planned);
|
|
32879
|
+
const now = this.packageRoots(planned);
|
|
32880
|
+
if (now.every((root) => held.includes(root))) return { value: await load(planned) };
|
|
32881
|
+
roots = [.../* @__PURE__ */ new Set([...held, ...now])].sort();
|
|
32882
|
+
stale = true;
|
|
32883
|
+
return void 0;
|
|
32884
|
+
});
|
|
32885
|
+
if (done5) return done5.value;
|
|
32886
|
+
}
|
|
32887
|
+
}
|
|
32654
32888
|
groupSession(pgid) {
|
|
32655
32889
|
return this.jobs.sessionOf(pgid);
|
|
32656
32890
|
}
|
|
@@ -32803,6 +33037,7 @@ var Launcher = class {
|
|
|
32803
33037
|
opfsOps: this.rootFs.opfsOps?.() ?? 0,
|
|
32804
33038
|
cwdChecks: this.cwds.checks,
|
|
32805
33039
|
renameAcks: this.rootFs.renameWaits?.(),
|
|
33040
|
+
swaps: this.swaps.counts(),
|
|
32806
33041
|
staleFds: staleFdCount(),
|
|
32807
33042
|
fileIds: this.rootFs.fileIdWrites?.() ?? 0,
|
|
32808
33043
|
holds: this.rootFs.holdCounts?.()
|
|
@@ -33059,6 +33294,7 @@ var Launcher = class {
|
|
|
33059
33294
|
spawner(ppid, report) {
|
|
33060
33295
|
return async (req, fds, grant) => {
|
|
33061
33296
|
const booked = this.takeTicket(req);
|
|
33297
|
+
await this.swaps.settled();
|
|
33062
33298
|
if (grant && !await this.grantedCwd(grant.caller, req.cwd)) {
|
|
33063
33299
|
await fds.closeAll();
|
|
33064
33300
|
throw new SpawnError("EACCES");
|
|
@@ -33079,7 +33315,7 @@ var Launcher = class {
|
|
|
33079
33315
|
const scope = grant ? "" : await this.scopeOf(cred.euid);
|
|
33080
33316
|
const file = booked === void 0 ? req.file : await this.ticketFile(req, fds);
|
|
33081
33317
|
const planned = await this.checkedPlan({ ...req, file }, { ppid, cred, scope }, fds);
|
|
33082
|
-
const redeemed = await this.redeemed(
|
|
33318
|
+
const { recheck, ...redeemed } = await this.redeemed(
|
|
33083
33319
|
{ ...req, file },
|
|
33084
33320
|
{ ppid, cred, scope, booked },
|
|
33085
33321
|
planned,
|
|
@@ -33087,7 +33323,9 @@ var Launcher = class {
|
|
|
33087
33323
|
);
|
|
33088
33324
|
const exec = req.exec ? { exec: true } : {};
|
|
33089
33325
|
const deciding = req.exec ? void 0 : this.undecided(ppid);
|
|
33090
|
-
const
|
|
33326
|
+
const replan = () => this.planOrSearch({ ...req, file }, { ppid, cred, scope });
|
|
33327
|
+
const again = { ...planned, replan, recheck };
|
|
33328
|
+
const handle = await this.launch(again, {
|
|
33091
33329
|
...deciding ? { decided: deciding.promise } : {},
|
|
33092
33330
|
cwd: req.cwd,
|
|
33093
33331
|
cwdFrom: inheritedCwd(req.chdir, this.cwdSlots.get(ppid)),
|
|
@@ -33969,10 +34207,12 @@ var Launcher = class {
|
|
|
33969
34207
|
nodes.changed = (path) => this.changes.publish(path);
|
|
33970
34208
|
nodes.movedAway = (from, to) => this.moved(from, to, nodes);
|
|
33971
34209
|
nodes.dirtied = (delta) => this.changes.dirtied(delta);
|
|
33972
|
-
|
|
34210
|
+
const kept = keepingOpen(fs, nodes, (path) => this.changes.publish(path));
|
|
34211
|
+
return this.swaps.wrap(unlinked.wrap(kept));
|
|
33973
34212
|
}
|
|
33974
34213
|
async starting(argv, dir, account, tags, base) {
|
|
33975
34214
|
const tag = tags?.[0];
|
|
34215
|
+
await this.swaps.settled();
|
|
33976
34216
|
this.resetCatalogs();
|
|
33977
34217
|
const scope = account.uid === 0 ? "" : pnpmHomeOf(account, this.pnpmHome);
|
|
33978
34218
|
const start2 = dir ?? "/";
|
|
@@ -33981,9 +34221,13 @@ var Launcher = class {
|
|
|
33981
34221
|
const file = await this.execFile(argv[0] ?? "", cwd, this.execGuard(credOf(account), 0, tag));
|
|
33982
34222
|
if (!await this.base.exists(cwd))
|
|
33983
34223
|
await this.stackFor(tags, base).fs.mkdir(cwd, { recursive: true });
|
|
33984
|
-
const
|
|
33985
|
-
|
|
33986
|
-
|
|
34224
|
+
const plan = async () => {
|
|
34225
|
+
const found = await this.plan(file, argv, cwd, scope);
|
|
34226
|
+
await this.mayExec(credOf(account), { file, cwd, pid: 0, tag }, found);
|
|
34227
|
+
return found;
|
|
34228
|
+
};
|
|
34229
|
+
const planned = await plan();
|
|
34230
|
+
return { cwd, file, planned: planned && { ...planned, replan: plan } };
|
|
33987
34231
|
}
|
|
33988
34232
|
async openTerminal(argv, options) {
|
|
33989
34233
|
const tagged = tagsOption(options);
|
|
@@ -34707,6 +34951,7 @@ function serveKernel(port, deps) {
|
|
|
34707
34951
|
await fs.reconcile();
|
|
34708
34952
|
const started = new Launcher({
|
|
34709
34953
|
fs,
|
|
34954
|
+
...name2 ? { packageLocks: name2 } : {},
|
|
34710
34955
|
...workers(deps),
|
|
34711
34956
|
...req.modules ? { modules: req.modules } : {},
|
|
34712
34957
|
...req.commands ? { commands: req.commands } : {},
|