@ai-ecoverse/slicc-kernel 1.51.1 → 1.53.0
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 +4 -4
- package/dist/kernel-worker.js +10 -7
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node-process-worker.js +241 -23
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +10 -7
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +241 -6
- package/dist/process-worker.js.map +4 -4
- package/package.json +1 -1
|
@@ -42,19 +42,35 @@ function hide(target, names) {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
+
function vacate(target, names) {
|
|
46
|
+
for (const name2 of names) {
|
|
47
|
+
for (let at = target; at && at !== Object.prototype; ) {
|
|
48
|
+
if (Object.getOwnPropertyDescriptor(at, name2)?.configurable) Reflect.deleteProperty(at, name2);
|
|
49
|
+
at = Object.getPrototypeOf(at);
|
|
50
|
+
}
|
|
51
|
+
Reflect.defineProperty(target, name2, {
|
|
52
|
+
value: void 0,
|
|
53
|
+
writable: true,
|
|
54
|
+
enumerable: false,
|
|
55
|
+
configurable: true
|
|
56
|
+
});
|
|
57
|
+
if (Reflect.get(target, name2) !== void 0) {
|
|
58
|
+
throw new Error(`slicc-kernel: cannot withhold ${name2} from a JS program`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
45
62
|
function lockdown(scope2 = globalThis) {
|
|
46
63
|
hide(scope2, BLOCKED_GLOBALS);
|
|
64
|
+
vacate(scope2, OPEN_SLOTS);
|
|
47
65
|
const navigator = scope2.navigator;
|
|
48
66
|
if (navigator && typeof navigator === "object") hide(navigator, BLOCKED_NAVIGATOR);
|
|
49
67
|
}
|
|
50
|
-
var BLOCKED_GLOBALS, BLOCKED_NAVIGATOR;
|
|
68
|
+
var BLOCKED_GLOBALS, BLOCKED_NAVIGATOR, OPEN_SLOTS;
|
|
51
69
|
var init_lockdown = __esm({
|
|
52
70
|
"src/process/js/lockdown.ts"() {
|
|
53
71
|
"use strict";
|
|
54
72
|
BLOCKED_GLOBALS = [
|
|
55
|
-
"fetch",
|
|
56
73
|
"XMLHttpRequest",
|
|
57
|
-
"WebSocket",
|
|
58
74
|
"WebSocketStream",
|
|
59
75
|
"WebTransport",
|
|
60
76
|
"EventSource",
|
|
@@ -69,6 +85,7 @@ var init_lockdown = __esm({
|
|
|
69
85
|
"close"
|
|
70
86
|
];
|
|
71
87
|
BLOCKED_NAVIGATOR = ["storage", "locks", "serviceWorker"];
|
|
88
|
+
OPEN_SLOTS = ["fetch", "WebSocket"];
|
|
72
89
|
}
|
|
73
90
|
});
|
|
74
91
|
|
|
@@ -969,6 +986,10 @@ function kernelEntry() {
|
|
|
969
986
|
function deviceEntry(meta) {
|
|
970
987
|
return { type: "device", device: meta.device, ...meta.access ? { access: meta.access } : {} };
|
|
971
988
|
}
|
|
989
|
+
function refuseWrite(s, oflags, rights) {
|
|
990
|
+
const writes = (rights & RIGHTS.FD_WRITE) !== 0n || (oflags & OFLAGS.TRUNC) !== 0;
|
|
991
|
+
if (s?.readonly && writes) throw new WasiError("EROFS");
|
|
992
|
+
}
|
|
972
993
|
function preopenOf(e) {
|
|
973
994
|
return {
|
|
974
995
|
...e.preopen ? { preopen: e.preopen } : {},
|
|
@@ -1436,6 +1457,7 @@ var init_wasi_fds = __esm({
|
|
|
1436
1457
|
return this.install({ type: "dir", path });
|
|
1437
1458
|
}
|
|
1438
1459
|
if (!s && !(oflags & OFLAGS.CREAT)) throw new WasiError("ENOENT");
|
|
1460
|
+
refuseWrite(s, oflags, rights);
|
|
1439
1461
|
if (this.shared) return this.kernelFile(path, s, oflags, rights, fdflags);
|
|
1440
1462
|
return this.install({ type: "file", file: this.file(path, s, oflags, rights, fdflags) });
|
|
1441
1463
|
}
|
|
@@ -4444,10 +4466,25 @@ function ttyOps(kernel) {
|
|
|
4444
4466
|
await kernel.call({ op: "tty-pgrp-set", fd, pgrp });
|
|
4445
4467
|
}
|
|
4446
4468
|
};
|
|
4469
|
+
const openOn = async (terminal, fd) => {
|
|
4470
|
+
const open = await kernel.json({ op: "fd-list" });
|
|
4471
|
+
const on = open.filter((entry) => entry.terminal === terminal);
|
|
4472
|
+
return (on.find((entry) => entry.fd === fd) ?? on[0])?.fd;
|
|
4473
|
+
};
|
|
4474
|
+
const reopened = async (terminal, termios) => {
|
|
4475
|
+
const fd = await kernel.json({ op: "fd-open-tty", name: terminal });
|
|
4476
|
+
try {
|
|
4477
|
+
await setAttr(fd, termios);
|
|
4478
|
+
} finally {
|
|
4479
|
+
await kernel.call({ op: "fd-close", fd });
|
|
4480
|
+
}
|
|
4481
|
+
};
|
|
4447
4482
|
const restore = async () => {
|
|
4448
4483
|
for (const [terminal, { fd, termios }] of [...saved].reverse()) {
|
|
4449
4484
|
saved.delete(terminal);
|
|
4450
|
-
await
|
|
4485
|
+
const at = await openOn(terminal, fd).catch(() => void 0);
|
|
4486
|
+
const back = at === void 0 ? reopened(terminal, termios) : setAttr(at, termios);
|
|
4487
|
+
await back.catch(() => void 0);
|
|
4451
4488
|
}
|
|
4452
4489
|
};
|
|
4453
4490
|
return { tty, restore };
|
|
@@ -8625,6 +8662,191 @@ var init_wasi_module = __esm({
|
|
|
8625
8662
|
}
|
|
8626
8663
|
});
|
|
8627
8664
|
|
|
8665
|
+
// src/process/wasi/wasi-procfs.ts
|
|
8666
|
+
function inProc(path) {
|
|
8667
|
+
return path === "/proc" || path.startsWith("/proc/");
|
|
8668
|
+
}
|
|
8669
|
+
function procfsBridge(fs, tree) {
|
|
8670
|
+
const over = {
|
|
8671
|
+
readFile: (p) => inProc(p) ? tree.read(p) : fs.readFile(p),
|
|
8672
|
+
stat: (p) => inProc(p) ? tree.stat(p) : fs.stat(p),
|
|
8673
|
+
lstat: (p) => inProc(p) ? tree.stat(p, false) : fs.lstat(p),
|
|
8674
|
+
readdir: (p) => {
|
|
8675
|
+
if (inProc(p)) return tree.readdir(p);
|
|
8676
|
+
const names = fs.readdir(p);
|
|
8677
|
+
return p === "/" && !names.includes("proc") ? [...names, "proc"] : names;
|
|
8678
|
+
},
|
|
8679
|
+
exists: (p) => inProc(p) ? tree.exists(p) : fs.exists(p),
|
|
8680
|
+
readlink: (p) => inProc(p) ? tree.readlink(p) : fs.readlink(p),
|
|
8681
|
+
readdirStat: (p) => {
|
|
8682
|
+
if (!inProc(p)) {
|
|
8683
|
+
const listed = fs.readdirStat(p);
|
|
8684
|
+
if (p !== "/" || listed.some(([name2]) => name2 === "proc")) return listed;
|
|
8685
|
+
return [...listed, ["proc", tree.stat("/proc")]];
|
|
8686
|
+
}
|
|
8687
|
+
return tree.readdir(p).map((name2) => {
|
|
8688
|
+
try {
|
|
8689
|
+
return [name2, tree.stat(`${p}/${name2}`, false)];
|
|
8690
|
+
} catch {
|
|
8691
|
+
return [name2, null];
|
|
8692
|
+
}
|
|
8693
|
+
});
|
|
8694
|
+
},
|
|
8695
|
+
rename: (from, to) => {
|
|
8696
|
+
if (inProc(from) || inProc(to)) throw syncError("EROFS", from);
|
|
8697
|
+
fs.rename(from, to);
|
|
8698
|
+
},
|
|
8699
|
+
hold: (p, ...rest2) => inProc(p) ? void 0 : fs.hold?.(p, ...rest2),
|
|
8700
|
+
...fs.pread ? {
|
|
8701
|
+
pread: (p, at, n, version) => inProc(p) ? tree.read(p).subarray(at, at + n) : fs.pread(p, at, n, version)
|
|
8702
|
+
} : {}
|
|
8703
|
+
};
|
|
8704
|
+
for (const name2 of READ_ONLY) {
|
|
8705
|
+
const fn = fs[name2];
|
|
8706
|
+
if (!fn) continue;
|
|
8707
|
+
over[name2] = (p, ...rest2) => {
|
|
8708
|
+
if (inProc(p)) throw syncError("EROFS", p);
|
|
8709
|
+
return fn.call(fs, p, ...rest2);
|
|
8710
|
+
};
|
|
8711
|
+
}
|
|
8712
|
+
return new Proxy(fs, {
|
|
8713
|
+
get: (target, key, receiver) => key in over ? over[key] : Reflect.get(target, key, receiver)
|
|
8714
|
+
});
|
|
8715
|
+
}
|
|
8716
|
+
var DIR_MODE3, FILE_MODE2, LINK_MODE3, PID_NAMES, SYSTEM_NAMES, ProcTree, READ_ONLY;
|
|
8717
|
+
var init_wasi_procfs = __esm({
|
|
8718
|
+
"src/process/wasi/wasi-procfs.ts"() {
|
|
8719
|
+
"use strict";
|
|
8720
|
+
init_sync_fs_wire();
|
|
8721
|
+
init_process_fds();
|
|
8722
|
+
init_procfs();
|
|
8723
|
+
DIR_MODE3 = 16749;
|
|
8724
|
+
FILE_MODE2 = 33060;
|
|
8725
|
+
LINK_MODE3 = 41471;
|
|
8726
|
+
PID_NAMES = PID_FILES;
|
|
8727
|
+
SYSTEM_NAMES = SYSTEM_FILES;
|
|
8728
|
+
ProcTree = class {
|
|
8729
|
+
source;
|
|
8730
|
+
pid;
|
|
8731
|
+
memory;
|
|
8732
|
+
constructor(source, pid, memory = memorySource()) {
|
|
8733
|
+
this.source = source;
|
|
8734
|
+
this.pid = pid;
|
|
8735
|
+
this.memory = memory;
|
|
8736
|
+
}
|
|
8737
|
+
listing() {
|
|
8738
|
+
return this.source.procList();
|
|
8739
|
+
}
|
|
8740
|
+
alive(pid) {
|
|
8741
|
+
return this.listing().processes.some((p) => p.pid === pid);
|
|
8742
|
+
}
|
|
8743
|
+
node(parts) {
|
|
8744
|
+
const [top, leaf, ...rest2] = parts;
|
|
8745
|
+
if (top === void 0) {
|
|
8746
|
+
return {
|
|
8747
|
+
kind: "dir",
|
|
8748
|
+
names: () => [
|
|
8749
|
+
...SYSTEM_NAMES,
|
|
8750
|
+
"mounts",
|
|
8751
|
+
"self",
|
|
8752
|
+
...this.listing().processes.map((p) => String(p.pid))
|
|
8753
|
+
]
|
|
8754
|
+
};
|
|
8755
|
+
}
|
|
8756
|
+
if (top === "self") {
|
|
8757
|
+
return leaf === void 0 ? { kind: "link", target: String(this.pid) } : void 0;
|
|
8758
|
+
}
|
|
8759
|
+
if (leaf === void 0 && top === "mounts") {
|
|
8760
|
+
return { kind: "file", content: () => mountTable(this.source.mountList()) };
|
|
8761
|
+
}
|
|
8762
|
+
if (leaf === void 0 && SYSTEM_NAMES.includes(top)) {
|
|
8763
|
+
return {
|
|
8764
|
+
kind: "file",
|
|
8765
|
+
content: () => systemFile(top, this.listing(), Date.now(), this.memory)
|
|
8766
|
+
};
|
|
8767
|
+
}
|
|
8768
|
+
if (!/^[1-9]\d*$/.test(top) || rest2.length > 0 || !this.alive(Number(top))) return void 0;
|
|
8769
|
+
if (leaf === void 0) return { kind: "dir", names: () => [...PID_NAMES] };
|
|
8770
|
+
if (!PID_NAMES.includes(leaf)) return void 0;
|
|
8771
|
+
return {
|
|
8772
|
+
kind: "file",
|
|
8773
|
+
content: () => {
|
|
8774
|
+
const listing = this.listing();
|
|
8775
|
+
const info = listing.processes.find((p) => p.pid === Number(top));
|
|
8776
|
+
if (!info) throw syncError("ENOENT", `/proc/${top}/${leaf}`);
|
|
8777
|
+
return pidFile(leaf, info, listing.boot);
|
|
8778
|
+
}
|
|
8779
|
+
};
|
|
8780
|
+
}
|
|
8781
|
+
parts(path, follow2) {
|
|
8782
|
+
const parts = path.split("/").filter((p) => p !== "").slice(1);
|
|
8783
|
+
if (parts[0] === "self" && (follow2 || parts.length > 1)) parts[0] = String(this.pid);
|
|
8784
|
+
return parts;
|
|
8785
|
+
}
|
|
8786
|
+
find(path, follow2) {
|
|
8787
|
+
const node = this.node(this.parts(path, follow2));
|
|
8788
|
+
if (!node) throw syncError("ENOENT", path);
|
|
8789
|
+
return node;
|
|
8790
|
+
}
|
|
8791
|
+
stat(path, follow2 = true) {
|
|
8792
|
+
const node = this.find(path, follow2);
|
|
8793
|
+
const base = {
|
|
8794
|
+
isFile: false,
|
|
8795
|
+
isDirectory: false,
|
|
8796
|
+
size: 0,
|
|
8797
|
+
mtimeMs: Date.now(),
|
|
8798
|
+
readonly: true
|
|
8799
|
+
};
|
|
8800
|
+
if (node.kind === "dir") return { ...base, isDirectory: true, mode: DIR_MODE3 };
|
|
8801
|
+
if (node.kind === "link") {
|
|
8802
|
+
return { ...base, isSymbolicLink: true, mode: LINK_MODE3, size: node.target.length };
|
|
8803
|
+
}
|
|
8804
|
+
return { ...base, isFile: true, mode: FILE_MODE2, size: this.bytes(node).length };
|
|
8805
|
+
}
|
|
8806
|
+
bytes(node) {
|
|
8807
|
+
return new TextEncoder().encode(node.kind === "file" ? node.content() : "");
|
|
8808
|
+
}
|
|
8809
|
+
read(path) {
|
|
8810
|
+
const node = this.find(path, true);
|
|
8811
|
+
if (node.kind !== "file") throw syncError("EISDIR", path);
|
|
8812
|
+
return this.bytes(node);
|
|
8813
|
+
}
|
|
8814
|
+
readdir(path) {
|
|
8815
|
+
const node = this.find(path, true);
|
|
8816
|
+
if (node.kind !== "dir") throw syncError("ENOTDIR", path);
|
|
8817
|
+
return node.names();
|
|
8818
|
+
}
|
|
8819
|
+
readlink(path) {
|
|
8820
|
+
const node = this.find(path, false);
|
|
8821
|
+
if (node.kind !== "link") throw syncError("EINVAL", path);
|
|
8822
|
+
return node.target;
|
|
8823
|
+
}
|
|
8824
|
+
exists(path) {
|
|
8825
|
+
try {
|
|
8826
|
+
this.find(path, true);
|
|
8827
|
+
return true;
|
|
8828
|
+
} catch {
|
|
8829
|
+
return false;
|
|
8830
|
+
}
|
|
8831
|
+
}
|
|
8832
|
+
};
|
|
8833
|
+
READ_ONLY = [
|
|
8834
|
+
"writeFile",
|
|
8835
|
+
"mkdir",
|
|
8836
|
+
"rm",
|
|
8837
|
+
"unlink",
|
|
8838
|
+
"rmdir",
|
|
8839
|
+
"symlink",
|
|
8840
|
+
"chmod",
|
|
8841
|
+
"utimes",
|
|
8842
|
+
"lutimes",
|
|
8843
|
+
"create",
|
|
8844
|
+
"pwrite",
|
|
8845
|
+
"truncate"
|
|
8846
|
+
];
|
|
8847
|
+
}
|
|
8848
|
+
});
|
|
8849
|
+
|
|
8628
8850
|
// src/process/wasi/wasi-signals.ts
|
|
8629
8851
|
var DELIVERED_MASK, KERNEL_DEFAULTS, LIBC_DEFAULT_EXIT, SA_RESTART, DISPOSITION_IGNORE, DISPOSITION_HANDLER, withBit, WASIX_LIBC_DEFAULT_LINE, WasiSignals;
|
|
8630
8852
|
var init_wasi_signals = __esm({
|
|
@@ -10768,6 +10990,15 @@ async function instantiate(host, module, memory, threads, {
|
|
|
10768
10990
|
}
|
|
10769
10991
|
return { instance, driver };
|
|
10770
10992
|
}
|
|
10993
|
+
function procTree(call2, pid) {
|
|
10994
|
+
return new ProcTree(
|
|
10995
|
+
{
|
|
10996
|
+
procList: () => call2({ op: "proc-list" }),
|
|
10997
|
+
mountList: () => call2({ op: "mount-list" })
|
|
10998
|
+
},
|
|
10999
|
+
pid
|
|
11000
|
+
);
|
|
11001
|
+
}
|
|
10771
11002
|
function exportedTable(instance) {
|
|
10772
11003
|
const table = instance.exports.__indirect_function_table;
|
|
10773
11004
|
return table instanceof WebAssembly.Table ? table : void 0;
|
|
@@ -10839,7 +11070,10 @@ async function runWasiProcess(init, port3) {
|
|
|
10839
11070
|
ppid: id.ppid,
|
|
10840
11071
|
parent: () => identify(transport, init).ppid,
|
|
10841
11072
|
kernel: { sys: traced(stats, "kernel", sys), call: call2 },
|
|
10842
|
-
fs:
|
|
11073
|
+
fs: procfsBridge(
|
|
11074
|
+
cachingBridge(traced(stats, "fs", createSyncFsSabBridge(transport))),
|
|
11075
|
+
procTree(call2, id.pid)
|
|
11076
|
+
),
|
|
10843
11077
|
...descriptors(init, fork, threads)
|
|
10844
11078
|
});
|
|
10845
11079
|
if (threads) {
|
|
@@ -10930,7 +11164,7 @@ async function runWasiThread(init, port3) {
|
|
|
10930
11164
|
ppid: id.ppid,
|
|
10931
11165
|
parent: () => identify(transport, init).ppid,
|
|
10932
11166
|
kernel: { sys, call: call2 },
|
|
10933
|
-
fs: cachingBridge(createSyncFsSabBridge(transport)),
|
|
11167
|
+
fs: procfsBridge(cachingBridge(createSyncFsSabBridge(transport)), procTree(call2, id.pid)),
|
|
10934
11168
|
shared: threads.ids
|
|
10935
11169
|
});
|
|
10936
11170
|
const program = await programImports(init.program, host, transport, thread.tid);
|
|
@@ -10985,6 +11219,7 @@ var init_wasi_runtime = __esm({
|
|
|
10985
11219
|
init_wasi_host();
|
|
10986
11220
|
init_wasi_imports();
|
|
10987
11221
|
init_wasi_module();
|
|
11222
|
+
init_wasi_procfs();
|
|
10988
11223
|
init_wasi_signals();
|
|
10989
11224
|
init_wasi_stats();
|
|
10990
11225
|
init_wasi_threads();
|
|
@@ -11084,23 +11319,6 @@ var NODE_SLOTS = [
|
|
|
11084
11319
|
"setImmediate",
|
|
11085
11320
|
"clearImmediate"
|
|
11086
11321
|
];
|
|
11087
|
-
function vacate(target, names) {
|
|
11088
|
-
for (const name2 of names) {
|
|
11089
|
-
for (let at = target; at && at !== Object.prototype; ) {
|
|
11090
|
-
if (Object.getOwnPropertyDescriptor(at, name2)?.configurable) Reflect.deleteProperty(at, name2);
|
|
11091
|
-
at = Object.getPrototypeOf(at);
|
|
11092
|
-
}
|
|
11093
|
-
Reflect.defineProperty(target, name2, {
|
|
11094
|
-
value: void 0,
|
|
11095
|
-
writable: true,
|
|
11096
|
-
enumerable: false,
|
|
11097
|
-
configurable: true
|
|
11098
|
-
});
|
|
11099
|
-
if (Reflect.get(target, name2) !== void 0) {
|
|
11100
|
-
throw new Error(`slicc-kernel: cannot withhold ${name2} from a JS program`);
|
|
11101
|
-
}
|
|
11102
|
-
}
|
|
11103
|
-
}
|
|
11104
11322
|
function refused(specifier) {
|
|
11105
11323
|
return Object.assign(new Error(`slicc-kernel: a JS program cannot import ${specifier}`), {
|
|
11106
11324
|
code: "ERR_ACCESS_DENIED"
|