@ai-ecoverse/slicc-kernel 1.64.2 → 1.65.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 +7 -1
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +314 -95
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +362 -187
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +297 -76
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +362 -187
- package/dist/process-worker.js.map +4 -4
- package/package.json +1 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -1,18 +1,99 @@
|
|
|
1
|
+
// src/fs/path-map.ts
|
|
2
|
+
function parentOf(path) {
|
|
3
|
+
if (path === "/" || path === "") return void 0;
|
|
4
|
+
const at = path.lastIndexOf("/");
|
|
5
|
+
return at <= 0 ? "/" : path.slice(0, at);
|
|
6
|
+
}
|
|
7
|
+
var PathMap = class {
|
|
8
|
+
values = /* @__PURE__ */ new Map();
|
|
9
|
+
children = /* @__PURE__ */ new Map();
|
|
10
|
+
get size() {
|
|
11
|
+
return this.values.size;
|
|
12
|
+
}
|
|
13
|
+
has(path) {
|
|
14
|
+
return this.values.has(path);
|
|
15
|
+
}
|
|
16
|
+
get(path) {
|
|
17
|
+
return this.values.get(path);
|
|
18
|
+
}
|
|
19
|
+
keys() {
|
|
20
|
+
return this.values.keys();
|
|
21
|
+
}
|
|
22
|
+
set(path, value) {
|
|
23
|
+
if (!this.values.has(path)) this.link(path);
|
|
24
|
+
this.values.set(path, value);
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
delete(path) {
|
|
28
|
+
if (!this.values.delete(path)) return false;
|
|
29
|
+
this.prune(path);
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
subtree(root) {
|
|
33
|
+
const out = [];
|
|
34
|
+
const stack = [root];
|
|
35
|
+
for (let path = stack.pop(); path !== void 0; path = stack.pop()) {
|
|
36
|
+
if (this.values.has(path)) out.push(path);
|
|
37
|
+
const below = this.children.get(path);
|
|
38
|
+
if (below) for (const child of below) stack.push(child);
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
entries() {
|
|
43
|
+
return this.values.entries();
|
|
44
|
+
}
|
|
45
|
+
deleteTree(root) {
|
|
46
|
+
const stack = [root];
|
|
47
|
+
for (let path = stack.pop(); path !== void 0; path = stack.pop()) {
|
|
48
|
+
this.values.delete(path);
|
|
49
|
+
const below = this.children.get(path);
|
|
50
|
+
if (below) for (const child of below) stack.push(child);
|
|
51
|
+
this.children.delete(path);
|
|
52
|
+
}
|
|
53
|
+
this.prune(root);
|
|
54
|
+
}
|
|
55
|
+
clear() {
|
|
56
|
+
this.values.clear();
|
|
57
|
+
this.children.clear();
|
|
58
|
+
}
|
|
59
|
+
link(path) {
|
|
60
|
+
for (let child = path, parent = parentOf(path); parent !== void 0; ) {
|
|
61
|
+
const set2 = this.children.get(parent);
|
|
62
|
+
if (set2?.has(child)) return;
|
|
63
|
+
if (set2) set2.add(child);
|
|
64
|
+
else this.children.set(parent, /* @__PURE__ */ new Set([child]));
|
|
65
|
+
child = parent;
|
|
66
|
+
parent = parentOf(parent);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
prune(path) {
|
|
70
|
+
for (let child = path, parent = parentOf(path); parent !== void 0; ) {
|
|
71
|
+
if (this.values.has(child) || this.children.has(child)) return;
|
|
72
|
+
const set2 = this.children.get(parent);
|
|
73
|
+
set2?.delete(child);
|
|
74
|
+
if (set2 && set2.size > 0) return;
|
|
75
|
+
this.children.delete(parent);
|
|
76
|
+
child = parent;
|
|
77
|
+
parent = parentOf(parent);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
1
82
|
// src/fs/meta.ts
|
|
2
83
|
var META_DB = "slicc-kernel";
|
|
3
84
|
var META_VERSION = 1;
|
|
4
85
|
var META_STORE = "entries";
|
|
5
|
-
function
|
|
86
|
+
function parentOf2(path) {
|
|
6
87
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
7
88
|
}
|
|
8
89
|
function moved(entry, path) {
|
|
9
|
-
return entry.link === void 0 ? { ...entry, path } : { ...entry, path, dir:
|
|
90
|
+
return entry.link === void 0 ? { ...entry, path } : { ...entry, path, dir: parentOf2(path) };
|
|
10
91
|
}
|
|
11
92
|
function under(path, root) {
|
|
12
93
|
return path === root || path.startsWith(`${root}/`);
|
|
13
94
|
}
|
|
14
95
|
var MemoryMeta = class {
|
|
15
|
-
entries =
|
|
96
|
+
entries = new PathMap();
|
|
16
97
|
async get(paths) {
|
|
17
98
|
return paths.map((path) => this.entries.get(path));
|
|
18
99
|
}
|
|
@@ -25,7 +106,7 @@ var MemoryMeta = class {
|
|
|
25
106
|
}
|
|
26
107
|
async move(from, to, root) {
|
|
27
108
|
await this.remove([to]);
|
|
28
|
-
const carried =
|
|
109
|
+
const carried = this.entries.subtree(from).map((path) => this.entries.get(path));
|
|
29
110
|
for (const entry of carried) this.entries.delete(entry.path);
|
|
30
111
|
for (const entry of carried) {
|
|
31
112
|
const path = to + entry.path.slice(from.length);
|
|
@@ -34,18 +115,16 @@ var MemoryMeta = class {
|
|
|
34
115
|
this.entries.set(to, moved(root(carried.find((entry) => entry.path === from)), to));
|
|
35
116
|
}
|
|
36
117
|
async remove(paths) {
|
|
37
|
-
for (const
|
|
38
|
-
if (paths.some((path) => under(key, path))) this.entries.delete(key);
|
|
39
|
-
}
|
|
118
|
+
for (const path of paths) this.entries.deleteTree(path);
|
|
40
119
|
}
|
|
41
120
|
async links(dir) {
|
|
42
|
-
return [...this.entries.
|
|
121
|
+
return [...this.entries.entries()].map(([, e]) => e).filter((entry) => entry.dir === dir);
|
|
43
122
|
}
|
|
44
123
|
async under(path) {
|
|
45
|
-
return [...this.entries.
|
|
124
|
+
return [...this.entries.entries()].map(([, e]) => e).filter((entry) => under(entry.path, path));
|
|
46
125
|
}
|
|
47
126
|
async all() {
|
|
48
|
-
return [...this.entries.
|
|
127
|
+
return [...this.entries.entries()].map(([, e]) => e);
|
|
49
128
|
}
|
|
50
129
|
};
|
|
51
130
|
function descendants(path) {
|
|
@@ -59,7 +138,7 @@ function settle(transaction, value) {
|
|
|
59
138
|
}
|
|
60
139
|
var IndexedDbMeta = class {
|
|
61
140
|
db;
|
|
62
|
-
cache =
|
|
141
|
+
cache = new PathMap();
|
|
63
142
|
channel;
|
|
64
143
|
generation = 0;
|
|
65
144
|
constructor(db) {
|
|
@@ -72,9 +151,7 @@ var IndexedDbMeta = class {
|
|
|
72
151
|
drop({ paths = [], trees = [] }) {
|
|
73
152
|
this.generation++;
|
|
74
153
|
for (const path of paths) this.cache.delete(path);
|
|
75
|
-
for (const
|
|
76
|
-
if (trees.some((tree2) => under(key, tree2))) this.cache.delete(key);
|
|
77
|
-
}
|
|
154
|
+
for (const tree2 of trees) this.cache.deleteTree(tree2);
|
|
78
155
|
}
|
|
79
156
|
changed(invalidation2) {
|
|
80
157
|
this.drop(invalidation2);
|
|
@@ -327,7 +404,7 @@ function missing(err) {
|
|
|
327
404
|
function split(path) {
|
|
328
405
|
return path.split("/").filter(Boolean);
|
|
329
406
|
}
|
|
330
|
-
function
|
|
407
|
+
function parentOf3(path) {
|
|
331
408
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
332
409
|
}
|
|
333
410
|
function baseOf(path) {
|
|
@@ -400,7 +477,7 @@ function isHandle(child) {
|
|
|
400
477
|
var OpfsFs = class {
|
|
401
478
|
root;
|
|
402
479
|
meta;
|
|
403
|
-
dirs =
|
|
480
|
+
dirs = new PathMap();
|
|
404
481
|
checked = /* @__PURE__ */ new WeakMap();
|
|
405
482
|
channel;
|
|
406
483
|
ranged;
|
|
@@ -449,7 +526,7 @@ var OpfsFs = class {
|
|
|
449
526
|
async ownerAt(path, entry) {
|
|
450
527
|
const own = ownOf(entry);
|
|
451
528
|
if (own) return own;
|
|
452
|
-
return path === "/" ? { ...ROOT_OWNER } : this.handedTo(
|
|
529
|
+
return path === "/" ? { ...ROOT_OWNER } : this.handedTo(parentOf3(path));
|
|
453
530
|
}
|
|
454
531
|
async owned(stat, path, entry) {
|
|
455
532
|
return this.owners ? { ...stat, ...await this.ownerAt(path, entry) } : stat;
|
|
@@ -479,7 +556,7 @@ var OpfsFs = class {
|
|
|
479
556
|
async chown(path, change) {
|
|
480
557
|
if (!this.owners) return;
|
|
481
558
|
if (change.kind === "new") {
|
|
482
|
-
const at = resolvePath((await this.locate(
|
|
559
|
+
const at = resolvePath((await this.locate(parentOf3(path), true)).path, baseOf(path));
|
|
483
560
|
const { uid = 0, gid = 0, mode } = change;
|
|
484
561
|
return this.stampNew(at, { uid, gid, ...mode !== void 0 ? { mode } : {} }, false);
|
|
485
562
|
}
|
|
@@ -543,7 +620,7 @@ var OpfsFs = class {
|
|
|
543
620
|
return true;
|
|
544
621
|
}
|
|
545
622
|
forget(path) {
|
|
546
|
-
|
|
623
|
+
this.dirs.deleteTree(path);
|
|
547
624
|
}
|
|
548
625
|
async inDir(path, op) {
|
|
549
626
|
const dir = await this.dir(path);
|
|
@@ -590,7 +667,7 @@ var OpfsFs = class {
|
|
|
590
667
|
async linkAlong(path) {
|
|
591
668
|
for (const entry of await this.meta.get(prefixes(path))) {
|
|
592
669
|
if (entry?.link === void 0) continue;
|
|
593
|
-
if (!await this.real(entry.path) && await this.real(
|
|
670
|
+
if (!await this.real(entry.path) && await this.real(parentOf3(entry.path))) return entry;
|
|
594
671
|
}
|
|
595
672
|
return void 0;
|
|
596
673
|
}
|
|
@@ -605,7 +682,7 @@ var OpfsFs = class {
|
|
|
605
682
|
if (!link2) throw err;
|
|
606
683
|
if (link2.path === current && !follow2) return { path: current, link: link2 };
|
|
607
684
|
const target = `${link2.link}${current.slice(link2.path.length)}`;
|
|
608
|
-
current = target.split("/").includes("..") ? await this.physical(
|
|
685
|
+
current = target.split("/").includes("..") ? await this.physical(parentOf3(link2.path), target, hops + 1) : resolvePath(parentOf3(link2.path), target);
|
|
609
686
|
}
|
|
610
687
|
}
|
|
611
688
|
throw fsError("ELOOP", path);
|
|
@@ -795,8 +872,8 @@ var OpfsFs = class {
|
|
|
795
872
|
if (!missing(err)) throw err;
|
|
796
873
|
}
|
|
797
874
|
const [entry] = await this.meta.get([path]);
|
|
798
|
-
const wanted = entry?.link === void 0 ? path : resolvePath(
|
|
799
|
-
return [resolvePath((await this.locate(
|
|
875
|
+
const wanted = entry?.link === void 0 ? path : resolvePath(parentOf3(path), entry.link);
|
|
876
|
+
return [resolvePath((await this.locate(parentOf3(wanted), true)).path, baseOf(wanted)), false];
|
|
800
877
|
}
|
|
801
878
|
async fileFor(path) {
|
|
802
879
|
const [target, existed] = await this.writeTarget(path);
|
|
@@ -806,7 +883,7 @@ var OpfsFs = class {
|
|
|
806
883
|
dir,
|
|
807
884
|
(parent) => parent.getFileHandle(name2, { create: true })
|
|
808
885
|
);
|
|
809
|
-
if (!existed) this.touch(
|
|
886
|
+
if (!existed) this.touch(parentOf3(target));
|
|
810
887
|
return [handle, existed, target];
|
|
811
888
|
} catch (err) {
|
|
812
889
|
const code = err?.name === "TypeMismatchError" ? "EISDIR" : null;
|
|
@@ -876,9 +953,9 @@ var OpfsFs = class {
|
|
|
876
953
|
gid: owner.gid,
|
|
877
954
|
...mode ? { mode, parents: mode } : {}
|
|
878
955
|
};
|
|
879
|
-
await this.mkdir(
|
|
956
|
+
await this.mkdir(parentOf3(path), { recursive: true, ...above ? { owner: above } : {} });
|
|
880
957
|
}
|
|
881
|
-
const parent = await this.locate(
|
|
958
|
+
const parent = await this.locate(parentOf3(path), true);
|
|
882
959
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
883
960
|
await parent.handle.getDirectoryHandle(baseOf(path), { create: true });
|
|
884
961
|
const made2 = `${parent.path === "/" ? "" : parent.path}/${baseOf(path)}`;
|
|
@@ -907,7 +984,7 @@ var OpfsFs = class {
|
|
|
907
984
|
this.changed(found.path);
|
|
908
985
|
}
|
|
909
986
|
await this.meta.remove([found.path]);
|
|
910
|
-
this.touch(
|
|
987
|
+
this.touch(parentOf3(found.path));
|
|
911
988
|
}
|
|
912
989
|
links() {
|
|
913
990
|
return false;
|
|
@@ -919,7 +996,7 @@ var OpfsFs = class {
|
|
|
919
996
|
if (from === to) return;
|
|
920
997
|
const source = await this.locate(from, false);
|
|
921
998
|
this.forget(source.path);
|
|
922
|
-
const parent = await this.locate(
|
|
999
|
+
const parent = await this.locate(parentOf3(to), true);
|
|
923
1000
|
const destination = resolvePath(parent.path, baseOf(to));
|
|
924
1001
|
const sourceStat = await this.describe(source);
|
|
925
1002
|
if (sourceStat.isDirectory && within(destination, source.path)) throw fsError("EINVAL", to);
|
|
@@ -947,7 +1024,7 @@ var OpfsFs = class {
|
|
|
947
1024
|
if (source.link) {
|
|
948
1025
|
if (target?.handle) await this.rm(destination);
|
|
949
1026
|
await this.meta.move(source.path, destination, carry);
|
|
950
|
-
this.touch(
|
|
1027
|
+
this.touch(parentOf3(source.path), parent.path);
|
|
951
1028
|
return;
|
|
952
1029
|
}
|
|
953
1030
|
const dir = parent.handle;
|
|
@@ -969,7 +1046,7 @@ var OpfsFs = class {
|
|
|
969
1046
|
}
|
|
970
1047
|
if (copied) await this.restamp(destination, timed2);
|
|
971
1048
|
this.changed(source.path, destination);
|
|
972
|
-
this.touch(
|
|
1049
|
+
this.touch(parentOf3(source.path), parent.path);
|
|
973
1050
|
}
|
|
974
1051
|
async modified(path) {
|
|
975
1052
|
const handle = await this.handle(path);
|
|
@@ -1015,7 +1092,7 @@ var OpfsFs = class {
|
|
|
1015
1092
|
for await (const child of handle.values()) await this.copy(child, target, child.name);
|
|
1016
1093
|
}
|
|
1017
1094
|
async symlink(target, path, owner) {
|
|
1018
|
-
const parent = await this.locate(
|
|
1095
|
+
const parent = await this.locate(parentOf3(path), true);
|
|
1019
1096
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
1020
1097
|
const at = resolvePath(parent.path, baseOf(path));
|
|
1021
1098
|
if (await this.locate(at, false).then(
|
|
@@ -1091,7 +1168,7 @@ var OpfsFs = class {
|
|
|
1091
1168
|
let removed = 0;
|
|
1092
1169
|
for (const entry of await this.meta.all()) {
|
|
1093
1170
|
const real = await this.real(entry.path);
|
|
1094
|
-
const stale = entry.link === void 0 ? !real : real || !await this.real(
|
|
1171
|
+
const stale = entry.link === void 0 ? !real : real || !await this.real(parentOf3(entry.path));
|
|
1095
1172
|
if (!stale) continue;
|
|
1096
1173
|
await this.meta.update(entry.path, () => void 0);
|
|
1097
1174
|
removed++;
|
|
@@ -1262,7 +1339,7 @@ function versionError(theirs) {
|
|
|
1262
1339
|
|
|
1263
1340
|
// src/fs/walk.ts
|
|
1264
1341
|
var MAX_LINKS2 = 40;
|
|
1265
|
-
function
|
|
1342
|
+
function parentOf4(path) {
|
|
1266
1343
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
1267
1344
|
}
|
|
1268
1345
|
async function mustBeDir(fs, path) {
|
|
@@ -1280,7 +1357,7 @@ async function realDir(fs, dir, budget = { hops: 0 }) {
|
|
|
1280
1357
|
const part = queue.shift();
|
|
1281
1358
|
if (part === ".") continue;
|
|
1282
1359
|
if (part === "..") {
|
|
1283
|
-
at =
|
|
1360
|
+
at = parentOf4(at);
|
|
1284
1361
|
continue;
|
|
1285
1362
|
}
|
|
1286
1363
|
const next2 = at === "/" ? `/${part}` : `${at}/${part}`;
|
|
@@ -1302,7 +1379,7 @@ function joinName(dir, name2) {
|
|
|
1302
1379
|
}
|
|
1303
1380
|
async function realTarget(fs, path) {
|
|
1304
1381
|
const budget = { hops: 0 };
|
|
1305
|
-
let dir = await realDir(fs,
|
|
1382
|
+
let dir = await realDir(fs, parentOf4(path), budget);
|
|
1306
1383
|
let name2 = path.slice(path.lastIndexOf("/") + 1);
|
|
1307
1384
|
for (; ; ) {
|
|
1308
1385
|
const link2 = await linkOf(fs, joinName(dir, name2));
|
|
@@ -1310,7 +1387,7 @@ async function realTarget(fs, path) {
|
|
|
1310
1387
|
if (budget.hops >= MAX_LINKS2) throw fsError("ELOOP", path);
|
|
1311
1388
|
budget.hops++;
|
|
1312
1389
|
const target = link2.startsWith("/") ? link2 : joinName(dir, link2);
|
|
1313
|
-
dir = await realDir(fs,
|
|
1390
|
+
dir = await realDir(fs, parentOf4(target), budget);
|
|
1314
1391
|
name2 = target.slice(target.lastIndexOf("/") + 1);
|
|
1315
1392
|
}
|
|
1316
1393
|
return joinName(dir, name2);
|
|
@@ -1384,7 +1461,7 @@ async function walk(fs, cred, path, follow2) {
|
|
|
1384
1461
|
if (!dir) return { path: joinName(at, [part, ...queue].join("/")), perm: void 0 };
|
|
1385
1462
|
if (!permits(cred, dir, X_OK)) return { path, perm: void 0, denied: at };
|
|
1386
1463
|
if (part === "..") {
|
|
1387
|
-
at =
|
|
1464
|
+
at = parentOf4(at);
|
|
1388
1465
|
continue;
|
|
1389
1466
|
}
|
|
1390
1467
|
const next2 = joinName(at, part);
|
|
@@ -1506,17 +1583,17 @@ async function stickyEntry(g, op, path, dir) {
|
|
|
1506
1583
|
}
|
|
1507
1584
|
async function inParent(g, op, path, old = false) {
|
|
1508
1585
|
if (old === "replaced") {
|
|
1509
|
-
const dir2 = await need(g, op,
|
|
1586
|
+
const dir2 = await need(g, op, parentOf4(path), W_OK | X_OK, DIR, path);
|
|
1510
1587
|
return dir2.denied === void 0 ? stickyEntry(g, op, path, dir2) : void 0;
|
|
1511
1588
|
}
|
|
1512
|
-
if (!old) return void await need(g, op,
|
|
1513
|
-
const dir = await access(g.fs, g.cred,
|
|
1589
|
+
if (!old) return void await need(g, op, parentOf4(path), W_OK | X_OK, DIR, path);
|
|
1590
|
+
const dir = await access(g.fs, g.cred, parentOf4(path), W_OK | X_OK, DIR);
|
|
1514
1591
|
if (dir.denied === void 0) return stickyEntry(g, op, path, dir);
|
|
1515
1592
|
const lookup = dir.denied === dir.path && dir.perm && permits(g.cred, dir.perm, X_OK);
|
|
1516
1593
|
if (!lookup || await present(g.fs, entryIn(dir, path), false)) deny(g, op, path);
|
|
1517
1594
|
}
|
|
1518
1595
|
async function makeIn(g, op, path) {
|
|
1519
|
-
for (let dir =
|
|
1596
|
+
for (let dir = parentOf4(path); ; dir = parentOf4(dir)) {
|
|
1520
1597
|
const walked = await access(g.fs, g.cred, dir, W_OK | X_OK, DIR);
|
|
1521
1598
|
if (walked.denied !== void 0) {
|
|
1522
1599
|
if (!await present(g.fs, path, true)) deny(g, op, path);
|
|
@@ -1544,7 +1621,7 @@ async function renamable(g, from, to) {
|
|
|
1544
1621
|
if (from === to) return void await need(g, "rename", from, 0, { follow: false });
|
|
1545
1622
|
await inParent(g, "rename", from, true);
|
|
1546
1623
|
await inParent(g, "rename", to, "replaced");
|
|
1547
|
-
if (g.cred.euid === 0 ||
|
|
1624
|
+
if (g.cred.euid === 0 || parentOf4(from) === parentOf4(to)) return;
|
|
1548
1625
|
const st = await g.fs.lstat(from).catch(() => void 0);
|
|
1549
1626
|
if (st?.isDirectory && !permits(g.cred, permOf(st), W_OK)) deny(g, "rename", from);
|
|
1550
1627
|
}
|
|
@@ -1598,7 +1675,7 @@ async function writable(g, op, path) {
|
|
|
1598
1675
|
}
|
|
1599
1676
|
async function creatable(g, op, path) {
|
|
1600
1677
|
const target = await need(g, op, path, 0);
|
|
1601
|
-
if (target.denied === void 0) await need(g, op,
|
|
1678
|
+
if (target.denied === void 0) await need(g, op, parentOf4(target.path), W_OK | X_OK, DIR, path);
|
|
1602
1679
|
}
|
|
1603
1680
|
async function openable(g, op, path, want, create) {
|
|
1604
1681
|
const st = create ? await g.fs.stat(path).catch(() => void 0) : void 0;
|
|
@@ -3516,7 +3593,7 @@ function cdpRegistry(send, gone) {
|
|
|
3516
3593
|
function visibleTo(g, notify) {
|
|
3517
3594
|
if (!g?.dac.enforcing) return notify;
|
|
3518
3595
|
let queue = Promise.resolve();
|
|
3519
|
-
const seen = async (path) => (await access(g.fs, g.cred,
|
|
3596
|
+
const seen = async (path) => (await access(g.fs, g.cred, parentOf4(path), R_OK | X_OK, { directory: true })).denied === void 0;
|
|
3520
3597
|
return (change) => {
|
|
3521
3598
|
queue = queue.then(async () => {
|
|
3522
3599
|
if (!("paths" in change)) return notify(change);
|
|
@@ -6504,7 +6581,7 @@ function webLocks() {
|
|
|
6504
6581
|
return globalThis.navigator?.locks;
|
|
6505
6582
|
}
|
|
6506
6583
|
var within3 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
6507
|
-
var
|
|
6584
|
+
var parentOf5 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
6508
6585
|
var lockName = (instance) => `slicc-unlinked:${instance}`;
|
|
6509
6586
|
var dirOf = (root) => root === "/" ? `/${UNLINKED_DIR}` : `${root}/${UNLINKED_DIR}`;
|
|
6510
6587
|
var PathGate = class {
|
|
@@ -6637,7 +6714,7 @@ var UnlinkedKeeper = class {
|
|
|
6637
6714
|
await this.serial(async () => {
|
|
6638
6715
|
await Promise.allSettled([this.fs.rename(file.hidden, path)]);
|
|
6639
6716
|
this.unlinkedName(file.hidden);
|
|
6640
|
-
await this.tidy(
|
|
6717
|
+
await this.tidy(parentOf5(file.hidden));
|
|
6641
6718
|
});
|
|
6642
6719
|
}
|
|
6643
6720
|
done4();
|
|
@@ -6678,7 +6755,7 @@ var UnlinkedKeeper = class {
|
|
|
6678
6755
|
}
|
|
6679
6756
|
await this.fs.rm(hidden).catch(() => void 0);
|
|
6680
6757
|
this.unlinkedName(hidden);
|
|
6681
|
-
await this.tidy(
|
|
6758
|
+
await this.tidy(parentOf5(hidden));
|
|
6682
6759
|
}
|
|
6683
6760
|
async linkedName(hidden) {
|
|
6684
6761
|
if (!mayLink(this.fs, hidden)) return;
|
|
@@ -6723,10 +6800,10 @@ var UnlinkedKeeper = class {
|
|
|
6723
6800
|
// src/fs/watch.ts
|
|
6724
6801
|
var WATCH_BATCH_LIMIT = 1e3;
|
|
6725
6802
|
var under2 = (path, dir) => dir === "/" || path.startsWith(`${dir}/`);
|
|
6726
|
-
var
|
|
6803
|
+
var parentOf6 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
6727
6804
|
function touches(watcher, changed) {
|
|
6728
6805
|
return watcher.paths.some(
|
|
6729
|
-
(watched) => changed === watched || under2(watched, changed) || (watcher.recursive ? under2(changed, watched) :
|
|
6806
|
+
(watched) => changed === watched || under2(watched, changed) || (watcher.recursive ? under2(changed, watched) : parentOf6(changed) === watched)
|
|
6730
6807
|
);
|
|
6731
6808
|
}
|
|
6732
6809
|
var FsWatchers = class {
|
|
@@ -6839,6 +6916,23 @@ var CONTINUED_STATUS = 65535;
|
|
|
6839
6916
|
function waitStatus(code, termsig) {
|
|
6840
6917
|
return termsig ? termsig & 127 : (code & 255) << 8;
|
|
6841
6918
|
}
|
|
6919
|
+
function capturing(chunks, max = Number.POSITIVE_INFINITY, overflow) {
|
|
6920
|
+
let size = 0;
|
|
6921
|
+
let over = false;
|
|
6922
|
+
return (bytes) => {
|
|
6923
|
+
if (over) return;
|
|
6924
|
+
const room = max - size;
|
|
6925
|
+
if (bytes.length > room) {
|
|
6926
|
+
over = true;
|
|
6927
|
+
if (room > 0) chunks.push(bytes.slice(0, room));
|
|
6928
|
+
size = max;
|
|
6929
|
+
overflow?.();
|
|
6930
|
+
return;
|
|
6931
|
+
}
|
|
6932
|
+
chunks.push(bytes);
|
|
6933
|
+
size += bytes.length;
|
|
6934
|
+
};
|
|
6935
|
+
}
|
|
6842
6936
|
function concat3(chunks) {
|
|
6843
6937
|
const out = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));
|
|
6844
6938
|
let offset = 0;
|
|
@@ -6872,15 +6966,15 @@ var ChildTable = class {
|
|
|
6872
6966
|
const fds = new FdTable();
|
|
6873
6967
|
const captured = /* @__PURE__ */ new Map();
|
|
6874
6968
|
try {
|
|
6875
|
-
for (const [n,
|
|
6876
|
-
for (const
|
|
6877
|
-
if (
|
|
6878
|
-
if ("device" in
|
|
6879
|
-
fds.installAt(
|
|
6969
|
+
for (const [n, slot2] of stdio.entries()) fds.installAt(n, this.openSlot(slot2, n, captured));
|
|
6970
|
+
for (const slot2 of inherit2) {
|
|
6971
|
+
if (slot2.fd <= 2) continue;
|
|
6972
|
+
if ("device" in slot2) {
|
|
6973
|
+
fds.installAt(slot2.fd, deviceFile(slot2.device, slot2.access));
|
|
6880
6974
|
continue;
|
|
6881
6975
|
}
|
|
6882
|
-
fds.installAt(
|
|
6883
|
-
if (
|
|
6976
|
+
fds.installAt(slot2.fd, this.parentFds.get(slot2.kernel).retain());
|
|
6977
|
+
if (slot2.flags !== void 0) fds.setStatusFlags(slot2.fd, slot2.flags);
|
|
6884
6978
|
}
|
|
6885
6979
|
} catch (e) {
|
|
6886
6980
|
await fds.closeAll();
|
|
@@ -6921,15 +7015,15 @@ var ChildTable = class {
|
|
|
6921
7015
|
this.watchers.set(pid, listener);
|
|
6922
7016
|
if (child.stoppedBy !== void 0) listener("stopped", child.stoppedBy);
|
|
6923
7017
|
}
|
|
6924
|
-
openSlot(
|
|
6925
|
-
if ("fd" in
|
|
6926
|
-
if ("input" in
|
|
6927
|
-
if ("device" in
|
|
6928
|
-
if ("dir" in
|
|
6929
|
-
if ("capture" in
|
|
7018
|
+
openSlot(slot2, n, captured) {
|
|
7019
|
+
if ("fd" in slot2) return this.parentFds.get(slot2.fd).retain();
|
|
7020
|
+
if ("input" in slot2) return bytesSource(slot2.input);
|
|
7021
|
+
if ("device" in slot2) return deviceFile(slot2.device, slot2.access);
|
|
7022
|
+
if ("dir" in slot2) return heldFile({ dir: slot2.dir });
|
|
7023
|
+
if ("capture" in slot2) {
|
|
6930
7024
|
const chunks = [];
|
|
6931
7025
|
captured.set(n, chunks);
|
|
6932
|
-
return sinkFile((
|
|
7026
|
+
return sinkFile(capturing(chunks, slot2.max, slot2.overflow));
|
|
6933
7027
|
}
|
|
6934
7028
|
return deviceFile("null");
|
|
6935
7029
|
}
|
|
@@ -6996,11 +7090,11 @@ var ChildTable = class {
|
|
|
6996
7090
|
pids() {
|
|
6997
7091
|
return [...this.children.keys()];
|
|
6998
7092
|
}
|
|
6999
|
-
captured(pid,
|
|
7093
|
+
captured(pid, slot2) {
|
|
7000
7094
|
const slots = this.leftovers.get(pid);
|
|
7001
|
-
const chunks = slots?.get(
|
|
7095
|
+
const chunks = slots?.get(slot2);
|
|
7002
7096
|
if (!slots || !chunks) return new Uint8Array(0);
|
|
7003
|
-
slots.delete(
|
|
7097
|
+
slots.delete(slot2);
|
|
7004
7098
|
if (slots.size === 0) this.leftovers.delete(pid);
|
|
7005
7099
|
return concat3(chunks);
|
|
7006
7100
|
}
|
|
@@ -7286,7 +7380,7 @@ var HeldPaths = class extends Map {
|
|
|
7286
7380
|
return this.revoked.has(path);
|
|
7287
7381
|
}
|
|
7288
7382
|
};
|
|
7289
|
-
var
|
|
7383
|
+
var parentOf7 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
7290
7384
|
var readonly = (mount) => mount.caps.readonly === true || mount.options.ro !== void 0;
|
|
7291
7385
|
function inodeless(mount, attr2) {
|
|
7292
7386
|
if (attr2.ino !== void 0) return false;
|
|
@@ -7566,7 +7660,7 @@ var MountTable = class {
|
|
|
7566
7660
|
mount.epoch++;
|
|
7567
7661
|
for (const key of [...mount.attrs.keys()]) if (within4(key, path)) mount.attrs.delete(key);
|
|
7568
7662
|
mount.lists.delete(path);
|
|
7569
|
-
mount.lists.delete(
|
|
7663
|
+
mount.lists.delete(parentOf7(path));
|
|
7570
7664
|
for (const key of [...mount.lists.keys()]) if (within4(key, path)) mount.lists.delete(key);
|
|
7571
7665
|
}
|
|
7572
7666
|
async getattr(mount, path, rel2, settled = false) {
|
|
@@ -7642,7 +7736,7 @@ var MountFs = class {
|
|
|
7642
7736
|
if (attr2.kind !== "symlink") return real;
|
|
7643
7737
|
if (hops >= MAX_LINKS6) throw errnoError("ELOOP", path);
|
|
7644
7738
|
const target = await found.mount.conn.call({ op: "readlink", path: found.rel });
|
|
7645
|
-
return this.follow(this.base.resolvePath(
|
|
7739
|
+
return this.follow(this.base.resolvePath(parentOf7(real), target), hops + 1, create);
|
|
7646
7740
|
}
|
|
7647
7741
|
async open(mount, rel2, write, owner) {
|
|
7648
7742
|
return await mount.conn.call({
|
|
@@ -7658,8 +7752,8 @@ var MountFs = class {
|
|
|
7658
7752
|
async driverOwner(found, real, owner, directory) {
|
|
7659
7753
|
const { mount, rel: rel2 } = found;
|
|
7660
7754
|
if (!owner || !mount.owners || !mount.caps.owners) return void 0;
|
|
7661
|
-
const dir =
|
|
7662
|
-
const above = statOf(await this.table.getattr(mount, dir,
|
|
7755
|
+
const dir = parentOf7(real);
|
|
7756
|
+
const above = statOf(await this.table.getattr(mount, dir, parentOf7(rel2)), dir, mount);
|
|
7663
7757
|
const setgid = (above.mode & S_ISGID4) !== 0;
|
|
7664
7758
|
let mode = owner.mode;
|
|
7665
7759
|
if (directory && setgid) mode = (mode ?? 493) | S_ISGID4;
|
|
@@ -7998,7 +8092,7 @@ var MountFs = class {
|
|
|
7998
8092
|
}
|
|
7999
8093
|
async named(path) {
|
|
8000
8094
|
const at = normalizePath(path);
|
|
8001
|
-
return joinName(await realDir(this,
|
|
8095
|
+
return joinName(await realDir(this, parentOf7(at)), at.slice(at.lastIndexOf("/") + 1));
|
|
8002
8096
|
}
|
|
8003
8097
|
async link(source, target, follow2 = false) {
|
|
8004
8098
|
const from = follow2 ? await realTarget(this, normalizePath(source)) : await this.named(source);
|
|
@@ -9234,6 +9328,7 @@ var HOST_OPS = [
|
|
|
9234
9328
|
"async-resolve",
|
|
9235
9329
|
"async-hold",
|
|
9236
9330
|
"async-cancel",
|
|
9331
|
+
"async-settle",
|
|
9237
9332
|
"async-close"
|
|
9238
9333
|
];
|
|
9239
9334
|
var json3 = (value) => ({ ok: true, kind: "json", json: value });
|
|
@@ -9265,12 +9360,16 @@ var LockTable = class {
|
|
|
9265
9360
|
for (const path of [...this.held.keys()]) this.unlock(pid, path);
|
|
9266
9361
|
}
|
|
9267
9362
|
};
|
|
9363
|
+
var KEPT_OPS = /* @__PURE__ */ new Set(["fd-write"]);
|
|
9364
|
+
var unknownSettled = false;
|
|
9268
9365
|
var AsyncOps = class {
|
|
9269
9366
|
next = 1;
|
|
9270
9367
|
results = /* @__PURE__ */ new Map();
|
|
9271
9368
|
ready = [];
|
|
9272
9369
|
running = /* @__PURE__ */ new Map();
|
|
9273
9370
|
waiters = /* @__PURE__ */ new Set();
|
|
9371
|
+
taken = /* @__PURE__ */ new Map();
|
|
9372
|
+
kept = /* @__PURE__ */ new Set();
|
|
9274
9373
|
closed = false;
|
|
9275
9374
|
run;
|
|
9276
9375
|
onReady;
|
|
@@ -9280,6 +9379,7 @@ var AsyncOps = class {
|
|
|
9280
9379
|
}
|
|
9281
9380
|
submit(req) {
|
|
9282
9381
|
const id2 = this.hold();
|
|
9382
|
+
if (KEPT_OPS.has(req.op)) this.kept.add(id2);
|
|
9283
9383
|
const running = new AbortController();
|
|
9284
9384
|
this.running.set(id2, running);
|
|
9285
9385
|
this.run(req, running.signal).then(
|
|
@@ -9303,9 +9403,26 @@ var AsyncOps = class {
|
|
|
9303
9403
|
const result = this.results.get(id2);
|
|
9304
9404
|
if (!result) throw new KernelError("EAGAIN");
|
|
9305
9405
|
this.forget(id2);
|
|
9406
|
+
if (this.kept.delete(id2)) this.taken.set(id2, result);
|
|
9306
9407
|
return result;
|
|
9307
9408
|
}
|
|
9409
|
+
ack(ids) {
|
|
9410
|
+
for (const id2 of ids) this.taken.delete(id2);
|
|
9411
|
+
}
|
|
9412
|
+
async settle(ids) {
|
|
9413
|
+
const never = new AbortController().signal;
|
|
9414
|
+
while (ids.some((id2) => this.running.has(id2))) await this.sleep(void 0, never);
|
|
9415
|
+
return ids.map((id2) => {
|
|
9416
|
+
const result = this.results.get(id2) ?? this.taken.get(id2) ?? null;
|
|
9417
|
+
if (!result && !unknownSettled) {
|
|
9418
|
+
unknownSettled = true;
|
|
9419
|
+
console.warn(`async-settle: no result for op ${id2}; its write counts as made`);
|
|
9420
|
+
}
|
|
9421
|
+
return result;
|
|
9422
|
+
});
|
|
9423
|
+
}
|
|
9308
9424
|
cancel(id2) {
|
|
9425
|
+
this.kept.delete(id2);
|
|
9309
9426
|
this.running.get(id2)?.abort();
|
|
9310
9427
|
this.forget(id2);
|
|
9311
9428
|
}
|
|
@@ -9381,6 +9498,7 @@ async function hostSyscall(req, ctx) {
|
|
|
9381
9498
|
return done2;
|
|
9382
9499
|
case "async-submit":
|
|
9383
9500
|
if (!ctx.valid(req.req)) throw new KernelError("EINVAL");
|
|
9501
|
+
if (req.ack) ctx.ops.ack(req.ack);
|
|
9384
9502
|
return json3(ctx.ops.submit(req.req));
|
|
9385
9503
|
case "async-wait":
|
|
9386
9504
|
return json3(await ctx.ops.wait(req.timeoutMs, ctx.blocking));
|
|
@@ -9393,6 +9511,8 @@ async function hostSyscall(req, ctx) {
|
|
|
9393
9511
|
case "async-cancel":
|
|
9394
9512
|
ctx.ops.cancel(req.id);
|
|
9395
9513
|
return done2;
|
|
9514
|
+
case "async-settle":
|
|
9515
|
+
return json3(await ctx.ops.settle(req.ids));
|
|
9396
9516
|
case "async-close":
|
|
9397
9517
|
ctx.ops.close();
|
|
9398
9518
|
return done2;
|
|
@@ -9900,8 +10020,8 @@ var KernelTty = class {
|
|
|
9900
10020
|
get canonical() {
|
|
9901
10021
|
return (this.termios.c_lflag & ICANON) !== 0;
|
|
9902
10022
|
}
|
|
9903
|
-
cc(
|
|
9904
|
-
return this.termios.c_cc[
|
|
10023
|
+
cc(slot2) {
|
|
10024
|
+
return this.termios.c_cc[slot2] ?? 0;
|
|
9905
10025
|
}
|
|
9906
10026
|
key(input) {
|
|
9907
10027
|
const { c_iflag, c_lflag } = this.termios;
|
|
@@ -10256,6 +10376,84 @@ function ptySyscall(req, ctx) {
|
|
|
10256
10376
|
}
|
|
10257
10377
|
}
|
|
10258
10378
|
|
|
10379
|
+
// src/kernel/run-child.ts
|
|
10380
|
+
var RUN_CAPTURE_CAP = 64 * 1024 * 1024;
|
|
10381
|
+
var RUN_MAX_BUFFER = 1024 * 1024;
|
|
10382
|
+
function capLimit(maxBuffer) {
|
|
10383
|
+
const asked = maxBuffer === void 0 ? RUN_MAX_BUFFER : maxBuffer;
|
|
10384
|
+
return Math.max(0, Math.min(asked, RUN_CAPTURE_CAP));
|
|
10385
|
+
}
|
|
10386
|
+
function slot(how, n, extra) {
|
|
10387
|
+
if (how === "inherit") return { fd: n };
|
|
10388
|
+
if (how === "ignore") return { none: true };
|
|
10389
|
+
return extra;
|
|
10390
|
+
}
|
|
10391
|
+
function frame2(outcome, out, err) {
|
|
10392
|
+
const head = new TextEncoder().encode(JSON.stringify(outcome));
|
|
10393
|
+
const bytes = new Uint8Array(4 + head.length + out.length + err.length);
|
|
10394
|
+
new DataView(bytes.buffer).setUint32(0, head.length, true);
|
|
10395
|
+
bytes.set(head, 4);
|
|
10396
|
+
bytes.set(out, 4 + head.length);
|
|
10397
|
+
bytes.set(err, 4 + head.length + out.length);
|
|
10398
|
+
return bytes;
|
|
10399
|
+
}
|
|
10400
|
+
async function reaped(deps, pid) {
|
|
10401
|
+
for (; ; ) {
|
|
10402
|
+
try {
|
|
10403
|
+
return (await deps.children.wait(pid, false, deps.interrupt()))[1];
|
|
10404
|
+
} catch (e) {
|
|
10405
|
+
if (!(e instanceof KernelError && e.code === "EINTR") || deps.dying()) throw e;
|
|
10406
|
+
}
|
|
10407
|
+
}
|
|
10408
|
+
}
|
|
10409
|
+
async function runChild(req, deps) {
|
|
10410
|
+
const max = capLimit(req.maxBuffer);
|
|
10411
|
+
let failure2;
|
|
10412
|
+
let pid = 0;
|
|
10413
|
+
const kill = () => void Promise.allSettled([deps.kill(pid, req.killSignal)]);
|
|
10414
|
+
const stop = (code) => {
|
|
10415
|
+
if (failure2 !== void 0) return;
|
|
10416
|
+
failure2 = code;
|
|
10417
|
+
if (pid !== 0) kill();
|
|
10418
|
+
};
|
|
10419
|
+
const capture = () => ({ capture: true, max, overflow: () => stop("ENOBUFS") });
|
|
10420
|
+
const stdio = [
|
|
10421
|
+
slot(req.stdin, 0, { input: req.input ?? new Uint8Array(0) }),
|
|
10422
|
+
slot(req.stdout, 1, capture()),
|
|
10423
|
+
slot(req.stderr, 2, capture())
|
|
10424
|
+
];
|
|
10425
|
+
try {
|
|
10426
|
+
pid = await deps.children.spawn(
|
|
10427
|
+
{ file: req.file, argv: req.argv, env: req.env, cwd: req.cwd },
|
|
10428
|
+
stdio
|
|
10429
|
+
);
|
|
10430
|
+
} catch (e) {
|
|
10431
|
+
if (!(e instanceof SpawnError)) throw e;
|
|
10432
|
+
const outcome2 = { pid: 0, status: null, error: { code: e.code }, out: 0, err: 0 };
|
|
10433
|
+
return frame2(outcome2, new Uint8Array(0), new Uint8Array(0));
|
|
10434
|
+
}
|
|
10435
|
+
if (failure2 !== void 0) kill();
|
|
10436
|
+
const timer = req.timeoutMs !== void 0 && req.timeoutMs > 0 ? setTimeout(() => stop("ETIMEDOUT"), req.timeoutMs) : void 0;
|
|
10437
|
+
let status;
|
|
10438
|
+
try {
|
|
10439
|
+
status = await reaped(deps, pid);
|
|
10440
|
+
} finally {
|
|
10441
|
+
clearTimeout(timer);
|
|
10442
|
+
}
|
|
10443
|
+
const out = deps.children.captured(pid, 1);
|
|
10444
|
+
const err = deps.children.captured(pid, 2);
|
|
10445
|
+
const termsig = status & 127;
|
|
10446
|
+
const outcome = {
|
|
10447
|
+
pid,
|
|
10448
|
+
status: termsig ? null : status >> 8 & 255,
|
|
10449
|
+
...termsig ? { signal: termsig } : {},
|
|
10450
|
+
...failure2 !== void 0 ? { error: { code: failure2 } } : {},
|
|
10451
|
+
out: out.length,
|
|
10452
|
+
err: err.length
|
|
10453
|
+
};
|
|
10454
|
+
return frame2(outcome, out, err);
|
|
10455
|
+
}
|
|
10456
|
+
|
|
10259
10457
|
// src/kernel/select.ts
|
|
10260
10458
|
function ready(fds, read, write) {
|
|
10261
10459
|
const hangup = /* @__PURE__ */ new Set();
|
|
@@ -10632,7 +10830,7 @@ var VfsNodes = class {
|
|
|
10632
10830
|
return run2;
|
|
10633
10831
|
}
|
|
10634
10832
|
async entryKey(path) {
|
|
10635
|
-
const parent =
|
|
10833
|
+
const parent = parentOf4(path);
|
|
10636
10834
|
const dir = await this.real(parent, true, () => realDir(this.fs, parent));
|
|
10637
10835
|
return joinName(dir, path.slice(path.lastIndexOf("/") + 1));
|
|
10638
10836
|
}
|
|
@@ -10834,7 +11032,7 @@ function errCode(err) {
|
|
|
10834
11032
|
return err?.code;
|
|
10835
11033
|
}
|
|
10836
11034
|
async function targetDir(fs, path) {
|
|
10837
|
-
return
|
|
11035
|
+
return parentOf4(await realTarget(fs, path).catch(() => path));
|
|
10838
11036
|
}
|
|
10839
11037
|
async function refuseReadonly(fs, path, flags, opts = {}) {
|
|
10840
11038
|
const writes = (flags & O_ACCMODE) !== 0 || opts.truncate === true;
|
|
@@ -11052,6 +11250,8 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
11052
11250
|
"proc-spawn",
|
|
11053
11251
|
"proc-wait",
|
|
11054
11252
|
"proc-captured",
|
|
11253
|
+
"proc-run",
|
|
11254
|
+
"proc-exit",
|
|
11055
11255
|
"proc-fork",
|
|
11056
11256
|
"proc-kill",
|
|
11057
11257
|
"thread-kill",
|
|
@@ -11172,6 +11372,14 @@ var WasmProcess = class {
|
|
|
11172
11372
|
else this.adoptExec(pid);
|
|
11173
11373
|
return pid;
|
|
11174
11374
|
}
|
|
11375
|
+
run(req) {
|
|
11376
|
+
return runChild(req, {
|
|
11377
|
+
children: this.children,
|
|
11378
|
+
kill: (pid, sig) => this.options.kill?.(pid, sig),
|
|
11379
|
+
interrupt: () => this.interrupt.signal,
|
|
11380
|
+
dying: () => this.dying
|
|
11381
|
+
});
|
|
11382
|
+
}
|
|
11175
11383
|
adoptExec(pid) {
|
|
11176
11384
|
this.execChild = pid;
|
|
11177
11385
|
this.children.watch(pid, (state, sig) => state === "stopped" ? this.stop(sig) : this.cont());
|
|
@@ -11720,6 +11928,12 @@ var WasmProcess = class {
|
|
|
11720
11928
|
return { ok: true, kind: "json", json: await this.spawn(req) };
|
|
11721
11929
|
case "proc-wait":
|
|
11722
11930
|
return { ok: true, kind: "json", json: await this.procWait(req, cancelled) };
|
|
11931
|
+
case "proc-run":
|
|
11932
|
+
return { ok: true, kind: "bytes", bytes: await this.run(req) };
|
|
11933
|
+
case "proc-exit":
|
|
11934
|
+
if (!this.options.exitNow) throw new KernelError("ENOSYS");
|
|
11935
|
+
this.options.exitNow(req.status & 255);
|
|
11936
|
+
return DYING;
|
|
11723
11937
|
case "proc-identity":
|
|
11724
11938
|
return { ok: true, kind: "json", json: await this.options.identity?.() ?? null };
|
|
11725
11939
|
case "proc-exec": {
|
|
@@ -12126,6 +12340,7 @@ function processOptions(opts, header3, hooks, created3) {
|
|
|
12126
12340
|
hasPending: () => Atomics.load(header3, SAB_I_SIGNALS) !== 0 || Atomics.load(header3, SAB_I_TIMERS) !== 0,
|
|
12127
12341
|
raise: hooks.raise,
|
|
12128
12342
|
threadKill: hooks.threadKill,
|
|
12343
|
+
...hooks.exitNow ? { exitNow: hooks.exitNow } : {},
|
|
12129
12344
|
...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header3, SAB_I_SIGNALS) } : {}
|
|
12130
12345
|
};
|
|
12131
12346
|
}
|
|
@@ -12142,7 +12357,8 @@ function spawnWasmProcess(opts) {
|
|
|
12142
12357
|
header3,
|
|
12143
12358
|
{
|
|
12144
12359
|
raise: (sig) => signal(sig),
|
|
12145
|
-
threadKill: (tid, sig) => killThread(threadSignals.get(tid), process.signalMasks().caught, sig)
|
|
12360
|
+
threadKill: (tid, sig) => killThread(threadSignals.get(tid), process.signalMasks().caught, sig),
|
|
12361
|
+
...opts.program.abi === "js" ? { exitNow: (code) => exitNow(code) } : {}
|
|
12146
12362
|
},
|
|
12147
12363
|
created3
|
|
12148
12364
|
)
|
|
@@ -12183,6 +12399,9 @@ function spawnWasmProcess(opts) {
|
|
|
12183
12399
|
() => settle3(code)
|
|
12184
12400
|
);
|
|
12185
12401
|
};
|
|
12402
|
+
const exitNow = (code) => {
|
|
12403
|
+
queueMicrotask(() => finish(...dying.status(code)));
|
|
12404
|
+
};
|
|
12186
12405
|
const handle = (data) => {
|
|
12187
12406
|
if (data?.type === WASM_PROCESS_EXIT) {
|
|
12188
12407
|
finish(...dying.status(data.code));
|
|
@@ -12918,15 +13137,15 @@ function granted(handle) {
|
|
|
12918
13137
|
);
|
|
12919
13138
|
}
|
|
12920
13139
|
function removableMedium(onLost, open = (handle) => new OpfsFs(handle)) {
|
|
12921
|
-
const
|
|
13140
|
+
const slot2 = mediumSlot(
|
|
12922
13141
|
async (err, handle) => denied(err) && !await granted(handle),
|
|
12923
13142
|
onLost
|
|
12924
13143
|
);
|
|
12925
13144
|
return {
|
|
12926
|
-
handlers:
|
|
12927
|
-
present:
|
|
12928
|
-
insert: (handle) =>
|
|
12929
|
-
eject:
|
|
13145
|
+
handlers: slot2.handlers,
|
|
13146
|
+
present: slot2.present,
|
|
13147
|
+
insert: (handle) => slot2.insert(handle, kernelFsHandlers(open(handle))),
|
|
13148
|
+
eject: slot2.eject
|
|
12930
13149
|
};
|
|
12931
13150
|
}
|
|
12932
13151
|
|
|
@@ -13710,7 +13929,7 @@ function grantConnect(hook, fetch2, liveness = {}) {
|
|
|
13710
13929
|
async function openHostfs(spec, connect, timing = {}) {
|
|
13711
13930
|
const readonly2 = spec.options?.ro !== void 0;
|
|
13712
13931
|
const { port1, port2 } = new MessageChannel();
|
|
13713
|
-
const
|
|
13932
|
+
const slot2 = mediumSlot(
|
|
13714
13933
|
async (err) => unreachable(err),
|
|
13715
13934
|
() => watching.kick()
|
|
13716
13935
|
);
|
|
@@ -13723,7 +13942,7 @@ async function openHostfs(spec, connect, timing = {}) {
|
|
|
13723
13942
|
});
|
|
13724
13943
|
const served = serveFilesystem(
|
|
13725
13944
|
port2,
|
|
13726
|
-
{ ...
|
|
13945
|
+
{ ...slot2.handlers, mount: ranged2 },
|
|
13727
13946
|
{
|
|
13728
13947
|
symlinks: true,
|
|
13729
13948
|
chmod: true,
|
|
@@ -13737,12 +13956,12 @@ async function openHostfs(spec, connect, timing = {}) {
|
|
|
13737
13956
|
connect: () => connect(spec.source, { readonly: readonly2 }),
|
|
13738
13957
|
up(client) {
|
|
13739
13958
|
active = timed(client, timing.callMs ?? HOSTFS_CALL_MS);
|
|
13740
|
-
|
|
13959
|
+
slot2.insert(client, handlers);
|
|
13741
13960
|
served.invalidate(true);
|
|
13742
13961
|
},
|
|
13743
13962
|
event: (event) => served.invalidate(invalidation(event)),
|
|
13744
13963
|
down() {
|
|
13745
|
-
|
|
13964
|
+
slot2.eject();
|
|
13746
13965
|
served.invalidate(true);
|
|
13747
13966
|
},
|
|
13748
13967
|
...timing
|
|
@@ -13752,7 +13971,7 @@ async function openHostfs(spec, connect, timing = {}) {
|
|
|
13752
13971
|
await watching.ready;
|
|
13753
13972
|
return {
|
|
13754
13973
|
port: port1,
|
|
13755
|
-
present:
|
|
13974
|
+
present: slot2.present,
|
|
13756
13975
|
dispose() {
|
|
13757
13976
|
stop.abort();
|
|
13758
13977
|
port1.close();
|
|
@@ -15025,7 +15244,7 @@ var Launcher = class {
|
|
|
15025
15244
|
async realLayoutPath(path) {
|
|
15026
15245
|
if (!await this.base.exists(path)) return void 0;
|
|
15027
15246
|
if (path === "/") return path;
|
|
15028
|
-
return joinName(await realDir(this.base,
|
|
15247
|
+
return joinName(await realDir(this.base, parentOf4(path)), baseName(path));
|
|
15029
15248
|
}
|
|
15030
15249
|
async provisionPnpmHome() {
|
|
15031
15250
|
await this.base.mkdir(this.pnpmHome, { recursive: true }).catch(() => void 0);
|
|
@@ -15046,16 +15265,16 @@ var Launcher = class {
|
|
|
15046
15265
|
}
|
|
15047
15266
|
async insert(target, handle, source) {
|
|
15048
15267
|
const at = normalizePath(target);
|
|
15049
|
-
const
|
|
15050
|
-
if (!
|
|
15051
|
-
if (source !== void 0 && source !== `fsa:${
|
|
15268
|
+
const slot2 = this.removable.get(at);
|
|
15269
|
+
if (!slot2) throw fsError("EINVAL", `${at} is not a removable mount`);
|
|
15270
|
+
if (source !== void 0 && source !== `fsa:${slot2.id}`) {
|
|
15052
15271
|
throw fsError("EINVAL", `${at} is no longer the drive ${source}`);
|
|
15053
15272
|
}
|
|
15054
15273
|
if (!await granted(handle)) throw fsError("EACCES", `${at}: no permission for this folder`);
|
|
15055
|
-
this.inserted.set(
|
|
15056
|
-
await this.media.put(
|
|
15057
|
-
|
|
15058
|
-
|
|
15274
|
+
this.inserted.set(slot2.id, handle);
|
|
15275
|
+
await this.media.put(slot2.id, handle);
|
|
15276
|
+
slot2.medium.insert(handle);
|
|
15277
|
+
slot2.served.invalidate(true);
|
|
15059
15278
|
void this.unlinked.sweep(at);
|
|
15060
15279
|
}
|
|
15061
15280
|
umount(target, detach = false) {
|