@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/node.js
CHANGED
|
@@ -3695,7 +3695,7 @@ function satisfies(version, range2) {
|
|
|
3695
3695
|
}
|
|
3696
3696
|
|
|
3697
3697
|
// src/version.ts
|
|
3698
|
-
var KERNEL_VERSION = true ? "1.
|
|
3698
|
+
var KERNEL_VERSION = true ? "1.168.1" : "0.0.0-dev";
|
|
3699
3699
|
var OS_RELEASE = "6.0.0-slicc";
|
|
3700
3700
|
function procVersion() {
|
|
3701
3701
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -3778,8 +3778,8 @@ function abiOf(raw2, fallback) {
|
|
|
3778
3778
|
const abi = raw2 ?? fallback;
|
|
3779
3779
|
return abi === "emscripten" || abi === "wasi" || abi === "js" ? abi : void 0;
|
|
3780
3780
|
}
|
|
3781
|
-
function commandOf(pkg, name2, raw2, packageAbi,
|
|
3782
|
-
const withEnv = envFields({ ...
|
|
3781
|
+
function commandOf(pkg, name2, raw2, packageAbi, shared2) {
|
|
3782
|
+
const withEnv = envFields({ ...shared2, ...envOf(pkg, raw2.env) });
|
|
3783
3783
|
const script = inside(pkg, raw2.script);
|
|
3784
3784
|
if (script) {
|
|
3785
3785
|
return { name: name2, abi: packageAbi, glue: script, wasm: script, argv0: name2, script, ...withEnv };
|
|
@@ -3829,13 +3829,13 @@ function commandsOf(pkg, manifest) {
|
|
|
3829
3829
|
const packageAbi = abiOf(slicc.abi, "emscripten");
|
|
3830
3830
|
const entries = slicc.commands;
|
|
3831
3831
|
if (!packageAbi || !entries || typeof entries !== "object") return [];
|
|
3832
|
-
const
|
|
3832
|
+
const shared2 = envOf(pkg, slicc.env);
|
|
3833
3833
|
const out = [];
|
|
3834
3834
|
for (const [name2, raw2] of Object.entries(entries)) {
|
|
3835
3835
|
if (!commandName(name2) || !raw2 || typeof raw2 !== "object") {
|
|
3836
3836
|
continue;
|
|
3837
3837
|
}
|
|
3838
|
-
const command = commandOf(pkg, name2, raw2, packageAbi,
|
|
3838
|
+
const command = commandOf(pkg, name2, raw2, packageAbi, shared2);
|
|
3839
3839
|
if (command) out.push(command);
|
|
3840
3840
|
}
|
|
3841
3841
|
return out;
|
|
@@ -5009,8 +5009,8 @@ var UnlinkedKeeper = class {
|
|
|
5009
5009
|
void peers.ask(tab, { kept: { items: [], paths } }, PEER_RM_MS);
|
|
5010
5010
|
throw fsError("EBUSY", `${target}: open in another tab that did not answer`);
|
|
5011
5011
|
}
|
|
5012
|
-
const { whole, sends, shared } = await this.setAside(target, asked);
|
|
5013
|
-
return { whole, undoing: (op) => this.undoing(op, peers, sends, heard,
|
|
5012
|
+
const { whole, sends, shared: shared2 } = await this.setAside(target, asked);
|
|
5013
|
+
return { whole, undoing: (op) => this.undoing(op, peers, sends, heard, shared2) };
|
|
5014
5014
|
}
|
|
5015
5015
|
async setAside(target, asked) {
|
|
5016
5016
|
const mine = this.heldWithin(target);
|
|
@@ -5018,25 +5018,25 @@ var UnlinkedKeeper = class {
|
|
|
5018
5018
|
for (const { holders } of asked)
|
|
5019
5019
|
for (const { path } of holders) tabsOf.set(path, (tabsOf.get(path) ?? 0) + 1);
|
|
5020
5020
|
const done4 = /* @__PURE__ */ new Map();
|
|
5021
|
-
const
|
|
5021
|
+
const shared2 = [];
|
|
5022
5022
|
const sends = [];
|
|
5023
5023
|
for (const { tab, holders, paths } of asked) {
|
|
5024
5024
|
const items = [];
|
|
5025
5025
|
for (const holder of holders) {
|
|
5026
5026
|
if (!done4.has(holder.path)) {
|
|
5027
5027
|
const many = mine.has(holder.path) || (tabsOf.get(holder.path) ?? 0) > 1;
|
|
5028
|
-
done4.set(holder.path, await this.asideOne(holder, many, mine,
|
|
5028
|
+
done4.set(holder.path, await this.asideOne(holder, many, mine, shared2));
|
|
5029
5029
|
}
|
|
5030
5030
|
items.push({ path: holder.path, hidden: done4.get(holder.path), fid: holder.fid });
|
|
5031
5031
|
}
|
|
5032
5032
|
sends.push({ tab, items, paths });
|
|
5033
5033
|
}
|
|
5034
|
-
return { whole: done4.get(target) !== void 0, sends, shared };
|
|
5034
|
+
return { whole: done4.get(target) !== void 0, sends, shared: shared2 };
|
|
5035
5035
|
}
|
|
5036
|
-
async asideOne(holder, many, mine,
|
|
5036
|
+
async asideOne(holder, many, mine, shared2) {
|
|
5037
5037
|
if (!many) return this.asideFor(holder.path, holder.instance);
|
|
5038
5038
|
const one = await this.sharedAside(holder.path, mine);
|
|
5039
|
-
if (one)
|
|
5039
|
+
if (one) shared2.push(one);
|
|
5040
5040
|
return one?.hidden;
|
|
5041
5041
|
}
|
|
5042
5042
|
async sharedAside(path, mine) {
|
|
@@ -5081,16 +5081,16 @@ var UnlinkedKeeper = class {
|
|
|
5081
5081
|
sharedLocks() {
|
|
5082
5082
|
return this.locks;
|
|
5083
5083
|
}
|
|
5084
|
-
async undoing(op, peers, sends, heard,
|
|
5084
|
+
async undoing(op, peers, sends, heard, shared2 = []) {
|
|
5085
5085
|
let failed3;
|
|
5086
5086
|
let out;
|
|
5087
5087
|
try {
|
|
5088
5088
|
out = await op();
|
|
5089
5089
|
} catch (err) {
|
|
5090
5090
|
failed3 = err ?? new Error("failed");
|
|
5091
|
-
await this.rollBackAsides(sends,
|
|
5091
|
+
await this.rollBackAsides(sends, shared2);
|
|
5092
5092
|
}
|
|
5093
|
-
const hiddenShared = new Set(
|
|
5093
|
+
const hiddenShared = new Set(shared2.map((one) => one.hidden));
|
|
5094
5094
|
const answers2 = sends.map(({ tab, items, paths }) => {
|
|
5095
5095
|
const keeps = items.some((item) => item.hidden && hiddenShared.has(item.hidden));
|
|
5096
5096
|
return {
|
|
@@ -5101,7 +5101,7 @@ var UnlinkedKeeper = class {
|
|
|
5101
5101
|
await Promise.all(
|
|
5102
5102
|
answers2.map(({ told }, i) => heard[i] ? Promise.race([told, delay(PEER_RM_MS)]) : void 0)
|
|
5103
5103
|
);
|
|
5104
|
-
for (const one of
|
|
5104
|
+
for (const one of shared2) {
|
|
5105
5105
|
const waits = answers2.filter(
|
|
5106
5106
|
({ keeps }, i) => keeps && sends[i]?.items.some((item) => item.hidden === one.hidden)
|
|
5107
5107
|
);
|
|
@@ -5111,7 +5111,7 @@ var UnlinkedKeeper = class {
|
|
|
5111
5111
|
if (failed3 !== void 0) throw failed3;
|
|
5112
5112
|
return out;
|
|
5113
5113
|
}
|
|
5114
|
-
async rollBackAsides(sends,
|
|
5114
|
+
async rollBackAsides(sends, shared2) {
|
|
5115
5115
|
const back = /* @__PURE__ */ new Map();
|
|
5116
5116
|
for (const item of sends.flatMap((send2) => send2.items)) {
|
|
5117
5117
|
const { hidden, path } = item;
|
|
@@ -5119,7 +5119,7 @@ var UnlinkedKeeper = class {
|
|
|
5119
5119
|
if (!back.has(hidden)) back.set(hidden, await this.moveBack(hidden, path));
|
|
5120
5120
|
if (back.get(hidden)) item.hidden = void 0;
|
|
5121
5121
|
}
|
|
5122
|
-
for (const { hidden, path, local: local2, file } of
|
|
5122
|
+
for (const { hidden, path, local: local2, file } of shared2) {
|
|
5123
5123
|
if (!back.get(hidden) || !file) continue;
|
|
5124
5124
|
for (const holder of local2) {
|
|
5125
5125
|
holder.unkeep(path, file);
|
|
@@ -7475,6 +7475,142 @@ var Integrity = class {
|
|
|
7475
7475
|
}
|
|
7476
7476
|
};
|
|
7477
7477
|
|
|
7478
|
+
// src/fs/path-map.ts
|
|
7479
|
+
function parentOf4(path) {
|
|
7480
|
+
if (path === "/" || path === "") return void 0;
|
|
7481
|
+
const at = path.lastIndexOf("/");
|
|
7482
|
+
return at <= 0 ? "/" : path.slice(0, at);
|
|
7483
|
+
}
|
|
7484
|
+
var PathMap = class {
|
|
7485
|
+
values = /* @__PURE__ */ new Map();
|
|
7486
|
+
children = /* @__PURE__ */ new Map();
|
|
7487
|
+
get size() {
|
|
7488
|
+
return this.values.size;
|
|
7489
|
+
}
|
|
7490
|
+
has(path) {
|
|
7491
|
+
return this.values.has(path);
|
|
7492
|
+
}
|
|
7493
|
+
get(path) {
|
|
7494
|
+
return this.values.get(path);
|
|
7495
|
+
}
|
|
7496
|
+
keys() {
|
|
7497
|
+
return this.values.keys();
|
|
7498
|
+
}
|
|
7499
|
+
set(path, value2) {
|
|
7500
|
+
if (!this.values.has(path)) this.link(path);
|
|
7501
|
+
this.values.set(path, value2);
|
|
7502
|
+
return this;
|
|
7503
|
+
}
|
|
7504
|
+
delete(path) {
|
|
7505
|
+
if (!this.values.delete(path)) return false;
|
|
7506
|
+
this.prune(path);
|
|
7507
|
+
return true;
|
|
7508
|
+
}
|
|
7509
|
+
subtree(root) {
|
|
7510
|
+
const out = [];
|
|
7511
|
+
const stack = [root];
|
|
7512
|
+
for (let path = stack.pop(); path !== void 0; path = stack.pop()) {
|
|
7513
|
+
if (this.values.has(path)) out.push(path);
|
|
7514
|
+
const below = this.children.get(path);
|
|
7515
|
+
if (below) for (const child of below) stack.push(child);
|
|
7516
|
+
}
|
|
7517
|
+
return out;
|
|
7518
|
+
}
|
|
7519
|
+
entries() {
|
|
7520
|
+
return this.values.entries();
|
|
7521
|
+
}
|
|
7522
|
+
deleteTree(root) {
|
|
7523
|
+
const stack = [root];
|
|
7524
|
+
for (let path = stack.pop(); path !== void 0; path = stack.pop()) {
|
|
7525
|
+
this.values.delete(path);
|
|
7526
|
+
const below = this.children.get(path);
|
|
7527
|
+
if (below) for (const child of below) stack.push(child);
|
|
7528
|
+
this.children.delete(path);
|
|
7529
|
+
}
|
|
7530
|
+
this.prune(root);
|
|
7531
|
+
}
|
|
7532
|
+
clear() {
|
|
7533
|
+
this.values.clear();
|
|
7534
|
+
this.children.clear();
|
|
7535
|
+
}
|
|
7536
|
+
link(path) {
|
|
7537
|
+
for (let child = path, parent = parentOf4(path); parent !== void 0; ) {
|
|
7538
|
+
const set3 = this.children.get(parent);
|
|
7539
|
+
if (set3?.has(child)) return;
|
|
7540
|
+
if (set3) set3.add(child);
|
|
7541
|
+
else this.children.set(parent, /* @__PURE__ */ new Set([child]));
|
|
7542
|
+
child = parent;
|
|
7543
|
+
parent = parentOf4(parent);
|
|
7544
|
+
}
|
|
7545
|
+
}
|
|
7546
|
+
prune(path) {
|
|
7547
|
+
for (let child = path, parent = parentOf4(path); parent !== void 0; ) {
|
|
7548
|
+
if (this.values.has(child) || this.children.has(child)) return;
|
|
7549
|
+
const set3 = this.children.get(parent);
|
|
7550
|
+
set3?.delete(child);
|
|
7551
|
+
if (set3 && set3.size > 0) return;
|
|
7552
|
+
this.children.delete(parent);
|
|
7553
|
+
child = parent;
|
|
7554
|
+
parent = parentOf4(parent);
|
|
7555
|
+
}
|
|
7556
|
+
}
|
|
7557
|
+
};
|
|
7558
|
+
|
|
7559
|
+
// src/fs/meta.ts
|
|
7560
|
+
var META_DB = "slicc-kernel";
|
|
7561
|
+
function parentOf5(path) {
|
|
7562
|
+
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
7563
|
+
}
|
|
7564
|
+
function moved(entry, path) {
|
|
7565
|
+
return entry.link === void 0 ? { ...entry, path } : { ...entry, path, dir: parentOf5(path) };
|
|
7566
|
+
}
|
|
7567
|
+
function under2(path, root) {
|
|
7568
|
+
return path === root || path.startsWith(`${root}/`);
|
|
7569
|
+
}
|
|
7570
|
+
var MemoryMeta = class {
|
|
7571
|
+
entries = new PathMap();
|
|
7572
|
+
async get(paths) {
|
|
7573
|
+
return paths.map((path) => this.entries.get(path));
|
|
7574
|
+
}
|
|
7575
|
+
async fresh(paths) {
|
|
7576
|
+
return this.get(paths);
|
|
7577
|
+
}
|
|
7578
|
+
async update(path, change) {
|
|
7579
|
+
this.set(path, change(this.entries.get(path)));
|
|
7580
|
+
}
|
|
7581
|
+
set(path, entry) {
|
|
7582
|
+
if (entry) this.entries.set(path, entry);
|
|
7583
|
+
else this.entries.delete(path);
|
|
7584
|
+
}
|
|
7585
|
+
async move(from, to, root, left) {
|
|
7586
|
+
await this.remove([to]);
|
|
7587
|
+
const carried = this.entries.subtree(from).map((path) => this.entries.get(path));
|
|
7588
|
+
for (const entry of carried) this.entries.delete(entry.path);
|
|
7589
|
+
for (const entry of carried) {
|
|
7590
|
+
const path = to + entry.path.slice(from.length);
|
|
7591
|
+
if (path !== to) this.entries.set(path, moved(entry, path));
|
|
7592
|
+
}
|
|
7593
|
+
this.entries.set(to, moved(root(carried.find((entry) => entry.path === from)), to));
|
|
7594
|
+
if (left) this.entries.set(from, left);
|
|
7595
|
+
}
|
|
7596
|
+
async remove(paths, left) {
|
|
7597
|
+
for (const path of paths) this.entries.deleteTree(path);
|
|
7598
|
+
if (left) this.entries.set(left.path, left);
|
|
7599
|
+
}
|
|
7600
|
+
absent(path) {
|
|
7601
|
+
return !this.entries.has(path);
|
|
7602
|
+
}
|
|
7603
|
+
async links(dir) {
|
|
7604
|
+
return [...this.entries.entries()].map(([, e]) => e).filter((entry) => entry.dir === dir);
|
|
7605
|
+
}
|
|
7606
|
+
async under(path) {
|
|
7607
|
+
return [...this.entries.entries()].map(([, e]) => e).filter((entry) => under2(entry.path, path));
|
|
7608
|
+
}
|
|
7609
|
+
async all() {
|
|
7610
|
+
return [...this.entries.entries()].map(([, e]) => e);
|
|
7611
|
+
}
|
|
7612
|
+
};
|
|
7613
|
+
|
|
7478
7614
|
// src/fs/physical-path.ts
|
|
7479
7615
|
var MAX_HOPS3 = 40;
|
|
7480
7616
|
function start(path) {
|
|
@@ -7526,11 +7662,11 @@ async function physicalPathAsync(fs, path) {
|
|
|
7526
7662
|
var WATCH_NOTES_LIMIT = 1e3;
|
|
7527
7663
|
var baseOf2 = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
7528
7664
|
var WATCH_BATCH_LIMIT = 1e3;
|
|
7529
|
-
var
|
|
7530
|
-
var
|
|
7665
|
+
var under3 = (path, dir) => dir === "/" || path.startsWith(`${dir}/`);
|
|
7666
|
+
var parentOf6 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
7531
7667
|
function touches(watcher, changed) {
|
|
7532
7668
|
return watcher.paths.some(
|
|
7533
|
-
(watched) => changed === watched ||
|
|
7669
|
+
(watched) => changed === watched || under3(watched, changed) || (watcher.recursive ? under3(changed, watched) : parentOf6(changed) === watched)
|
|
7534
7670
|
);
|
|
7535
7671
|
}
|
|
7536
7672
|
var REALS_KEPT = 4096;
|
|
@@ -7553,13 +7689,13 @@ function route(watch, type, path, seq2) {
|
|
|
7553
7689
|
for (const root of watch.roots) if (routed(watch, root, type, path, seq2)) return;
|
|
7554
7690
|
}
|
|
7555
7691
|
function routed(watch, root, type, path, seq2) {
|
|
7556
|
-
if (path === root || type === "rename" && root !== "/" &&
|
|
7692
|
+
if (path === root || type === "rename" && root !== "/" && under3(root, path)) {
|
|
7557
7693
|
noted(watch, { type, filename: watch.names.get(root) ?? baseOf2(root), seq: seq2 });
|
|
7558
7694
|
if (type === "rename") noted(watch, { ended: true, seq: seq2 });
|
|
7559
7695
|
return true;
|
|
7560
7696
|
}
|
|
7561
|
-
if (
|
|
7562
|
-
else if (watch.recursive &&
|
|
7697
|
+
if (parentOf6(path) === root) noted(watch, { type, filename: baseOf2(path), seq: seq2 });
|
|
7698
|
+
else if (watch.recursive && under3(path, root)) {
|
|
7563
7699
|
noted(watch, { type, filename: path.slice(root === "/" ? 1 : root.length + 1), seq: seq2 });
|
|
7564
7700
|
} else return false;
|
|
7565
7701
|
return true;
|
|
@@ -7643,7 +7779,7 @@ var FsWatchers = class {
|
|
|
7643
7779
|
covers(path) {
|
|
7644
7780
|
for (const watch of this.typed) {
|
|
7645
7781
|
for (const root of watch.roots) {
|
|
7646
|
-
if (path === root ||
|
|
7782
|
+
if (path === root || parentOf6(path) === root || watch.recursive && under3(path, root))
|
|
7647
7783
|
return true;
|
|
7648
7784
|
}
|
|
7649
7785
|
}
|
|
@@ -7700,7 +7836,7 @@ var FsWatchers = class {
|
|
|
7700
7836
|
const at = normalizePath(path);
|
|
7701
7837
|
const seq2 = ++this.seq;
|
|
7702
7838
|
for (const watch of [...this.typed]) {
|
|
7703
|
-
if (type === "rename" && watch.roots.some((root) => at === root ||
|
|
7839
|
+
if (type === "rename" && watch.roots.some((root) => at === root || under3(root, at)))
|
|
7704
7840
|
continue;
|
|
7705
7841
|
if (type === "change" && watch.directory && watch.roots.includes(at)) continue;
|
|
7706
7842
|
route(watch, type, at, seq2);
|
|
@@ -8932,7 +9068,7 @@ var FifoTable = class {
|
|
|
8932
9068
|
// src/kernel/held-cwd.ts
|
|
8933
9069
|
var CWD_SLOTS = 1024;
|
|
8934
9070
|
var UNTRACKED = CWD_SLOTS - 1;
|
|
8935
|
-
var
|
|
9071
|
+
var under4 = (path, changed) => changed === "/" || path === changed || path.startsWith(`${changed}/`);
|
|
8936
9072
|
var CwdTable = class {
|
|
8937
9073
|
sab = new SharedArrayBuffer(CWD_SLOTS * 4);
|
|
8938
9074
|
view = new Int32Array(this.sab);
|
|
@@ -8945,8 +9081,8 @@ var CwdTable = class {
|
|
|
8945
9081
|
this.inodeOf = inodeOf2;
|
|
8946
9082
|
}
|
|
8947
9083
|
async hold(path, from) {
|
|
8948
|
-
const
|
|
8949
|
-
if (
|
|
9084
|
+
const shared2 = from === void 0 ? void 0 : this.held.get(from);
|
|
9085
|
+
if (shared2 && shared2.path === path) return this.share(from);
|
|
8950
9086
|
const ino = await this.inodeOf(path).catch(() => void 0);
|
|
8951
9087
|
const slot2 = this.free.pop() ?? (this.next < UNTRACKED ? this.next++ : UNTRACKED);
|
|
8952
9088
|
if (slot2 === UNTRACKED) return slot2;
|
|
@@ -8980,7 +9116,7 @@ var CwdTable = class {
|
|
|
8980
9116
|
if (this.held.size === 0) return;
|
|
8981
9117
|
for (const [slot2, held] of this.held) {
|
|
8982
9118
|
if (held.dead) continue;
|
|
8983
|
-
if (paths.some((p) =>
|
|
9119
|
+
if (paths.some((p) => under4(held.path, p)) || trees.some((t) => under4(held.path, t))) {
|
|
8984
9120
|
Atomics.add(this.view, slot2, 1);
|
|
8985
9121
|
}
|
|
8986
9122
|
}
|
|
@@ -9438,7 +9574,7 @@ var HeldPaths = class extends Map {
|
|
|
9438
9574
|
return this.revoked.has(path);
|
|
9439
9575
|
}
|
|
9440
9576
|
};
|
|
9441
|
-
var
|
|
9577
|
+
var parentOf7 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
9442
9578
|
var readonly = (mount) => mount.caps.readonly === true || mount.options.ro !== void 0;
|
|
9443
9579
|
function inodeless(mount, attr2) {
|
|
9444
9580
|
if (attr2.ino !== void 0) return false;
|
|
@@ -9738,7 +9874,7 @@ var MountTable = class {
|
|
|
9738
9874
|
for (const [key, cached] of [...mount.attrs])
|
|
9739
9875
|
if (within5(key, path) || linked2(cached.value)) mount.attrs.delete(key);
|
|
9740
9876
|
mount.lists.delete(path);
|
|
9741
|
-
mount.lists.delete(
|
|
9877
|
+
mount.lists.delete(parentOf7(path));
|
|
9742
9878
|
for (const [key, cached] of [...mount.lists])
|
|
9743
9879
|
if (within5(key, path) || cached.value.some((e) => linked2(e.attr))) mount.lists.delete(key);
|
|
9744
9880
|
}
|
|
@@ -9859,7 +9995,7 @@ var MountFs = class _MountFs {
|
|
|
9859
9995
|
const real = normalizePath(path);
|
|
9860
9996
|
if (this.at(real)) return real;
|
|
9861
9997
|
try {
|
|
9862
|
-
await this.base.stat(
|
|
9998
|
+
await this.base.stat(parentOf7(real));
|
|
9863
9999
|
return real;
|
|
9864
10000
|
} catch (err) {
|
|
9865
10001
|
const moved2 = redirectOf(err);
|
|
@@ -9901,7 +10037,7 @@ var MountFs = class _MountFs {
|
|
|
9901
10037
|
if (this.rejectLinks) throw errnoError("ELOOP", path);
|
|
9902
10038
|
if (hops >= MAX_LINKS5) throw errnoError("ELOOP", path);
|
|
9903
10039
|
const target = await found.mount.conn.call({ op: "readlink", path: found.rel });
|
|
9904
|
-
return this.follow(this.base.resolvePath(
|
|
10040
|
+
return this.follow(this.base.resolvePath(parentOf7(real), target), hops + 1, create);
|
|
9905
10041
|
}
|
|
9906
10042
|
async open(mount, rel2, write, owner, create = write) {
|
|
9907
10043
|
return await mount.conn.call({
|
|
@@ -9917,8 +10053,8 @@ var MountFs = class _MountFs {
|
|
|
9917
10053
|
async driverOwner(found, real, owner, directory) {
|
|
9918
10054
|
const { mount, rel: rel2 } = found;
|
|
9919
10055
|
if (!owner || !mount.owners || !mount.caps.owners) return void 0;
|
|
9920
|
-
const dir =
|
|
9921
|
-
const above = statOf2(await this.table.getattr(mount, dir,
|
|
10056
|
+
const dir = parentOf7(real);
|
|
10057
|
+
const above = statOf2(await this.table.getattr(mount, dir, parentOf7(rel2)), dir, mount);
|
|
9922
10058
|
const setgid = (above.mode & S_ISGID3) !== 0;
|
|
9923
10059
|
let mode = owner.mode;
|
|
9924
10060
|
if (directory && setgid) mode = (mode ?? 493) | S_ISGID3;
|
|
@@ -10437,7 +10573,7 @@ var MountFs = class _MountFs {
|
|
|
10437
10573
|
}
|
|
10438
10574
|
async named(path) {
|
|
10439
10575
|
const at = normalizePath(path);
|
|
10440
|
-
return joinName(await realDir(this,
|
|
10576
|
+
return joinName(await realDir(this, parentOf7(at)), at.slice(at.lastIndexOf("/") + 1));
|
|
10441
10577
|
}
|
|
10442
10578
|
async link(source, target, follow2 = false) {
|
|
10443
10579
|
const from = follow2 ? await realTarget(this, normalizePath(source)) : await this.named(source);
|
|
@@ -12112,6 +12248,8 @@ var SYS_TREE = {
|
|
|
12112
12248
|
slicc_opfs_ops: (listing) => `${listing.opfsOps ?? 0}
|
|
12113
12249
|
`,
|
|
12114
12250
|
slicc_cwd_checks: (listing) => `${listing.cwdChecks ?? 0}
|
|
12251
|
+
`,
|
|
12252
|
+
slicc_package_swaps: ({ swaps }) => `${swaps?.swaps ?? 0} ${(swaps?.longestMs ?? 0).toFixed(1)} ${swaps?.waits ?? 0} ${(swaps?.waitedMs ?? 0).toFixed(1)}
|
|
12115
12253
|
`,
|
|
12116
12254
|
slicc_rename_ack_busy: (listing) => `${listing.renameAcks?.busy ?? 0}
|
|
12117
12255
|
`,
|
|
@@ -13327,13 +13465,13 @@ async function flock(req, ctx) {
|
|
|
13327
13465
|
if (!FLOCK_KINDS.has(req.kind)) throw new KernelError("EINVAL");
|
|
13328
13466
|
const { key, owner } = await flockOf(req.fd);
|
|
13329
13467
|
const granted2 = req.kind !== "unlock";
|
|
13330
|
-
const
|
|
13331
|
-
if (
|
|
13468
|
+
const shared2 = locks.shared?.() === true;
|
|
13469
|
+
if (shared2 && !granted2) await ctx.settle?.(req.fd, false);
|
|
13332
13470
|
if (req.kind !== "unlock" && req.wait)
|
|
13333
13471
|
await locks.flocks.wait(key, owner, req.kind, ctx.blocking);
|
|
13334
13472
|
else if (!await locks.flocks.set(key, owner, req.kind)) throw new KernelError("EAGAIN");
|
|
13335
|
-
if (
|
|
13336
|
-
return
|
|
13473
|
+
if (shared2 && granted2) await grantedAcross(ctx, req.fd);
|
|
13474
|
+
return shared2 ? json3(true) : done2;
|
|
13337
13475
|
}
|
|
13338
13476
|
async function grantedAcross(ctx, fd) {
|
|
13339
13477
|
ctx.locks?.fresh?.();
|
|
@@ -13361,15 +13499,15 @@ async function recordLock2(req, ctx) {
|
|
|
13361
13499
|
return json3({ kind: held.kind, pid: held.owner, start: held.start, len });
|
|
13362
13500
|
}
|
|
13363
13501
|
const granted2 = req.kind !== "unlock";
|
|
13364
|
-
const
|
|
13365
|
-
const fd =
|
|
13502
|
+
const shared2 = locks.shared?.() === true;
|
|
13503
|
+
const fd = shared2 ? req.fd : void 0;
|
|
13366
13504
|
if (!granted2 && fd !== void 0) await ctx.settle?.(fd, false);
|
|
13367
13505
|
if (req.kind !== "unlock" && req.wait)
|
|
13368
13506
|
await locks.wait(key, owner, req.kind, range2, ctx.blocking);
|
|
13369
13507
|
else if (!await locks.set(key, owner, req.kind, range2.start, range2.end))
|
|
13370
13508
|
throw new KernelError("EAGAIN");
|
|
13371
|
-
if (granted2 &&
|
|
13372
|
-
return
|
|
13509
|
+
if (granted2 && shared2) await grantedAcross(ctx, fd);
|
|
13510
|
+
return shared2 ? json3(true) : done2;
|
|
13373
13511
|
}
|
|
13374
13512
|
|
|
13375
13513
|
// src/kernel/net/loopback-transport.ts
|
|
@@ -19449,9 +19587,9 @@ function pausing(signal) {
|
|
|
19449
19587
|
return { pausedAt, select };
|
|
19450
19588
|
}
|
|
19451
19589
|
async function serveSecure(proc, socket, req) {
|
|
19452
|
-
const
|
|
19453
|
-
if (req.listener && !
|
|
19454
|
-
const server =
|
|
19590
|
+
const shared2 = req.listener?.serving;
|
|
19591
|
+
if (req.listener && !shared2) throw new KernelError("EINVAL", "the listener has no tls");
|
|
19592
|
+
const server = shared2 ?? await serverOf(proc, req);
|
|
19455
19593
|
const { engine, leaf, alpn, store, flags: flags2 } = server;
|
|
19456
19594
|
const limit = handshakeSignal(proc, server.timeoutMs);
|
|
19457
19595
|
const { pausedAt, select } = pausing(limit.signal);
|
|
@@ -19465,12 +19603,12 @@ async function serveSecure(proc, socket, req) {
|
|
|
19465
19603
|
(flags2 & TLS_KEYLOG) !== 0
|
|
19466
19604
|
),
|
|
19467
19605
|
limit.signal,
|
|
19468
|
-
(reason) => !
|
|
19606
|
+
(reason) => !shared2 && reason === timedOut
|
|
19469
19607
|
).finally(() => {
|
|
19470
19608
|
limit.done();
|
|
19471
19609
|
selections.delete(socket);
|
|
19472
19610
|
socket.pending = void 0;
|
|
19473
|
-
if (!
|
|
19611
|
+
if (!shared2) server.release();
|
|
19474
19612
|
});
|
|
19475
19613
|
run2.catch(() => void 0);
|
|
19476
19614
|
const first = await Promise.race([run2, pausedAt.then((pause2) => ({ pause: pause2 }))]);
|
|
@@ -21086,7 +21224,7 @@ function isWatchSyscall(req) {
|
|
|
21086
21224
|
return WATCHING.has(req.op);
|
|
21087
21225
|
}
|
|
21088
21226
|
var WATCHES_MAX = 8192;
|
|
21089
|
-
var
|
|
21227
|
+
var parentOf8 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
21090
21228
|
function visibleTo(watch, root, visible) {
|
|
21091
21229
|
return {
|
|
21092
21230
|
close: () => watch.close(),
|
|
@@ -21097,7 +21235,7 @@ function visibleTo(watch, root, visible) {
|
|
|
21097
21235
|
notes.map(async (note) => {
|
|
21098
21236
|
if (!("filename" in note) || !note.filename.includes("/")) return true;
|
|
21099
21237
|
const at = watch.root?.() ?? root;
|
|
21100
|
-
const dir =
|
|
21238
|
+
const dir = parentOf8(`${at === "/" ? "" : at}/${note.filename}`);
|
|
21101
21239
|
if (!seen.has(dir)) seen.set(dir, visible(dir));
|
|
21102
21240
|
return seen.get(dir);
|
|
21103
21241
|
})
|
|
@@ -25103,6 +25241,105 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
25103
25241
|
};
|
|
25104
25242
|
}
|
|
25105
25243
|
|
|
25244
|
+
// src/kernel/package-swaps.ts
|
|
25245
|
+
var SWAP_GAP_MS = 2e3;
|
|
25246
|
+
var STAGES = ["_tmp_", "_pacquet-stage_"];
|
|
25247
|
+
function staged(source, target) {
|
|
25248
|
+
if (parentOf(source) !== parentOf(target)) return false;
|
|
25249
|
+
const name2 = target.slice(target.lastIndexOf("/") + 1);
|
|
25250
|
+
const from = source.slice(source.lastIndexOf("/") + 1);
|
|
25251
|
+
return from.startsWith(`.${name2}-`) || STAGES.some((stage) => from.startsWith(`${name2}${stage}`));
|
|
25252
|
+
}
|
|
25253
|
+
var PackageSwaps = class {
|
|
25254
|
+
gaps = /* @__PURE__ */ new Map();
|
|
25255
|
+
isRoot;
|
|
25256
|
+
hold;
|
|
25257
|
+
closed;
|
|
25258
|
+
gapMs;
|
|
25259
|
+
tally = { swaps: 0, longestMs: 0, waits: 0, waitedMs: 0 };
|
|
25260
|
+
constructor(isRoot, hold, closed, gapMs = SWAP_GAP_MS) {
|
|
25261
|
+
this.isRoot = isRoot;
|
|
25262
|
+
this.hold = hold;
|
|
25263
|
+
this.closed = closed;
|
|
25264
|
+
this.gapMs = gapMs;
|
|
25265
|
+
}
|
|
25266
|
+
counts() {
|
|
25267
|
+
return { ...this.tally };
|
|
25268
|
+
}
|
|
25269
|
+
settled() {
|
|
25270
|
+
if (this.gaps.size === 0) return Promise.resolve();
|
|
25271
|
+
const started = performance.now();
|
|
25272
|
+
this.tally.waits++;
|
|
25273
|
+
return Promise.all([...this.gaps.values()].map((gap) => gap.settled)).then(() => {
|
|
25274
|
+
this.tally.waitedMs += performance.now() - started;
|
|
25275
|
+
});
|
|
25276
|
+
}
|
|
25277
|
+
wrap(fs) {
|
|
25278
|
+
return { ...fs, rename: (from, to) => this.rename(fs, from, to) };
|
|
25279
|
+
}
|
|
25280
|
+
async rename(fs, from, to) {
|
|
25281
|
+
const source = fs.resolvePath("/", from);
|
|
25282
|
+
const target = fs.resolvePath("/", to);
|
|
25283
|
+
const gap = this.gaps.get(target);
|
|
25284
|
+
if (gap) return this.land(gap, target, () => fs.rename(from, to));
|
|
25285
|
+
if (source === target || this.gaps.has(source) || staged(source, target) || !this.isRoot(source)) {
|
|
25286
|
+
return fs.rename(from, to);
|
|
25287
|
+
}
|
|
25288
|
+
const release = await this.hold(source);
|
|
25289
|
+
let kept = false;
|
|
25290
|
+
try {
|
|
25291
|
+
await fs.rename(from, to);
|
|
25292
|
+
kept = await fs.stat(`${target}/package.json`).then(
|
|
25293
|
+
(st) => st.isFile,
|
|
25294
|
+
() => false
|
|
25295
|
+
);
|
|
25296
|
+
if (kept) this.open(source, release);
|
|
25297
|
+
} finally {
|
|
25298
|
+
if (!kept) release();
|
|
25299
|
+
}
|
|
25300
|
+
}
|
|
25301
|
+
open(root, release) {
|
|
25302
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
25303
|
+
const gap = {
|
|
25304
|
+
release,
|
|
25305
|
+
done: () => resolve2(),
|
|
25306
|
+
settled: promise,
|
|
25307
|
+
timer: void 0,
|
|
25308
|
+
landing: 0,
|
|
25309
|
+
opened: performance.now()
|
|
25310
|
+
};
|
|
25311
|
+
this.gaps.set(root, gap);
|
|
25312
|
+
this.tally.swaps++;
|
|
25313
|
+
this.arm(root, gap);
|
|
25314
|
+
}
|
|
25315
|
+
arm(root, gap) {
|
|
25316
|
+
const timer = setTimeout(() => this.close(root, gap), this.gapMs);
|
|
25317
|
+
timer.unref?.();
|
|
25318
|
+
gap.timer = timer;
|
|
25319
|
+
}
|
|
25320
|
+
close(root, gap) {
|
|
25321
|
+
if (this.gaps.get(root) !== gap) return;
|
|
25322
|
+
clearTimeout(gap.timer);
|
|
25323
|
+
this.gaps.delete(root);
|
|
25324
|
+
this.tally.longestMs = Math.max(this.tally.longestMs, performance.now() - gap.opened);
|
|
25325
|
+
this.closed();
|
|
25326
|
+
gap.done();
|
|
25327
|
+
gap.release();
|
|
25328
|
+
}
|
|
25329
|
+
async land(gap, root, run2) {
|
|
25330
|
+
gap.landing++;
|
|
25331
|
+
clearTimeout(gap.timer);
|
|
25332
|
+
try {
|
|
25333
|
+
await run2();
|
|
25334
|
+
} catch (err) {
|
|
25335
|
+
gap.landing--;
|
|
25336
|
+
if (gap.landing === 0 && this.gaps.get(root) === gap) this.arm(root, gap);
|
|
25337
|
+
throw err;
|
|
25338
|
+
}
|
|
25339
|
+
this.close(root, gap);
|
|
25340
|
+
}
|
|
25341
|
+
};
|
|
25342
|
+
|
|
25106
25343
|
// src/kernel/rename-log.ts
|
|
25107
25344
|
var RENAME_LOG_SIZE = 4096;
|
|
25108
25345
|
function within8(path, root) {
|
|
@@ -25140,6 +25377,51 @@ var RenameLog = class {
|
|
|
25140
25377
|
}
|
|
25141
25378
|
};
|
|
25142
25379
|
|
|
25380
|
+
// src/kernel/replacing.ts
|
|
25381
|
+
var REPLACING_LOCK = "slicc-kernel-replacing:v1:";
|
|
25382
|
+
function replacingLocks(scope = globalThis) {
|
|
25383
|
+
const locks = scope.navigator?.locks;
|
|
25384
|
+
return typeof locks?.request === "function" ? locks : void 0;
|
|
25385
|
+
}
|
|
25386
|
+
function replacingLock(metadata, root) {
|
|
25387
|
+
return `${REPLACING_LOCK}${metadata}:${root}`;
|
|
25388
|
+
}
|
|
25389
|
+
function shared(locks, names2, run2, waited) {
|
|
25390
|
+
const [name2, ...rest2] = names2;
|
|
25391
|
+
if (name2 === void 0) return run2(waited);
|
|
25392
|
+
const next3 = (after) => shared(locks, rest2, run2, after);
|
|
25393
|
+
return locks.request(
|
|
25394
|
+
name2,
|
|
25395
|
+
{ mode: "shared", ifAvailable: true },
|
|
25396
|
+
(lock) => lock ? next3(waited) : locks.request(name2, { mode: "shared" }, () => next3(true))
|
|
25397
|
+
);
|
|
25398
|
+
}
|
|
25399
|
+
var PackageLocks = class {
|
|
25400
|
+
locks;
|
|
25401
|
+
metadata;
|
|
25402
|
+
constructor(metadata, locks = replacingLocks()) {
|
|
25403
|
+
this.metadata = metadata;
|
|
25404
|
+
this.locks = locks;
|
|
25405
|
+
}
|
|
25406
|
+
loading(roots, run2) {
|
|
25407
|
+
if (!this.locks || roots.length === 0) return run2(false);
|
|
25408
|
+
const names2 = roots.map((root) => replacingLock(this.metadata, root));
|
|
25409
|
+
return shared(this.locks, names2, run2, false);
|
|
25410
|
+
}
|
|
25411
|
+
holding(root) {
|
|
25412
|
+
const { locks } = this;
|
|
25413
|
+
if (!locks) return Promise.resolve(() => {
|
|
25414
|
+
});
|
|
25415
|
+
const { promise: held, resolve: release } = Promise.withResolvers();
|
|
25416
|
+
return new Promise((granted2, failed3) => {
|
|
25417
|
+
locks.request(replacingLock(this.metadata, root), { mode: "exclusive" }, () => {
|
|
25418
|
+
granted2(() => release());
|
|
25419
|
+
return held;
|
|
25420
|
+
}).catch(failed3);
|
|
25421
|
+
});
|
|
25422
|
+
}
|
|
25423
|
+
};
|
|
25424
|
+
|
|
25143
25425
|
// src/kernel/settling.ts
|
|
25144
25426
|
var SETUP_OPS = /* @__PURE__ */ new Set([
|
|
25145
25427
|
"proc-list",
|
|
@@ -25436,141 +25718,6 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
|
|
|
25436
25718
|
return { invalidate: (paths) => reply({ invalidate: paths }) };
|
|
25437
25719
|
}
|
|
25438
25720
|
|
|
25439
|
-
// src/fs/path-map.ts
|
|
25440
|
-
function parentOf7(path) {
|
|
25441
|
-
if (path === "/" || path === "") return void 0;
|
|
25442
|
-
const at = path.lastIndexOf("/");
|
|
25443
|
-
return at <= 0 ? "/" : path.slice(0, at);
|
|
25444
|
-
}
|
|
25445
|
-
var PathMap = class {
|
|
25446
|
-
values = /* @__PURE__ */ new Map();
|
|
25447
|
-
children = /* @__PURE__ */ new Map();
|
|
25448
|
-
get size() {
|
|
25449
|
-
return this.values.size;
|
|
25450
|
-
}
|
|
25451
|
-
has(path) {
|
|
25452
|
-
return this.values.has(path);
|
|
25453
|
-
}
|
|
25454
|
-
get(path) {
|
|
25455
|
-
return this.values.get(path);
|
|
25456
|
-
}
|
|
25457
|
-
keys() {
|
|
25458
|
-
return this.values.keys();
|
|
25459
|
-
}
|
|
25460
|
-
set(path, value2) {
|
|
25461
|
-
if (!this.values.has(path)) this.link(path);
|
|
25462
|
-
this.values.set(path, value2);
|
|
25463
|
-
return this;
|
|
25464
|
-
}
|
|
25465
|
-
delete(path) {
|
|
25466
|
-
if (!this.values.delete(path)) return false;
|
|
25467
|
-
this.prune(path);
|
|
25468
|
-
return true;
|
|
25469
|
-
}
|
|
25470
|
-
subtree(root) {
|
|
25471
|
-
const out = [];
|
|
25472
|
-
const stack = [root];
|
|
25473
|
-
for (let path = stack.pop(); path !== void 0; path = stack.pop()) {
|
|
25474
|
-
if (this.values.has(path)) out.push(path);
|
|
25475
|
-
const below = this.children.get(path);
|
|
25476
|
-
if (below) for (const child of below) stack.push(child);
|
|
25477
|
-
}
|
|
25478
|
-
return out;
|
|
25479
|
-
}
|
|
25480
|
-
entries() {
|
|
25481
|
-
return this.values.entries();
|
|
25482
|
-
}
|
|
25483
|
-
deleteTree(root) {
|
|
25484
|
-
const stack = [root];
|
|
25485
|
-
for (let path = stack.pop(); path !== void 0; path = stack.pop()) {
|
|
25486
|
-
this.values.delete(path);
|
|
25487
|
-
const below = this.children.get(path);
|
|
25488
|
-
if (below) for (const child of below) stack.push(child);
|
|
25489
|
-
this.children.delete(path);
|
|
25490
|
-
}
|
|
25491
|
-
this.prune(root);
|
|
25492
|
-
}
|
|
25493
|
-
clear() {
|
|
25494
|
-
this.values.clear();
|
|
25495
|
-
this.children.clear();
|
|
25496
|
-
}
|
|
25497
|
-
link(path) {
|
|
25498
|
-
for (let child = path, parent = parentOf7(path); parent !== void 0; ) {
|
|
25499
|
-
const set3 = this.children.get(parent);
|
|
25500
|
-
if (set3?.has(child)) return;
|
|
25501
|
-
if (set3) set3.add(child);
|
|
25502
|
-
else this.children.set(parent, /* @__PURE__ */ new Set([child]));
|
|
25503
|
-
child = parent;
|
|
25504
|
-
parent = parentOf7(parent);
|
|
25505
|
-
}
|
|
25506
|
-
}
|
|
25507
|
-
prune(path) {
|
|
25508
|
-
for (let child = path, parent = parentOf7(path); parent !== void 0; ) {
|
|
25509
|
-
if (this.values.has(child) || this.children.has(child)) return;
|
|
25510
|
-
const set3 = this.children.get(parent);
|
|
25511
|
-
set3?.delete(child);
|
|
25512
|
-
if (set3 && set3.size > 0) return;
|
|
25513
|
-
this.children.delete(parent);
|
|
25514
|
-
child = parent;
|
|
25515
|
-
parent = parentOf7(parent);
|
|
25516
|
-
}
|
|
25517
|
-
}
|
|
25518
|
-
};
|
|
25519
|
-
|
|
25520
|
-
// src/fs/meta.ts
|
|
25521
|
-
function parentOf8(path) {
|
|
25522
|
-
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
25523
|
-
}
|
|
25524
|
-
function moved(entry, path) {
|
|
25525
|
-
return entry.link === void 0 ? { ...entry, path } : { ...entry, path, dir: parentOf8(path) };
|
|
25526
|
-
}
|
|
25527
|
-
function under4(path, root) {
|
|
25528
|
-
return path === root || path.startsWith(`${root}/`);
|
|
25529
|
-
}
|
|
25530
|
-
var MemoryMeta = class {
|
|
25531
|
-
entries = new PathMap();
|
|
25532
|
-
async get(paths) {
|
|
25533
|
-
return paths.map((path) => this.entries.get(path));
|
|
25534
|
-
}
|
|
25535
|
-
async fresh(paths) {
|
|
25536
|
-
return this.get(paths);
|
|
25537
|
-
}
|
|
25538
|
-
async update(path, change) {
|
|
25539
|
-
this.set(path, change(this.entries.get(path)));
|
|
25540
|
-
}
|
|
25541
|
-
set(path, entry) {
|
|
25542
|
-
if (entry) this.entries.set(path, entry);
|
|
25543
|
-
else this.entries.delete(path);
|
|
25544
|
-
}
|
|
25545
|
-
async move(from, to, root, left) {
|
|
25546
|
-
await this.remove([to]);
|
|
25547
|
-
const carried = this.entries.subtree(from).map((path) => this.entries.get(path));
|
|
25548
|
-
for (const entry of carried) this.entries.delete(entry.path);
|
|
25549
|
-
for (const entry of carried) {
|
|
25550
|
-
const path = to + entry.path.slice(from.length);
|
|
25551
|
-
if (path !== to) this.entries.set(path, moved(entry, path));
|
|
25552
|
-
}
|
|
25553
|
-
this.entries.set(to, moved(root(carried.find((entry) => entry.path === from)), to));
|
|
25554
|
-
if (left) this.entries.set(from, left);
|
|
25555
|
-
}
|
|
25556
|
-
async remove(paths, left) {
|
|
25557
|
-
for (const path of paths) this.entries.deleteTree(path);
|
|
25558
|
-
if (left) this.entries.set(left.path, left);
|
|
25559
|
-
}
|
|
25560
|
-
absent(path) {
|
|
25561
|
-
return !this.entries.has(path);
|
|
25562
|
-
}
|
|
25563
|
-
async links(dir) {
|
|
25564
|
-
return [...this.entries.entries()].map(([, e]) => e).filter((entry) => entry.dir === dir);
|
|
25565
|
-
}
|
|
25566
|
-
async under(path) {
|
|
25567
|
-
return [...this.entries.entries()].map(([, e]) => e).filter((entry) => under4(entry.path, path));
|
|
25568
|
-
}
|
|
25569
|
-
async all() {
|
|
25570
|
-
return [...this.entries.entries()].map(([, e]) => e);
|
|
25571
|
-
}
|
|
25572
|
-
};
|
|
25573
|
-
|
|
25574
25721
|
// src/fs/notice.ts
|
|
25575
25722
|
function noticeOf(data) {
|
|
25576
25723
|
if (Array.isArray(data)) return { paths: data.filter((p) => typeof p === "string"), trees: [] };
|
|
@@ -25879,9 +26026,11 @@ var OpfsFs = class {
|
|
|
25879
26026
|
this.channel.onmessage = ({ data }) => {
|
|
25880
26027
|
const { paths, trees, outside } = noticeOf(data);
|
|
25881
26028
|
for (const path of [...paths, ...trees]) this.forget(normalizePath(path));
|
|
25882
|
-
|
|
25883
|
-
|
|
25884
|
-
|
|
26029
|
+
if (!outside) remote?.emit({ paths, trees });
|
|
26030
|
+
else
|
|
26031
|
+
void this.noticed(paths.map(normalizePath), Date.now()).finally(
|
|
26032
|
+
() => remote?.emit({ paths, trees, outside: true })
|
|
26033
|
+
);
|
|
25885
26034
|
};
|
|
25886
26035
|
this.channel.unref?.();
|
|
25887
26036
|
}
|
|
@@ -26247,6 +26396,9 @@ var OpfsFs = class {
|
|
|
26247
26396
|
this.exact--;
|
|
26248
26397
|
}
|
|
26249
26398
|
}
|
|
26399
|
+
refresh(trees) {
|
|
26400
|
+
for (const tree2 of trees) this.forget(normalizePath(tree2));
|
|
26401
|
+
}
|
|
26250
26402
|
forget(path) {
|
|
26251
26403
|
this.changes++;
|
|
26252
26404
|
this.dirs.deleteTree(path);
|
|
@@ -27203,15 +27355,15 @@ var OpfsFs = class {
|
|
|
27203
27355
|
const hooks = {};
|
|
27204
27356
|
const staging = swap ? `.${name2}.${crypto.randomUUID()}` : name2;
|
|
27205
27357
|
const copying = sourceStat.isDirectory && !movable(source.handle);
|
|
27206
|
-
const
|
|
27358
|
+
const staged2 = resolvePath(parent.path, staging);
|
|
27207
27359
|
const place = async () => {
|
|
27208
27360
|
this.forget(destination);
|
|
27209
27361
|
const copies = /* @__PURE__ */ new Map();
|
|
27210
27362
|
const root = { ino: inodeOf(source.path), ...moving };
|
|
27211
27363
|
const owned4 = lock ? { lock } : {};
|
|
27212
27364
|
hooks.notify?.();
|
|
27213
|
-
const first = copying ? await this.intend({ from: source.path, to:
|
|
27214
|
-
const second = copying && swap ? await this.intend({ from:
|
|
27365
|
+
const first = copying ? await this.intend({ from: source.path, to: staged2, root, ...owned4 }) : void 0;
|
|
27366
|
+
const second = copying && swap ? await this.intend({ from: staged2, to: destination, replace: true, root, ...owned4 }) : void 0;
|
|
27215
27367
|
await hooks.started?.().catch(async (err) => {
|
|
27216
27368
|
for (const intent of [first, second]) {
|
|
27217
27369
|
if (intent) await this.meta.update(intent, () => void 0);
|
|
@@ -27222,11 +27374,11 @@ var OpfsFs = class {
|
|
|
27222
27374
|
targetStat !== null,
|
|
27223
27375
|
() => this.place(source.handle, dir, staging, copies)
|
|
27224
27376
|
).catch(async (err) => {
|
|
27225
|
-
if (first) await this.rollBack(
|
|
27377
|
+
if (first) await this.rollBack(staged2, source.path, [first, second]);
|
|
27226
27378
|
throw err;
|
|
27227
27379
|
});
|
|
27228
27380
|
if (swap) await this.rm(destination, { recursive: true });
|
|
27229
|
-
if (second) await this.intend({ from:
|
|
27381
|
+
if (second) await this.intend({ from: staged2, to: destination, root, ...owned4 }, second);
|
|
27230
27382
|
await this.meta.move(source.path, destination, carry, left);
|
|
27231
27383
|
this.movePending(source.path, destination);
|
|
27232
27384
|
if (!moved2) {
|
|
@@ -29686,14 +29838,14 @@ var UserDb = class {
|
|
|
29686
29838
|
this.fs = fs;
|
|
29687
29839
|
this.owners = owners;
|
|
29688
29840
|
}
|
|
29689
|
-
async stampHome(row,
|
|
29841
|
+
async stampHome(row, shared2, homeMode) {
|
|
29690
29842
|
const home = this.fs.resolvePath("/", row.home);
|
|
29691
29843
|
if (!this.owners || !this.fs.chown || !HOME_DIR.test(home)) return;
|
|
29692
29844
|
if (!await this.realDir(home)) return;
|
|
29693
|
-
const gid =
|
|
29845
|
+
const gid = shared2?.gid ?? row.gid;
|
|
29694
29846
|
await this.fs.chown(home, { uid: row.uid, gid, follow: false, kind: "adopt" });
|
|
29695
29847
|
const scoop = row.name.startsWith("scoop-");
|
|
29696
|
-
await this.fs.chmod(home, homeMode ?? (
|
|
29848
|
+
await this.fs.chmod(home, homeMode ?? (shared2 ? 1512 : scoop ? 488 : 448));
|
|
29697
29849
|
const pnpm = `${home}/.local/share/pnpm`;
|
|
29698
29850
|
if (await this.realDir(pnpm)) await this.fs.chmod(pnpm, scoop ? 488 : 448);
|
|
29699
29851
|
}
|
|
@@ -29730,9 +29882,9 @@ var UserDb = class {
|
|
|
29730
29882
|
const [passwd, group] = await this.texts();
|
|
29731
29883
|
return { passwd: parsePasswd(passwd), group: parseGroup(group) };
|
|
29732
29884
|
}
|
|
29733
|
-
async provision(row, umask,
|
|
29734
|
-
const dirs = 511 & ~umask | (
|
|
29735
|
-
const gid =
|
|
29885
|
+
async provision(row, umask, shared2) {
|
|
29886
|
+
const dirs = 511 & ~umask | (shared2 ? 1024 : 0);
|
|
29887
|
+
const gid = shared2?.gid ?? row.gid;
|
|
29736
29888
|
const owner = this.owners ? { uid: row.uid, gid } : void 0;
|
|
29737
29889
|
const made2 = owner ? { recursive: true, owner: { ...owner, mode: dirs, parents: dirs } } : { recursive: true };
|
|
29738
29890
|
const pnpm = `${row.home}/.local/share/pnpm`;
|
|
@@ -29836,7 +29988,7 @@ var UserDb = class {
|
|
|
29836
29988
|
const users = parsed(passwd);
|
|
29837
29989
|
const groups = parsed(group);
|
|
29838
29990
|
const found = users.find((r) => r.name === name2);
|
|
29839
|
-
const
|
|
29991
|
+
const shared2 = homeGroupOf(groups, options.homeGroup);
|
|
29840
29992
|
const homeMode = homeModeOf(options.homeMode);
|
|
29841
29993
|
if (found) {
|
|
29842
29994
|
const more = groupsOf(groups, options.groups ?? []);
|
|
@@ -29844,8 +29996,8 @@ var UserDb = class {
|
|
|
29844
29996
|
throw fsError("EINVAL", `a user is no member of its own group ${name2}`);
|
|
29845
29997
|
}
|
|
29846
29998
|
if (found.uid >= FIRST_UID && found.uid <= LAST_UID) {
|
|
29847
|
-
await this.provision(found, this.umaskFor(options),
|
|
29848
|
-
await this.stampHome(found,
|
|
29999
|
+
await this.provision(found, this.umaskFor(options), shared2);
|
|
30000
|
+
await this.stampHome(found, shared2, homeMode);
|
|
29849
30001
|
}
|
|
29850
30002
|
if (joined4(name2, more)) await this.fs.writeFile(GROUP, formatGroup(group));
|
|
29851
30003
|
remember();
|
|
@@ -29862,8 +30014,8 @@ var UserDb = class {
|
|
|
29862
30014
|
const fresh3 = !await this.fs.exists(home);
|
|
29863
30015
|
await this.fs.mkdir(home, { recursive: true });
|
|
29864
30016
|
try {
|
|
29865
|
-
await this.provision(row, this.umaskFor(options),
|
|
29866
|
-
await this.stampHome(row,
|
|
30017
|
+
await this.provision(row, this.umaskFor(options), shared2);
|
|
30018
|
+
await this.stampHome(row, shared2, homeMode);
|
|
29867
30019
|
await this.fs.mkdir("/etc", { recursive: true });
|
|
29868
30020
|
await this.commit(formatPasswd(passwd), formatGroup(group));
|
|
29869
30021
|
} catch (err) {
|
|
@@ -29912,19 +30064,19 @@ var UserDb = class {
|
|
|
29912
30064
|
);
|
|
29913
30065
|
for (const r of parsed(keptGroups)) r.members = r.members.filter((m) => m !== name2);
|
|
29914
30066
|
const home = this.fs.resolvePath("/", row.home);
|
|
29915
|
-
const
|
|
30067
|
+
const shared2 = parsed(passwd).some(
|
|
29916
30068
|
(r) => r !== row && this.fs.resolvePath("/", r.home) === home
|
|
29917
30069
|
);
|
|
29918
|
-
const removeHome = !options.keepHome && !
|
|
29919
|
-
const
|
|
30070
|
+
const removeHome = !options.keepHome && !shared2 && HOME_DIR.test(home) && await this.fs.exists(home);
|
|
30071
|
+
const staged2 = `/home/.${name2}.removed-${Date.now()}`;
|
|
29920
30072
|
await this.commit(
|
|
29921
30073
|
formatPasswd(passwd.filter((r) => r !== row)),
|
|
29922
30074
|
formatGroup(keptGroups),
|
|
29923
|
-
removeHome ? () => this.fs.rename(home,
|
|
30075
|
+
removeHome ? () => this.fs.rename(home, staged2) : void 0
|
|
29924
30076
|
);
|
|
29925
30077
|
this.umasks.delete(name2);
|
|
29926
30078
|
if (removeHome)
|
|
29927
|
-
await this.fs.rm(
|
|
30079
|
+
await this.fs.rm(staged2, { recursive: true, force: true }).catch(() => void 0);
|
|
29928
30080
|
return true;
|
|
29929
30081
|
});
|
|
29930
30082
|
}
|
|
@@ -30404,6 +30556,7 @@ var COMMAND2 = /^\/(?:usr\/)?bin\/([^/]+)$/;
|
|
|
30404
30556
|
var SHIM_MARKER = /^\/\/ pnpm-wasm-shim=(\{.*\})$/gm;
|
|
30405
30557
|
var SHIM_MAX = 64 * 1024;
|
|
30406
30558
|
var PACKAGE_ROOT = /^(.*\/node_modules\/(?:@[^/]+\/)?[^/]+)\//;
|
|
30559
|
+
var NODE_MODULES = /\/node_modules(?:\/|$)/;
|
|
30407
30560
|
var ENV_REFERENCE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
30408
30561
|
var WASM_MAGIC = [0, 97, 115, 109];
|
|
30409
30562
|
var SHEBANG_MAX = 256;
|
|
@@ -30471,6 +30624,21 @@ function packageRootOf(path, roots) {
|
|
|
30471
30624
|
}
|
|
30472
30625
|
return void 0;
|
|
30473
30626
|
}
|
|
30627
|
+
function planFiles(planned) {
|
|
30628
|
+
const { target } = planned;
|
|
30629
|
+
const files = [
|
|
30630
|
+
target.glue,
|
|
30631
|
+
target.wasm,
|
|
30632
|
+
target.imports,
|
|
30633
|
+
target.copy,
|
|
30634
|
+
...(target.variants ?? []).map((variant) => variant.wasm),
|
|
30635
|
+
...planned.sources ?? []
|
|
30636
|
+
];
|
|
30637
|
+
return files.filter((file) => file !== void 0);
|
|
30638
|
+
}
|
|
30639
|
+
function sameList(a, b) {
|
|
30640
|
+
return a.length === b.length && a.every((item, i) => item === b[i]);
|
|
30641
|
+
}
|
|
30474
30642
|
function modulePath(glue) {
|
|
30475
30643
|
return glue.endsWith(".js") ? `${glue.slice(0, -3)}.wasm` : `${glue}.wasm`;
|
|
30476
30644
|
}
|
|
@@ -30644,6 +30812,12 @@ var Launcher = class {
|
|
|
30644
30812
|
sudoer;
|
|
30645
30813
|
jobs = new JobTable();
|
|
30646
30814
|
locks;
|
|
30815
|
+
packageLocks;
|
|
30816
|
+
swaps = new PackageSwaps(
|
|
30817
|
+
(path) => this.packageRootIs(path),
|
|
30818
|
+
(root) => this.packageLocks.holding(root),
|
|
30819
|
+
() => this.resetCatalogs()
|
|
30820
|
+
);
|
|
30647
30821
|
fifos = new FifoTable();
|
|
30648
30822
|
memories;
|
|
30649
30823
|
sems = new SemTable();
|
|
@@ -30716,6 +30890,7 @@ var Launcher = class {
|
|
|
30716
30890
|
this.memories = memoriesOf(options.wasmMemories);
|
|
30717
30891
|
this.rootFs = options.fs;
|
|
30718
30892
|
this.locks = kernelLocks(options.fs.rootName, this.flushingPeers(options.fs));
|
|
30893
|
+
this.packageLocks = new PackageLocks(options.packageLocks ?? META_DB);
|
|
30719
30894
|
this.dac = this.usersMode === "off" ? void 0 : new Dac(this.usersMode, options.onDenial);
|
|
30720
30895
|
if (this.dac) this.wireDac(this.dac);
|
|
30721
30896
|
this.clipboard = new ClipboardBroker(
|
|
@@ -30809,15 +30984,7 @@ var Launcher = class {
|
|
|
30809
30984
|
this.nodes.keepsOnDisk = true;
|
|
30810
30985
|
this.openFiles.add(this.nodes);
|
|
30811
30986
|
options.fs.onPeer?.(() => this.flushOpen());
|
|
30812
|
-
options.fs.remoteChanges?.((change) =>
|
|
30813
|
-
this.held.doubt(change.paths, change.moved?.to);
|
|
30814
|
-
if (change.moved) this.moved(change.moved.from, change.moved.to);
|
|
30815
|
-
this.changes.flush();
|
|
30816
|
-
this.cwds.touched(change.paths, change.trees);
|
|
30817
|
-
this.rewritten(change.paths, change.trees);
|
|
30818
|
-
this.watchers.heard(change.content ? "change" : "rename", change.paths);
|
|
30819
|
-
this.watchers.heard("rename", change.trees ?? []);
|
|
30820
|
-
});
|
|
30987
|
+
options.fs.remoteChanges?.((change) => this.remoteChanged(change));
|
|
30821
30988
|
const holders = [this.held, this.openFiles];
|
|
30822
30989
|
options.fs.heldBy?.(
|
|
30823
30990
|
(dir) => holders.flatMap((set3) => [...set3].flatMap((holder) => [...holder.held()])).filter((p) => p.startsWith(`${dir}/`) && this.mounts.locate(p) === void 0)
|
|
@@ -30941,7 +31108,7 @@ var Launcher = class {
|
|
|
30941
31108
|
commands(scope = "") {
|
|
30942
31109
|
let found = this.catalogs.get(scope);
|
|
30943
31110
|
if (!found) {
|
|
30944
|
-
found = this.trustedAppended().then(async (appended2) => {
|
|
31111
|
+
found = this.swaps.settled().then(() => this.trustedAppended()).then(async (appended2) => {
|
|
30945
31112
|
const tiers = await this.tiers(scope, appended2);
|
|
30946
31113
|
const refused3 = [];
|
|
30947
31114
|
const commands = await scanCommands(
|
|
@@ -31027,6 +31194,26 @@ var Launcher = class {
|
|
|
31027
31194
|
}
|
|
31028
31195
|
return trusted;
|
|
31029
31196
|
}
|
|
31197
|
+
remoteChanged(change) {
|
|
31198
|
+
this.held.doubt(change.paths, change.moved?.to);
|
|
31199
|
+
if (change.moved) this.moved(change.moved.from, change.moved.to);
|
|
31200
|
+
this.changes.flush();
|
|
31201
|
+
this.cwds.touched(change.paths, change.trees);
|
|
31202
|
+
this.rewritten(change.paths, change.trees);
|
|
31203
|
+
this.watchers.heard(change.content ? "change" : "rename", change.paths);
|
|
31204
|
+
this.watchers.heard("rename", change.trees ?? []);
|
|
31205
|
+
if (change.outside && this.catalogChanged([...change.paths, ...change.trees ?? []])) {
|
|
31206
|
+
this.resetCatalogs();
|
|
31207
|
+
}
|
|
31208
|
+
}
|
|
31209
|
+
catalogChanged(paths) {
|
|
31210
|
+
const roots = [this.modulesDir, this.pnpmHome, ...this.appended].map(normalizePath);
|
|
31211
|
+
return paths.map(normalizePath).some(
|
|
31212
|
+
(at) => at === "/" || NODE_MODULES.test(at) || roots.some(
|
|
31213
|
+
(root) => at === root || at.startsWith(`${root}/`) || root.startsWith(`${at}/`)
|
|
31214
|
+
)
|
|
31215
|
+
);
|
|
31216
|
+
}
|
|
31030
31217
|
resetCatalogs() {
|
|
31031
31218
|
this.catalogs.clear();
|
|
31032
31219
|
this.ownCatalogs.clear();
|
|
@@ -31427,7 +31614,11 @@ var Launcher = class {
|
|
|
31427
31614
|
secrets.push({ name: name2, value: value2, placeholder });
|
|
31428
31615
|
}
|
|
31429
31616
|
const scrub = scrubberOf(secrets);
|
|
31430
|
-
|
|
31617
|
+
const recheck = async (next3) => {
|
|
31618
|
+
const same2 = 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;
|
|
31619
|
+
if (!same2) throw new SpawnError("EACCES");
|
|
31620
|
+
};
|
|
31621
|
+
return { env, pid, cwd: booked.cwd, ...scrub ? { scrub } : {}, recheck };
|
|
31431
31622
|
}
|
|
31432
31623
|
async interpreterChain(planned, cwd, scope) {
|
|
31433
31624
|
const out = [];
|
|
@@ -31712,25 +31903,16 @@ var Launcher = class {
|
|
|
31712
31903
|
async launch(asked, req) {
|
|
31713
31904
|
const cwd = await physicalPathAsync(this.base, req.cwd);
|
|
31714
31905
|
const seen = { ...req.env, HOSTNAME: this.hostname, cwd };
|
|
31715
|
-
const env = { ...expandDefaults(asked.target.env, seen), ...req.env };
|
|
31716
|
-
for (const key of asked.target.unset ?? []) delete env[key];
|
|
31717
|
-
delete env[TICKET_ENV];
|
|
31718
|
-
const own = env.HOSTNAME;
|
|
31719
|
-
if (asked.target.abi === "wasi") env.HOSTNAME = this.hostname;
|
|
31720
|
-
const planned = chosen2(asked, env);
|
|
31721
|
-
const { target, args } = planned;
|
|
31722
|
-
let program;
|
|
31723
|
-
let exeId;
|
|
31724
31906
|
await this.pnpmReady();
|
|
31907
|
+
let loaded;
|
|
31725
31908
|
try {
|
|
31726
|
-
|
|
31727
|
-
if (this.integrity) await this.checkedSources(planned, caller);
|
|
31728
|
-
[program, exeId] = await this.loaded(target, env, caller);
|
|
31729
|
-
if (readsEtcHostname(program)) setOrDrop(env, "HOSTNAME", own);
|
|
31909
|
+
loaded = await this.loadedUnder(asked, (planned2) => this.loadPlanned(planned2, req, seen));
|
|
31730
31910
|
} catch (err) {
|
|
31731
31911
|
await req.fds.closeAll();
|
|
31732
31912
|
throw err;
|
|
31733
31913
|
}
|
|
31914
|
+
const { planned, env, program, exeId } = loaded;
|
|
31915
|
+
const { target, args } = planned;
|
|
31734
31916
|
const done4 = this.heldUrl(program);
|
|
31735
31917
|
try {
|
|
31736
31918
|
const cwdSlot = await this.cwds.hold(cwd, req.cwdFrom);
|
|
@@ -31758,6 +31940,59 @@ var Launcher = class {
|
|
|
31758
31940
|
throw err;
|
|
31759
31941
|
}
|
|
31760
31942
|
}
|
|
31943
|
+
async loadPlanned(asked, req, seen) {
|
|
31944
|
+
const env = { ...expandDefaults(asked.target.env, seen), ...req.env };
|
|
31945
|
+
for (const key of asked.target.unset ?? []) delete env[key];
|
|
31946
|
+
delete env[TICKET_ENV];
|
|
31947
|
+
const own = env.HOSTNAME;
|
|
31948
|
+
if (asked.target.abi === "wasi") env.HOSTNAME = this.hostname;
|
|
31949
|
+
const planned = chosen2(asked, env);
|
|
31950
|
+
const caller = { pid: req.ppid ?? 0, uid: req.cred.euid, tag: req.tags?.[0] };
|
|
31951
|
+
if (this.integrity) await this.checkedSources(planned, caller);
|
|
31952
|
+
const [program, exeId] = await this.loaded(planned.target, env, caller);
|
|
31953
|
+
if (readsEtcHostname(program)) setOrDrop(env, "HOSTNAME", own);
|
|
31954
|
+
return { planned, env, program, exeId };
|
|
31955
|
+
}
|
|
31956
|
+
packageRootIs(path) {
|
|
31957
|
+
const at = normalizePath(path);
|
|
31958
|
+
const within10 = `${at}/`;
|
|
31959
|
+
const roots = [this.modulesDir, ...this.appended];
|
|
31960
|
+
const root = PACKAGE_ROOT.exec(within10)?.[1] ?? packageRootOf(within10, roots);
|
|
31961
|
+
return root === at;
|
|
31962
|
+
}
|
|
31963
|
+
packageRoots(planned) {
|
|
31964
|
+
const packages2 = [this.modulesDir, ...this.appended];
|
|
31965
|
+
const roots = /* @__PURE__ */ new Set();
|
|
31966
|
+
for (const file of planFiles(planned)) {
|
|
31967
|
+
if (!file.startsWith("/")) continue;
|
|
31968
|
+
const at = normalizePath(file);
|
|
31969
|
+
const root = PACKAGE_ROOT.exec(at)?.[1] ?? packageRootOf(at, packages2);
|
|
31970
|
+
if (root !== void 0 && root !== at) roots.add(root);
|
|
31971
|
+
}
|
|
31972
|
+
return [...roots].sort();
|
|
31973
|
+
}
|
|
31974
|
+
async loadedUnder(asked, load) {
|
|
31975
|
+
const { replan, recheck } = asked;
|
|
31976
|
+
let planned = asked;
|
|
31977
|
+
let roots = this.packageRoots(planned);
|
|
31978
|
+
let stale = false;
|
|
31979
|
+
for (; ; ) {
|
|
31980
|
+
const held = roots;
|
|
31981
|
+
const done4 = await this.packageLocks.loading(held, async (waited) => {
|
|
31982
|
+
if (!waited && !stale) return { value: await load(planned) };
|
|
31983
|
+
this.rootFs.refresh?.(held);
|
|
31984
|
+
this.resetCatalogs();
|
|
31985
|
+
if (replan) planned = await replan() ?? planned;
|
|
31986
|
+
await recheck?.(planned);
|
|
31987
|
+
const now = this.packageRoots(planned);
|
|
31988
|
+
if (now.every((root) => held.includes(root))) return { value: await load(planned) };
|
|
31989
|
+
roots = [.../* @__PURE__ */ new Set([...held, ...now])].sort();
|
|
31990
|
+
stale = true;
|
|
31991
|
+
return void 0;
|
|
31992
|
+
});
|
|
31993
|
+
if (done4) return done4.value;
|
|
31994
|
+
}
|
|
31995
|
+
}
|
|
31761
31996
|
groupSession(pgid) {
|
|
31762
31997
|
return this.jobs.sessionOf(pgid);
|
|
31763
31998
|
}
|
|
@@ -31910,6 +32145,7 @@ var Launcher = class {
|
|
|
31910
32145
|
opfsOps: this.rootFs.opfsOps?.() ?? 0,
|
|
31911
32146
|
cwdChecks: this.cwds.checks,
|
|
31912
32147
|
renameAcks: this.rootFs.renameWaits?.(),
|
|
32148
|
+
swaps: this.swaps.counts(),
|
|
31913
32149
|
staleFds: staleFdCount(),
|
|
31914
32150
|
fileIds: this.rootFs.fileIdWrites?.() ?? 0,
|
|
31915
32151
|
holds: this.rootFs.holdCounts?.()
|
|
@@ -32166,6 +32402,7 @@ var Launcher = class {
|
|
|
32166
32402
|
spawner(ppid, report) {
|
|
32167
32403
|
return async (req, fds, grant) => {
|
|
32168
32404
|
const booked = this.takeTicket(req);
|
|
32405
|
+
await this.swaps.settled();
|
|
32169
32406
|
if (grant && !await this.grantedCwd(grant.caller, req.cwd)) {
|
|
32170
32407
|
await fds.closeAll();
|
|
32171
32408
|
throw new SpawnError("EACCES");
|
|
@@ -32186,7 +32423,7 @@ var Launcher = class {
|
|
|
32186
32423
|
const scope = grant ? "" : await this.scopeOf(cred.euid);
|
|
32187
32424
|
const file = booked === void 0 ? req.file : await this.ticketFile(req, fds);
|
|
32188
32425
|
const planned = await this.checkedPlan({ ...req, file }, { ppid, cred, scope }, fds);
|
|
32189
|
-
const redeemed = await this.redeemed(
|
|
32426
|
+
const { recheck, ...redeemed } = await this.redeemed(
|
|
32190
32427
|
{ ...req, file },
|
|
32191
32428
|
{ ppid, cred, scope, booked },
|
|
32192
32429
|
planned,
|
|
@@ -32194,7 +32431,9 @@ var Launcher = class {
|
|
|
32194
32431
|
);
|
|
32195
32432
|
const exec = req.exec ? { exec: true } : {};
|
|
32196
32433
|
const deciding = req.exec ? void 0 : this.undecided(ppid);
|
|
32197
|
-
const
|
|
32434
|
+
const replan = () => this.planOrSearch({ ...req, file }, { ppid, cred, scope });
|
|
32435
|
+
const again = { ...planned, replan, recheck };
|
|
32436
|
+
const handle = await this.launch(again, {
|
|
32198
32437
|
...deciding ? { decided: deciding.promise } : {},
|
|
32199
32438
|
cwd: req.cwd,
|
|
32200
32439
|
cwdFrom: inheritedCwd(req.chdir, this.cwdSlots.get(ppid)),
|
|
@@ -33076,10 +33315,12 @@ var Launcher = class {
|
|
|
33076
33315
|
nodes.changed = (path) => this.changes.publish(path);
|
|
33077
33316
|
nodes.movedAway = (from, to) => this.moved(from, to, nodes);
|
|
33078
33317
|
nodes.dirtied = (delta) => this.changes.dirtied(delta);
|
|
33079
|
-
|
|
33318
|
+
const kept = keepingOpen(fs, nodes, (path) => this.changes.publish(path));
|
|
33319
|
+
return this.swaps.wrap(unlinked.wrap(kept));
|
|
33080
33320
|
}
|
|
33081
33321
|
async starting(argv, dir, account, tags, base) {
|
|
33082
33322
|
const tag = tags?.[0];
|
|
33323
|
+
await this.swaps.settled();
|
|
33083
33324
|
this.resetCatalogs();
|
|
33084
33325
|
const scope = account.uid === 0 ? "" : pnpmHomeOf(account, this.pnpmHome);
|
|
33085
33326
|
const start2 = dir ?? "/";
|
|
@@ -33088,9 +33329,13 @@ var Launcher = class {
|
|
|
33088
33329
|
const file = await this.execFile(argv[0] ?? "", cwd, this.execGuard(credOf(account), 0, tag));
|
|
33089
33330
|
if (!await this.base.exists(cwd))
|
|
33090
33331
|
await this.stackFor(tags, base).fs.mkdir(cwd, { recursive: true });
|
|
33091
|
-
const
|
|
33092
|
-
|
|
33093
|
-
|
|
33332
|
+
const plan = async () => {
|
|
33333
|
+
const found = await this.plan(file, argv, cwd, scope);
|
|
33334
|
+
await this.mayExec(credOf(account), { file, cwd, pid: 0, tag }, found);
|
|
33335
|
+
return found;
|
|
33336
|
+
};
|
|
33337
|
+
const planned = await plan();
|
|
33338
|
+
return { cwd, file, planned: planned && { ...planned, replan: plan } };
|
|
33094
33339
|
}
|
|
33095
33340
|
async openTerminal(argv, options) {
|
|
33096
33341
|
const tagged = tagsOption(options);
|