@ai-ecoverse/slicc-kernel 1.54.1 → 1.54.3
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 +1 -1
- package/dist/kernel-worker.js +759 -358
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +217 -56
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +861 -460
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +217 -56
- package/dist/process-worker.js.map +3 -3
- package/package.json +3 -3
package/dist/node.js
CHANGED
|
@@ -329,6 +329,32 @@ function bytesSource(data) {
|
|
|
329
329
|
}
|
|
330
330
|
});
|
|
331
331
|
}
|
|
332
|
+
function memoryFile(data, path, position = 0) {
|
|
333
|
+
let offset = position;
|
|
334
|
+
return new OpenFile({
|
|
335
|
+
read: async (max) => {
|
|
336
|
+
const out = data.subarray(offset, offset + max);
|
|
337
|
+
offset += out.length;
|
|
338
|
+
return out;
|
|
339
|
+
},
|
|
340
|
+
pread: async (max, at) => data.subarray(at, at + max),
|
|
341
|
+
seek: async (by, whence) => {
|
|
342
|
+
const at = (whence === 1 ? offset : whence === 2 ? data.length : 0) + by;
|
|
343
|
+
if (at < 0) throw new KernelError("EINVAL");
|
|
344
|
+
offset = at;
|
|
345
|
+
return at;
|
|
346
|
+
},
|
|
347
|
+
pwrite: async () => {
|
|
348
|
+
throw new KernelError("EBADF");
|
|
349
|
+
},
|
|
350
|
+
resize: async () => {
|
|
351
|
+
throw new KernelError("EBADF");
|
|
352
|
+
},
|
|
353
|
+
stat: async () => ({ path, size: data.length }),
|
|
354
|
+
close: () => {
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
}
|
|
332
358
|
function sinkFile(onData) {
|
|
333
359
|
return new OpenFile({
|
|
334
360
|
write: async (bytes) => {
|
|
@@ -5866,179 +5892,6 @@ function attachSyncSabResponder(port, sab, token, opts) {
|
|
|
5866
5892
|
};
|
|
5867
5893
|
}
|
|
5868
5894
|
|
|
5869
|
-
// src/kernel/host-ops.ts
|
|
5870
|
-
var HOST_OPS = [
|
|
5871
|
-
"lock",
|
|
5872
|
-
"unlock",
|
|
5873
|
-
"async-submit",
|
|
5874
|
-
"async-wait",
|
|
5875
|
-
"async-take",
|
|
5876
|
-
"async-resolve",
|
|
5877
|
-
"async-hold",
|
|
5878
|
-
"async-cancel",
|
|
5879
|
-
"async-close"
|
|
5880
|
-
];
|
|
5881
|
-
var json3 = (value) => ({ ok: true, kind: "json", json: value });
|
|
5882
|
-
var done2 = { ok: true, kind: "void" };
|
|
5883
|
-
var LockTable = class {
|
|
5884
|
-
held = /* @__PURE__ */ new Map();
|
|
5885
|
-
lock(pid, path, exclusive, fd) {
|
|
5886
|
-
const holders = this.held.get(path) ?? /* @__PURE__ */ new Map();
|
|
5887
|
-
for (const [other, h] of holders) if (other !== pid && (exclusive || h.exclusive)) return false;
|
|
5888
|
-
const mine = holders.get(pid) ?? { exclusive, fds: /* @__PURE__ */ new Set() };
|
|
5889
|
-
mine.exclusive = exclusive;
|
|
5890
|
-
mine.fds.add(fd);
|
|
5891
|
-
holders.set(pid, mine);
|
|
5892
|
-
this.held.set(path, holders);
|
|
5893
|
-
return true;
|
|
5894
|
-
}
|
|
5895
|
-
unlock(pid, path) {
|
|
5896
|
-
const holders = this.held.get(path);
|
|
5897
|
-
holders?.delete(pid);
|
|
5898
|
-
if (holders?.size === 0) this.held.delete(path);
|
|
5899
|
-
}
|
|
5900
|
-
closed(pid, fd) {
|
|
5901
|
-
for (const [path, holders] of [...this.held]) {
|
|
5902
|
-
const mine = holders.get(pid);
|
|
5903
|
-
if (mine?.fds.delete(fd) && mine.fds.size === 0) this.unlock(pid, path);
|
|
5904
|
-
}
|
|
5905
|
-
}
|
|
5906
|
-
release(pid) {
|
|
5907
|
-
for (const path of [...this.held.keys()]) this.unlock(pid, path);
|
|
5908
|
-
}
|
|
5909
|
-
};
|
|
5910
|
-
var AsyncOps = class {
|
|
5911
|
-
next = 1;
|
|
5912
|
-
results = /* @__PURE__ */ new Map();
|
|
5913
|
-
ready = [];
|
|
5914
|
-
running = /* @__PURE__ */ new Map();
|
|
5915
|
-
waiters = /* @__PURE__ */ new Set();
|
|
5916
|
-
closed = false;
|
|
5917
|
-
run;
|
|
5918
|
-
onReady;
|
|
5919
|
-
constructor(run2, onReady) {
|
|
5920
|
-
this.run = run2;
|
|
5921
|
-
this.onReady = onReady;
|
|
5922
|
-
}
|
|
5923
|
-
submit(req) {
|
|
5924
|
-
const id2 = this.hold();
|
|
5925
|
-
const running = new AbortController();
|
|
5926
|
-
this.running.set(id2, running);
|
|
5927
|
-
this.run(req, running.signal).then(
|
|
5928
|
-
(result) => this.complete(id2, result),
|
|
5929
|
-
(err) => this.complete(id2, { ok: false, errno: "EIO", message: String(err) })
|
|
5930
|
-
);
|
|
5931
|
-
return id2;
|
|
5932
|
-
}
|
|
5933
|
-
resolve(value) {
|
|
5934
|
-
const id2 = this.hold();
|
|
5935
|
-
this.complete(id2, json3(value));
|
|
5936
|
-
return id2;
|
|
5937
|
-
}
|
|
5938
|
-
hold() {
|
|
5939
|
-
const id2 = this.next++;
|
|
5940
|
-
this.results.set(id2, void 0);
|
|
5941
|
-
return id2;
|
|
5942
|
-
}
|
|
5943
|
-
take(id2) {
|
|
5944
|
-
if (!this.results.has(id2)) throw new KernelError("EINVAL");
|
|
5945
|
-
const result = this.results.get(id2);
|
|
5946
|
-
if (!result) throw new KernelError("EAGAIN");
|
|
5947
|
-
this.forget(id2);
|
|
5948
|
-
return result;
|
|
5949
|
-
}
|
|
5950
|
-
cancel(id2) {
|
|
5951
|
-
this.running.get(id2)?.abort();
|
|
5952
|
-
this.forget(id2);
|
|
5953
|
-
}
|
|
5954
|
-
forget(id2) {
|
|
5955
|
-
this.running.delete(id2);
|
|
5956
|
-
this.results.delete(id2);
|
|
5957
|
-
const at = this.ready.indexOf(id2);
|
|
5958
|
-
if (at >= 0) this.ready.splice(at, 1);
|
|
5959
|
-
}
|
|
5960
|
-
async wait(timeoutMs, signal) {
|
|
5961
|
-
for (; ; ) {
|
|
5962
|
-
if (this.closed) return -1;
|
|
5963
|
-
const id2 = this.ready.shift();
|
|
5964
|
-
if (id2 !== void 0) return id2;
|
|
5965
|
-
if (timeoutMs !== void 0 && timeoutMs <= 0) return 0;
|
|
5966
|
-
const woke = await this.sleep(timeoutMs, signal);
|
|
5967
|
-
if (!woke) return 0;
|
|
5968
|
-
}
|
|
5969
|
-
}
|
|
5970
|
-
close() {
|
|
5971
|
-
this.closed = true;
|
|
5972
|
-
this.wake();
|
|
5973
|
-
}
|
|
5974
|
-
sleep(timeoutMs, signal) {
|
|
5975
|
-
return new Promise((resolve, reject) => {
|
|
5976
|
-
let timer;
|
|
5977
|
-
const cleanup = () => {
|
|
5978
|
-
clearTimeout(timer);
|
|
5979
|
-
this.waiters.delete(wake);
|
|
5980
|
-
signal.removeEventListener("abort", abort);
|
|
5981
|
-
};
|
|
5982
|
-
const wake = () => {
|
|
5983
|
-
cleanup();
|
|
5984
|
-
resolve(true);
|
|
5985
|
-
};
|
|
5986
|
-
const abort = () => {
|
|
5987
|
-
cleanup();
|
|
5988
|
-
reject(new KernelError("EINTR"));
|
|
5989
|
-
};
|
|
5990
|
-
this.waiters.add(wake);
|
|
5991
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
5992
|
-
if (timeoutMs !== void 0) {
|
|
5993
|
-
timer = setTimeout(() => {
|
|
5994
|
-
cleanup();
|
|
5995
|
-
resolve(false);
|
|
5996
|
-
}, timeoutMs);
|
|
5997
|
-
}
|
|
5998
|
-
});
|
|
5999
|
-
}
|
|
6000
|
-
complete(id2, result) {
|
|
6001
|
-
this.running.delete(id2);
|
|
6002
|
-
if (!this.results.has(id2)) return;
|
|
6003
|
-
this.results.set(id2, result);
|
|
6004
|
-
this.ready.push(id2);
|
|
6005
|
-
this.wake();
|
|
6006
|
-
this.onReady?.();
|
|
6007
|
-
}
|
|
6008
|
-
wake() {
|
|
6009
|
-
for (const wake of [...this.waiters]) wake();
|
|
6010
|
-
}
|
|
6011
|
-
};
|
|
6012
|
-
async function hostSyscall(req, ctx) {
|
|
6013
|
-
switch (req.op) {
|
|
6014
|
-
case "lock":
|
|
6015
|
-
if (!ctx.locks) throw new KernelError("ENOSYS");
|
|
6016
|
-
if (!ctx.locks.lock(ctx.pid, req.path, req.exclusive, req.fd))
|
|
6017
|
-
throw new KernelError("EAGAIN");
|
|
6018
|
-
return done2;
|
|
6019
|
-
case "unlock":
|
|
6020
|
-
ctx.locks?.unlock(ctx.pid, req.path);
|
|
6021
|
-
return done2;
|
|
6022
|
-
case "async-submit":
|
|
6023
|
-
if (!ctx.valid(req.req)) throw new KernelError("EINVAL");
|
|
6024
|
-
return json3(ctx.ops.submit(req.req));
|
|
6025
|
-
case "async-wait":
|
|
6026
|
-
return json3(await ctx.ops.wait(req.timeoutMs, ctx.blocking()));
|
|
6027
|
-
case "async-take":
|
|
6028
|
-
return ctx.ops.take(req.id);
|
|
6029
|
-
case "async-resolve":
|
|
6030
|
-
return json3(ctx.ops.resolve(req.value));
|
|
6031
|
-
case "async-hold":
|
|
6032
|
-
return json3(ctx.ops.hold());
|
|
6033
|
-
case "async-cancel":
|
|
6034
|
-
ctx.ops.cancel(req.id);
|
|
6035
|
-
return done2;
|
|
6036
|
-
case "async-close":
|
|
6037
|
-
ctx.ops.close();
|
|
6038
|
-
return done2;
|
|
6039
|
-
}
|
|
6040
|
-
}
|
|
6041
|
-
|
|
6042
5895
|
// src/kernel/net/loopback-names.ts
|
|
6043
5896
|
var HOST_LOOPBACK = "host.slicc.internal";
|
|
6044
5897
|
var HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2];
|
|
@@ -6066,66 +5919,815 @@ function ownNames(hostname) {
|
|
|
6066
5919
|
return [.../* @__PURE__ */ new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];
|
|
6067
5920
|
}
|
|
6068
5921
|
|
|
6069
|
-
// src/
|
|
6070
|
-
var
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
};
|
|
6082
|
-
var HOP_BY_HOP = /* @__PURE__ */ new Set([
|
|
6083
|
-
"connection",
|
|
6084
|
-
"keep-alive",
|
|
6085
|
-
"proxy-connection",
|
|
6086
|
-
"proxy-authenticate",
|
|
6087
|
-
"proxy-authorization",
|
|
6088
|
-
"te",
|
|
6089
|
-
"trailer",
|
|
6090
|
-
"transfer-encoding",
|
|
6091
|
-
"upgrade"
|
|
6092
|
-
]);
|
|
6093
|
-
var REQUEST_OWN = /* @__PURE__ */ new Set(["host", "content-length", "expect"]);
|
|
6094
|
-
var Budget = class {
|
|
6095
|
-
free;
|
|
6096
|
-
waiters = [];
|
|
6097
|
-
constructor(free) {
|
|
6098
|
-
this.free = free;
|
|
5922
|
+
// src/process/process-fds.ts
|
|
5923
|
+
var field2 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
5924
|
+
function mountTable(mounts = []) {
|
|
5925
|
+
const root = globalThis.navigator?.storage ? "opfs" : "memory";
|
|
5926
|
+
const lines2 = [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0"];
|
|
5927
|
+
for (const m of mounts) {
|
|
5928
|
+
const options = Object.entries(m.options).map(([k, v]) => v === "" ? k : `${k}=${v}`);
|
|
5929
|
+
if (m.state !== "ok") options.push(m.state);
|
|
5930
|
+
const access = options.includes("ro") ? [] : ["rw"];
|
|
5931
|
+
lines2.push(
|
|
5932
|
+
`${field2(m.source)} ${field2(m.target)} ${m.type} ${[...access, ...options].join(",")} 0 0`
|
|
5933
|
+
);
|
|
6099
5934
|
}
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
5935
|
+
return `${lines2.join("\n")}
|
|
5936
|
+
`;
|
|
5937
|
+
}
|
|
5938
|
+
|
|
5939
|
+
// src/process/procfs.ts
|
|
5940
|
+
var HZ = 100;
|
|
5941
|
+
var KIB = 1024;
|
|
5942
|
+
var FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
|
|
5943
|
+
var PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
|
|
5944
|
+
var SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime"];
|
|
5945
|
+
function commOf(info) {
|
|
5946
|
+
const name2 = info.argv[0] ?? "";
|
|
5947
|
+
return name2.slice(name2.lastIndexOf("/") + 1).slice(0, 15);
|
|
5948
|
+
}
|
|
5949
|
+
function ttyNumber(tty) {
|
|
5950
|
+
const pts = tty && /^\/dev\/pts\/(\d+)$/.exec(tty);
|
|
5951
|
+
if (pts) return 136 << 8 | Number(pts[1]);
|
|
5952
|
+
const vt = tty && /^\/dev\/tty(\d+)$/.exec(tty);
|
|
5953
|
+
return vt ? 4 << 8 | Number(vt[1]) : 0;
|
|
5954
|
+
}
|
|
5955
|
+
function pages(bytes) {
|
|
5956
|
+
return Math.ceil(bytes / 4096);
|
|
5957
|
+
}
|
|
5958
|
+
function ticks(ms) {
|
|
5959
|
+
return Math.max(0, Math.floor(ms * HZ / 1e3));
|
|
5960
|
+
}
|
|
5961
|
+
function pidStat(info, boot) {
|
|
5962
|
+
const fields = [
|
|
5963
|
+
info.pid,
|
|
5964
|
+
`(${commOf(info)})`,
|
|
5965
|
+
info.state,
|
|
5966
|
+
info.ppid,
|
|
5967
|
+
info.pgid,
|
|
5968
|
+
info.sid,
|
|
5969
|
+
ttyNumber(info.tty),
|
|
5970
|
+
info.tty ? info.pgid : -1,
|
|
5971
|
+
4194304,
|
|
5972
|
+
0,
|
|
5973
|
+
0,
|
|
5974
|
+
0,
|
|
5975
|
+
0,
|
|
5976
|
+
0,
|
|
5977
|
+
0,
|
|
5978
|
+
0,
|
|
5979
|
+
0,
|
|
5980
|
+
20,
|
|
5981
|
+
0,
|
|
5982
|
+
1,
|
|
5983
|
+
0,
|
|
5984
|
+
ticks(info.started - boot),
|
|
5985
|
+
info.memory,
|
|
5986
|
+
pages(info.memory),
|
|
5987
|
+
"18446744073709551615",
|
|
5988
|
+
...Array(12).fill(0),
|
|
5989
|
+
17,
|
|
5990
|
+
0,
|
|
5991
|
+
0,
|
|
5992
|
+
0,
|
|
5993
|
+
0,
|
|
5994
|
+
0,
|
|
5995
|
+
0,
|
|
5996
|
+
...Array(7).fill(0),
|
|
5997
|
+
0
|
|
5998
|
+
];
|
|
5999
|
+
return `${fields.join(" ")}
|
|
6000
|
+
`;
|
|
6001
|
+
}
|
|
6002
|
+
var sigMask = (mask = 0) => (mask >>> 1).toString(16).padStart(16, "0");
|
|
6003
|
+
function pidStatus(info) {
|
|
6004
|
+
const state = info.state === "Z" ? "Z (zombie)" : "S (sleeping)";
|
|
6005
|
+
const c = info.cred ?? ROOT;
|
|
6006
|
+
const ids = (r, e, s) => `${r} ${e} ${s} ${e}`;
|
|
6007
|
+
return [
|
|
6008
|
+
`Name: ${commOf(info)}`,
|
|
6009
|
+
`Umask: ${(info.umask ?? 18).toString(8).padStart(4, "0")}`,
|
|
6010
|
+
`State: ${state}`,
|
|
6011
|
+
`Tgid: ${info.pid}`,
|
|
6012
|
+
"Ngid: 0",
|
|
6013
|
+
`Pid: ${info.pid}`,
|
|
6014
|
+
`PPid: ${info.ppid}`,
|
|
6015
|
+
"TracerPid: 0",
|
|
6016
|
+
`Uid: ${ids(c.ruid, c.euid, c.suid)}`,
|
|
6017
|
+
`Gid: ${ids(c.rgid, c.egid, c.sgid)}`,
|
|
6018
|
+
"FDSize: 64",
|
|
6019
|
+
`VmSize: ${Math.ceil(info.memory / KIB)} kB`,
|
|
6020
|
+
`VmRSS: ${Math.ceil(info.memory / KIB)} kB`,
|
|
6021
|
+
`Groups: ${c.groups.join(" ")}`,
|
|
6022
|
+
`NSpid: ${info.pid}`,
|
|
6023
|
+
`NSpgid: ${info.pgid}`,
|
|
6024
|
+
`NSsid: ${info.sid}`,
|
|
6025
|
+
"Threads: 1",
|
|
6026
|
+
"SigQ: 0/0",
|
|
6027
|
+
"SigPnd: 0000000000000000",
|
|
6028
|
+
"ShdPnd: 0000000000000000",
|
|
6029
|
+
"SigBlk: 0000000000000000",
|
|
6030
|
+
`SigIgn: ${sigMask(info.sigIgn)}`,
|
|
6031
|
+
`SigCgt: ${sigMask(info.sigCgt)}`,
|
|
6032
|
+
""
|
|
6033
|
+
].join("\n");
|
|
6034
|
+
}
|
|
6035
|
+
function pidFile(name2, info, boot) {
|
|
6036
|
+
if (name2 === "cmdline") return info.state === "Z" ? "" : `${info.argv.join("\0")}\0`;
|
|
6037
|
+
if (name2 === "comm") return `${commOf(info)}
|
|
6038
|
+
`;
|
|
6039
|
+
if (name2 === "stat") return pidStat(info, boot);
|
|
6040
|
+
if (name2 === "statm") {
|
|
6041
|
+
const p = pages(info.memory);
|
|
6042
|
+
return `${p} ${p} 0 0 0 ${p} 0
|
|
6043
|
+
`;
|
|
6113
6044
|
}
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6045
|
+
return pidStatus(info);
|
|
6046
|
+
}
|
|
6047
|
+
function memoryInfo(source, used = 0) {
|
|
6048
|
+
const total = source.deviceMemory ? source.deviceMemory * KIB * KIB * KIB : FALLBACK_MEMORY;
|
|
6049
|
+
const free = Math.max(0, total - used - (source.usedHeap ?? 0));
|
|
6050
|
+
const kb = (bytes) => `${Math.floor(bytes / KIB)} kB`;
|
|
6051
|
+
return [
|
|
6052
|
+
["MemTotal", kb(total)],
|
|
6053
|
+
["MemFree", kb(free)],
|
|
6054
|
+
["MemAvailable", kb(free)],
|
|
6055
|
+
["Buffers", kb(0)],
|
|
6056
|
+
["Cached", kb(0)],
|
|
6057
|
+
["SwapCached", kb(0)],
|
|
6058
|
+
["Shmem", kb(0)],
|
|
6059
|
+
["SReclaimable", kb(0)],
|
|
6060
|
+
["SwapTotal", kb(0)],
|
|
6061
|
+
["SwapFree", kb(0)]
|
|
6062
|
+
].map(([key, value]) => `${`${key}:`.padEnd(16)}${value.padStart(12)}`).concat("").join("\n");
|
|
6063
|
+
}
|
|
6064
|
+
function systemFile(name2, listing, now, memory) {
|
|
6065
|
+
const up = Math.max(0, now - listing.boot) / 1e3;
|
|
6066
|
+
if (name2 === "uptime") return `${up.toFixed(2)} ${up.toFixed(2)}
|
|
6067
|
+
`;
|
|
6068
|
+
if (name2 === "meminfo") {
|
|
6069
|
+
return memoryInfo(
|
|
6070
|
+
memory,
|
|
6071
|
+
listing.processes.reduce((sum, p) => sum + p.memory, 0)
|
|
6072
|
+
);
|
|
6119
6073
|
}
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
} catch {
|
|
6126
|
-
return void 0;
|
|
6074
|
+
const live = listing.processes.filter((p) => p.state !== "Z");
|
|
6075
|
+
if (name2 === "loadavg") {
|
|
6076
|
+
const last = Math.max(0, ...listing.processes.map((p) => p.pid));
|
|
6077
|
+
return `0.00 0.00 0.00 1/${live.length} ${last}
|
|
6078
|
+
`;
|
|
6127
6079
|
}
|
|
6128
|
-
|
|
6080
|
+
const idle = ticks(now - listing.boot);
|
|
6081
|
+
return [
|
|
6082
|
+
`cpu 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
6083
|
+
`cpu0 0 0 0 ${idle} 0 0 0 0 0 0`,
|
|
6084
|
+
"intr 0",
|
|
6085
|
+
"ctxt 0",
|
|
6086
|
+
`btime ${Math.floor(listing.boot / 1e3)}`,
|
|
6087
|
+
`processes ${listing.processes.length}`,
|
|
6088
|
+
"procs_running 1",
|
|
6089
|
+
"procs_blocked 0",
|
|
6090
|
+
""
|
|
6091
|
+
].join("\n");
|
|
6092
|
+
}
|
|
6093
|
+
function memorySource(scope = globalThis) {
|
|
6094
|
+
const nav = scope.navigator;
|
|
6095
|
+
const perf = scope.performance;
|
|
6096
|
+
const deviceMemory = nav?.deviceMemory;
|
|
6097
|
+
const used = perf?.memory?.usedJSHeapSize;
|
|
6098
|
+
return {
|
|
6099
|
+
...typeof deviceMemory === "number" && deviceMemory > 0 ? { deviceMemory } : {},
|
|
6100
|
+
...typeof used === "number" ? { usedHeap: used } : {}
|
|
6101
|
+
};
|
|
6102
|
+
}
|
|
6103
|
+
|
|
6104
|
+
// src/fs/pages.ts
|
|
6105
|
+
var PAGE = 64 * 1024;
|
|
6106
|
+
var READAHEAD = 1024 * 1024;
|
|
6107
|
+
var CLEAN_LIMIT = 4 * 1024 * 1024;
|
|
6108
|
+
var WRITEBACK = 8 * 1024 * 1024;
|
|
6109
|
+
var RUN = 1024 * 1024;
|
|
6110
|
+
var Pages = class {
|
|
6111
|
+
length;
|
|
6112
|
+
stored;
|
|
6113
|
+
shrink;
|
|
6114
|
+
pages = /* @__PURE__ */ new Map();
|
|
6115
|
+
dirty = /* @__PURE__ */ new Set();
|
|
6116
|
+
free = [];
|
|
6117
|
+
pinned = false;
|
|
6118
|
+
constructor(size) {
|
|
6119
|
+
this.length = size;
|
|
6120
|
+
this.stored = size;
|
|
6121
|
+
}
|
|
6122
|
+
get dirtyBytes() {
|
|
6123
|
+
return this.dirty.size * PAGE;
|
|
6124
|
+
}
|
|
6125
|
+
get changed() {
|
|
6126
|
+
return this.dirty.size > 0 || this.shrink !== void 0 || this.length !== this.stored;
|
|
6127
|
+
}
|
|
6128
|
+
missing(at, length2) {
|
|
6129
|
+
this.evict();
|
|
6130
|
+
const end = Math.min(this.stored, at + length2, this.length);
|
|
6131
|
+
const runs = [];
|
|
6132
|
+
for (let page = Math.floor(at / PAGE); page * PAGE < end; page++) {
|
|
6133
|
+
if (this.pages.has(page)) continue;
|
|
6134
|
+
const last2 = runs[runs.length - 1];
|
|
6135
|
+
if (last2 && last2[0] + last2[1] === page * PAGE) last2[1] += PAGE;
|
|
6136
|
+
else runs.push([page * PAGE, PAGE]);
|
|
6137
|
+
}
|
|
6138
|
+
const last = runs[runs.length - 1];
|
|
6139
|
+
if (last) last[1] = Math.max(last[1], Math.min(READAHEAD, this.stored - last[0]));
|
|
6140
|
+
return runs.map(([start2, n]) => [start2, Math.min(n, this.stored - start2)]);
|
|
6141
|
+
}
|
|
6142
|
+
partial(at, length2) {
|
|
6143
|
+
if (length2 === 0) return [];
|
|
6144
|
+
this.evict();
|
|
6145
|
+
const edges = /* @__PURE__ */ new Set([Math.floor(at / PAGE), Math.floor((at + length2 - 1) / PAGE)]);
|
|
6146
|
+
const runs = [];
|
|
6147
|
+
for (const page of edges) {
|
|
6148
|
+
const start2 = page * PAGE;
|
|
6149
|
+
const covered = at <= start2 && at + length2 >= start2 + PAGE;
|
|
6150
|
+
if (covered || this.pages.has(page) || start2 >= this.stored) continue;
|
|
6151
|
+
runs.push([start2, Math.min(PAGE, this.stored - start2)]);
|
|
6152
|
+
}
|
|
6153
|
+
return runs;
|
|
6154
|
+
}
|
|
6155
|
+
fill(start2, bytes) {
|
|
6156
|
+
for (let at = 0; at < bytes.length; at += PAGE) {
|
|
6157
|
+
const page = (start2 + at) / PAGE;
|
|
6158
|
+
if (this.pages.has(page)) continue;
|
|
6159
|
+
const part = bytes.subarray(at, Math.min(at + PAGE, bytes.length));
|
|
6160
|
+
const fresh = this.take(part.length);
|
|
6161
|
+
fresh.set(part);
|
|
6162
|
+
this.pages.set(page, fresh);
|
|
6163
|
+
}
|
|
6164
|
+
}
|
|
6165
|
+
read(at, length2) {
|
|
6166
|
+
const out = new Uint8Array(Math.max(0, Math.min(this.length, at + length2) - at));
|
|
6167
|
+
this.readInto(at, out);
|
|
6168
|
+
return out;
|
|
6169
|
+
}
|
|
6170
|
+
readInto(at, out) {
|
|
6171
|
+
const end = Math.min(this.length, at + out.length);
|
|
6172
|
+
for (let pos = at; pos < end; ) {
|
|
6173
|
+
const page = Math.floor(pos / PAGE);
|
|
6174
|
+
const from = pos - page * PAGE;
|
|
6175
|
+
const n = Math.min(PAGE - from, end - pos);
|
|
6176
|
+
const bytes = this.pages.get(page);
|
|
6177
|
+
if (bytes) out.set(bytes.subarray(from, from + n), pos - at);
|
|
6178
|
+
else out.fill(0, pos - at, pos - at + n);
|
|
6179
|
+
pos += n;
|
|
6180
|
+
}
|
|
6181
|
+
return Math.max(0, end - at);
|
|
6182
|
+
}
|
|
6183
|
+
write(at, bytes) {
|
|
6184
|
+
for (let done4 = 0; done4 < bytes.length; ) {
|
|
6185
|
+
const pos = at + done4;
|
|
6186
|
+
const page = Math.floor(pos / PAGE);
|
|
6187
|
+
const from = pos - page * PAGE;
|
|
6188
|
+
const n = Math.min(PAGE - from, bytes.length - done4);
|
|
6189
|
+
let target = this.pages.get(page);
|
|
6190
|
+
if (!target) {
|
|
6191
|
+
target = this.take(0);
|
|
6192
|
+
this.pages.set(page, target);
|
|
6193
|
+
}
|
|
6194
|
+
target.set(bytes.subarray(done4, done4 + n), from);
|
|
6195
|
+
this.dirty.add(page);
|
|
6196
|
+
done4 += n;
|
|
6197
|
+
}
|
|
6198
|
+
this.length = Math.max(this.length, at + bytes.length);
|
|
6199
|
+
}
|
|
6200
|
+
truncate(size) {
|
|
6201
|
+
if (size < this.stored) {
|
|
6202
|
+
this.stored = size;
|
|
6203
|
+
this.shrink = Math.min(this.shrink ?? size, size);
|
|
6204
|
+
}
|
|
6205
|
+
if (size < this.length) {
|
|
6206
|
+
const edge = Math.floor(size / PAGE);
|
|
6207
|
+
for (const page of [...this.pages.keys()]) {
|
|
6208
|
+
if (page > edge || page === edge && size === edge * PAGE) this.drop(page);
|
|
6209
|
+
}
|
|
6210
|
+
this.pages.get(edge)?.fill(0, size - edge * PAGE);
|
|
6211
|
+
}
|
|
6212
|
+
this.length = size;
|
|
6213
|
+
}
|
|
6214
|
+
plan() {
|
|
6215
|
+
const runs = [];
|
|
6216
|
+
const sorted = [...this.dirty].sort((a, b) => a - b);
|
|
6217
|
+
for (let i = 0; i < sorted.length; ) {
|
|
6218
|
+
let j = i + 1;
|
|
6219
|
+
const first = sorted[i];
|
|
6220
|
+
while (j < sorted.length && sorted[j] === first + (j - i) && sorted[j] * PAGE % RUN !== 0) {
|
|
6221
|
+
j++;
|
|
6222
|
+
}
|
|
6223
|
+
const start2 = first * PAGE;
|
|
6224
|
+
const end = Math.min(this.length, (first + (j - i)) * PAGE);
|
|
6225
|
+
const bytes = new Uint8Array(end - start2);
|
|
6226
|
+
for (let k = i; k < j; k++) {
|
|
6227
|
+
const page = this.pages.get(sorted[k]);
|
|
6228
|
+
bytes.set(page.subarray(0, Math.min(PAGE, end - (k - i) * PAGE - start2)), (k - i) * PAGE);
|
|
6229
|
+
}
|
|
6230
|
+
runs.push({ offset: start2, bytes });
|
|
6231
|
+
i = j;
|
|
6232
|
+
}
|
|
6233
|
+
const written2 = Math.max(this.stored, ...runs.map((r) => r.offset + r.bytes.length));
|
|
6234
|
+
return {
|
|
6235
|
+
...this.shrink !== void 0 ? { shrink: this.shrink } : {},
|
|
6236
|
+
runs,
|
|
6237
|
+
...this.length > written2 ? { extend: this.length } : {}
|
|
6238
|
+
};
|
|
6239
|
+
}
|
|
6240
|
+
flushed() {
|
|
6241
|
+
this.dirty.clear();
|
|
6242
|
+
this.shrink = void 0;
|
|
6243
|
+
this.stored = this.length;
|
|
6244
|
+
this.evict();
|
|
6245
|
+
}
|
|
6246
|
+
pin() {
|
|
6247
|
+
this.pinned = true;
|
|
6248
|
+
}
|
|
6249
|
+
reset(size) {
|
|
6250
|
+
if (this.pinned) return;
|
|
6251
|
+
for (const page of [...this.pages.keys()]) if (!this.dirty.has(page)) this.drop(page);
|
|
6252
|
+
if (this.changed) return;
|
|
6253
|
+
this.length = size;
|
|
6254
|
+
this.stored = size;
|
|
6255
|
+
}
|
|
6256
|
+
evict() {
|
|
6257
|
+
if (this.pinned) return;
|
|
6258
|
+
let clean = (this.pages.size - this.dirty.size) * PAGE;
|
|
6259
|
+
for (const page of this.pages.keys()) {
|
|
6260
|
+
if (clean <= CLEAN_LIMIT) return;
|
|
6261
|
+
if (this.dirty.has(page)) continue;
|
|
6262
|
+
this.drop(page);
|
|
6263
|
+
clean -= PAGE;
|
|
6264
|
+
}
|
|
6265
|
+
}
|
|
6266
|
+
take(used) {
|
|
6267
|
+
const page = this.free.pop();
|
|
6268
|
+
if (!page) return new Uint8Array(PAGE);
|
|
6269
|
+
page.fill(0, used);
|
|
6270
|
+
return page;
|
|
6271
|
+
}
|
|
6272
|
+
drop(page) {
|
|
6273
|
+
const bytes = this.pages.get(page);
|
|
6274
|
+
this.pages.delete(page);
|
|
6275
|
+
this.dirty.delete(page);
|
|
6276
|
+
if (this.free.length < CLEAN_LIMIT / PAGE) this.free.push(bytes);
|
|
6277
|
+
}
|
|
6278
|
+
};
|
|
6279
|
+
|
|
6280
|
+
// src/fs/ranged.ts
|
|
6281
|
+
var AsyncRangedFile = class {
|
|
6282
|
+
pages;
|
|
6283
|
+
io;
|
|
6284
|
+
pinned = false;
|
|
6285
|
+
version;
|
|
6286
|
+
path;
|
|
6287
|
+
constructor(io, path, size, version) {
|
|
6288
|
+
this.io = io;
|
|
6289
|
+
this.path = path;
|
|
6290
|
+
this.version = version;
|
|
6291
|
+
this.pages = new Pages(size);
|
|
6292
|
+
}
|
|
6293
|
+
size() {
|
|
6294
|
+
return this.pages.length;
|
|
6295
|
+
}
|
|
6296
|
+
async fetch(runs) {
|
|
6297
|
+
for (const [start2, n] of runs) {
|
|
6298
|
+
this.pages.fill(start2, await this.io.pread(this.path, start2, n, this.version));
|
|
6299
|
+
}
|
|
6300
|
+
}
|
|
6301
|
+
async read(at, length2) {
|
|
6302
|
+
await this.fetch(this.pages.missing(at, length2));
|
|
6303
|
+
return this.pages.read(at, length2);
|
|
6304
|
+
}
|
|
6305
|
+
async write(at, bytes) {
|
|
6306
|
+
await this.fetch(this.pages.partial(at, bytes.length));
|
|
6307
|
+
this.pages.write(at, bytes);
|
|
6308
|
+
if (!this.pinned && this.pages.dirtyBytes >= WRITEBACK) await this.flush();
|
|
6309
|
+
}
|
|
6310
|
+
truncate(size) {
|
|
6311
|
+
this.pages.truncate(size);
|
|
6312
|
+
}
|
|
6313
|
+
async flush() {
|
|
6314
|
+
if (this.pinned || !this.pages.changed) return;
|
|
6315
|
+
const plan = this.pages.plan();
|
|
6316
|
+
if (plan.shrink !== void 0) await this.io.truncate(this.path, plan.shrink);
|
|
6317
|
+
for (const run2 of plan.runs) await this.io.pwrite(this.path, run2.offset, run2.bytes, true);
|
|
6318
|
+
if (plan.extend !== void 0) await this.io.truncate(this.path, plan.extend);
|
|
6319
|
+
this.version = void 0;
|
|
6320
|
+
this.pages.flushed();
|
|
6321
|
+
}
|
|
6322
|
+
async pin() {
|
|
6323
|
+
this.pinned = true;
|
|
6324
|
+
this.pages.pin();
|
|
6325
|
+
await this.fetch(this.pages.missing(0, this.pages.length));
|
|
6326
|
+
}
|
|
6327
|
+
};
|
|
6328
|
+
|
|
6329
|
+
// src/process/wasi/wasi-files.ts
|
|
6330
|
+
function normalize(path) {
|
|
6331
|
+
const out = [];
|
|
6332
|
+
for (const seg of path.split("/")) {
|
|
6333
|
+
if (seg === "" || seg === ".") continue;
|
|
6334
|
+
if (seg === "..") out.pop();
|
|
6335
|
+
else out.push(seg);
|
|
6336
|
+
}
|
|
6337
|
+
return `/${out.join("/")}`;
|
|
6338
|
+
}
|
|
6339
|
+
|
|
6340
|
+
// src/process/wasi/wasi-procfs.ts
|
|
6341
|
+
var DIR_MODE = 16749;
|
|
6342
|
+
var FILE_MODE = 33060;
|
|
6343
|
+
var LINK_MODE = 41471;
|
|
6344
|
+
var PID_NAMES = PID_FILES;
|
|
6345
|
+
var SYSTEM_NAMES = SYSTEM_FILES;
|
|
6346
|
+
function inProc(path) {
|
|
6347
|
+
return path === "/proc" || path.startsWith("/proc/");
|
|
6348
|
+
}
|
|
6349
|
+
var ProcTree = class {
|
|
6350
|
+
source;
|
|
6351
|
+
pid;
|
|
6352
|
+
memory;
|
|
6353
|
+
constructor(source, pid, memory = memorySource()) {
|
|
6354
|
+
this.source = source;
|
|
6355
|
+
this.pid = pid;
|
|
6356
|
+
this.memory = memory;
|
|
6357
|
+
}
|
|
6358
|
+
listing() {
|
|
6359
|
+
return this.source.procList();
|
|
6360
|
+
}
|
|
6361
|
+
alive(pid) {
|
|
6362
|
+
return this.listing().processes.some((p) => p.pid === pid);
|
|
6363
|
+
}
|
|
6364
|
+
node(parts) {
|
|
6365
|
+
const [top, leaf, ...rest2] = parts;
|
|
6366
|
+
if (top === void 0) {
|
|
6367
|
+
return {
|
|
6368
|
+
kind: "dir",
|
|
6369
|
+
names: () => [
|
|
6370
|
+
...SYSTEM_NAMES,
|
|
6371
|
+
"mounts",
|
|
6372
|
+
"self",
|
|
6373
|
+
...this.listing().processes.map((p) => String(p.pid))
|
|
6374
|
+
]
|
|
6375
|
+
};
|
|
6376
|
+
}
|
|
6377
|
+
if (top === "self") {
|
|
6378
|
+
return leaf === void 0 ? { kind: "link", target: String(this.pid) } : void 0;
|
|
6379
|
+
}
|
|
6380
|
+
if (leaf === void 0 && top === "mounts") {
|
|
6381
|
+
return { kind: "file", content: () => mountTable(this.source.mountList()) };
|
|
6382
|
+
}
|
|
6383
|
+
if (leaf === void 0 && SYSTEM_NAMES.includes(top)) {
|
|
6384
|
+
return {
|
|
6385
|
+
kind: "file",
|
|
6386
|
+
content: () => systemFile(top, this.listing(), Date.now(), this.memory)
|
|
6387
|
+
};
|
|
6388
|
+
}
|
|
6389
|
+
if (!/^[1-9]\d*$/.test(top) || rest2.length > 0 || !this.alive(Number(top))) return void 0;
|
|
6390
|
+
if (leaf === void 0) return { kind: "dir", names: () => [...PID_NAMES] };
|
|
6391
|
+
if (!PID_NAMES.includes(leaf)) return void 0;
|
|
6392
|
+
return {
|
|
6393
|
+
kind: "file",
|
|
6394
|
+
content: () => {
|
|
6395
|
+
const listing = this.listing();
|
|
6396
|
+
const info = listing.processes.find((p) => p.pid === Number(top));
|
|
6397
|
+
if (!info) throw syncError("ENOENT", `/proc/${top}/${leaf}`);
|
|
6398
|
+
return pidFile(leaf, info, listing.boot);
|
|
6399
|
+
}
|
|
6400
|
+
};
|
|
6401
|
+
}
|
|
6402
|
+
parts(path, follow2) {
|
|
6403
|
+
const parts = path.split("/").filter((p) => p !== "").slice(1);
|
|
6404
|
+
if (parts[0] === "self" && (follow2 || parts.length > 1)) parts[0] = String(this.pid);
|
|
6405
|
+
return parts;
|
|
6406
|
+
}
|
|
6407
|
+
find(path, follow2) {
|
|
6408
|
+
const node = this.node(this.parts(path, follow2));
|
|
6409
|
+
if (!node) throw syncError("ENOENT", path);
|
|
6410
|
+
return node;
|
|
6411
|
+
}
|
|
6412
|
+
stat(path, follow2 = true) {
|
|
6413
|
+
const node = this.find(path, follow2);
|
|
6414
|
+
const base = {
|
|
6415
|
+
isFile: false,
|
|
6416
|
+
isDirectory: false,
|
|
6417
|
+
size: 0,
|
|
6418
|
+
mtimeMs: Date.now(),
|
|
6419
|
+
readonly: true
|
|
6420
|
+
};
|
|
6421
|
+
if (node.kind === "dir") return { ...base, isDirectory: true, mode: DIR_MODE };
|
|
6422
|
+
if (node.kind === "link") {
|
|
6423
|
+
return { ...base, isSymbolicLink: true, mode: LINK_MODE, size: node.target.length };
|
|
6424
|
+
}
|
|
6425
|
+
return { ...base, isFile: true, mode: FILE_MODE, size: this.bytes(node).length };
|
|
6426
|
+
}
|
|
6427
|
+
bytes(node) {
|
|
6428
|
+
return new TextEncoder().encode(node.kind === "file" ? node.content() : "");
|
|
6429
|
+
}
|
|
6430
|
+
read(path) {
|
|
6431
|
+
const node = this.find(path, true);
|
|
6432
|
+
if (node.kind !== "file") throw syncError("EISDIR", path);
|
|
6433
|
+
return this.bytes(node);
|
|
6434
|
+
}
|
|
6435
|
+
readdir(path) {
|
|
6436
|
+
const node = this.find(path, true);
|
|
6437
|
+
if (node.kind !== "dir") throw syncError("ENOTDIR", path);
|
|
6438
|
+
return node.names();
|
|
6439
|
+
}
|
|
6440
|
+
readlink(path) {
|
|
6441
|
+
const node = this.find(path, false);
|
|
6442
|
+
if (node.kind !== "link") throw syncError("EINVAL", path);
|
|
6443
|
+
return node.target;
|
|
6444
|
+
}
|
|
6445
|
+
exists(path) {
|
|
6446
|
+
try {
|
|
6447
|
+
this.find(path, true);
|
|
6448
|
+
return true;
|
|
6449
|
+
} catch {
|
|
6450
|
+
return false;
|
|
6451
|
+
}
|
|
6452
|
+
}
|
|
6453
|
+
};
|
|
6454
|
+
var MAX_HOPS2 = 40;
|
|
6455
|
+
function* procWalk(path, follow2) {
|
|
6456
|
+
let done4 = [];
|
|
6457
|
+
let todo = path.split("/").filter((part) => part !== "");
|
|
6458
|
+
let hops = 0;
|
|
6459
|
+
while (todo.length > 0) {
|
|
6460
|
+
const part = todo.shift();
|
|
6461
|
+
if (part === ".") continue;
|
|
6462
|
+
if (part === "..") {
|
|
6463
|
+
done4.pop();
|
|
6464
|
+
continue;
|
|
6465
|
+
}
|
|
6466
|
+
const at = `/${[...done4, part].join("/")}`;
|
|
6467
|
+
const whole = normalize(`/${[...done4, part, ...todo].join("/")}`);
|
|
6468
|
+
if (inProc(at) && inProc(whole)) return whole;
|
|
6469
|
+
if (!follow2 && todo.length === 0) return void 0;
|
|
6470
|
+
const target = yield at;
|
|
6471
|
+
if (target === null) return void 0;
|
|
6472
|
+
if (target === void 0) done4.push(part);
|
|
6473
|
+
else {
|
|
6474
|
+
if (++hops > MAX_HOPS2) return void 0;
|
|
6475
|
+
if (target.startsWith("/")) done4 = [];
|
|
6476
|
+
todo = [...target.split("/").filter((part2) => part2 !== ""), ...todo];
|
|
6477
|
+
}
|
|
6478
|
+
}
|
|
6479
|
+
return void 0;
|
|
6480
|
+
}
|
|
6481
|
+
async function procAlias(fs, path, follow2) {
|
|
6482
|
+
const { readlink, lstat } = fs;
|
|
6483
|
+
if (!readlink || !lstat) return void 0;
|
|
6484
|
+
const physical = await lstat.call(fs, "/proc").then(
|
|
6485
|
+
() => true,
|
|
6486
|
+
() => false
|
|
6487
|
+
);
|
|
6488
|
+
if (!physical) return void 0;
|
|
6489
|
+
const walk = procWalk(path, follow2);
|
|
6490
|
+
let step = walk.next();
|
|
6491
|
+
while (!step.done) {
|
|
6492
|
+
const target = await readlink.call(fs, step.value).catch(() => void 0);
|
|
6493
|
+
step = walk.next(target);
|
|
6494
|
+
}
|
|
6495
|
+
return step.value;
|
|
6496
|
+
}
|
|
6497
|
+
|
|
6498
|
+
// src/kernel/host-ops.ts
|
|
6499
|
+
var HOST_OPS = [
|
|
6500
|
+
"lock",
|
|
6501
|
+
"unlock",
|
|
6502
|
+
"async-submit",
|
|
6503
|
+
"async-wait",
|
|
6504
|
+
"async-take",
|
|
6505
|
+
"async-resolve",
|
|
6506
|
+
"async-hold",
|
|
6507
|
+
"async-cancel",
|
|
6508
|
+
"async-close"
|
|
6509
|
+
];
|
|
6510
|
+
var json3 = (value) => ({ ok: true, kind: "json", json: value });
|
|
6511
|
+
var done2 = { ok: true, kind: "void" };
|
|
6512
|
+
var LockTable = class {
|
|
6513
|
+
held = /* @__PURE__ */ new Map();
|
|
6514
|
+
lock(pid, path, exclusive, fd) {
|
|
6515
|
+
const holders = this.held.get(path) ?? /* @__PURE__ */ new Map();
|
|
6516
|
+
for (const [other, h] of holders) if (other !== pid && (exclusive || h.exclusive)) return false;
|
|
6517
|
+
const mine = holders.get(pid) ?? { exclusive, fds: /* @__PURE__ */ new Set() };
|
|
6518
|
+
mine.exclusive = exclusive;
|
|
6519
|
+
mine.fds.add(fd);
|
|
6520
|
+
holders.set(pid, mine);
|
|
6521
|
+
this.held.set(path, holders);
|
|
6522
|
+
return true;
|
|
6523
|
+
}
|
|
6524
|
+
unlock(pid, path) {
|
|
6525
|
+
const holders = this.held.get(path);
|
|
6526
|
+
holders?.delete(pid);
|
|
6527
|
+
if (holders?.size === 0) this.held.delete(path);
|
|
6528
|
+
}
|
|
6529
|
+
closed(pid, fd) {
|
|
6530
|
+
for (const [path, holders] of [...this.held]) {
|
|
6531
|
+
const mine = holders.get(pid);
|
|
6532
|
+
if (mine?.fds.delete(fd) && mine.fds.size === 0) this.unlock(pid, path);
|
|
6533
|
+
}
|
|
6534
|
+
}
|
|
6535
|
+
release(pid) {
|
|
6536
|
+
for (const path of [...this.held.keys()]) this.unlock(pid, path);
|
|
6537
|
+
}
|
|
6538
|
+
};
|
|
6539
|
+
var AsyncOps = class {
|
|
6540
|
+
next = 1;
|
|
6541
|
+
results = /* @__PURE__ */ new Map();
|
|
6542
|
+
ready = [];
|
|
6543
|
+
running = /* @__PURE__ */ new Map();
|
|
6544
|
+
waiters = /* @__PURE__ */ new Set();
|
|
6545
|
+
closed = false;
|
|
6546
|
+
run;
|
|
6547
|
+
onReady;
|
|
6548
|
+
constructor(run2, onReady) {
|
|
6549
|
+
this.run = run2;
|
|
6550
|
+
this.onReady = onReady;
|
|
6551
|
+
}
|
|
6552
|
+
submit(req) {
|
|
6553
|
+
const id2 = this.hold();
|
|
6554
|
+
const running = new AbortController();
|
|
6555
|
+
this.running.set(id2, running);
|
|
6556
|
+
this.run(req, running.signal).then(
|
|
6557
|
+
(result) => this.complete(id2, result),
|
|
6558
|
+
(err) => this.complete(id2, { ok: false, errno: "EIO", message: String(err) })
|
|
6559
|
+
);
|
|
6560
|
+
return id2;
|
|
6561
|
+
}
|
|
6562
|
+
resolve(value) {
|
|
6563
|
+
const id2 = this.hold();
|
|
6564
|
+
this.complete(id2, json3(value));
|
|
6565
|
+
return id2;
|
|
6566
|
+
}
|
|
6567
|
+
hold() {
|
|
6568
|
+
const id2 = this.next++;
|
|
6569
|
+
this.results.set(id2, void 0);
|
|
6570
|
+
return id2;
|
|
6571
|
+
}
|
|
6572
|
+
take(id2) {
|
|
6573
|
+
if (!this.results.has(id2)) throw new KernelError("EINVAL");
|
|
6574
|
+
const result = this.results.get(id2);
|
|
6575
|
+
if (!result) throw new KernelError("EAGAIN");
|
|
6576
|
+
this.forget(id2);
|
|
6577
|
+
return result;
|
|
6578
|
+
}
|
|
6579
|
+
cancel(id2) {
|
|
6580
|
+
this.running.get(id2)?.abort();
|
|
6581
|
+
this.forget(id2);
|
|
6582
|
+
}
|
|
6583
|
+
forget(id2) {
|
|
6584
|
+
this.running.delete(id2);
|
|
6585
|
+
this.results.delete(id2);
|
|
6586
|
+
const at = this.ready.indexOf(id2);
|
|
6587
|
+
if (at >= 0) this.ready.splice(at, 1);
|
|
6588
|
+
}
|
|
6589
|
+
async wait(timeoutMs, signal) {
|
|
6590
|
+
for (; ; ) {
|
|
6591
|
+
if (this.closed) return -1;
|
|
6592
|
+
const id2 = this.ready.shift();
|
|
6593
|
+
if (id2 !== void 0) return id2;
|
|
6594
|
+
if (timeoutMs !== void 0 && timeoutMs <= 0) return 0;
|
|
6595
|
+
const woke = await this.sleep(timeoutMs, signal);
|
|
6596
|
+
if (!woke) return 0;
|
|
6597
|
+
}
|
|
6598
|
+
}
|
|
6599
|
+
close() {
|
|
6600
|
+
this.closed = true;
|
|
6601
|
+
this.wake();
|
|
6602
|
+
}
|
|
6603
|
+
sleep(timeoutMs, signal) {
|
|
6604
|
+
return new Promise((resolve, reject) => {
|
|
6605
|
+
let timer;
|
|
6606
|
+
const cleanup = () => {
|
|
6607
|
+
clearTimeout(timer);
|
|
6608
|
+
this.waiters.delete(wake);
|
|
6609
|
+
signal.removeEventListener("abort", abort);
|
|
6610
|
+
};
|
|
6611
|
+
const wake = () => {
|
|
6612
|
+
cleanup();
|
|
6613
|
+
resolve(true);
|
|
6614
|
+
};
|
|
6615
|
+
const abort = () => {
|
|
6616
|
+
cleanup();
|
|
6617
|
+
reject(new KernelError("EINTR"));
|
|
6618
|
+
};
|
|
6619
|
+
this.waiters.add(wake);
|
|
6620
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
6621
|
+
if (timeoutMs !== void 0) {
|
|
6622
|
+
timer = setTimeout(() => {
|
|
6623
|
+
cleanup();
|
|
6624
|
+
resolve(false);
|
|
6625
|
+
}, timeoutMs);
|
|
6626
|
+
}
|
|
6627
|
+
});
|
|
6628
|
+
}
|
|
6629
|
+
complete(id2, result) {
|
|
6630
|
+
this.running.delete(id2);
|
|
6631
|
+
if (!this.results.has(id2)) return;
|
|
6632
|
+
this.results.set(id2, result);
|
|
6633
|
+
this.ready.push(id2);
|
|
6634
|
+
this.wake();
|
|
6635
|
+
this.onReady?.();
|
|
6636
|
+
}
|
|
6637
|
+
wake() {
|
|
6638
|
+
for (const wake of [...this.waiters]) wake();
|
|
6639
|
+
}
|
|
6640
|
+
};
|
|
6641
|
+
async function hostSyscall(req, ctx) {
|
|
6642
|
+
switch (req.op) {
|
|
6643
|
+
case "lock":
|
|
6644
|
+
if (!ctx.locks) throw new KernelError("ENOSYS");
|
|
6645
|
+
if (!ctx.locks.lock(ctx.pid, req.path, req.exclusive, req.fd))
|
|
6646
|
+
throw new KernelError("EAGAIN");
|
|
6647
|
+
return done2;
|
|
6648
|
+
case "unlock":
|
|
6649
|
+
ctx.locks?.unlock(ctx.pid, req.path);
|
|
6650
|
+
return done2;
|
|
6651
|
+
case "async-submit":
|
|
6652
|
+
if (!ctx.valid(req.req)) throw new KernelError("EINVAL");
|
|
6653
|
+
return json3(ctx.ops.submit(req.req));
|
|
6654
|
+
case "async-wait":
|
|
6655
|
+
return json3(await ctx.ops.wait(req.timeoutMs, ctx.blocking()));
|
|
6656
|
+
case "async-take":
|
|
6657
|
+
return ctx.ops.take(req.id);
|
|
6658
|
+
case "async-resolve":
|
|
6659
|
+
return json3(ctx.ops.resolve(req.value));
|
|
6660
|
+
case "async-hold":
|
|
6661
|
+
return json3(ctx.ops.hold());
|
|
6662
|
+
case "async-cancel":
|
|
6663
|
+
ctx.ops.cancel(req.id);
|
|
6664
|
+
return done2;
|
|
6665
|
+
case "async-close":
|
|
6666
|
+
ctx.ops.close();
|
|
6667
|
+
return done2;
|
|
6668
|
+
}
|
|
6669
|
+
}
|
|
6670
|
+
|
|
6671
|
+
// src/kernel/net/proxy-service.ts
|
|
6672
|
+
var SEND_BUFFER2 = 1024 * 1024;
|
|
6673
|
+
var TLS_HANDSHAKE = 22;
|
|
6674
|
+
var TOKEN2 = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
6675
|
+
var NO_WEBSOCKET2 = "WebSocket not supported by this transport (fetchTransport needs { webSocket: true })";
|
|
6676
|
+
var REALM_PROXY_PORT = 3128;
|
|
6677
|
+
var DEFAULT_LIMITS = {
|
|
6678
|
+
maxConnections: 64,
|
|
6679
|
+
maxHead: 64 * 1024,
|
|
6680
|
+
idleMs: 12e4,
|
|
6681
|
+
bodyBudget: 128 * 1024 * 1024,
|
|
6682
|
+
closeWaitMs: 5e3
|
|
6683
|
+
};
|
|
6684
|
+
var HOP_BY_HOP = /* @__PURE__ */ new Set([
|
|
6685
|
+
"connection",
|
|
6686
|
+
"keep-alive",
|
|
6687
|
+
"proxy-connection",
|
|
6688
|
+
"proxy-authenticate",
|
|
6689
|
+
"proxy-authorization",
|
|
6690
|
+
"te",
|
|
6691
|
+
"trailer",
|
|
6692
|
+
"transfer-encoding",
|
|
6693
|
+
"upgrade"
|
|
6694
|
+
]);
|
|
6695
|
+
var REQUEST_OWN = /* @__PURE__ */ new Set(["host", "content-length", "expect"]);
|
|
6696
|
+
var Budget = class {
|
|
6697
|
+
free;
|
|
6698
|
+
waiters = [];
|
|
6699
|
+
constructor(free) {
|
|
6700
|
+
this.free = free;
|
|
6701
|
+
}
|
|
6702
|
+
async acquire(n, signal) {
|
|
6703
|
+
while (this.free < n) {
|
|
6704
|
+
signal.throwIfAborted();
|
|
6705
|
+
await new Promise((resolve) => {
|
|
6706
|
+
const done4 = () => {
|
|
6707
|
+
signal.removeEventListener("abort", done4);
|
|
6708
|
+
resolve();
|
|
6709
|
+
};
|
|
6710
|
+
this.waiters.push(done4);
|
|
6711
|
+
signal.addEventListener("abort", done4, { once: true });
|
|
6712
|
+
});
|
|
6713
|
+
}
|
|
6714
|
+
this.free -= n;
|
|
6715
|
+
}
|
|
6716
|
+
release(n) {
|
|
6717
|
+
this.free += n;
|
|
6718
|
+
const waiters = this.waiters;
|
|
6719
|
+
this.waiters = [];
|
|
6720
|
+
for (const wake of waiters) wake();
|
|
6721
|
+
}
|
|
6722
|
+
};
|
|
6723
|
+
function canonicalHost2(host) {
|
|
6724
|
+
const bare = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
6725
|
+
try {
|
|
6726
|
+
return new URL(`http://${bare}/`).hostname;
|
|
6727
|
+
} catch {
|
|
6728
|
+
return void 0;
|
|
6729
|
+
}
|
|
6730
|
+
}
|
|
6129
6731
|
function localV4(a, b) {
|
|
6130
6732
|
return a === 127 || a === 0 || a === 169 && b === 254;
|
|
6131
6733
|
}
|
|
@@ -8372,231 +8974,6 @@ async function accept(proc, fd, nonblock) {
|
|
|
8372
8974
|
return { fd: proc.fds.install(new OpenFile(socket), 3), peer: socket.peer };
|
|
8373
8975
|
}
|
|
8374
8976
|
|
|
8375
|
-
// src/fs/pages.ts
|
|
8376
|
-
var PAGE = 64 * 1024;
|
|
8377
|
-
var READAHEAD = 1024 * 1024;
|
|
8378
|
-
var CLEAN_LIMIT = 4 * 1024 * 1024;
|
|
8379
|
-
var WRITEBACK = 8 * 1024 * 1024;
|
|
8380
|
-
var RUN = 1024 * 1024;
|
|
8381
|
-
var Pages = class {
|
|
8382
|
-
length;
|
|
8383
|
-
stored;
|
|
8384
|
-
shrink;
|
|
8385
|
-
pages = /* @__PURE__ */ new Map();
|
|
8386
|
-
dirty = /* @__PURE__ */ new Set();
|
|
8387
|
-
free = [];
|
|
8388
|
-
pinned = false;
|
|
8389
|
-
constructor(size) {
|
|
8390
|
-
this.length = size;
|
|
8391
|
-
this.stored = size;
|
|
8392
|
-
}
|
|
8393
|
-
get dirtyBytes() {
|
|
8394
|
-
return this.dirty.size * PAGE;
|
|
8395
|
-
}
|
|
8396
|
-
get changed() {
|
|
8397
|
-
return this.dirty.size > 0 || this.shrink !== void 0 || this.length !== this.stored;
|
|
8398
|
-
}
|
|
8399
|
-
missing(at, length2) {
|
|
8400
|
-
this.evict();
|
|
8401
|
-
const end = Math.min(this.stored, at + length2, this.length);
|
|
8402
|
-
const runs = [];
|
|
8403
|
-
for (let page = Math.floor(at / PAGE); page * PAGE < end; page++) {
|
|
8404
|
-
if (this.pages.has(page)) continue;
|
|
8405
|
-
const last2 = runs[runs.length - 1];
|
|
8406
|
-
if (last2 && last2[0] + last2[1] === page * PAGE) last2[1] += PAGE;
|
|
8407
|
-
else runs.push([page * PAGE, PAGE]);
|
|
8408
|
-
}
|
|
8409
|
-
const last = runs[runs.length - 1];
|
|
8410
|
-
if (last) last[1] = Math.max(last[1], Math.min(READAHEAD, this.stored - last[0]));
|
|
8411
|
-
return runs.map(([start2, n]) => [start2, Math.min(n, this.stored - start2)]);
|
|
8412
|
-
}
|
|
8413
|
-
partial(at, length2) {
|
|
8414
|
-
if (length2 === 0) return [];
|
|
8415
|
-
this.evict();
|
|
8416
|
-
const edges = /* @__PURE__ */ new Set([Math.floor(at / PAGE), Math.floor((at + length2 - 1) / PAGE)]);
|
|
8417
|
-
const runs = [];
|
|
8418
|
-
for (const page of edges) {
|
|
8419
|
-
const start2 = page * PAGE;
|
|
8420
|
-
const covered = at <= start2 && at + length2 >= start2 + PAGE;
|
|
8421
|
-
if (covered || this.pages.has(page) || start2 >= this.stored) continue;
|
|
8422
|
-
runs.push([start2, Math.min(PAGE, this.stored - start2)]);
|
|
8423
|
-
}
|
|
8424
|
-
return runs;
|
|
8425
|
-
}
|
|
8426
|
-
fill(start2, bytes) {
|
|
8427
|
-
for (let at = 0; at < bytes.length; at += PAGE) {
|
|
8428
|
-
const page = (start2 + at) / PAGE;
|
|
8429
|
-
if (this.pages.has(page)) continue;
|
|
8430
|
-
const part = bytes.subarray(at, Math.min(at + PAGE, bytes.length));
|
|
8431
|
-
const fresh = this.take(part.length);
|
|
8432
|
-
fresh.set(part);
|
|
8433
|
-
this.pages.set(page, fresh);
|
|
8434
|
-
}
|
|
8435
|
-
}
|
|
8436
|
-
read(at, length2) {
|
|
8437
|
-
const out = new Uint8Array(Math.max(0, Math.min(this.length, at + length2) - at));
|
|
8438
|
-
this.readInto(at, out);
|
|
8439
|
-
return out;
|
|
8440
|
-
}
|
|
8441
|
-
readInto(at, out) {
|
|
8442
|
-
const end = Math.min(this.length, at + out.length);
|
|
8443
|
-
for (let pos = at; pos < end; ) {
|
|
8444
|
-
const page = Math.floor(pos / PAGE);
|
|
8445
|
-
const from = pos - page * PAGE;
|
|
8446
|
-
const n = Math.min(PAGE - from, end - pos);
|
|
8447
|
-
const bytes = this.pages.get(page);
|
|
8448
|
-
if (bytes) out.set(bytes.subarray(from, from + n), pos - at);
|
|
8449
|
-
else out.fill(0, pos - at, pos - at + n);
|
|
8450
|
-
pos += n;
|
|
8451
|
-
}
|
|
8452
|
-
return Math.max(0, end - at);
|
|
8453
|
-
}
|
|
8454
|
-
write(at, bytes) {
|
|
8455
|
-
for (let done4 = 0; done4 < bytes.length; ) {
|
|
8456
|
-
const pos = at + done4;
|
|
8457
|
-
const page = Math.floor(pos / PAGE);
|
|
8458
|
-
const from = pos - page * PAGE;
|
|
8459
|
-
const n = Math.min(PAGE - from, bytes.length - done4);
|
|
8460
|
-
let target = this.pages.get(page);
|
|
8461
|
-
if (!target) {
|
|
8462
|
-
target = this.take(0);
|
|
8463
|
-
this.pages.set(page, target);
|
|
8464
|
-
}
|
|
8465
|
-
target.set(bytes.subarray(done4, done4 + n), from);
|
|
8466
|
-
this.dirty.add(page);
|
|
8467
|
-
done4 += n;
|
|
8468
|
-
}
|
|
8469
|
-
this.length = Math.max(this.length, at + bytes.length);
|
|
8470
|
-
}
|
|
8471
|
-
truncate(size) {
|
|
8472
|
-
if (size < this.stored) {
|
|
8473
|
-
this.stored = size;
|
|
8474
|
-
this.shrink = Math.min(this.shrink ?? size, size);
|
|
8475
|
-
}
|
|
8476
|
-
if (size < this.length) {
|
|
8477
|
-
const edge = Math.floor(size / PAGE);
|
|
8478
|
-
for (const page of [...this.pages.keys()]) {
|
|
8479
|
-
if (page > edge || page === edge && size === edge * PAGE) this.drop(page);
|
|
8480
|
-
}
|
|
8481
|
-
this.pages.get(edge)?.fill(0, size - edge * PAGE);
|
|
8482
|
-
}
|
|
8483
|
-
this.length = size;
|
|
8484
|
-
}
|
|
8485
|
-
plan() {
|
|
8486
|
-
const runs = [];
|
|
8487
|
-
const sorted = [...this.dirty].sort((a, b) => a - b);
|
|
8488
|
-
for (let i = 0; i < sorted.length; ) {
|
|
8489
|
-
let j = i + 1;
|
|
8490
|
-
const first = sorted[i];
|
|
8491
|
-
while (j < sorted.length && sorted[j] === first + (j - i) && sorted[j] * PAGE % RUN !== 0) {
|
|
8492
|
-
j++;
|
|
8493
|
-
}
|
|
8494
|
-
const start2 = first * PAGE;
|
|
8495
|
-
const end = Math.min(this.length, (first + (j - i)) * PAGE);
|
|
8496
|
-
const bytes = new Uint8Array(end - start2);
|
|
8497
|
-
for (let k = i; k < j; k++) {
|
|
8498
|
-
const page = this.pages.get(sorted[k]);
|
|
8499
|
-
bytes.set(page.subarray(0, Math.min(PAGE, end - (k - i) * PAGE - start2)), (k - i) * PAGE);
|
|
8500
|
-
}
|
|
8501
|
-
runs.push({ offset: start2, bytes });
|
|
8502
|
-
i = j;
|
|
8503
|
-
}
|
|
8504
|
-
const written2 = Math.max(this.stored, ...runs.map((r) => r.offset + r.bytes.length));
|
|
8505
|
-
return {
|
|
8506
|
-
...this.shrink !== void 0 ? { shrink: this.shrink } : {},
|
|
8507
|
-
runs,
|
|
8508
|
-
...this.length > written2 ? { extend: this.length } : {}
|
|
8509
|
-
};
|
|
8510
|
-
}
|
|
8511
|
-
flushed() {
|
|
8512
|
-
this.dirty.clear();
|
|
8513
|
-
this.shrink = void 0;
|
|
8514
|
-
this.stored = this.length;
|
|
8515
|
-
this.evict();
|
|
8516
|
-
}
|
|
8517
|
-
pin() {
|
|
8518
|
-
this.pinned = true;
|
|
8519
|
-
}
|
|
8520
|
-
reset(size) {
|
|
8521
|
-
if (this.pinned) return;
|
|
8522
|
-
for (const page of [...this.pages.keys()]) if (!this.dirty.has(page)) this.drop(page);
|
|
8523
|
-
if (this.changed) return;
|
|
8524
|
-
this.length = size;
|
|
8525
|
-
this.stored = size;
|
|
8526
|
-
}
|
|
8527
|
-
evict() {
|
|
8528
|
-
if (this.pinned) return;
|
|
8529
|
-
let clean = (this.pages.size - this.dirty.size) * PAGE;
|
|
8530
|
-
for (const page of this.pages.keys()) {
|
|
8531
|
-
if (clean <= CLEAN_LIMIT) return;
|
|
8532
|
-
if (this.dirty.has(page)) continue;
|
|
8533
|
-
this.drop(page);
|
|
8534
|
-
clean -= PAGE;
|
|
8535
|
-
}
|
|
8536
|
-
}
|
|
8537
|
-
take(used) {
|
|
8538
|
-
const page = this.free.pop();
|
|
8539
|
-
if (!page) return new Uint8Array(PAGE);
|
|
8540
|
-
page.fill(0, used);
|
|
8541
|
-
return page;
|
|
8542
|
-
}
|
|
8543
|
-
drop(page) {
|
|
8544
|
-
const bytes = this.pages.get(page);
|
|
8545
|
-
this.pages.delete(page);
|
|
8546
|
-
this.dirty.delete(page);
|
|
8547
|
-
if (this.free.length < CLEAN_LIMIT / PAGE) this.free.push(bytes);
|
|
8548
|
-
}
|
|
8549
|
-
};
|
|
8550
|
-
|
|
8551
|
-
// src/fs/ranged.ts
|
|
8552
|
-
var AsyncRangedFile = class {
|
|
8553
|
-
pages;
|
|
8554
|
-
io;
|
|
8555
|
-
pinned = false;
|
|
8556
|
-
version;
|
|
8557
|
-
path;
|
|
8558
|
-
constructor(io, path, size, version) {
|
|
8559
|
-
this.io = io;
|
|
8560
|
-
this.path = path;
|
|
8561
|
-
this.version = version;
|
|
8562
|
-
this.pages = new Pages(size);
|
|
8563
|
-
}
|
|
8564
|
-
size() {
|
|
8565
|
-
return this.pages.length;
|
|
8566
|
-
}
|
|
8567
|
-
async fetch(runs) {
|
|
8568
|
-
for (const [start2, n] of runs) {
|
|
8569
|
-
this.pages.fill(start2, await this.io.pread(this.path, start2, n, this.version));
|
|
8570
|
-
}
|
|
8571
|
-
}
|
|
8572
|
-
async read(at, length2) {
|
|
8573
|
-
await this.fetch(this.pages.missing(at, length2));
|
|
8574
|
-
return this.pages.read(at, length2);
|
|
8575
|
-
}
|
|
8576
|
-
async write(at, bytes) {
|
|
8577
|
-
await this.fetch(this.pages.partial(at, bytes.length));
|
|
8578
|
-
this.pages.write(at, bytes);
|
|
8579
|
-
if (!this.pinned && this.pages.dirtyBytes >= WRITEBACK) await this.flush();
|
|
8580
|
-
}
|
|
8581
|
-
truncate(size) {
|
|
8582
|
-
this.pages.truncate(size);
|
|
8583
|
-
}
|
|
8584
|
-
async flush() {
|
|
8585
|
-
if (this.pinned || !this.pages.changed) return;
|
|
8586
|
-
const plan = this.pages.plan();
|
|
8587
|
-
if (plan.shrink !== void 0) await this.io.truncate(this.path, plan.shrink);
|
|
8588
|
-
for (const run2 of plan.runs) await this.io.pwrite(this.path, run2.offset, run2.bytes, true);
|
|
8589
|
-
if (plan.extend !== void 0) await this.io.truncate(this.path, plan.extend);
|
|
8590
|
-
this.version = void 0;
|
|
8591
|
-
this.pages.flushed();
|
|
8592
|
-
}
|
|
8593
|
-
async pin() {
|
|
8594
|
-
this.pinned = true;
|
|
8595
|
-
this.pages.pin();
|
|
8596
|
-
await this.fetch(this.pages.missing(0, this.pages.length));
|
|
8597
|
-
}
|
|
8598
|
-
};
|
|
8599
|
-
|
|
8600
8977
|
// src/kernel/vfs-file.ts
|
|
8601
8978
|
var O_ACCMODE = 3;
|
|
8602
8979
|
var O_WRONLY = 1;
|
|
@@ -9236,6 +9613,7 @@ function isWasmSyscall(req) {
|
|
|
9236
9613
|
return typeof op === "string" && SYSCALL_OPS.has(op);
|
|
9237
9614
|
}
|
|
9238
9615
|
var MAX_READ = 1024 * 1024;
|
|
9616
|
+
var WRITE_ACCESS = 3;
|
|
9239
9617
|
var KEYBOARD = /* @__PURE__ */ new Set([SIG.INT, SIG.QUIT, SIG.TSTP]);
|
|
9240
9618
|
var DEFAULT_UMASK = 18;
|
|
9241
9619
|
var DYING = { ok: false, errno: "EINTR", message: "the process is being killed" };
|
|
@@ -9446,11 +9824,18 @@ var WasmProcess = class {
|
|
|
9446
9824
|
);
|
|
9447
9825
|
}
|
|
9448
9826
|
async openVfs(req) {
|
|
9827
|
+
if (inProc(req.path)) return this.openProc(req, req.path);
|
|
9828
|
+
const alias = req.orphan ? void 0 : await procAlias(this.options.fs, req.path, !req.exclusive);
|
|
9829
|
+
if (alias !== void 0) return this.openProc(req, alias);
|
|
9449
9830
|
await refuseReadonly(this.options.fs, req.path, req.flags, req);
|
|
9450
9831
|
const fd = this.fds.install(heldFile(), 3);
|
|
9451
9832
|
try {
|
|
9452
9833
|
const nodes = this.nodes;
|
|
9453
9834
|
const path = req.orphan ? req.path : req.exclusive ? await nodes.entryKey(req.path) : req.create ? await nodes.targetKey(req.path) : await this.keptOr(await nodes.targetKey(req.path), req.handle);
|
|
9835
|
+
if (inProc(path)) {
|
|
9836
|
+
this.fds.installAt(fd, await this.procFile(req, path));
|
|
9837
|
+
return fd;
|
|
9838
|
+
}
|
|
9454
9839
|
const open = { ...req, path };
|
|
9455
9840
|
if (req.exclusive) {
|
|
9456
9841
|
await nodes.createExclusive(path);
|
|
@@ -9472,6 +9857,22 @@ var WasmProcess = class {
|
|
|
9472
9857
|
}
|
|
9473
9858
|
return fd;
|
|
9474
9859
|
}
|
|
9860
|
+
async openProc(req, path) {
|
|
9861
|
+
return this.fds.install(await this.procFile(req, path), 3);
|
|
9862
|
+
}
|
|
9863
|
+
async procFile(req, path) {
|
|
9864
|
+
if (req.flags & WRITE_ACCESS || req.create || req.truncate || req.exclusive) {
|
|
9865
|
+
throw new KernelError("EROFS");
|
|
9866
|
+
}
|
|
9867
|
+
const tree = new ProcTree(
|
|
9868
|
+
{
|
|
9869
|
+
procList: () => this.options.processes?.() ?? { boot: 0, processes: [] },
|
|
9870
|
+
mountList: () => this.options.mounts?.() ?? []
|
|
9871
|
+
},
|
|
9872
|
+
(await this.options.identity?.())?.pid ?? this.pid
|
|
9873
|
+
);
|
|
9874
|
+
return memoryFile(tree.read(path), path, req.position);
|
|
9875
|
+
}
|
|
9475
9876
|
openVfsFile(req) {
|
|
9476
9877
|
return vfsFile(
|
|
9477
9878
|
this.options.fs,
|
|
@@ -10974,8 +11375,8 @@ function umountCall(target, flags) {
|
|
|
10974
11375
|
var FSTAB_PATH = "/etc/fstab";
|
|
10975
11376
|
var FSTAB_RETRIES = [1e3, 4e3, 16e3];
|
|
10976
11377
|
var FINAL = /* @__PURE__ */ new Set(["EINVAL", "EBUSY", "EPERM", "EACCES"]);
|
|
10977
|
-
function unescape(
|
|
10978
|
-
return
|
|
11378
|
+
function unescape(field3) {
|
|
11379
|
+
return field3.replace(
|
|
10979
11380
|
/\\([0-7]{3})/g,
|
|
10980
11381
|
(_, octal) => String.fromCharCode(Number.parseInt(octal, 8))
|
|
10981
11382
|
);
|
|
@@ -11868,7 +12269,7 @@ function importedMemory(bytes) {
|
|
|
11868
12269
|
const count = u32();
|
|
11869
12270
|
for (let i = 0; i < count; i++) {
|
|
11870
12271
|
const module = name2();
|
|
11871
|
-
const
|
|
12272
|
+
const field3 = name2();
|
|
11872
12273
|
const kind = bytes[at++];
|
|
11873
12274
|
if (kind === 0) u32();
|
|
11874
12275
|
else if (kind === 1) {
|
|
@@ -11876,7 +12277,7 @@ function importedMemory(bytes) {
|
|
|
11876
12277
|
limits();
|
|
11877
12278
|
} else if (kind === 2) {
|
|
11878
12279
|
const l = limits();
|
|
11879
|
-
return { module, name:
|
|
12280
|
+
return { module, name: field3, ...l };
|
|
11880
12281
|
} else if (kind === 3) at += 2;
|
|
11881
12282
|
else if (kind === 4) {
|
|
11882
12283
|
at++;
|
|
@@ -11967,12 +12368,12 @@ function readImports(r, types) {
|
|
|
11967
12368
|
const foreign = {};
|
|
11968
12369
|
for (let i = r.u32(); i > 0; i--) {
|
|
11969
12370
|
const module = r.name();
|
|
11970
|
-
const
|
|
12371
|
+
const field3 = r.name();
|
|
11971
12372
|
const kind = r.byte();
|
|
11972
12373
|
if (kind !== 0) skipImport(r, kind);
|
|
11973
12374
|
else {
|
|
11974
12375
|
const type = types[r.u32()] ?? "other";
|
|
11975
|
-
if (!RESERVED_NAMESPACES.has(module)) (foreign[module] ??= {})[
|
|
12376
|
+
if (!RESERVED_NAMESPACES.has(module)) (foreign[module] ??= {})[field3] = type;
|
|
11976
12377
|
}
|
|
11977
12378
|
}
|
|
11978
12379
|
return foreign;
|