@ai-ecoverse/slicc-kernel 1.67.1 → 1.69.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 +11 -0
- package/dist/index.js +49 -2
- package/dist/index.js.map +3 -3
- package/dist/kernel-worker.js +286 -22
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +606 -82
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +242 -15
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +603 -79
- package/dist/process-worker.js.map +4 -4
- package/package.json +1 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -1991,6 +1991,16 @@ function written(device, bytes) {
|
|
|
1991
1991
|
if (device === "full" && bytes.length > 0) throw new KernelError("ENOSPC");
|
|
1992
1992
|
return bytes.length;
|
|
1993
1993
|
}
|
|
1994
|
+
var DEVICE_PATHS = /* @__PURE__ */ new Map([
|
|
1995
|
+
["/dev/null", "null"],
|
|
1996
|
+
["/dev/zero", "zero"],
|
|
1997
|
+
["/dev/full", "full"],
|
|
1998
|
+
["/dev/urandom", "urandom"],
|
|
1999
|
+
["/dev/random", "urandom"]
|
|
2000
|
+
]);
|
|
2001
|
+
function deviceAt(path) {
|
|
2002
|
+
return DEVICE_PATHS.get(path);
|
|
2003
|
+
}
|
|
1994
2004
|
function deviceFile(device, access2) {
|
|
1995
2005
|
const read = async (max) => {
|
|
1996
2006
|
if (device === "null") return new Uint8Array(0);
|
|
@@ -2019,6 +2029,7 @@ function kernelFdKind(file) {
|
|
|
2019
2029
|
if (file.held) return "held";
|
|
2020
2030
|
if (file.heldMeta && "device" in file.heldMeta) return "device";
|
|
2021
2031
|
if (file.tty) return "tty";
|
|
2032
|
+
if (file.sealed) return "sealed";
|
|
2022
2033
|
return file.seek ? "file" : "stream";
|
|
2023
2034
|
}
|
|
2024
2035
|
var FdTable = class _FdTable {
|
|
@@ -11407,6 +11418,7 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
11407
11418
|
"fd-open-tty",
|
|
11408
11419
|
"fd-tty-names",
|
|
11409
11420
|
"fd-tty-owner",
|
|
11421
|
+
"fd-open-sealed",
|
|
11410
11422
|
"tty-get",
|
|
11411
11423
|
"tty-set",
|
|
11412
11424
|
"tty-winsz",
|
|
@@ -11462,6 +11474,7 @@ var WasmProcess = class {
|
|
|
11462
11474
|
ignored = 0;
|
|
11463
11475
|
inherited = 0;
|
|
11464
11476
|
interrupt = new AbortController();
|
|
11477
|
+
gone = new AbortController();
|
|
11465
11478
|
dying = false;
|
|
11466
11479
|
umask = DEFAULT_UMASK;
|
|
11467
11480
|
cred;
|
|
@@ -11684,6 +11697,7 @@ var WasmProcess = class {
|
|
|
11684
11697
|
}
|
|
11685
11698
|
async write(fd, body, nonblock = false, cancelled) {
|
|
11686
11699
|
const file = this.fds.get(fd).file;
|
|
11700
|
+
if (file.sealed) return file.sealed.send(body, await this.sealedCaller(), this.gone.signal);
|
|
11687
11701
|
if (!file.write) throw new KernelError("EBADF");
|
|
11688
11702
|
if (!pollFile(file).writable) {
|
|
11689
11703
|
if (nonblock) throw new KernelError("EAGAIN");
|
|
@@ -11697,6 +11711,8 @@ var WasmProcess = class {
|
|
|
11697
11711
|
}
|
|
11698
11712
|
async openVfs(req) {
|
|
11699
11713
|
if (inProc(req.path)) return this.openProc(req, req.path);
|
|
11714
|
+
const device = req.orphan ? void 0 : deviceAt(req.path);
|
|
11715
|
+
if (device) return this.openDevice(req, device);
|
|
11700
11716
|
const alias = req.orphan ? void 0 : await procAlias(this.options.fs, req.path, !req.exclusive);
|
|
11701
11717
|
if (typeof alias === "object")
|
|
11702
11718
|
throw Object.assign(new Error(alias.refused), { code: alias.refused });
|
|
@@ -11734,6 +11750,14 @@ var WasmProcess = class {
|
|
|
11734
11750
|
}
|
|
11735
11751
|
return fd;
|
|
11736
11752
|
}
|
|
11753
|
+
openDevice(req, device) {
|
|
11754
|
+
if (req.exclusive) throw Object.assign(new Error(req.path), { code: "EEXIST" });
|
|
11755
|
+
const access2 = req.flags & WRITE_ACCESS;
|
|
11756
|
+
return this.fds.install(
|
|
11757
|
+
deviceFile(device, access2 === 0 ? "read" : access2 === 1 ? "write" : void 0),
|
|
11758
|
+
3
|
|
11759
|
+
);
|
|
11760
|
+
}
|
|
11737
11761
|
async identified(stat, known) {
|
|
11738
11762
|
const first = await stat();
|
|
11739
11763
|
if (first.orphan) return first;
|
|
@@ -11765,6 +11789,24 @@ var WasmProcess = class {
|
|
|
11765
11789
|
if (name2 !== void 0) ttyOpenable(this.guarded(), tty);
|
|
11766
11790
|
return this.fds.install(tty.file(), 3);
|
|
11767
11791
|
}
|
|
11792
|
+
openSealed() {
|
|
11793
|
+
const broker = this.options.sealed;
|
|
11794
|
+
if (!broker) throw new KernelError("ENOENT");
|
|
11795
|
+
return this.fds.install(broker.open(), 3);
|
|
11796
|
+
}
|
|
11797
|
+
async sealedCaller() {
|
|
11798
|
+
const shown = await this.options.identity?.();
|
|
11799
|
+
const broker = this.options.sealed;
|
|
11800
|
+
const tag = broker.tagOf(this.pid);
|
|
11801
|
+
return {
|
|
11802
|
+
pid: shown?.pid ?? this.pid,
|
|
11803
|
+
ppid: shown?.ppid ?? 0,
|
|
11804
|
+
uid: this.cred.euid,
|
|
11805
|
+
gid: this.cred.egid,
|
|
11806
|
+
...tag !== void 0 ? { tag } : {},
|
|
11807
|
+
users: broker.users
|
|
11808
|
+
};
|
|
11809
|
+
}
|
|
11768
11810
|
guarded() {
|
|
11769
11811
|
const { guard: guard2 } = this.options;
|
|
11770
11812
|
return guard2 && { fs: guard2.fs, dac: guard2.dac, cred: this.cred, pid: this.pid };
|
|
@@ -11885,6 +11927,8 @@ var WasmProcess = class {
|
|
|
11885
11927
|
return { ok: true, kind: "json", json: this.openTty(req.name) };
|
|
11886
11928
|
case "fd-tty-names":
|
|
11887
11929
|
return { ok: true, kind: "json", json: this.options.jobs?.terminalNames() ?? [] };
|
|
11930
|
+
case "fd-open-sealed":
|
|
11931
|
+
return { ok: true, kind: "json", json: this.openSealed() };
|
|
11888
11932
|
case "fd-tty-owner":
|
|
11889
11933
|
return { ok: true, kind: "json", json: this.terminalByName(req.name).owner ?? null };
|
|
11890
11934
|
case "fd-select": {
|
|
@@ -12320,6 +12364,7 @@ var WasmProcess = class {
|
|
|
12320
12364
|
async exit() {
|
|
12321
12365
|
if (this.exited) return;
|
|
12322
12366
|
this.exited = true;
|
|
12367
|
+
this.gone.abort();
|
|
12323
12368
|
this.die();
|
|
12324
12369
|
this.clearAlarm();
|
|
12325
12370
|
this.interrupt.abort();
|
|
@@ -12507,6 +12552,7 @@ function processOptions(opts, header3, hooks, created3) {
|
|
|
12507
12552
|
return {
|
|
12508
12553
|
...inherited(opts),
|
|
12509
12554
|
...opts.owners ? { owners: true } : {},
|
|
12555
|
+
...opts.sealed ? { sealed: opts.sealed } : {},
|
|
12510
12556
|
...opts.dac ? { guard: { dac: opts.dac, fs: opts.fs, created: created3 } } : {},
|
|
12511
12557
|
...opts.identity ? { identity: opts.identity } : {},
|
|
12512
12558
|
...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
|
|
@@ -12989,6 +13035,178 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
12989
13035
|
};
|
|
12990
13036
|
}
|
|
12991
13037
|
|
|
13038
|
+
// src/kernel/sealed.ts
|
|
13039
|
+
var SEALED_MAX_BYTES = 64 * 1024;
|
|
13040
|
+
var SEALED_TIMEOUT_MS = 1e4;
|
|
13041
|
+
var SEALED_OPS = /* @__PURE__ */ new Set([
|
|
13042
|
+
"seal",
|
|
13043
|
+
"placeholder",
|
|
13044
|
+
"list",
|
|
13045
|
+
"test",
|
|
13046
|
+
"request",
|
|
13047
|
+
"status",
|
|
13048
|
+
"cancel",
|
|
13049
|
+
"materialize"
|
|
13050
|
+
]);
|
|
13051
|
+
var encoder3 = new TextEncoder();
|
|
13052
|
+
var decoder2 = new TextDecoder("utf-8", { fatal: true });
|
|
13053
|
+
function parseSealed(bytes) {
|
|
13054
|
+
try {
|
|
13055
|
+
if (bytes.length > SEALED_MAX_BYTES) throw new KernelError("EMSGSIZE");
|
|
13056
|
+
let parsed2;
|
|
13057
|
+
try {
|
|
13058
|
+
parsed2 = JSON.parse(decoder2.decode(bytes));
|
|
13059
|
+
} catch {
|
|
13060
|
+
throw new KernelError("EINVAL");
|
|
13061
|
+
}
|
|
13062
|
+
if (typeof parsed2 !== "object" || parsed2 === null || Array.isArray(parsed2))
|
|
13063
|
+
throw new KernelError("EINVAL");
|
|
13064
|
+
const req = parsed2;
|
|
13065
|
+
if (req.v !== 1 || typeof req.op !== "string" || !SEALED_OPS.has(req.op))
|
|
13066
|
+
throw new KernelError("EINVAL");
|
|
13067
|
+
return req;
|
|
13068
|
+
} finally {
|
|
13069
|
+
bytes.fill(0);
|
|
13070
|
+
}
|
|
13071
|
+
}
|
|
13072
|
+
function errorReply(code, message3) {
|
|
13073
|
+
return { v: 1, error: { code, message: message3 } };
|
|
13074
|
+
}
|
|
13075
|
+
function isRecord(value) {
|
|
13076
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
13077
|
+
}
|
|
13078
|
+
function serialized(reply) {
|
|
13079
|
+
let plain;
|
|
13080
|
+
try {
|
|
13081
|
+
const text = JSON.stringify(reply);
|
|
13082
|
+
plain = text === void 0 ? void 0 : JSON.parse(text);
|
|
13083
|
+
} catch (err) {
|
|
13084
|
+
return JSON.stringify(errorReply("EIO", lineOf(err)));
|
|
13085
|
+
}
|
|
13086
|
+
if (!isRecord(plain)) return JSON.stringify(errorReply("EIO", "the vault gave no reply"));
|
|
13087
|
+
const { v: _, ...rest2 } = plain;
|
|
13088
|
+
return JSON.stringify({ v: 1, ...rest2 });
|
|
13089
|
+
}
|
|
13090
|
+
function lineOf(err) {
|
|
13091
|
+
const text = err instanceof Error ? err.message : String(err);
|
|
13092
|
+
return (text.split("\n")[0] ?? "").slice(0, 200);
|
|
13093
|
+
}
|
|
13094
|
+
var SealedChannel = class {
|
|
13095
|
+
reply;
|
|
13096
|
+
offset = 0;
|
|
13097
|
+
inflight;
|
|
13098
|
+
broker;
|
|
13099
|
+
constructor(broker) {
|
|
13100
|
+
this.broker = broker;
|
|
13101
|
+
}
|
|
13102
|
+
send(bytes, caller, gone) {
|
|
13103
|
+
const length2 = bytes.length;
|
|
13104
|
+
const fields = parseSealed(bytes);
|
|
13105
|
+
this.reply = void 0;
|
|
13106
|
+
this.offset = 0;
|
|
13107
|
+
this.inflight?.control.abort("replaced");
|
|
13108
|
+
const control = new AbortController();
|
|
13109
|
+
const withdraw = () => control.abort("withdrawn");
|
|
13110
|
+
if (gone.aborted) withdraw();
|
|
13111
|
+
else gone.addEventListener("abort", withdraw, { once: true });
|
|
13112
|
+
const timer = setTimeout(() => control.abort("timeout"), this.broker.timeoutMs);
|
|
13113
|
+
const req = { ...fields, v: 1, op: fields.op, caller };
|
|
13114
|
+
const flight = { control, done: Promise.resolve() };
|
|
13115
|
+
flight.done = this.answer(req, control.signal).then((reply) => {
|
|
13116
|
+
clearTimeout(timer);
|
|
13117
|
+
gone.removeEventListener("abort", withdraw);
|
|
13118
|
+
if (this.inflight !== flight) return;
|
|
13119
|
+
this.inflight = void 0;
|
|
13120
|
+
if (reply) this.reply = encoder3.encode(serialized(reply));
|
|
13121
|
+
});
|
|
13122
|
+
this.inflight = flight;
|
|
13123
|
+
return length2;
|
|
13124
|
+
}
|
|
13125
|
+
async answer(req, signal) {
|
|
13126
|
+
const hook = this.broker.hook;
|
|
13127
|
+
if (!hook) return errorReply("ENOTCONN", "no vault is connected");
|
|
13128
|
+
const stopped = new Promise((resolve) => {
|
|
13129
|
+
signal.addEventListener("abort", () => resolve(void 0), { once: true });
|
|
13130
|
+
});
|
|
13131
|
+
if (signal.aborted) return void 0;
|
|
13132
|
+
const asked = Promise.resolve().then(() => hook(req, { signal })).then(
|
|
13133
|
+
(reply2) => isRecord(reply2) ? reply2 : errorReply("EIO", "the vault gave no reply"),
|
|
13134
|
+
(err) => errorReply("EIO", lineOf(err))
|
|
13135
|
+
);
|
|
13136
|
+
const reply = await Promise.race([asked, stopped]);
|
|
13137
|
+
if (!signal.aborted) return reply;
|
|
13138
|
+
return signal.reason === "timeout" ? errorReply("ETIMEDOUT", "the vault did not answer within 10 s") : void 0;
|
|
13139
|
+
}
|
|
13140
|
+
async read(max, signal) {
|
|
13141
|
+
for (; ; ) {
|
|
13142
|
+
if (this.reply) {
|
|
13143
|
+
const out = this.reply.slice(this.offset, this.offset + max);
|
|
13144
|
+
this.offset += out.length;
|
|
13145
|
+
if (this.offset >= this.reply.length) {
|
|
13146
|
+
this.reply = void 0;
|
|
13147
|
+
this.offset = 0;
|
|
13148
|
+
}
|
|
13149
|
+
return out;
|
|
13150
|
+
}
|
|
13151
|
+
const flight = this.inflight;
|
|
13152
|
+
if (!flight) return new Uint8Array(0);
|
|
13153
|
+
await this.until(flight, signal);
|
|
13154
|
+
}
|
|
13155
|
+
}
|
|
13156
|
+
async until(flight, signal) {
|
|
13157
|
+
if (!signal) return flight.done;
|
|
13158
|
+
if (signal.aborted) throw new KernelError("EINTR");
|
|
13159
|
+
let stop = () => {
|
|
13160
|
+
};
|
|
13161
|
+
const interrupted2 = new Promise((_, reject) => {
|
|
13162
|
+
stop = () => reject(new KernelError("EINTR"));
|
|
13163
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
13164
|
+
});
|
|
13165
|
+
try {
|
|
13166
|
+
await Promise.race([flight.done, interrupted2]);
|
|
13167
|
+
} finally {
|
|
13168
|
+
signal.removeEventListener("abort", stop);
|
|
13169
|
+
}
|
|
13170
|
+
}
|
|
13171
|
+
poll() {
|
|
13172
|
+
return { readable: this.reply !== void 0 || !this.inflight, writable: true, hangup: false };
|
|
13173
|
+
}
|
|
13174
|
+
async changed(signal) {
|
|
13175
|
+
const flight = this.inflight;
|
|
13176
|
+
if (flight) await this.until(flight, signal);
|
|
13177
|
+
}
|
|
13178
|
+
close() {
|
|
13179
|
+
this.inflight?.control.abort("withdrawn");
|
|
13180
|
+
this.inflight = void 0;
|
|
13181
|
+
this.reply = void 0;
|
|
13182
|
+
}
|
|
13183
|
+
};
|
|
13184
|
+
var SealedBroker = class {
|
|
13185
|
+
hook;
|
|
13186
|
+
users;
|
|
13187
|
+
timeoutMs;
|
|
13188
|
+
tagOf;
|
|
13189
|
+
constructor(hook, users, timeoutMs = SEALED_TIMEOUT_MS, tagOf = () => void 0) {
|
|
13190
|
+
this.hook = hook;
|
|
13191
|
+
this.users = users;
|
|
13192
|
+
this.timeoutMs = timeoutMs;
|
|
13193
|
+
this.tagOf = tagOf;
|
|
13194
|
+
}
|
|
13195
|
+
open() {
|
|
13196
|
+
const channel = new SealedChannel(this);
|
|
13197
|
+
return new OpenFile({
|
|
13198
|
+
read: (max, signal) => channel.read(max, signal),
|
|
13199
|
+
write: async () => {
|
|
13200
|
+
throw new KernelError("EINVAL");
|
|
13201
|
+
},
|
|
13202
|
+
poll: () => channel.poll(),
|
|
13203
|
+
changed: (signal) => channel.changed(signal),
|
|
13204
|
+
close: () => channel.close(),
|
|
13205
|
+
sealed: channel
|
|
13206
|
+
});
|
|
13207
|
+
}
|
|
13208
|
+
};
|
|
13209
|
+
|
|
12992
13210
|
// src/kernel/settling.ts
|
|
12993
13211
|
var SETUP_OPS = /* @__PURE__ */ new Set([
|
|
12994
13212
|
"proc-list",
|
|
@@ -13636,13 +13854,13 @@ var HostfsClient = class {
|
|
|
13636
13854
|
const response = await this.send("/api/hostfs/watch", { method: "POST", signal });
|
|
13637
13855
|
onOpen();
|
|
13638
13856
|
const reader = response.body.getReader();
|
|
13639
|
-
const
|
|
13857
|
+
const decoder3 = new TextDecoder();
|
|
13640
13858
|
let buffered = "";
|
|
13641
13859
|
try {
|
|
13642
13860
|
for (; ; ) {
|
|
13643
13861
|
const { done: done4, value } = await reader.read();
|
|
13644
13862
|
if (done4) return;
|
|
13645
|
-
buffered +=
|
|
13863
|
+
buffered += decoder3.decode(value, { stream: true });
|
|
13646
13864
|
let end = buffered.indexOf("\n");
|
|
13647
13865
|
while (end >= 0) {
|
|
13648
13866
|
const line = buffered.slice(0, end).trim();
|
|
@@ -15020,7 +15238,7 @@ var LAYOUT = [
|
|
|
15020
15238
|
];
|
|
15021
15239
|
var LOAD_SAMPLE_MS = 5e3;
|
|
15022
15240
|
var LOAD_WINDOWS_MS = [6e4, 3e5, 9e5];
|
|
15023
|
-
var
|
|
15241
|
+
var encoder4 = new TextEncoder();
|
|
15024
15242
|
var USERS_MODES = ["off", "report", "enforce"];
|
|
15025
15243
|
function usersMode(mode = "off") {
|
|
15026
15244
|
if (USERS_MODES.includes(mode)) return mode;
|
|
@@ -15170,12 +15388,19 @@ var Launcher = class {
|
|
|
15170
15388
|
fstab = Promise.resolve([]);
|
|
15171
15389
|
usersMode;
|
|
15172
15390
|
dac;
|
|
15391
|
+
sealed;
|
|
15173
15392
|
nextPid = 1e3;
|
|
15174
15393
|
boot = Date.now();
|
|
15175
15394
|
terminals = 0;
|
|
15176
15395
|
constructor(options) {
|
|
15177
15396
|
this.usersMode = usersMode(options.users);
|
|
15178
15397
|
this.dac = this.usersMode === "off" ? void 0 : new Dac(this.usersMode, options.onDenial);
|
|
15398
|
+
this.sealed = new SealedBroker(
|
|
15399
|
+
options.sealed,
|
|
15400
|
+
this.usersMode,
|
|
15401
|
+
void 0,
|
|
15402
|
+
(pid) => this.tagOf(pid)
|
|
15403
|
+
);
|
|
15179
15404
|
if (this.owners) options.fs.trackOwners?.();
|
|
15180
15405
|
this.mounts = new MountTable({
|
|
15181
15406
|
open: (type, spec) => this.driver(type, spec),
|
|
@@ -15575,6 +15800,7 @@ var Launcher = class {
|
|
|
15575
15800
|
...req.umask !== void 0 ? { umask: req.umask } : {},
|
|
15576
15801
|
cred: req.cred,
|
|
15577
15802
|
...this.owners ? { owners: true } : {},
|
|
15803
|
+
sealed: this.sealed,
|
|
15578
15804
|
...this.dac ? { dac: this.dac } : {},
|
|
15579
15805
|
program: req.program,
|
|
15580
15806
|
argv0: req.argv0,
|
|
@@ -16213,7 +16439,7 @@ var Launcher = class {
|
|
|
16213
16439
|
},
|
|
16214
16440
|
account
|
|
16215
16441
|
);
|
|
16216
|
-
const report = (message3) => options.onData(
|
|
16442
|
+
const report = (message3) => options.onData(encoder4.encode(`${message3}\r
|
|
16217
16443
|
`));
|
|
16218
16444
|
const handle = await this.launch(planned, {
|
|
16219
16445
|
env,
|
|
@@ -16250,7 +16476,7 @@ var Launcher = class {
|
|
|
16250
16476
|
};
|
|
16251
16477
|
const stdout = collect(out, options.onStdout);
|
|
16252
16478
|
const stderr = collect(err, options.onStderr);
|
|
16253
|
-
const report = (message3) => stderr(
|
|
16479
|
+
const report = (message3) => stderr(encoder4.encode(`${message3}
|
|
16254
16480
|
`));
|
|
16255
16481
|
if (!planned) {
|
|
16256
16482
|
report(`${file}: command not found`);
|
|
@@ -16275,6 +16501,33 @@ var Launcher = class {
|
|
|
16275
16501
|
}
|
|
16276
16502
|
};
|
|
16277
16503
|
|
|
16504
|
+
// src/sealed-relay.ts
|
|
16505
|
+
function sealedAsker(port) {
|
|
16506
|
+
const asks = /* @__PURE__ */ new Map();
|
|
16507
|
+
let next2 = 0;
|
|
16508
|
+
const hook = (req, { signal }) => {
|
|
16509
|
+
const id2 = ++next2;
|
|
16510
|
+
const waiting = Promise.withResolvers();
|
|
16511
|
+
asks.set(id2, waiting);
|
|
16512
|
+
const abort = () => {
|
|
16513
|
+
if (!asks.delete(id2)) return;
|
|
16514
|
+
port.postMessage({ sealedAbort: { id: id2, reason: signal.reason } });
|
|
16515
|
+
waiting.reject(new Error(String(signal.reason)));
|
|
16516
|
+
};
|
|
16517
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
16518
|
+
port.postMessage({ sealedAsk: { id: id2, req } });
|
|
16519
|
+
return waiting.promise.finally(() => signal.removeEventListener("abort", abort));
|
|
16520
|
+
};
|
|
16521
|
+
const answer = ({ id: id2, reply, error }) => {
|
|
16522
|
+
const waiting = asks.get(id2);
|
|
16523
|
+
if (!waiting) return;
|
|
16524
|
+
asks.delete(id2);
|
|
16525
|
+
if (reply) waiting.resolve(reply);
|
|
16526
|
+
else waiting.reject(new Error(error ?? "no reply"));
|
|
16527
|
+
};
|
|
16528
|
+
return { hook, answer };
|
|
16529
|
+
}
|
|
16530
|
+
|
|
16278
16531
|
// src/serve.ts
|
|
16279
16532
|
async function inOpfs(deps, root) {
|
|
16280
16533
|
if (deps.syncAccess !== true) return false;
|
|
@@ -16389,11 +16642,31 @@ function usersOp(l, req) {
|
|
|
16389
16642
|
if (req.op === "groups-remove-member") return l.users.removeMember(req.group, req.user);
|
|
16390
16643
|
return l.users.list();
|
|
16391
16644
|
}
|
|
16392
|
-
function hostOptions(req, port) {
|
|
16645
|
+
function hostOptions(req, port, sealed) {
|
|
16393
16646
|
return {
|
|
16394
16647
|
...req.hostname !== void 0 ? { hostname: req.hostname } : {},
|
|
16395
16648
|
...req.users !== void 0 ? { users: req.users } : {},
|
|
16396
|
-
...req.denials ? { onDenial: (denial) => port.postMessage({ denial }) } : {}
|
|
16649
|
+
...req.denials ? { onDenial: (denial) => port.postMessage({ denial }) } : {},
|
|
16650
|
+
...req.sealed ? { sealed } : {}
|
|
16651
|
+
};
|
|
16652
|
+
}
|
|
16653
|
+
function policyAsker(port) {
|
|
16654
|
+
const policies = /* @__PURE__ */ new Map();
|
|
16655
|
+
let nextPolicy = 0;
|
|
16656
|
+
const askPolicy = (req) => new Promise((resolve) => {
|
|
16657
|
+
const id2 = ++nextPolicy;
|
|
16658
|
+
policies.set(id2, resolve);
|
|
16659
|
+
port.postMessage({ mountPolicy: { id: id2, req } });
|
|
16660
|
+
});
|
|
16661
|
+
return {
|
|
16662
|
+
mountPolicy: (policy) => policy === void 0 ? {} : { processMounts: policy === "ask" ? askPolicy : policy },
|
|
16663
|
+
allowed(data) {
|
|
16664
|
+
const answer = data.mountAllowed;
|
|
16665
|
+
if (!answer) return false;
|
|
16666
|
+
policies.get(answer.id)?.(answer.allowed);
|
|
16667
|
+
policies.delete(answer.id);
|
|
16668
|
+
return true;
|
|
16669
|
+
}
|
|
16397
16670
|
};
|
|
16398
16671
|
}
|
|
16399
16672
|
function serveKernel(port, deps) {
|
|
@@ -16403,6 +16676,7 @@ function serveKernel(port, deps) {
|
|
|
16403
16676
|
const terminals = /* @__PURE__ */ new Map();
|
|
16404
16677
|
const reply = (id2, body, transfer) => port.postMessage({ id: id2, ...body }, transfer);
|
|
16405
16678
|
const clients = /* @__PURE__ */ new Set();
|
|
16679
|
+
const sealed = sealedAsker(port);
|
|
16406
16680
|
const approvals = sudoApprovals(port);
|
|
16407
16681
|
const locks = deps.locks === null ? void 0 : deps.locks ?? locksOf();
|
|
16408
16682
|
let holding;
|
|
@@ -16467,7 +16741,7 @@ function serveKernel(port, deps) {
|
|
|
16467
16741
|
...deps.createDriverWorker ? { createDriverWorker: deps.createDriverWorker } : {},
|
|
16468
16742
|
...req.modules ? { modules: req.modules } : {},
|
|
16469
16743
|
...req.env ? { env: req.env } : {},
|
|
16470
|
-
...hostOptions(req, port),
|
|
16744
|
+
...hostOptions(req, port, sealed.hook),
|
|
16471
16745
|
...req.approve ? { approve: approvals.ask } : {},
|
|
16472
16746
|
...net,
|
|
16473
16747
|
...media ? { media } : {},
|
|
@@ -16530,23 +16804,13 @@ function serveKernel(port, deps) {
|
|
|
16530
16804
|
if (grant) waiting.resolve(grant);
|
|
16531
16805
|
else waiting.reject(Object.assign(new Error(error ?? "no grant"), { code: "EACCES" }));
|
|
16532
16806
|
}
|
|
16533
|
-
const
|
|
16534
|
-
let nextPolicy = 0;
|
|
16535
|
-
const askPolicy = (req) => new Promise((resolve) => {
|
|
16536
|
-
const id2 = ++nextPolicy;
|
|
16537
|
-
policies.set(id2, resolve);
|
|
16538
|
-
port.postMessage({ mountPolicy: { id: id2, req } });
|
|
16539
|
-
});
|
|
16540
|
-
const mountPolicy = (policy) => policy === void 0 ? {} : { processMounts: policy === "ask" ? askPolicy : policy };
|
|
16807
|
+
const { mountPolicy, allowed } = policyAsker(port);
|
|
16541
16808
|
port.addEventListener("message", (event) => {
|
|
16809
|
+
const sealedReply = event.data.sealedReply;
|
|
16810
|
+
if (sealedReply) return sealed.answer(sealedReply);
|
|
16542
16811
|
const grant = event.data.hostfsGrant;
|
|
16543
16812
|
if (grant) return granted2(grant);
|
|
16544
|
-
|
|
16545
|
-
if (answer) {
|
|
16546
|
-
policies.get(answer.id)?.(answer.allowed);
|
|
16547
|
-
policies.delete(answer.id);
|
|
16548
|
-
return;
|
|
16549
|
-
}
|
|
16813
|
+
if (allowed(event.data)) return;
|
|
16550
16814
|
if (answered(event.data, remote, uplink, approvals)) return;
|
|
16551
16815
|
const req = event.data;
|
|
16552
16816
|
handle(req).then(
|