@ai-ecoverse/slicc-kernel 1.103.4 → 1.106.2
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 +56 -15
- package/dist/driver-worker.js +36 -1
- package/dist/driver-worker.js.map +2 -2
- package/dist/index.js +89 -5
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +783 -289
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js.map +2 -2
- package/dist/node-driver-worker.js +36 -1
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.js +447 -224
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +831 -309
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +384 -161
- package/dist/process-worker.js.map +4 -4
- package/dist/types/commands.d.ts +6 -1
- package/dist/types/fs/command-stat.d.ts +3 -0
- package/dist/types/fs/commands.d.ts +7 -1
- package/dist/types/fs/engines.d.ts +5 -0
- package/dist/types/fs/types.d.ts +1 -0
- package/dist/types/kernel/host.d.ts +1 -0
- package/dist/types/kernel/net/http-syscalls.d.ts +10 -0
- package/dist/types/kernel/net/http1.d.ts +1 -0
- package/dist/types/kernel/net/remote-transport.d.ts +18 -0
- package/dist/types/kernel/net/transport.d.ts +2 -0
- package/dist/types/kernel/process.d.ts +8 -0
- package/dist/types/launcher.d.ts +4 -0
- package/dist/types/process/process-signals.d.ts +3 -0
- package/dist/types/process/wasi/wasi-cred.d.ts +11 -0
- package/dist/types/process/wasi/wasi-files.d.ts +1 -0
- package/dist/types/process/wasi/wasi-host.d.ts +9 -0
- package/dist/types/process/wasi/wasi-sigmask.d.ts +7 -1
- package/dist/types/process/wasi/wasix-epoll.d.ts +3 -0
- package/dist/types/refused-command.d.ts +4 -0
- package/dist/types/transport.d.ts +1 -0
- package/package.json +12 -12
package/dist/node.js
CHANGED
|
@@ -323,11 +323,11 @@ async function realDir(fs, dir, budget = { hops: 0 }) {
|
|
|
323
323
|
at = parentOf(at);
|
|
324
324
|
continue;
|
|
325
325
|
}
|
|
326
|
-
const
|
|
327
|
-
const link2 = await linkOf(fs,
|
|
326
|
+
const next3 = at === "/" ? `/${part}` : `${at}/${part}`;
|
|
327
|
+
const link2 = await linkOf(fs, next3);
|
|
328
328
|
if (link2 === void 0) {
|
|
329
|
-
if (queue.find((p) => p !== ".") === "..") await mustBeDir(fs,
|
|
330
|
-
at =
|
|
329
|
+
if (queue.find((p) => p !== ".") === "..") await mustBeDir(fs, next3);
|
|
330
|
+
at = next3;
|
|
331
331
|
continue;
|
|
332
332
|
}
|
|
333
333
|
if (budget.hops >= MAX_LINKS) throw fsError("ELOOP", dir);
|
|
@@ -430,18 +430,18 @@ async function walk(fs, cred, path, follow2, links) {
|
|
|
430
430
|
at = parentOf(at);
|
|
431
431
|
continue;
|
|
432
432
|
}
|
|
433
|
-
const
|
|
434
|
-
const perm = await perms.at(
|
|
433
|
+
const next3 = joinName(at, part);
|
|
434
|
+
const perm = await perms.at(next3);
|
|
435
435
|
const last = queue.length === 0;
|
|
436
436
|
if (perm?.link !== void 0 && (!last || follow2)) {
|
|
437
|
-
if (!trustedLink(perm, links)) return { path, perm: void 0, denied:
|
|
438
|
-
if (++hops > MAX_LINKS2) return { path:
|
|
437
|
+
if (!trustedLink(perm, links)) return { path, perm: void 0, denied: next3, link: true };
|
|
438
|
+
if (++hops > MAX_LINKS2) return { path: next3, perm: void 0 };
|
|
439
439
|
queue.unshift(...parts(perm.link));
|
|
440
440
|
if (perm.link.startsWith("/")) at = "/";
|
|
441
441
|
continue;
|
|
442
442
|
}
|
|
443
|
-
if (last) return { path:
|
|
444
|
-
at =
|
|
443
|
+
if (last) return { path: next3, perm };
|
|
444
|
+
at = next3;
|
|
445
445
|
}
|
|
446
446
|
return { path: at, perm: await perms.at(at) };
|
|
447
447
|
}
|
|
@@ -546,8 +546,13 @@ function ttyOpenable(g, tty) {
|
|
|
546
546
|
async function need(g, op, path, want, options = {}, shown = path) {
|
|
547
547
|
const walked = await access(g.fs, g.cred, path, want, linked(g, options));
|
|
548
548
|
if (walked.denied !== void 0) deny(g, op, walked.link ? walked.denied : shown);
|
|
549
|
+
else if (want & R_OK && g.fs.commandTarget) await readsAs(g, op, walked.path, shown);
|
|
549
550
|
return walked;
|
|
550
551
|
}
|
|
552
|
+
async function readsAs(g, op, path, shown) {
|
|
553
|
+
const target = await g.fs.commandTarget?.(path);
|
|
554
|
+
if (target !== void 0) await need(g, op, target, R_OK, { directory: false }, shown);
|
|
555
|
+
}
|
|
551
556
|
function entryIn(dir, path) {
|
|
552
557
|
return joinName(dir.path, path.slice(path.lastIndexOf("/") + 1));
|
|
553
558
|
}
|
|
@@ -706,14 +711,14 @@ function changeCred(cur, change) {
|
|
|
706
711
|
throw fsError("EINVAL", "not a change");
|
|
707
712
|
}
|
|
708
713
|
const privileged = cur.euid === 0;
|
|
709
|
-
const
|
|
714
|
+
const next3 = copyCred(cur);
|
|
710
715
|
for (const keys of [UIDS, GIDS]) {
|
|
711
716
|
const own = keys.map((key) => cur[key]);
|
|
712
717
|
for (const key of keys) {
|
|
713
718
|
const value = id(change[key]);
|
|
714
719
|
if (value === void 0) continue;
|
|
715
720
|
if (!privileged && !own.includes(value)) throw fsError("EPERM", `${key} ${value}`);
|
|
716
|
-
|
|
721
|
+
next3[key] = value;
|
|
717
722
|
}
|
|
718
723
|
}
|
|
719
724
|
if (change.groups !== void 0) {
|
|
@@ -723,9 +728,9 @@ function changeCred(cur, change) {
|
|
|
723
728
|
const groups = change.groups.map((g) => id(g) ?? Number.NaN);
|
|
724
729
|
if (groups.some(Number.isNaN)) throw fsError("EINVAL", "not a group list");
|
|
725
730
|
if (!privileged) throw fsError("EPERM", "setgroups");
|
|
726
|
-
|
|
731
|
+
next3.groups = groups;
|
|
727
732
|
}
|
|
728
|
-
return
|
|
733
|
+
return next3;
|
|
729
734
|
}
|
|
730
735
|
function maySignal(sender, target) {
|
|
731
736
|
if (sender.euid === 0) return true;
|
|
@@ -1638,10 +1643,10 @@ var KernelSocket = class _KernelSocket {
|
|
|
1638
1643
|
async accept(signal, nonblock = false) {
|
|
1639
1644
|
for (; ; ) {
|
|
1640
1645
|
if (this.state !== "listening") throw new KernelError("EINVAL");
|
|
1641
|
-
const
|
|
1642
|
-
if (
|
|
1646
|
+
const next3 = this.queue.shift();
|
|
1647
|
+
if (next3) {
|
|
1643
1648
|
this.room.wake();
|
|
1644
|
-
return
|
|
1649
|
+
return next3;
|
|
1645
1650
|
}
|
|
1646
1651
|
if (nonblock) throw new KernelError("EAGAIN");
|
|
1647
1652
|
await this.changes.wait(signal);
|
|
@@ -2181,12 +2186,12 @@ var MessageQueue = class {
|
|
|
2181
2186
|
}
|
|
2182
2187
|
async *[Symbol.asyncIterator]() {
|
|
2183
2188
|
for (; ; ) {
|
|
2184
|
-
const
|
|
2185
|
-
if (
|
|
2186
|
-
const n = payloadSize(
|
|
2189
|
+
const next3 = this.items.shift();
|
|
2190
|
+
if (next3 !== void 0) {
|
|
2191
|
+
const n = payloadSize(next3);
|
|
2187
2192
|
this.size -= n;
|
|
2188
2193
|
this.taken?.(n);
|
|
2189
|
-
yield
|
|
2194
|
+
yield next3;
|
|
2190
2195
|
continue;
|
|
2191
2196
|
}
|
|
2192
2197
|
if (this.ended) return;
|
|
@@ -2313,13 +2318,35 @@ async function* chunks(body, idleMs) {
|
|
|
2313
2318
|
if (!body) return;
|
|
2314
2319
|
const reader = body.getReader();
|
|
2315
2320
|
try {
|
|
2316
|
-
for (let
|
|
2317
|
-
if (
|
|
2321
|
+
for (let next3 = await readWithin(reader, idleMs); !next3.done; next3 = await readWithin(reader, idleMs)) {
|
|
2322
|
+
if (next3.value.byteLength > 0) yield next3.value;
|
|
2318
2323
|
}
|
|
2319
2324
|
} finally {
|
|
2320
2325
|
await reader.cancel().catch(() => void 0);
|
|
2321
2326
|
}
|
|
2322
2327
|
}
|
|
2328
|
+
function streamOf(body) {
|
|
2329
|
+
const it = body[Symbol.asyncIterator]();
|
|
2330
|
+
return new ReadableStream(
|
|
2331
|
+
{
|
|
2332
|
+
async pull(controller) {
|
|
2333
|
+
const next3 = await it.next();
|
|
2334
|
+
if (next3.done) controller.close();
|
|
2335
|
+
else controller.enqueue(next3.value);
|
|
2336
|
+
},
|
|
2337
|
+
async cancel(reason) {
|
|
2338
|
+
await it.return?.(reason);
|
|
2339
|
+
}
|
|
2340
|
+
},
|
|
2341
|
+
{ highWaterMark: 0 }
|
|
2342
|
+
);
|
|
2343
|
+
}
|
|
2344
|
+
function requestBody(request) {
|
|
2345
|
+
if (request.bodyStream) {
|
|
2346
|
+
return { body: streamOf(request.bodyStream), duplex: "half" };
|
|
2347
|
+
}
|
|
2348
|
+
return request.body ? { body: request.body } : {};
|
|
2349
|
+
}
|
|
2323
2350
|
function fetchTransport(options = {}) {
|
|
2324
2351
|
const send = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
2325
2352
|
const Socket = options.webSocket === true ? globalThis.WebSocket : options.webSocket || void 0;
|
|
@@ -2331,7 +2358,8 @@ function fetchTransport(options = {}) {
|
|
|
2331
2358
|
encodedBodies: false,
|
|
2332
2359
|
maxRequestBody: options.maxRequestBody ?? MAX_REQUEST_BODY,
|
|
2333
2360
|
crossOrigin: "cors",
|
|
2334
|
-
...Socket ? { websocket: true } : {}
|
|
2361
|
+
...Socket ? { websocket: true } : {},
|
|
2362
|
+
...options.streamingBodies ? { streamingBodies: true } : {}
|
|
2335
2363
|
},
|
|
2336
2364
|
...Socket ? { websocket: (request) => openWebSocket(Socket, request, headers) } : {},
|
|
2337
2365
|
async fetch(request) {
|
|
@@ -2340,7 +2368,7 @@ function fetchTransport(options = {}) {
|
|
|
2340
2368
|
response = await send(request.url, {
|
|
2341
2369
|
method: request.method,
|
|
2342
2370
|
headers: joinHeaders(request.headers),
|
|
2343
|
-
...request
|
|
2371
|
+
...requestBody(request),
|
|
2344
2372
|
signal: request.signal,
|
|
2345
2373
|
redirect,
|
|
2346
2374
|
credentials: "omit",
|
|
@@ -2377,6 +2405,29 @@ function fetchTransport(options = {}) {
|
|
|
2377
2405
|
}
|
|
2378
2406
|
};
|
|
2379
2407
|
}
|
|
2408
|
+
function uploadsFor(peer) {
|
|
2409
|
+
const pulls = /* @__PURE__ */ new Map();
|
|
2410
|
+
const of = (nid, signal) => ({
|
|
2411
|
+
async *[Symbol.asyncIterator]() {
|
|
2412
|
+
for (; ; ) {
|
|
2413
|
+
signal.throwIfAborted();
|
|
2414
|
+
const got = await new Promise((resolve2, reject) => {
|
|
2415
|
+
const stop = () => reject(signal.reason);
|
|
2416
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
2417
|
+
pulls.set(nid, (call) => {
|
|
2418
|
+
signal.removeEventListener("abort", stop);
|
|
2419
|
+
resolve2(call);
|
|
2420
|
+
});
|
|
2421
|
+
peer.postMessage({ net: "body-pull", nid });
|
|
2422
|
+
}).finally(() => pulls.delete(nid));
|
|
2423
|
+
if (got.net === "body-end") return;
|
|
2424
|
+
if (got.net === "body-error") throw new Error(got.message);
|
|
2425
|
+
if (got.net === "body-chunk") yield got.bytes;
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
});
|
|
2429
|
+
return { of, answer: (call) => pulls.get(call.nid)?.(call) };
|
|
2430
|
+
}
|
|
2380
2431
|
function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
2381
2432
|
const open = /* @__PURE__ */ new Map();
|
|
2382
2433
|
const fail3 = (nid, e) => {
|
|
@@ -2390,6 +2441,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
2390
2441
|
...typeof code === "string" ? { code } : {}
|
|
2391
2442
|
});
|
|
2392
2443
|
};
|
|
2444
|
+
const uploads = uploadsFor(peer);
|
|
2393
2445
|
const start2 = async (call) => {
|
|
2394
2446
|
const abort = new AbortController();
|
|
2395
2447
|
const entry = { abort };
|
|
@@ -2399,7 +2451,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
2399
2451
|
url: call.url,
|
|
2400
2452
|
method: call.method,
|
|
2401
2453
|
headers: call.headers,
|
|
2402
|
-
...call.body ? { body: call.body } : {},
|
|
2454
|
+
...call.streamed ? { bodyStream: uploads.of(call.nid, abort.signal) } : call.body ? { body: call.body } : {},
|
|
2403
2455
|
signal: abort.signal
|
|
2404
2456
|
});
|
|
2405
2457
|
if (!open.has(call.nid)) {
|
|
@@ -2471,9 +2523,9 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
2471
2523
|
try {
|
|
2472
2524
|
const messages = socket.messages[Symbol.asyncIterator]();
|
|
2473
2525
|
for (; ; ) {
|
|
2474
|
-
const
|
|
2475
|
-
if (
|
|
2476
|
-
const data =
|
|
2526
|
+
const next3 = await Promise.race([messages.next(), unanswered]);
|
|
2527
|
+
if (next3 === "late" || next3.done) break;
|
|
2528
|
+
const data = next3.value;
|
|
2477
2529
|
if (flow.closing) continue;
|
|
2478
2530
|
if (payloadSize(data) > MESSAGE_LIMIT) {
|
|
2479
2531
|
oversize = true;
|
|
@@ -2514,12 +2566,12 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
2514
2566
|
const body = open.get(nid)?.body;
|
|
2515
2567
|
if (!body) return;
|
|
2516
2568
|
try {
|
|
2517
|
-
const
|
|
2518
|
-
if (
|
|
2569
|
+
const next3 = await body.next();
|
|
2570
|
+
if (next3.done) {
|
|
2519
2571
|
open.delete(nid);
|
|
2520
2572
|
peer.postMessage({ net: "end", nid });
|
|
2521
2573
|
} else {
|
|
2522
|
-
const bytes = fresh(
|
|
2574
|
+
const bytes = fresh(next3.value);
|
|
2523
2575
|
peer.postMessage({ net: "chunk", nid, bytes }, [bytes.buffer]);
|
|
2524
2576
|
}
|
|
2525
2577
|
} catch (e) {
|
|
@@ -2537,7 +2589,9 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
2537
2589
|
return {
|
|
2538
2590
|
answer(call) {
|
|
2539
2591
|
if (call.net === "fetch") void start2(call);
|
|
2540
|
-
else if (call.net === "
|
|
2592
|
+
else if (call.net === "body-chunk" || call.net === "body-end" || call.net === "body-error") {
|
|
2593
|
+
uploads.answer(call);
|
|
2594
|
+
} else if (call.net === "read") void read(call.nid);
|
|
2541
2595
|
else if (call.net === "ws-open") void openSocket(call);
|
|
2542
2596
|
else if (call.net === "ws-send") void sendOn(call);
|
|
2543
2597
|
else if (call.net === "ws-close") {
|
|
@@ -2747,9 +2801,9 @@ var UserDb = class {
|
|
|
2747
2801
|
}
|
|
2748
2802
|
}
|
|
2749
2803
|
serial(work) {
|
|
2750
|
-
const
|
|
2751
|
-
this.writing =
|
|
2752
|
-
return
|
|
2804
|
+
const next3 = this.writing.then(work);
|
|
2805
|
+
this.writing = next3.catch(() => void 0);
|
|
2806
|
+
return next3;
|
|
2753
2807
|
}
|
|
2754
2808
|
async ensure() {
|
|
2755
2809
|
await this.fs.mkdir("/etc", { recursive: true });
|
|
@@ -2948,14 +3002,14 @@ async function realpath(fs, path) {
|
|
|
2948
3002
|
let resolved2 = "";
|
|
2949
3003
|
for (let hops = 0; parts2.length > 0; ) {
|
|
2950
3004
|
const [name2, ...rest2] = parts2;
|
|
2951
|
-
const
|
|
2952
|
-
if (!(await fs.lstat(
|
|
2953
|
-
resolved2 =
|
|
3005
|
+
const next3 = `${resolved2}/${name2}`;
|
|
3006
|
+
if (!(await fs.lstat(next3)).isSymbolicLink) {
|
|
3007
|
+
resolved2 = next3;
|
|
2954
3008
|
parts2 = rest2;
|
|
2955
3009
|
continue;
|
|
2956
3010
|
}
|
|
2957
3011
|
if (++hops > MAX_LINKS3) throw fsError("ELOOP", path);
|
|
2958
|
-
const target = await fs.readlink(
|
|
3012
|
+
const target = await fs.readlink(next3);
|
|
2959
3013
|
const base = target.startsWith("/") ? "/" : resolved2 || "/";
|
|
2960
3014
|
parts2 = [...fs.resolvePath(base, target).split("/").filter(Boolean), ...rest2];
|
|
2961
3015
|
resolved2 = "";
|
|
@@ -3434,9 +3488,9 @@ var PathMap = class {
|
|
|
3434
3488
|
}
|
|
3435
3489
|
link(path) {
|
|
3436
3490
|
for (let child = path, parent = parentOf2(path); parent !== void 0; ) {
|
|
3437
|
-
const
|
|
3438
|
-
if (
|
|
3439
|
-
if (
|
|
3491
|
+
const set3 = this.children.get(parent);
|
|
3492
|
+
if (set3?.has(child)) return;
|
|
3493
|
+
if (set3) set3.add(child);
|
|
3440
3494
|
else this.children.set(parent, /* @__PURE__ */ new Set([child]));
|
|
3441
3495
|
child = parent;
|
|
3442
3496
|
parent = parentOf2(parent);
|
|
@@ -3445,9 +3499,9 @@ var PathMap = class {
|
|
|
3445
3499
|
prune(path) {
|
|
3446
3500
|
for (let child = path, parent = parentOf2(path); parent !== void 0; ) {
|
|
3447
3501
|
if (this.values.has(child) || this.children.has(child)) return;
|
|
3448
|
-
const
|
|
3449
|
-
|
|
3450
|
-
if (
|
|
3502
|
+
const set3 = this.children.get(parent);
|
|
3503
|
+
set3?.delete(child);
|
|
3504
|
+
if (set3 && set3.size > 0) return;
|
|
3451
3505
|
this.children.delete(parent);
|
|
3452
3506
|
child = parent;
|
|
3453
3507
|
parent = parentOf2(parent);
|
|
@@ -3588,14 +3642,14 @@ var Integrity = class {
|
|
|
3588
3642
|
if (!this.root.version) return void 0;
|
|
3589
3643
|
return `${real}\0${await this.root.version(real)}`;
|
|
3590
3644
|
}
|
|
3591
|
-
async read(path, caller,
|
|
3592
|
-
return (await this.readKeyed(path, caller,
|
|
3645
|
+
async read(path, caller, plain2, asked) {
|
|
3646
|
+
return (await this.readKeyed(path, caller, plain2, asked)).bytes;
|
|
3593
3647
|
}
|
|
3594
|
-
async readKeyed(path, caller,
|
|
3648
|
+
async readKeyed(path, caller, plain2, asked) {
|
|
3595
3649
|
const found = await this.real(path, asked);
|
|
3596
|
-
if (found === void 0) return { bytes: await
|
|
3650
|
+
if (found === void 0) return { bytes: await plain2() };
|
|
3597
3651
|
const { real, name: name2 } = found;
|
|
3598
|
-
const read = name2 !== real ? { bytes: await
|
|
3652
|
+
const read = name2 !== real ? { bytes: await plain2(), version: void 0 } : this.root.readVersioned ? await this.root.readVersioned(real) : { bytes: await this.root.readFileBuffer(real), version: void 0 };
|
|
3599
3653
|
const { bytes } = read;
|
|
3600
3654
|
const keyed = read.version === void 0 ? { bytes } : { bytes, key: `${real}\0${read.version}` };
|
|
3601
3655
|
await this.verify(name2, bytes, caller, EXEC_OPS);
|
|
@@ -3604,9 +3658,9 @@ var Integrity = class {
|
|
|
3604
3658
|
get readsChecked() {
|
|
3605
3659
|
return this.sources.length > 0;
|
|
3606
3660
|
}
|
|
3607
|
-
async readSource(path, caller,
|
|
3661
|
+
async readSource(path, caller, plain2) {
|
|
3608
3662
|
const found = await this.source(path);
|
|
3609
|
-
return found === void 0 ?
|
|
3663
|
+
return found === void 0 ? plain2() : this.checked(found, caller, plain2);
|
|
3610
3664
|
}
|
|
3611
3665
|
async openSource(path, caller, real) {
|
|
3612
3666
|
const found = await this.source(path, real);
|
|
@@ -3616,10 +3670,10 @@ var Integrity = class {
|
|
|
3616
3670
|
}
|
|
3617
3671
|
await this.checked(found, caller, () => this.root.readFileBuffer(found.real));
|
|
3618
3672
|
}
|
|
3619
|
-
async checked(found, caller,
|
|
3673
|
+
async checked(found, caller, plain2) {
|
|
3620
3674
|
const { real, name: name2 } = found;
|
|
3621
3675
|
if (name2 !== real || !this.root.readVersioned) {
|
|
3622
|
-
const bytes2 = await
|
|
3676
|
+
const bytes2 = await plain2();
|
|
3623
3677
|
await this.verify(name2, bytes2, caller, READ_OPS);
|
|
3624
3678
|
return bytes2;
|
|
3625
3679
|
}
|
|
@@ -4328,8 +4382,8 @@ var OpfsFs = class {
|
|
|
4328
4382
|
this.refuse(found.path);
|
|
4329
4383
|
const [stored] = found.link ? [found.link] : await this.meta.get([found.path]);
|
|
4330
4384
|
const current = await this.ownerAt(found.path, stored);
|
|
4331
|
-
const
|
|
4332
|
-
const handing = found.handle?.kind === "directory" && !sameOwner(
|
|
4385
|
+
const next3 = { uid: change.uid ?? current.uid, gid: change.gid ?? current.gid };
|
|
4386
|
+
const handing = found.handle?.kind === "directory" && !sameOwner(next3, current);
|
|
4333
4387
|
const heir = change.kind === "adopt" ? void 0 : stored?.heir ?? (handing ? [current.uid, current.gid] : void 0);
|
|
4334
4388
|
const ctimeMs = Date.now();
|
|
4335
4389
|
await this.meta.update(found.path, (entry) => {
|
|
@@ -4337,7 +4391,7 @@ var OpfsFs = class {
|
|
|
4337
4391
|
return {
|
|
4338
4392
|
...rest2,
|
|
4339
4393
|
path: found.path,
|
|
4340
|
-
...
|
|
4394
|
+
...next3,
|
|
4341
4395
|
...heir ? { heir } : {},
|
|
4342
4396
|
...change.mode !== void 0 ? { mode: change.mode & PERM_MASK } : {},
|
|
4343
4397
|
ctimeMs
|
|
@@ -5264,9 +5318,9 @@ var UnlinkedKeeper = class {
|
|
|
5264
5318
|
void locks?.request(lockName(this.instance), () => new Promise(() => void 0));
|
|
5265
5319
|
}
|
|
5266
5320
|
serial(op) {
|
|
5267
|
-
const
|
|
5268
|
-
this.queue =
|
|
5269
|
-
return
|
|
5321
|
+
const next3 = this.queue.then(op);
|
|
5322
|
+
this.queue = next3.catch(() => void 0);
|
|
5323
|
+
return next3;
|
|
5270
5324
|
}
|
|
5271
5325
|
wrap(fs = this.fs) {
|
|
5272
5326
|
const keeper = this;
|
|
@@ -5475,10 +5529,10 @@ var Incoming = class {
|
|
|
5475
5529
|
this.eof = true;
|
|
5476
5530
|
return false;
|
|
5477
5531
|
}
|
|
5478
|
-
const
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
this.buf =
|
|
5532
|
+
const next3 = new Uint8Array(this.buf.length + chunk2.length);
|
|
5533
|
+
next3.set(this.buf);
|
|
5534
|
+
next3.set(chunk2, this.buf.length);
|
|
5535
|
+
this.buf = next3;
|
|
5482
5536
|
return true;
|
|
5483
5537
|
}
|
|
5484
5538
|
take(n) {
|
|
@@ -5618,23 +5672,50 @@ async function readBody(incoming, framing, cap, signal) {
|
|
|
5618
5672
|
const chunks2 = [];
|
|
5619
5673
|
let total = 0;
|
|
5620
5674
|
for (; ; ) {
|
|
5621
|
-
const
|
|
5622
|
-
const size = /^([0-9A-Fa-f]{1,12})[ \t]*(;.*)?$/.exec(sizeLine);
|
|
5623
|
-
if (!size) throw new HttpError(400, "malformed chunk size");
|
|
5624
|
-
const n = Number.parseInt(size[1], 16);
|
|
5675
|
+
const n = await chunkSize(incoming, signal);
|
|
5625
5676
|
if (n === 0) break;
|
|
5626
5677
|
total += n;
|
|
5627
5678
|
if (total > cap) throw new HttpError(413, `request body over ${cap} bytes`);
|
|
5628
5679
|
chunks2.push(await incoming.exactly(n, signal));
|
|
5629
5680
|
if (await incoming.line(2, signal) !== "") throw new HttpError(400, "malformed chunk");
|
|
5630
5681
|
}
|
|
5682
|
+
await skipTrailers(incoming, signal);
|
|
5683
|
+
return concat(chunks2, total);
|
|
5684
|
+
}
|
|
5685
|
+
async function chunkSize(incoming, signal) {
|
|
5686
|
+
const sizeLine = await incoming.line(MAX_CHUNK_LINE, signal);
|
|
5687
|
+
const size = /^([0-9A-Fa-f]{1,12})[ \t]*(;.*)?$/.exec(sizeLine);
|
|
5688
|
+
if (!size) throw new HttpError(400, "malformed chunk size");
|
|
5689
|
+
return Number.parseInt(size[1], 16);
|
|
5690
|
+
}
|
|
5691
|
+
async function skipTrailers(incoming, signal) {
|
|
5631
5692
|
let trailers = 0;
|
|
5632
5693
|
for (let line = await incoming.line(MAX_TRAILERS, signal); line !== ""; ) {
|
|
5633
5694
|
trailers += line.length;
|
|
5634
5695
|
if (trailers > MAX_TRAILERS) throw new HttpError(431, "trailers too large");
|
|
5635
5696
|
line = await incoming.line(MAX_TRAILERS, signal);
|
|
5636
5697
|
}
|
|
5637
|
-
|
|
5698
|
+
}
|
|
5699
|
+
var STREAM_PIECE = 64 * 1024;
|
|
5700
|
+
async function* pieces(incoming, n, signal) {
|
|
5701
|
+
for (let left = n; left > 0; ) {
|
|
5702
|
+
const piece = await incoming.some(Math.min(left, STREAM_PIECE), signal);
|
|
5703
|
+
if (piece.length === 0) throw new HttpError(400, "connection closed inside a body");
|
|
5704
|
+
left -= piece.length;
|
|
5705
|
+
yield piece;
|
|
5706
|
+
}
|
|
5707
|
+
}
|
|
5708
|
+
async function* streamBody(incoming, framing, signal) {
|
|
5709
|
+
if (framing.kind === "none") return;
|
|
5710
|
+
if (framing.kind === "length") {
|
|
5711
|
+
yield* pieces(incoming, framing.length, signal);
|
|
5712
|
+
return;
|
|
5713
|
+
}
|
|
5714
|
+
for (let n = await chunkSize(incoming, signal); n !== 0; n = await chunkSize(incoming, signal)) {
|
|
5715
|
+
yield* pieces(incoming, n, signal);
|
|
5716
|
+
if (await incoming.line(2, signal) !== "") throw new HttpError(400, "malformed chunk");
|
|
5717
|
+
}
|
|
5718
|
+
await skipTrailers(incoming, signal);
|
|
5638
5719
|
}
|
|
5639
5720
|
function concat(chunks2, total = chunks2.reduce((n, c) => n + c.length, 0)) {
|
|
5640
5721
|
const out = new Uint8Array(total);
|
|
@@ -5747,11 +5828,11 @@ function frame(opcode, payload) {
|
|
|
5747
5828
|
return out;
|
|
5748
5829
|
}
|
|
5749
5830
|
function clientFrame(opcode, payload) {
|
|
5750
|
-
const
|
|
5751
|
-
const head =
|
|
5831
|
+
const plain2 = frame(opcode, payload);
|
|
5832
|
+
const head = plain2.length - payload.length;
|
|
5752
5833
|
const mask = crypto.getRandomValues(new Uint8Array(4));
|
|
5753
|
-
const out = new Uint8Array(
|
|
5754
|
-
out.set(
|
|
5834
|
+
const out = new Uint8Array(plain2.length + 4);
|
|
5835
|
+
out.set(plain2.subarray(0, head));
|
|
5755
5836
|
out[1] = out[1] | 128;
|
|
5756
5837
|
out.set(mask, head);
|
|
5757
5838
|
for (let i = 0; i < payload.length; i++) {
|
|
@@ -6203,6 +6284,164 @@ function closeAll(entry) {
|
|
|
6203
6284
|
}
|
|
6204
6285
|
}
|
|
6205
6286
|
|
|
6287
|
+
// src/fs/engines.ts
|
|
6288
|
+
var NUMBER = /^(0|[1-9]\d*)$/;
|
|
6289
|
+
var PART = /^(?:0|[1-9]\d*|[xX*])$/;
|
|
6290
|
+
var IDENTIFIER = /^(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)$/;
|
|
6291
|
+
function identifiers(pre) {
|
|
6292
|
+
if (pre === void 0) return [];
|
|
6293
|
+
const ids = pre.split(".");
|
|
6294
|
+
return ids.every((id2) => IDENTIFIER.test(id2)) ? ids : void 0;
|
|
6295
|
+
}
|
|
6296
|
+
function parseVersion(text) {
|
|
6297
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(text.trim());
|
|
6298
|
+
const pre = identifiers(m?.[4]);
|
|
6299
|
+
if (!m || !pre || ![m[1], m[2], m[3]].every((n) => NUMBER.test(n))) return void 0;
|
|
6300
|
+
return [Number(m[1]), Number(m[2]), Number(m[3]), pre];
|
|
6301
|
+
}
|
|
6302
|
+
function comparePre(a, b) {
|
|
6303
|
+
if (a.length === 0 || b.length === 0) return b.length - a.length;
|
|
6304
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
6305
|
+
const [x, y] = [a[i], b[i]];
|
|
6306
|
+
if (x === void 0 || y === void 0) return x === void 0 ? -1 : 1;
|
|
6307
|
+
if (x === y) continue;
|
|
6308
|
+
const [nx, ny] = [NUMBER.test(x), NUMBER.test(y)];
|
|
6309
|
+
if (nx && ny) return Number(x) - Number(y);
|
|
6310
|
+
if (nx !== ny) return nx ? -1 : 1;
|
|
6311
|
+
return x < y ? -1 : 1;
|
|
6312
|
+
}
|
|
6313
|
+
return 0;
|
|
6314
|
+
}
|
|
6315
|
+
function compare(a, b) {
|
|
6316
|
+
return a[0] - b[0] || a[1] - b[1] || a[2] - b[2] || comparePre(a[3], b[3]);
|
|
6317
|
+
}
|
|
6318
|
+
function partial(text) {
|
|
6319
|
+
const m = /^v?([^.+-]+)(?:\.([^.+-]+))?(?:\.([^.+-]+))?(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(
|
|
6320
|
+
text
|
|
6321
|
+
);
|
|
6322
|
+
if (!m) return void 0;
|
|
6323
|
+
const raw = [m[1], m[2], m[3]];
|
|
6324
|
+
if (!raw.every((p) => p === void 0 || PART.test(p))) return void 0;
|
|
6325
|
+
const parts2 = [];
|
|
6326
|
+
for (const p of raw) {
|
|
6327
|
+
if (p === void 0 || /^[xX*]$/.test(p) || parts2.includes(void 0)) parts2.push(void 0);
|
|
6328
|
+
else parts2.push(Number(p));
|
|
6329
|
+
}
|
|
6330
|
+
const pre = identifiers(m[4]);
|
|
6331
|
+
return pre && { parts: parts2, pre };
|
|
6332
|
+
}
|
|
6333
|
+
function floor(p) {
|
|
6334
|
+
const [a = 0, b = 0, c = 0] = p.parts;
|
|
6335
|
+
return [a, b, c, p.parts.includes(void 0) ? [] : p.pre];
|
|
6336
|
+
}
|
|
6337
|
+
function next(p) {
|
|
6338
|
+
const [a, b] = p.parts;
|
|
6339
|
+
if (a === void 0) return void 0;
|
|
6340
|
+
if (b === void 0) return [a + 1, 0, 0, ["0"]];
|
|
6341
|
+
return [a, b + 1, 0, ["0"]];
|
|
6342
|
+
}
|
|
6343
|
+
var ANY = [[">=", [0, 0, 0, []]]];
|
|
6344
|
+
var NOTHING = [["<", [0, 0, 0, ["0"]]]];
|
|
6345
|
+
function plain(op, p) {
|
|
6346
|
+
const exact = !p.parts.includes(void 0);
|
|
6347
|
+
const low = floor(p);
|
|
6348
|
+
const high = next(p);
|
|
6349
|
+
if (op === ">=") return [[">=", low]];
|
|
6350
|
+
if (op === "<") return [["<", exact ? low : [low[0], low[1], low[2], ["0"]]]];
|
|
6351
|
+
if (exact) return [[op === "" ? "=" : op, low]];
|
|
6352
|
+
if (op === ">") return high ? [[">=", high]] : NOTHING;
|
|
6353
|
+
if (op === "<=") return high ? [["<", high]] : ANY;
|
|
6354
|
+
return high ? [
|
|
6355
|
+
[">=", low],
|
|
6356
|
+
["<", high]
|
|
6357
|
+
] : ANY;
|
|
6358
|
+
}
|
|
6359
|
+
function caret(p) {
|
|
6360
|
+
const [a = 0, b, c] = p.parts;
|
|
6361
|
+
const low = floor(p);
|
|
6362
|
+
if (b === void 0)
|
|
6363
|
+
return [
|
|
6364
|
+
[">=", low],
|
|
6365
|
+
["<", [a + 1, 0, 0, ["0"]]]
|
|
6366
|
+
];
|
|
6367
|
+
if (a > 0)
|
|
6368
|
+
return [
|
|
6369
|
+
[">=", low],
|
|
6370
|
+
["<", [a + 1, 0, 0, ["0"]]]
|
|
6371
|
+
];
|
|
6372
|
+
if (c === void 0 || b > 0)
|
|
6373
|
+
return [
|
|
6374
|
+
[">=", low],
|
|
6375
|
+
["<", [0, b + 1, 0, ["0"]]]
|
|
6376
|
+
];
|
|
6377
|
+
return [
|
|
6378
|
+
[">=", low],
|
|
6379
|
+
["<", [0, b, c + 1, ["0"]]]
|
|
6380
|
+
];
|
|
6381
|
+
}
|
|
6382
|
+
function tilde(p) {
|
|
6383
|
+
const [a = 0, b] = p.parts;
|
|
6384
|
+
const low = floor(p);
|
|
6385
|
+
return [
|
|
6386
|
+
[">=", low],
|
|
6387
|
+
["<", b === void 0 ? [a + 1, 0, 0, ["0"]] : [a, b + 1, 0, ["0"]]]
|
|
6388
|
+
];
|
|
6389
|
+
}
|
|
6390
|
+
function hyphen(from, to) {
|
|
6391
|
+
const high = to.parts.includes(void 0) ? next(to) : void 0;
|
|
6392
|
+
const upper = to.parts.includes(void 0) ? high ? [["<", high]] : [] : [["<=", floor(to)]];
|
|
6393
|
+
return [[">=", floor(from)], ...upper];
|
|
6394
|
+
}
|
|
6395
|
+
function comparator(token) {
|
|
6396
|
+
const m = /^(<=|>=|<|>|=|\^|~>?)?\s*(.*)$/.exec(token);
|
|
6397
|
+
const op = m?.[1] ?? "";
|
|
6398
|
+
const p = partial(m?.[2] ?? "");
|
|
6399
|
+
if (!p) return void 0;
|
|
6400
|
+
const wild = p.parts[0] === void 0;
|
|
6401
|
+
if (op === "^") return wild ? ANY : caret(p);
|
|
6402
|
+
if (op.startsWith("~")) return wild ? ANY : tilde(p);
|
|
6403
|
+
return plain(op, p);
|
|
6404
|
+
}
|
|
6405
|
+
function set(text) {
|
|
6406
|
+
const trimmed = text.trim().replace(/(<=|>=|<|>|=|\^|~>?)\s+/g, "$1");
|
|
6407
|
+
if (trimmed === "") return ANY;
|
|
6408
|
+
const range = /^(\S+)\s+-\s+(\S+)$/.exec(trimmed);
|
|
6409
|
+
if (range) {
|
|
6410
|
+
const [from, to] = [partial(range[1]), partial(range[2])];
|
|
6411
|
+
return from && to ? hyphen(from, to) : void 0;
|
|
6412
|
+
}
|
|
6413
|
+
const out = [];
|
|
6414
|
+
for (const token of trimmed.split(/\s+/)) {
|
|
6415
|
+
const found = comparator(token);
|
|
6416
|
+
if (!found) return void 0;
|
|
6417
|
+
out.push(...found);
|
|
6418
|
+
}
|
|
6419
|
+
return out;
|
|
6420
|
+
}
|
|
6421
|
+
function holds(v, [op, w]) {
|
|
6422
|
+
const c = compare(v, w);
|
|
6423
|
+
if (op === "<") return c < 0;
|
|
6424
|
+
if (op === "<=") return c <= 0;
|
|
6425
|
+
if (op === ">") return c > 0;
|
|
6426
|
+
if (op === ">=") return c >= 0;
|
|
6427
|
+
return c === 0;
|
|
6428
|
+
}
|
|
6429
|
+
function satisfies(version, range) {
|
|
6430
|
+
const v = parseVersion(version);
|
|
6431
|
+
if (!v) return void 0;
|
|
6432
|
+
const sets = range.split("||").map(set);
|
|
6433
|
+
if (sets.some((s) => s === void 0)) return void 0;
|
|
6434
|
+
return sets.some((s) => s.every((c) => holds(v, c)));
|
|
6435
|
+
}
|
|
6436
|
+
|
|
6437
|
+
// src/version.ts
|
|
6438
|
+
var KERNEL_VERSION = true ? "1.106.2" : "0.0.0-dev";
|
|
6439
|
+
var OS_RELEASE = "6.0.0-slicc";
|
|
6440
|
+
function procVersion() {
|
|
6441
|
+
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
6442
|
+
`;
|
|
6443
|
+
}
|
|
6444
|
+
|
|
6206
6445
|
// src/commands.ts
|
|
6207
6446
|
var NAME2 = /^[A-Za-z0-9._+-]+$/;
|
|
6208
6447
|
var COMMAND_NAME = /^[^/\s\p{Cc}]+$/u;
|
|
@@ -6414,13 +6653,25 @@ async function binCommandsOf(physical, pkg, manifest, taken) {
|
|
|
6414
6653
|
}
|
|
6415
6654
|
return out;
|
|
6416
6655
|
}
|
|
6656
|
+
function engineRefusal(manifest, kernel) {
|
|
6657
|
+
const engines = manifest.engines;
|
|
6658
|
+
const range = engines && typeof engines === "object" ? engines["slicc-kernel"] : void 0;
|
|
6659
|
+
const running = parseVersion(kernel);
|
|
6660
|
+
if (typeof range !== "string" || !running || running.slice(0, 3).every((n) => n === 0)) {
|
|
6661
|
+
return void 0;
|
|
6662
|
+
}
|
|
6663
|
+
const fits = satisfies(kernel, range);
|
|
6664
|
+
if (fits) return void 0;
|
|
6665
|
+
const who = `${String(manifest.name ?? "?")}@${String(manifest.version ?? "?")}`;
|
|
6666
|
+
return fits === false ? `${who} needs slicc-kernel ${range}; this kernel is ${kernel}` : `${who} has an engines.slicc-kernel range this kernel can't read: ${JSON.stringify(range)}`;
|
|
6667
|
+
}
|
|
6417
6668
|
var PACKAGE_NAME = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
6418
6669
|
function replacesOf(manifest) {
|
|
6419
6670
|
const replaces = manifest.slicc?.replaces;
|
|
6420
6671
|
if (!Array.isArray(replaces)) return [];
|
|
6421
6672
|
return replaces.every((name2) => typeof name2 === "string" && PACKAGE_NAME.test(name2)) ? replaces : [];
|
|
6422
6673
|
}
|
|
6423
|
-
async function tierPackages(fs, physical, roots, bins) {
|
|
6674
|
+
async function tierPackages(fs, physical, roots, bins, kernel) {
|
|
6424
6675
|
const out = [];
|
|
6425
6676
|
for (const root of roots) {
|
|
6426
6677
|
for (const pkg of await packages(fs, root)) {
|
|
@@ -6433,11 +6684,13 @@ async function tierPackages(fs, physical, roots, bins) {
|
|
|
6433
6684
|
const own = commandsOf(pkg, manifest);
|
|
6434
6685
|
const named = new Set(own.map((command) => command.name));
|
|
6435
6686
|
const extra = bins ? await binCommandsOf(physical, pkg, manifest, named) : [];
|
|
6687
|
+
const refused2 = engineRefusal(manifest, kernel);
|
|
6688
|
+
const commands = [...own, ...extra];
|
|
6436
6689
|
out.push({
|
|
6437
6690
|
name: pkg.slice(root.length + 1),
|
|
6438
6691
|
pkg,
|
|
6439
6692
|
replaces: replacesOf(manifest),
|
|
6440
|
-
commands:
|
|
6693
|
+
commands: refused2 ? commands.map((command) => ({ ...command, refused: refused2 })) : commands
|
|
6441
6694
|
});
|
|
6442
6695
|
}
|
|
6443
6696
|
}
|
|
@@ -6463,14 +6716,14 @@ function winners(tier) {
|
|
|
6463
6716
|
}
|
|
6464
6717
|
return out;
|
|
6465
6718
|
}
|
|
6466
|
-
async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY) {
|
|
6719
|
+
async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, kernel = KERNEL_VERSION) {
|
|
6467
6720
|
const found = /* @__PURE__ */ new Map();
|
|
6468
6721
|
const physical = physicalResolver(fs);
|
|
6469
6722
|
const tiers = (typeof modules === "string" ? [modules] : modules).map(
|
|
6470
6723
|
(tier) => typeof tier === "string" ? [tier] : tier
|
|
6471
6724
|
);
|
|
6472
6725
|
for (const [index, roots] of tiers.entries()) {
|
|
6473
|
-
const tier = await tierPackages(fs, physical, roots, index >= binsFrom);
|
|
6726
|
+
const tier = await tierPackages(fs, physical, roots, index >= binsFrom, kernel);
|
|
6474
6727
|
for (const [name2, { pkg, command }] of winners(tier)) {
|
|
6475
6728
|
if (!found.has(name2)) found.set(name2, await withPackagePaths(fs, pkg, command));
|
|
6476
6729
|
}
|
|
@@ -6719,6 +6972,11 @@ async function watchHangup(conn, abort, until) {
|
|
|
6719
6972
|
}
|
|
6720
6973
|
}
|
|
6721
6974
|
}
|
|
6975
|
+
var BODILESS_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
|
|
6976
|
+
async function* drain(body, done4) {
|
|
6977
|
+
yield* body;
|
|
6978
|
+
done4();
|
|
6979
|
+
}
|
|
6722
6980
|
function untilAborted(response, signal) {
|
|
6723
6981
|
return new Promise((resolve2, reject) => {
|
|
6724
6982
|
const onAbort = () => {
|
|
@@ -6861,7 +7119,8 @@ var RealmProxy = class {
|
|
|
6861
7119
|
const url = ctx.origin ? tunnelRequestUrl(req, ctx.origin) : requestUrl(req);
|
|
6862
7120
|
const keep2 = keepsAlive(req);
|
|
6863
7121
|
const framing = requestFraming(req.headers);
|
|
6864
|
-
const
|
|
7122
|
+
const streaming = this.options.transport.traits.streamingBodies === true && framing.kind !== "none" && !BODILESS_METHODS.has(req.method);
|
|
7123
|
+
const reserve = streaming ? 0 : framing.kind === "length" ? framing.length : framing.kind === "chunked" ? this.cap() : 0;
|
|
6865
7124
|
if (reserve > this.cap()) throw new HttpError(413, `request body over ${this.cap()} bytes`);
|
|
6866
7125
|
await this.expectContinue(conn, req, framing.kind !== "none");
|
|
6867
7126
|
await this.bodies.acquire(reserve, this.stop.signal);
|
|
@@ -6869,9 +7128,12 @@ var RealmProxy = class {
|
|
|
6869
7128
|
const abort = new AbortController();
|
|
6870
7129
|
const stopExchange = () => abort.abort();
|
|
6871
7130
|
this.stop.signal.addEventListener("abort", stopExchange, { once: true });
|
|
7131
|
+
let drained = !streaming;
|
|
6872
7132
|
try {
|
|
6873
7133
|
try {
|
|
6874
|
-
const body =
|
|
7134
|
+
const body = streaming ? drain(streamBody(incoming, framing, abort.signal), () => {
|
|
7135
|
+
drained = true;
|
|
7136
|
+
}) : await readBody(incoming, framing, this.cap());
|
|
6875
7137
|
const waiting = new AbortController();
|
|
6876
7138
|
void watchHangup(ctx.socket, abort, waiting.signal);
|
|
6877
7139
|
try {
|
|
@@ -6882,7 +7144,8 @@ var RealmProxy = class {
|
|
|
6882
7144
|
} finally {
|
|
6883
7145
|
this.bodies.release(reserve);
|
|
6884
7146
|
}
|
|
6885
|
-
|
|
7147
|
+
const kept = await this.relay(conn, req.method, req.minor, response, keep2 && drained);
|
|
7148
|
+
return kept && drained;
|
|
6886
7149
|
} finally {
|
|
6887
7150
|
this.stop.signal.removeEventListener("abort", stopExchange);
|
|
6888
7151
|
abort.abort();
|
|
@@ -6902,13 +7165,14 @@ var RealmProxy = class {
|
|
|
6902
7165
|
}
|
|
6903
7166
|
}
|
|
6904
7167
|
async upstream(req, url, body, signal, owner) {
|
|
7168
|
+
const sent = BODILESS_METHODS.has(req.method) ? void 0 : body;
|
|
6905
7169
|
try {
|
|
6906
7170
|
const fetching = this.options.transport.fetch(
|
|
6907
7171
|
{
|
|
6908
7172
|
url: toHostLoopback(url),
|
|
6909
7173
|
method: req.method.toUpperCase(),
|
|
6910
7174
|
headers: forwardRequestHeaders(req.headers),
|
|
6911
|
-
body:
|
|
7175
|
+
...sent instanceof Uint8Array ? { body: sent } : sent ? { bodyStream: sent } : {},
|
|
6912
7176
|
signal
|
|
6913
7177
|
},
|
|
6914
7178
|
owner
|
|
@@ -7404,6 +7668,7 @@ var S_IFDIR2 = 16384;
|
|
|
7404
7668
|
var S_IFREG2 = 32768;
|
|
7405
7669
|
var COMMAND = /^\/(?:usr\/)?bin\/([^/]+)$/;
|
|
7406
7670
|
var MAX_LINKS6 = 40;
|
|
7671
|
+
var BIN_ENTRY = /\/bin\/[^/]+$/;
|
|
7407
7672
|
function missing3(err) {
|
|
7408
7673
|
return err?.code === "ENOENT";
|
|
7409
7674
|
}
|
|
@@ -7431,7 +7696,20 @@ async function followLinks(fs, path) {
|
|
|
7431
7696
|
}
|
|
7432
7697
|
return current;
|
|
7433
7698
|
}
|
|
7434
|
-
|
|
7699
|
+
var NOBODY = { ruid: -1, euid: -1, suid: -1, rgid: -1, egid: -1, sgid: -1, groups: [] };
|
|
7700
|
+
var EMPTY = new Uint8Array(0);
|
|
7701
|
+
function quiet2(promise) {
|
|
7702
|
+
return promise.catch(() => void 0);
|
|
7703
|
+
}
|
|
7704
|
+
async function readsAs2(fs, cred, target) {
|
|
7705
|
+
const walked = await quiet2(access(fs, cred, target, R_OK, { directory: false }));
|
|
7706
|
+
return walked !== void 0 && walked.denied === void 0 && !walked.missing;
|
|
7707
|
+
}
|
|
7708
|
+
async function shownTarget(fs, target) {
|
|
7709
|
+
const st = await quiet2(fs.stat(target));
|
|
7710
|
+
return st?.isFile && await readsAs2(fs, NOBODY, target) ? st : void 0;
|
|
7711
|
+
}
|
|
7712
|
+
function withCommandDirs(fs, names, userDir = async () => void 0, owners = false, targetOf2 = async () => void 0) {
|
|
7435
7713
|
async function nearest(path) {
|
|
7436
7714
|
const st = await fs.stat(path).catch(() => void 0);
|
|
7437
7715
|
if (st || path === "/") return st ?? {};
|
|
@@ -7463,9 +7741,54 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
7463
7741
|
const own = await userDir(dir);
|
|
7464
7742
|
return own?.has(path.slice(slash + 1)) ? owned4(synthetic(false, path), dir) : void 0;
|
|
7465
7743
|
}
|
|
7744
|
+
let generation;
|
|
7745
|
+
const targets = /* @__PURE__ */ new Map();
|
|
7746
|
+
async function targetStat(target) {
|
|
7747
|
+
const now = await names();
|
|
7748
|
+
if (now !== generation) {
|
|
7749
|
+
generation = now;
|
|
7750
|
+
targets.clear();
|
|
7751
|
+
}
|
|
7752
|
+
let found = targets.get(target);
|
|
7753
|
+
if (!found) {
|
|
7754
|
+
found = shownTarget(fs, target);
|
|
7755
|
+
targets.set(target, found);
|
|
7756
|
+
}
|
|
7757
|
+
return found;
|
|
7758
|
+
}
|
|
7759
|
+
async function shown(path) {
|
|
7760
|
+
const st = await virtual(path);
|
|
7761
|
+
if (!st?.isFile) return st;
|
|
7762
|
+
const target = await targetOf2(path);
|
|
7763
|
+
const real = target === void 0 ? void 0 : await targetStat(target.path);
|
|
7764
|
+
return real ? { ...st, size: real.size, mtime: real.mtime, ctime: real.mtime, atime: real.mtime } : st;
|
|
7765
|
+
}
|
|
7466
7766
|
async function linked2(path) {
|
|
7467
|
-
return await
|
|
7767
|
+
return await shown(path) ?? shown(await followLinks(fs, path));
|
|
7768
|
+
}
|
|
7769
|
+
async function entryTarget(path) {
|
|
7770
|
+
if (!BIN_ENTRY.test(path) || !(await virtual(path))?.isFile) return void 0;
|
|
7771
|
+
if (!await fs.lstat(path).then(() => false, missing3)) return void 0;
|
|
7772
|
+
const target = await targetOf2(path);
|
|
7773
|
+
return target?.path === path ? void 0 : target;
|
|
7468
7774
|
}
|
|
7775
|
+
async function redirected2(path) {
|
|
7776
|
+
const target = await entryTarget(path) ?? await entryTarget(await followLinks(fs, path));
|
|
7777
|
+
if (owners && target?.owner && !await readsAs2(fs, target.owner, target.path)) {
|
|
7778
|
+
throw fsError("EACCES", path);
|
|
7779
|
+
}
|
|
7780
|
+
return target?.path;
|
|
7781
|
+
}
|
|
7782
|
+
const absent2 = (err) => {
|
|
7783
|
+
if (missing3(err)) return EMPTY;
|
|
7784
|
+
throw err;
|
|
7785
|
+
};
|
|
7786
|
+
async function content(path, err) {
|
|
7787
|
+
if (!missing3(err) || !(await linked2(path))?.isFile) throw err;
|
|
7788
|
+
const target = await redirected2(path);
|
|
7789
|
+
return target === void 0 ? EMPTY : fs.readFileBuffer(target).catch(absent2);
|
|
7790
|
+
}
|
|
7791
|
+
const ranged2 = rangedOps(fs);
|
|
7469
7792
|
async function stat(path, real) {
|
|
7470
7793
|
try {
|
|
7471
7794
|
return await real(path);
|
|
@@ -7477,16 +7800,13 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
7477
7800
|
}
|
|
7478
7801
|
return {
|
|
7479
7802
|
resolvePath: (base, path) => fs.resolvePath(base, path),
|
|
7480
|
-
readFile: (path) => fs.readFile(path)
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
}
|
|
7488
|
-
},
|
|
7489
|
-
writeFile: (path, content, owner) => fs.writeFile(path, content, owner),
|
|
7803
|
+
readFile: (path) => fs.readFile(path).catch(async (err) => {
|
|
7804
|
+
if (!BIN_ENTRY.test(await followLinks(fs, path))) throw err;
|
|
7805
|
+
return new TextDecoder().decode(await content(path, err));
|
|
7806
|
+
}),
|
|
7807
|
+
readFileBuffer: (path) => fs.readFileBuffer(path).catch((err) => content(path, err)),
|
|
7808
|
+
commandTarget: async (path) => (await entryTarget(path))?.path,
|
|
7809
|
+
writeFile: (path, content2, owner) => fs.writeFile(path, content2, owner),
|
|
7490
7810
|
link: (from, to, follow2) => fs.link(from, to, follow2),
|
|
7491
7811
|
links: (path) => mayLink(fs, path),
|
|
7492
7812
|
async exists(path) {
|
|
@@ -7517,7 +7837,7 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
7517
7837
|
added.map(
|
|
7518
7838
|
async (name2) => [
|
|
7519
7839
|
name2,
|
|
7520
|
-
await
|
|
7840
|
+
await shown(`${base}/${name2}`)
|
|
7521
7841
|
]
|
|
7522
7842
|
)
|
|
7523
7843
|
);
|
|
@@ -7535,7 +7855,14 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
7535
7855
|
chmod: (path, mode) => fs.chmod(path, mode),
|
|
7536
7856
|
utimes: (path, atime, mtime) => fs.utimes(path, atime, mtime),
|
|
7537
7857
|
lutimes: (path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
|
|
7538
|
-
...
|
|
7858
|
+
...ranged2 ? {
|
|
7859
|
+
...ranged2,
|
|
7860
|
+
pread: (path, offset, length2, version) => ranged2.pread(path, offset, length2, version).catch(async (err) => {
|
|
7861
|
+
const target = missing3(err) ? await redirected2(path) : void 0;
|
|
7862
|
+
if (target === void 0) throw err;
|
|
7863
|
+
return ranged2.pread(target, offset, length2).catch(absent2);
|
|
7864
|
+
})
|
|
7865
|
+
} : {}
|
|
7539
7866
|
};
|
|
7540
7867
|
}
|
|
7541
7868
|
|
|
@@ -7680,7 +8007,7 @@ var MAX_HOPS2 = 40;
|
|
|
7680
8007
|
function start(path) {
|
|
7681
8008
|
return { done: [], todo: path.split("/").filter((p) => p !== ""), hops: 0 };
|
|
7682
8009
|
}
|
|
7683
|
-
function
|
|
8010
|
+
function next2(walk2) {
|
|
7684
8011
|
while (walk2.todo.length > 0) {
|
|
7685
8012
|
const part = walk2.todo.shift();
|
|
7686
8013
|
if (part === ".") continue;
|
|
@@ -7694,7 +8021,7 @@ function next(walk2) {
|
|
|
7694
8021
|
}
|
|
7695
8022
|
function lexical(path) {
|
|
7696
8023
|
const walk2 = start(path);
|
|
7697
|
-
for (let part =
|
|
8024
|
+
for (let part = next2(walk2); part !== void 0; part = next2(walk2)) walk2.done.push(part);
|
|
7698
8025
|
return `/${walk2.done.join("/")}`;
|
|
7699
8026
|
}
|
|
7700
8027
|
function rest(walk2, part) {
|
|
@@ -7708,7 +8035,7 @@ function follow(walk2, target) {
|
|
|
7708
8035
|
}
|
|
7709
8036
|
async function physicalPathAsync(fs, path) {
|
|
7710
8037
|
const walk2 = start(path);
|
|
7711
|
-
for (let part =
|
|
8038
|
+
for (let part = next2(walk2); part !== void 0; part = next2(walk2)) {
|
|
7712
8039
|
const at = `/${[...walk2.done, part].join("/")}`;
|
|
7713
8040
|
let target;
|
|
7714
8041
|
try {
|
|
@@ -8006,7 +8333,8 @@ var ChildTable = class {
|
|
|
8006
8333
|
const child = this.children.get(pid);
|
|
8007
8334
|
if (!child) return;
|
|
8008
8335
|
this.watchers.set(pid, listener);
|
|
8009
|
-
if (child.stoppedBy !== void 0
|
|
8336
|
+
if (child.stoppedBy !== void 0 && child.code === void 0)
|
|
8337
|
+
listener("stopped", child.stoppedBy);
|
|
8010
8338
|
}
|
|
8011
8339
|
openSlot(slot2, n, captured) {
|
|
8012
8340
|
if ("fd" in slot2) return this.parentFds.get(slot2.fd).retain();
|
|
@@ -8475,14 +8803,14 @@ var HeldSet = class extends Set {
|
|
|
8475
8803
|
super();
|
|
8476
8804
|
this.idle = idle;
|
|
8477
8805
|
}
|
|
8478
|
-
add(
|
|
8479
|
-
|
|
8480
|
-
return super.add(
|
|
8806
|
+
add(holds2) {
|
|
8807
|
+
holds2.onIdle = this.idle;
|
|
8808
|
+
return super.add(holds2);
|
|
8481
8809
|
}
|
|
8482
|
-
delete(
|
|
8483
|
-
const removed = super.delete(
|
|
8484
|
-
for (const path of /* @__PURE__ */ new Set([...
|
|
8485
|
-
|
|
8810
|
+
delete(holds2) {
|
|
8811
|
+
const removed = super.delete(holds2);
|
|
8812
|
+
for (const path of /* @__PURE__ */ new Set([...holds2.keys(), ...holds2.opens.keys()])) this.idle(path);
|
|
8813
|
+
holds2.releaseAll();
|
|
8486
8814
|
return removed;
|
|
8487
8815
|
}
|
|
8488
8816
|
};
|
|
@@ -9669,9 +9997,9 @@ var MountFs = class _MountFs {
|
|
|
9669
9997
|
this.writable(mount, real);
|
|
9670
9998
|
const { uid, gid, mode } = change;
|
|
9671
9999
|
const fresh2 = change.kind === "new" && { uid, gid, mode };
|
|
9672
|
-
const
|
|
10000
|
+
const set3 = fresh2 ? await this.driverOwner(found, real, fresh2, false) : change;
|
|
9673
10001
|
this.table.forget(mount, real);
|
|
9674
|
-
const attrs = Object.entries({ uid:
|
|
10002
|
+
const attrs = Object.entries({ uid: set3.uid, gid: set3.gid, mode: set3.mode });
|
|
9675
10003
|
await mount.conn.call({
|
|
9676
10004
|
op: "setattr",
|
|
9677
10005
|
path: rel2,
|
|
@@ -9698,11 +10026,11 @@ var MountFs = class _MountFs {
|
|
|
9698
10026
|
const real = await this.follow(path);
|
|
9699
10027
|
const found = this.at(real);
|
|
9700
10028
|
if (!found) {
|
|
9701
|
-
const
|
|
10029
|
+
const set3 = () => this.base.utimes(real, atime, mtime);
|
|
9702
10030
|
return this.based(
|
|
9703
10031
|
[real],
|
|
9704
10032
|
redirects,
|
|
9705
|
-
|
|
10033
|
+
set3,
|
|
9706
10034
|
([to], n) => this.utimes(to, atime, mtime, n)
|
|
9707
10035
|
);
|
|
9708
10036
|
}
|
|
@@ -9711,11 +10039,11 @@ var MountFs = class _MountFs {
|
|
|
9711
10039
|
async lutimes(path, atime, mtime, redirects = 0) {
|
|
9712
10040
|
const found = this.at(path);
|
|
9713
10041
|
if (!found) {
|
|
9714
|
-
const
|
|
10042
|
+
const set3 = () => lutimesOf(this.base, path, atime, mtime);
|
|
9715
10043
|
return this.based(
|
|
9716
10044
|
[path],
|
|
9717
10045
|
redirects,
|
|
9718
|
-
|
|
10046
|
+
set3,
|
|
9719
10047
|
([to], n) => this.lutimes(to, atime, mtime, n)
|
|
9720
10048
|
);
|
|
9721
10049
|
}
|
|
@@ -9737,6 +10065,20 @@ var MountFs = class _MountFs {
|
|
|
9737
10065
|
}
|
|
9738
10066
|
};
|
|
9739
10067
|
|
|
10068
|
+
// src/fs/command-stat.ts
|
|
10069
|
+
async function callerStat(g, path, st) {
|
|
10070
|
+
if (!g?.fs.commandTarget || !st.isFile || st.size > 0) return st;
|
|
10071
|
+
const target = await g.fs.commandTarget(path);
|
|
10072
|
+
if (target === void 0) return st;
|
|
10073
|
+
const options = { directory: false, ...g.links === void 0 ? {} : { links: g.links } };
|
|
10074
|
+
const walked = await access(g.fs, g.cred, target, R_OK, options).catch(() => void 0);
|
|
10075
|
+
if (!walked || walked.denied !== void 0 || walked.missing) return st;
|
|
10076
|
+
const real = await g.fs.stat(target).catch(() => void 0);
|
|
10077
|
+
if (!real?.isFile) return st;
|
|
10078
|
+
const { size, mtime } = real;
|
|
10079
|
+
return { ...st, size, mtime, atime: mtime, ctime: mtime };
|
|
10080
|
+
}
|
|
10081
|
+
|
|
9740
10082
|
// src/realm/sync-fs-token-registry.ts
|
|
9741
10083
|
var registry = /* @__PURE__ */ new Map();
|
|
9742
10084
|
function mintSyncFsToken(entry) {
|
|
@@ -9823,8 +10165,10 @@ function statJson(s) {
|
|
|
9823
10165
|
...s.gid !== void 0 ? { gid: s.gid } : {}
|
|
9824
10166
|
};
|
|
9825
10167
|
}
|
|
9826
|
-
async function readdirStat(fs, dir) {
|
|
9827
|
-
|
|
10168
|
+
async function readdirStat(fs, dir, g) {
|
|
10169
|
+
const listed = await fs.readdirStat(dir);
|
|
10170
|
+
const shown = async (name2, stat) => stat && statJson(await callerStat(g, joinName(dir, name2), stat));
|
|
10171
|
+
return Promise.all(listed.map(async ([name2, stat]) => [name2, await shown(name2, stat)]));
|
|
9828
10172
|
}
|
|
9829
10173
|
async function usageAt(entry, path) {
|
|
9830
10174
|
if (!entry.statfs) return void 0;
|
|
@@ -9893,18 +10237,22 @@ async function chown(entry, path, req) {
|
|
|
9893
10237
|
}
|
|
9894
10238
|
async function runMkdir(entry, path, req) {
|
|
9895
10239
|
const { fs } = entry;
|
|
9896
|
-
const
|
|
10240
|
+
const plain2 = plainDirMode(entry, req.mode);
|
|
9897
10241
|
const parentsMode = !req.exclusive ? plainParentsMode(entry) : void 0;
|
|
9898
10242
|
const fixParents = parentsMode !== void 0 ? await missingParents(fs, path, parentsMode) : void 0;
|
|
9899
|
-
const fresh2 =
|
|
10243
|
+
const fresh2 = plain2 !== void 0 && !await fs.exists(path);
|
|
9900
10244
|
await (req.exclusive ? mkdirExclusive(entry, path, req.mode) : fs.mkdir(path, mkdirOptions(entry, req.mode)));
|
|
9901
10245
|
await fixParents?.();
|
|
9902
|
-
if (fresh2) await fs.chmod(path,
|
|
10246
|
+
if (fresh2) await fs.chmod(path, plain2);
|
|
9903
10247
|
return done;
|
|
9904
10248
|
}
|
|
10249
|
+
async function shownAs(entry, path, st) {
|
|
10250
|
+
const real = st.isFile && st.size === 0 ? entry.fs.realpath?.(path, true) : void 0;
|
|
10251
|
+
return callerStat(guardOf(entry), await real?.catch(() => path) ?? path, st);
|
|
10252
|
+
}
|
|
9905
10253
|
function readSource(entry, path) {
|
|
9906
|
-
const
|
|
9907
|
-
return entry.source ? entry.source.read(path,
|
|
10254
|
+
const plain2 = () => entry.fs.readFileBuffer(path);
|
|
10255
|
+
return entry.source ? entry.source.read(path, plain2) : plain2();
|
|
9908
10256
|
}
|
|
9909
10257
|
async function run(entry, path, req) {
|
|
9910
10258
|
const { fs, cwd } = entry;
|
|
@@ -9917,13 +10265,13 @@ async function run(entry, path, req) {
|
|
|
9917
10265
|
case "exists":
|
|
9918
10266
|
return json2(await fs.exists(path));
|
|
9919
10267
|
case "stat":
|
|
9920
|
-
return json2(statJson(await fs.stat(path)));
|
|
10268
|
+
return json2(statJson(await shownAs(entry, path, await fs.stat(path))));
|
|
9921
10269
|
case "lstat":
|
|
9922
|
-
return json2(statJson(await fs.lstat(path)));
|
|
10270
|
+
return json2(statJson(await shownAs(entry, path, await fs.lstat(path))));
|
|
9923
10271
|
case "readdir":
|
|
9924
10272
|
return json2(await fs.readdir(path));
|
|
9925
10273
|
case "readdir-stat":
|
|
9926
|
-
return json2(await readdirStat(fs, path));
|
|
10274
|
+
return json2(await readdirStat(fs, path, guardOf(entry)));
|
|
9927
10275
|
case "mkdir":
|
|
9928
10276
|
return runMkdir(entry, path, req);
|
|
9929
10277
|
case "rm":
|
|
@@ -10859,18 +11207,18 @@ var KernelDgram = class {
|
|
|
10859
11207
|
const pending = this.takeError();
|
|
10860
11208
|
if (pending) throw new KernelError(pending);
|
|
10861
11209
|
if (this.closed) throw new KernelError("EBADF");
|
|
10862
|
-
const
|
|
10863
|
-
if (
|
|
11210
|
+
const next3 = this.queue[0];
|
|
11211
|
+
if (next3) {
|
|
10864
11212
|
if (!peek) {
|
|
10865
11213
|
this.queue.shift();
|
|
10866
|
-
this.queued -=
|
|
11214
|
+
this.queued -= next3.bytes.length;
|
|
10867
11215
|
this.changes.wake();
|
|
10868
11216
|
}
|
|
10869
11217
|
const size = Math.max(0, max);
|
|
10870
11218
|
return {
|
|
10871
|
-
bytes:
|
|
10872
|
-
from:
|
|
10873
|
-
truncated:
|
|
11219
|
+
bytes: next3.bytes.slice(0, size),
|
|
11220
|
+
from: next3.from,
|
|
11221
|
+
truncated: next3.bytes.length > size
|
|
10874
11222
|
};
|
|
10875
11223
|
}
|
|
10876
11224
|
await this.changes.wait(signal);
|
|
@@ -11189,14 +11537,6 @@ var PATH_OPS = new Set(SYNC_FS_OPS);
|
|
|
11189
11537
|
// src/realm/live-vfs-fs.ts
|
|
11190
11538
|
var EARLY_WHOLE_FILE = 64 * 1024;
|
|
11191
11539
|
|
|
11192
|
-
// src/version.ts
|
|
11193
|
-
var KERNEL_VERSION = true ? "1.103.4" : "0.0.0-dev";
|
|
11194
|
-
var OS_RELEASE = "6.0.0-slicc";
|
|
11195
|
-
function procVersion() {
|
|
11196
|
-
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
11197
|
-
`;
|
|
11198
|
-
}
|
|
11199
|
-
|
|
11200
11540
|
// src/process/process-fds.ts
|
|
11201
11541
|
var field2 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
11202
11542
|
var pinnedRoot;
|
|
@@ -11588,7 +11928,7 @@ function* procWalk(path, follow2) {
|
|
|
11588
11928
|
const whole = normalize(`/${[...done4, part, ...todo].join("/")}`);
|
|
11589
11929
|
if (inProc(at) && inProc(whole)) return broken ?? whole;
|
|
11590
11930
|
if (!follow2 && todo.length === 0) return void 0;
|
|
11591
|
-
const target = yield { at, check: todo.find((
|
|
11931
|
+
const target = yield { at, check: todo.find((next3) => next3 !== ".") === ".." };
|
|
11592
11932
|
if (typeof target === "string") {
|
|
11593
11933
|
if (++hops > MAX_HOPS3) return void 0;
|
|
11594
11934
|
[done4, todo] = throughLink(target, done4, todo);
|
|
@@ -11724,18 +12064,18 @@ function timerAfter(ms, fire) {
|
|
|
11724
12064
|
return timerAt(performance.now() + ms, fire);
|
|
11725
12065
|
}
|
|
11726
12066
|
function repeating(first, every, fire) {
|
|
11727
|
-
let
|
|
12067
|
+
let next3 = performance.now() + first;
|
|
11728
12068
|
let cancel = () => {
|
|
11729
12069
|
};
|
|
11730
12070
|
const tick = () => {
|
|
11731
12071
|
fire();
|
|
11732
12072
|
if (every <= 0) return;
|
|
11733
|
-
|
|
12073
|
+
next3 += every;
|
|
11734
12074
|
const now = performance.now();
|
|
11735
|
-
if (
|
|
11736
|
-
cancel = timerAt(
|
|
12075
|
+
if (next3 <= now) next3 += (Math.floor((now - next3) / every) + 1) * every;
|
|
12076
|
+
cancel = timerAt(next3, tick);
|
|
11737
12077
|
};
|
|
11738
|
-
cancel = timerAt(
|
|
12078
|
+
cancel = timerAt(next3, tick);
|
|
11739
12079
|
return () => cancel();
|
|
11740
12080
|
}
|
|
11741
12081
|
|
|
@@ -12026,11 +12366,11 @@ var LockTable = class {
|
|
|
12026
12366
|
}
|
|
12027
12367
|
changed(key, signal) {
|
|
12028
12368
|
return new Promise((resolve2, reject) => {
|
|
12029
|
-
const
|
|
12030
|
-
this.wakers.set(key,
|
|
12369
|
+
const set3 = this.wakers.get(key) ?? /* @__PURE__ */ new Set();
|
|
12370
|
+
this.wakers.set(key, set3);
|
|
12031
12371
|
const done4 = () => {
|
|
12032
|
-
|
|
12033
|
-
if (
|
|
12372
|
+
set3.delete(wake);
|
|
12373
|
+
if (set3.size === 0 && this.wakers.get(key) === set3) this.wakers.delete(key);
|
|
12034
12374
|
signal.removeEventListener("abort", abort);
|
|
12035
12375
|
};
|
|
12036
12376
|
const wake = () => {
|
|
@@ -12041,7 +12381,7 @@ var LockTable = class {
|
|
|
12041
12381
|
done4();
|
|
12042
12382
|
reject(new KernelError("EINTR"));
|
|
12043
12383
|
};
|
|
12044
|
-
|
|
12384
|
+
set3.add(wake);
|
|
12045
12385
|
signal.addEventListener("abort", abort, { once: true });
|
|
12046
12386
|
});
|
|
12047
12387
|
}
|
|
@@ -12570,10 +12910,10 @@ var LoopbackWebSocket = class {
|
|
|
12570
12910
|
this.messages = {
|
|
12571
12911
|
[Symbol.asyncIterator]: async function* () {
|
|
12572
12912
|
for (; ; ) {
|
|
12573
|
-
const
|
|
12574
|
-
if (
|
|
12575
|
-
taken(
|
|
12576
|
-
yield
|
|
12913
|
+
const next3 = queue.shift();
|
|
12914
|
+
if (next3 !== void 0) {
|
|
12915
|
+
taken(next3);
|
|
12916
|
+
yield next3;
|
|
12577
12917
|
continue;
|
|
12578
12918
|
}
|
|
12579
12919
|
if (ended) return;
|
|
@@ -12678,7 +13018,7 @@ function tlv(tag, ...contents2) {
|
|
|
12678
13018
|
return concat4([Uint8Array.of(tag), length(body.length), body]);
|
|
12679
13019
|
}
|
|
12680
13020
|
var seq = (...parts2) => tlv(48, ...parts2);
|
|
12681
|
-
var
|
|
13021
|
+
var set2 = (...parts2) => tlv(49, ...parts2);
|
|
12682
13022
|
var octets = (bytes) => tlv(4, bytes);
|
|
12683
13023
|
var bits = (bytes, unused = 0) => tlv(3, Uint8Array.of(unused), bytes);
|
|
12684
13024
|
var TRUE = tlv(1, Uint8Array.of(255));
|
|
@@ -12711,8 +13051,8 @@ function time(date) {
|
|
|
12711
13051
|
var ECDSA_SHA256 = seq(oid("1.2.840.10045.4.3.2"));
|
|
12712
13052
|
function name(dn) {
|
|
12713
13053
|
const rdns = [];
|
|
12714
|
-
if (dn.organization) rdns.push(
|
|
12715
|
-
rdns.push(
|
|
13054
|
+
if (dn.organization) rdns.push(set2(seq(oid("2.5.4.10"), utf8(dn.organization))));
|
|
13055
|
+
rdns.push(set2(seq(oid("2.5.4.3"), utf8(dn.commonName))));
|
|
12716
13056
|
return seq(...rdns);
|
|
12717
13057
|
}
|
|
12718
13058
|
function extension(id2, critical, value) {
|
|
@@ -13347,9 +13687,9 @@ var WsHandles = class {
|
|
|
13347
13687
|
open = /* @__PURE__ */ new Map();
|
|
13348
13688
|
next;
|
|
13349
13689
|
local;
|
|
13350
|
-
constructor(transport,
|
|
13690
|
+
constructor(transport, next3, local) {
|
|
13351
13691
|
this.transport = transport;
|
|
13352
|
-
this.next =
|
|
13692
|
+
this.next = next3;
|
|
13353
13693
|
this.local = local;
|
|
13354
13694
|
}
|
|
13355
13695
|
owns(handle) {
|
|
@@ -13411,9 +13751,9 @@ var WsHandles = class {
|
|
|
13411
13751
|
}
|
|
13412
13752
|
async recv(socket, entry) {
|
|
13413
13753
|
try {
|
|
13414
|
-
const
|
|
13415
|
-
if (!
|
|
13416
|
-
return typeof
|
|
13754
|
+
const next3 = await entry.messages.next();
|
|
13755
|
+
if (!next3.done) {
|
|
13756
|
+
return typeof next3.value === "string" ? { ok: true, kind: "json", json: { text: next3.value } } : { ok: true, kind: "bytes", bytes: next3.value };
|
|
13417
13757
|
}
|
|
13418
13758
|
const closed = await socket.closed;
|
|
13419
13759
|
return {
|
|
@@ -13461,11 +13801,49 @@ var HTTP_OPS = [
|
|
|
13461
13801
|
"net-open",
|
|
13462
13802
|
"net-head",
|
|
13463
13803
|
"net-read",
|
|
13804
|
+
"net-write",
|
|
13805
|
+
"net-end",
|
|
13464
13806
|
"net-close",
|
|
13465
13807
|
"net-traits",
|
|
13466
13808
|
...WS_OPS
|
|
13467
13809
|
];
|
|
13468
|
-
var
|
|
13810
|
+
var Upload = class {
|
|
13811
|
+
queue = [];
|
|
13812
|
+
ended = false;
|
|
13813
|
+
wake;
|
|
13814
|
+
write(bytes) {
|
|
13815
|
+
if (this.ended) return Promise.resolve(false);
|
|
13816
|
+
return new Promise((taken) => {
|
|
13817
|
+
this.queue.push({ bytes, taken });
|
|
13818
|
+
this.wake?.();
|
|
13819
|
+
});
|
|
13820
|
+
}
|
|
13821
|
+
end() {
|
|
13822
|
+
this.ended = true;
|
|
13823
|
+
this.wake?.();
|
|
13824
|
+
}
|
|
13825
|
+
cancel() {
|
|
13826
|
+
this.ended = true;
|
|
13827
|
+
for (const { taken } of this.queue.splice(0)) taken(false);
|
|
13828
|
+
this.wake?.();
|
|
13829
|
+
}
|
|
13830
|
+
async *[Symbol.asyncIterator]() {
|
|
13831
|
+
for (; ; ) {
|
|
13832
|
+
const next3 = this.queue.shift();
|
|
13833
|
+
if (next3) {
|
|
13834
|
+
next3.taken(true);
|
|
13835
|
+
yield next3.bytes;
|
|
13836
|
+
continue;
|
|
13837
|
+
}
|
|
13838
|
+
if (this.ended) return;
|
|
13839
|
+
await new Promise((resolve2) => {
|
|
13840
|
+
this.wake = resolve2;
|
|
13841
|
+
});
|
|
13842
|
+
this.wake = void 0;
|
|
13843
|
+
}
|
|
13844
|
+
}
|
|
13845
|
+
};
|
|
13846
|
+
var EMPTY2 = new Uint8Array(0);
|
|
13469
13847
|
function message2(e) {
|
|
13470
13848
|
return e instanceof Error ? e.message : String(e);
|
|
13471
13849
|
}
|
|
@@ -13495,6 +13873,8 @@ var HttpHandles = class {
|
|
|
13495
13873
|
if (req.op === "net-open") return Promise.resolve(this.opened(req));
|
|
13496
13874
|
if (req.op === "net-head") return this.head(req.handle);
|
|
13497
13875
|
if (req.op === "net-read") return this.read(req.handle, req.max);
|
|
13876
|
+
if (req.op === "net-write") return this.write(req.handle, req.bytes);
|
|
13877
|
+
if (req.op === "net-end") return Promise.resolve(this.end(req.handle));
|
|
13498
13878
|
if (req.op === "net-traits") return Promise.resolve(this.traits(req.url));
|
|
13499
13879
|
return this.close(req.handle);
|
|
13500
13880
|
}
|
|
@@ -13513,19 +13893,37 @@ var HttpHandles = class {
|
|
|
13513
13893
|
return result;
|
|
13514
13894
|
}
|
|
13515
13895
|
opened(req) {
|
|
13896
|
+
if (req.stream && (this.local?.port(req.url) !== void 0 || !this.transport.traits.streamingBodies)) {
|
|
13897
|
+
return { ok: false, errno: "ENOTSUP", message: "this transport takes whole request bodies" };
|
|
13898
|
+
}
|
|
13516
13899
|
return { ok: true, kind: "json", json: this.start(req).handle };
|
|
13517
13900
|
}
|
|
13901
|
+
async write(handle, bytes) {
|
|
13902
|
+
const upload = this.open.get(handle)?.upload;
|
|
13903
|
+
if (!upload) return { ok: false, errno: "EBADF", message: `no upload ${handle}` };
|
|
13904
|
+
if (!await upload.write(bytes)) {
|
|
13905
|
+
return { ok: false, errno: "EPIPE", message: "the request no longer takes a body" };
|
|
13906
|
+
}
|
|
13907
|
+
return { ok: true, kind: "void" };
|
|
13908
|
+
}
|
|
13909
|
+
end(handle) {
|
|
13910
|
+
const upload = this.open.get(handle)?.upload;
|
|
13911
|
+
if (!upload) return { ok: false, errno: "EBADF", message: `no upload ${handle}` };
|
|
13912
|
+
upload.end();
|
|
13913
|
+
return { ok: true, kind: "void" };
|
|
13914
|
+
}
|
|
13518
13915
|
start(req) {
|
|
13519
13916
|
const handle = ++this.nextHandle;
|
|
13520
13917
|
const abort = new AbortController();
|
|
13521
13918
|
const entry = {
|
|
13522
13919
|
abort,
|
|
13523
13920
|
head: Promise.resolve({ ok: true, kind: "void" }),
|
|
13524
|
-
body: once(
|
|
13525
|
-
left:
|
|
13921
|
+
body: once(EMPTY2),
|
|
13922
|
+
left: EMPTY2,
|
|
13526
13923
|
done: false,
|
|
13527
13924
|
reading: Promise.resolve(),
|
|
13528
|
-
cancel: async () => void 0
|
|
13925
|
+
cancel: async () => void 0,
|
|
13926
|
+
...req.stream ? { upload: new Upload() } : {}
|
|
13529
13927
|
};
|
|
13530
13928
|
this.open.set(handle, entry);
|
|
13531
13929
|
entry.head = this.respond(handle, req, entry);
|
|
@@ -13539,7 +13937,7 @@ var HttpHandles = class {
|
|
|
13539
13937
|
url: target,
|
|
13540
13938
|
method: req.method,
|
|
13541
13939
|
headers: req.headers,
|
|
13542
|
-
...req.body ? { body: req.body } : {},
|
|
13940
|
+
...entry.upload ? { bodyStream: entry.upload } : req.body ? { body: req.body } : {},
|
|
13543
13941
|
signal: entry.abort.signal
|
|
13544
13942
|
};
|
|
13545
13943
|
const response = port === void 0 ? await this.transport.fetch(request, this.owner) : await this.local.fetch(request, port);
|
|
@@ -13550,6 +13948,7 @@ var HttpHandles = class {
|
|
|
13550
13948
|
const head = this.headOf(handle, shown, response);
|
|
13551
13949
|
return response.redirected ? { ...head, json: { ...head.json, redirected: true } } : head;
|
|
13552
13950
|
} catch (e) {
|
|
13951
|
+
entry.upload?.cancel();
|
|
13553
13952
|
const text = message2(e);
|
|
13554
13953
|
if (port !== void 0) return { ok: false, errno: codeOf2(e), message: text };
|
|
13555
13954
|
const status = e.status;
|
|
@@ -13586,9 +13985,9 @@ var HttpHandles = class {
|
|
|
13586
13985
|
async take(entry, max) {
|
|
13587
13986
|
if (entry.left.length === 0 && !entry.done) {
|
|
13588
13987
|
try {
|
|
13589
|
-
const
|
|
13590
|
-
if (
|
|
13591
|
-
else entry.left =
|
|
13988
|
+
const next3 = await entry.body.next();
|
|
13989
|
+
if (next3.done) entry.done = true;
|
|
13990
|
+
else entry.left = next3.value;
|
|
13592
13991
|
} catch (e) {
|
|
13593
13992
|
entry.done = true;
|
|
13594
13993
|
const timedOut = e?.code === "ETIMEDOUT";
|
|
@@ -13607,6 +14006,7 @@ var HttpHandles = class {
|
|
|
13607
14006
|
const entry = this.open.get(handle);
|
|
13608
14007
|
if (!entry) return { ok: false, errno: "EBADF", message: `no request ${handle}` };
|
|
13609
14008
|
this.open.delete(handle);
|
|
14009
|
+
entry.upload?.cancel();
|
|
13610
14010
|
entry.abort.abort();
|
|
13611
14011
|
await entry.cancel().catch(() => void 0);
|
|
13612
14012
|
return { ok: true, kind: "void" };
|
|
@@ -13961,12 +14361,12 @@ var KernelTty = class {
|
|
|
13961
14361
|
const chunks2 = [];
|
|
13962
14362
|
let n = 0;
|
|
13963
14363
|
while (this.readable.length > 0 && n < max) {
|
|
13964
|
-
const
|
|
13965
|
-
if (
|
|
13966
|
-
const take =
|
|
14364
|
+
const next3 = this.readable[0];
|
|
14365
|
+
if (next3 === null || next3 === void 0) break;
|
|
14366
|
+
const take = next3.subarray(0, max - n);
|
|
13967
14367
|
chunks2.push(take);
|
|
13968
14368
|
n += take.length;
|
|
13969
|
-
if (take.length <
|
|
14369
|
+
if (take.length < next3.length) this.readable[0] = next3.subarray(take.length);
|
|
13970
14370
|
else this.readable.shift();
|
|
13971
14371
|
if (this.canonical) break;
|
|
13972
14372
|
}
|
|
@@ -14063,11 +14463,11 @@ var PtyPair = class {
|
|
|
14063
14463
|
const chunks2 = [];
|
|
14064
14464
|
let n = 0;
|
|
14065
14465
|
while (this.queue.length > 0 && n < max - status) {
|
|
14066
|
-
const
|
|
14067
|
-
const take =
|
|
14466
|
+
const next3 = this.queue[0];
|
|
14467
|
+
const take = next3.subarray(0, max - status - n);
|
|
14068
14468
|
chunks2.push(take);
|
|
14069
14469
|
n += take.length;
|
|
14070
|
-
if (take.length <
|
|
14470
|
+
if (take.length < next3.length) this.queue[0] = next3.subarray(take.length);
|
|
14071
14471
|
else this.queue.shift();
|
|
14072
14472
|
}
|
|
14073
14473
|
const out = new Uint8Array(status + n);
|
|
@@ -14387,8 +14787,8 @@ var Semaphore = class {
|
|
|
14387
14787
|
this.mode = mode;
|
|
14388
14788
|
}
|
|
14389
14789
|
post() {
|
|
14390
|
-
const
|
|
14391
|
-
if (
|
|
14790
|
+
const next3 = this.waiters.shift();
|
|
14791
|
+
if (next3) next3.grant();
|
|
14392
14792
|
else if (this.value >= SEM_VALUE_MAX) throw new KernelError("EOVERFLOW");
|
|
14393
14793
|
else this.value++;
|
|
14394
14794
|
}
|
|
@@ -14816,9 +15216,9 @@ var VfsNode = class {
|
|
|
14816
15216
|
if (dirty && contents2 !== void 0) this.markDirty();
|
|
14817
15217
|
}
|
|
14818
15218
|
serial(op) {
|
|
14819
|
-
const
|
|
14820
|
-
this.queue =
|
|
14821
|
-
return
|
|
15219
|
+
const next3 = this.queue.then(op);
|
|
15220
|
+
this.queue = next3.catch(() => void 0);
|
|
15221
|
+
return next3;
|
|
14822
15222
|
}
|
|
14823
15223
|
revoke() {
|
|
14824
15224
|
this.revoked = true;
|
|
@@ -15240,9 +15640,9 @@ var VfsNodes = class {
|
|
|
15240
15640
|
}
|
|
15241
15641
|
for (const [p] of moved2) this.byPath.delete(p);
|
|
15242
15642
|
for (const [p, node] of moved2) {
|
|
15243
|
-
const
|
|
15244
|
-
if (node.path === p) node.renamedTo(
|
|
15245
|
-
this.byPath.set(
|
|
15643
|
+
const next3 = to + p.slice(from.length);
|
|
15644
|
+
if (node.path === p) node.renamedTo(next3);
|
|
15645
|
+
this.byPath.set(next3, node);
|
|
15246
15646
|
}
|
|
15247
15647
|
}
|
|
15248
15648
|
};
|
|
@@ -15617,6 +16017,7 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
15617
16017
|
"tty-pgrp-get",
|
|
15618
16018
|
"tty-pgrp-set",
|
|
15619
16019
|
"sig-mask",
|
|
16020
|
+
"sig-waiting",
|
|
15620
16021
|
"sig-pause",
|
|
15621
16022
|
...SOCKET_OPS,
|
|
15622
16023
|
...EPOLL_OPS,
|
|
@@ -15730,16 +16131,8 @@ var WasmProcess = class {
|
|
|
15730
16131
|
if (sig === SIG.STOP) return this.stop(sig);
|
|
15731
16132
|
const bit = sigbit(sig);
|
|
15732
16133
|
if (this.ignores(bit)) return "ignore";
|
|
15733
|
-
if (((this.options.blockedBits?.() ?? 0) & bit) !== 0) {
|
|
15734
|
-
|
|
15735
|
-
if (tid === void 0) {
|
|
15736
|
-
this.options.onPending?.(sig);
|
|
15737
|
-
return "deliver";
|
|
15738
|
-
}
|
|
15739
|
-
if (this.caught & bit) {
|
|
15740
|
-
this.options.threadKill?.(tid, sig);
|
|
15741
|
-
return "deliver";
|
|
15742
|
-
}
|
|
16134
|
+
if (((this.options.blockedBits?.() ?? 0) & bit) !== 0 && this.routeBlocked(sig, bit)) {
|
|
16135
|
+
return "deliver";
|
|
15743
16136
|
}
|
|
15744
16137
|
if (!(this.caught & bit)) {
|
|
15745
16138
|
const action = defaultAction(sig);
|
|
@@ -15756,6 +16149,17 @@ var WasmProcess = class {
|
|
|
15756
16149
|
blocked2.abort();
|
|
15757
16150
|
return "deliver";
|
|
15758
16151
|
}
|
|
16152
|
+
routeBlocked(sig, bit) {
|
|
16153
|
+
const waiter = this.waiterFor(bit);
|
|
16154
|
+
const tid = waiter ?? this.options.unblockedThread?.(sig);
|
|
16155
|
+
if (tid === void 0 || tid === 1) {
|
|
16156
|
+
this.options.onPending?.(sig);
|
|
16157
|
+
return true;
|
|
16158
|
+
}
|
|
16159
|
+
if (waiter === void 0 && !(this.caught & bit)) return false;
|
|
16160
|
+
this.options.threadKill?.(tid, sig);
|
|
16161
|
+
return true;
|
|
16162
|
+
}
|
|
15759
16163
|
async spawn(req) {
|
|
15760
16164
|
const { file, argv, argv0, env, cwd, chdir, stdio, inherit: inherit2, exec, pgid, session, deathSignal } = req;
|
|
15761
16165
|
if (deathSignal !== void 0 && (exec || !isSignal(deathSignal))) {
|
|
@@ -15836,6 +16240,16 @@ var WasmProcess = class {
|
|
|
15836
16240
|
}
|
|
15837
16241
|
blocks = /* @__PURE__ */ new WeakMap();
|
|
15838
16242
|
sizesRead = /* @__PURE__ */ new WeakMap();
|
|
16243
|
+
sigwaiters = /* @__PURE__ */ new Map();
|
|
16244
|
+
setSigwaiter(tid, set3) {
|
|
16245
|
+
if (set3 === 0) this.sigwaiters.delete(tid);
|
|
16246
|
+
else this.sigwaiters.set(tid, set3);
|
|
16247
|
+
}
|
|
16248
|
+
waiterFor(bit) {
|
|
16249
|
+
if (((this.sigwaiters.get(1) ?? 0) & bit) !== 0) return 1;
|
|
16250
|
+
for (const [tid, set3] of this.sigwaiters) if (set3 & bit) return tid;
|
|
16251
|
+
return void 0;
|
|
16252
|
+
}
|
|
15839
16253
|
async syscall(req, cancelled, block) {
|
|
15840
16254
|
this.options.onSyscall?.(req);
|
|
15841
16255
|
const started = performance.now();
|
|
@@ -16092,18 +16506,18 @@ var WasmProcess = class {
|
|
|
16092
16506
|
}
|
|
16093
16507
|
if (this.writesAt(req) && this.options.readonlyAt?.(path)) throw new KernelError("EROFS");
|
|
16094
16508
|
const open = { ...req, path };
|
|
16095
|
-
const
|
|
16509
|
+
const plain2 = this.plainMode(req.mode);
|
|
16096
16510
|
if (req.exclusive) {
|
|
16097
16511
|
await nodes.createExclusive(path, this.newOwner(req.mode));
|
|
16098
|
-
if (
|
|
16512
|
+
if (plain2 !== void 0) await fs.chmod?.(path, plain2);
|
|
16099
16513
|
this.fds.installAt(fd, this.openVfsFile(open, void 0, fs));
|
|
16100
16514
|
} else if (req.create) {
|
|
16101
16515
|
await nodes.onEntry(path, async () => {
|
|
16102
|
-
const marks = this.options.owners ||
|
|
16516
|
+
const marks = this.options.owners || plain2 !== void 0;
|
|
16103
16517
|
const fresh2 = marks && !await present2(fs, path, true);
|
|
16104
16518
|
this.fds.installAt(fd, this.openVfsFile(open, await nodes.identify(path), fs));
|
|
16105
16519
|
await this.fds.get(fd).file.stat?.();
|
|
16106
|
-
if (fresh2 &&
|
|
16520
|
+
if (fresh2 && plain2 !== void 0) await fs.chmod?.(path, plain2);
|
|
16107
16521
|
else if (fresh2) {
|
|
16108
16522
|
await fs.chown?.(path, { ...this.newOwner(req.mode), kind: "new" });
|
|
16109
16523
|
}
|
|
@@ -16744,6 +17158,9 @@ var WasmProcess = class {
|
|
|
16744
17158
|
case "dl-unlock":
|
|
16745
17159
|
this.unlockDl(req.owner);
|
|
16746
17160
|
return { ok: true, kind: "void" };
|
|
17161
|
+
case "sig-waiting":
|
|
17162
|
+
this.setSigwaiter(req.tid, req.set);
|
|
17163
|
+
return { ok: true, kind: "void" };
|
|
16747
17164
|
case "sig-mask":
|
|
16748
17165
|
this.caught = req.caught;
|
|
16749
17166
|
this.ignored = req.ignored;
|
|
@@ -16811,8 +17228,8 @@ var WasmProcess = class {
|
|
|
16811
17228
|
};
|
|
16812
17229
|
withDl(state) {
|
|
16813
17230
|
if (this.dlLog.length === 0) return state;
|
|
16814
|
-
const { next:
|
|
16815
|
-
const dl = { log: [...this.dlLog], next:
|
|
17231
|
+
const { next: next3, handle, free, live } = this.closures;
|
|
17232
|
+
const dl = { log: [...this.dlLog], next: next3, handle, free: [...free], live: [...live] };
|
|
16816
17233
|
return { ...state, dl };
|
|
16817
17234
|
}
|
|
16818
17235
|
seedDl(dl) {
|
|
@@ -16823,8 +17240,8 @@ var WasmProcess = class {
|
|
|
16823
17240
|
this.closures.free.push(...dl.free);
|
|
16824
17241
|
for (const index of dl.live) this.closures.live.add(index);
|
|
16825
17242
|
}
|
|
16826
|
-
allocateClosure(
|
|
16827
|
-
const index = this.closures.free.pop() ?? Math.max(
|
|
17243
|
+
allocateClosure(floor2) {
|
|
17244
|
+
const index = this.closures.free.pop() ?? Math.max(floor2, this.closures.next);
|
|
16828
17245
|
this.closures.next = Math.max(this.closures.next, index + 1);
|
|
16829
17246
|
this.closures.live.add(index);
|
|
16830
17247
|
this.dlLog.push({ kind: "closure", index });
|
|
@@ -16876,8 +17293,8 @@ var WasmProcess = class {
|
|
|
16876
17293
|
wakeDl() {
|
|
16877
17294
|
for (const waiter of [...this.dlLock.waiters]) waiter.wake(false);
|
|
16878
17295
|
}
|
|
16879
|
-
reserveSlots(
|
|
16880
|
-
const base = Math.max(
|
|
17296
|
+
reserveSlots(floor2, size) {
|
|
17297
|
+
const base = Math.max(floor2, this.closures.next);
|
|
16881
17298
|
this.closures.next = base + size;
|
|
16882
17299
|
return base;
|
|
16883
17300
|
}
|
|
@@ -16934,6 +17351,7 @@ var WASM_MAX_THREADS = 256;
|
|
|
16934
17351
|
// src/kernel/host.ts
|
|
16935
17352
|
var CRASHED = 70;
|
|
16936
17353
|
var KILL_GRACE_MS = 2e3;
|
|
17354
|
+
var KILL_HARD_MS = 5e3;
|
|
16937
17355
|
var descIds = /* @__PURE__ */ new WeakMap();
|
|
16938
17356
|
var nextDescId = 1;
|
|
16939
17357
|
function descId(file) {
|
|
@@ -16960,16 +17378,21 @@ function inheritedFds(fds) {
|
|
|
16960
17378
|
var Dying = class {
|
|
16961
17379
|
ending;
|
|
16962
17380
|
timer;
|
|
17381
|
+
hard;
|
|
16963
17382
|
busy = 0;
|
|
16964
17383
|
finish;
|
|
16965
17384
|
start(code, sig, header4, process2, finish) {
|
|
16966
17385
|
if (this.ending) return;
|
|
16967
17386
|
this.ending = { code, sig };
|
|
16968
17387
|
this.finish = finish;
|
|
17388
|
+
this.hard = setTimeout(finish, KILL_HARD_MS);
|
|
16969
17389
|
this.arm();
|
|
16970
17390
|
Atomics.store(header4, SAB_I_KILLED, code);
|
|
16971
17391
|
process2.die();
|
|
16972
17392
|
}
|
|
17393
|
+
serve(req, work) {
|
|
17394
|
+
return this.ending && isWasmSyscall(req) ? work() : this.serving(work);
|
|
17395
|
+
}
|
|
16973
17396
|
async serving(work) {
|
|
16974
17397
|
this.busy++;
|
|
16975
17398
|
clearTimeout(this.timer);
|
|
@@ -16986,6 +17409,7 @@ var Dying = class {
|
|
|
16986
17409
|
}
|
|
16987
17410
|
clear() {
|
|
16988
17411
|
clearTimeout(this.timer);
|
|
17412
|
+
clearTimeout(this.hard);
|
|
16989
17413
|
}
|
|
16990
17414
|
status(reported2) {
|
|
16991
17415
|
if (this.ending) return [this.ending.code, this.ending.sig];
|
|
@@ -16997,8 +17421,8 @@ function killThread(thread, caught, sig) {
|
|
|
16997
17421
|
const held = (Atomics.load(thread.header, SAB_I_BLOCKED) & sigbit(sig)) !== 0;
|
|
16998
17422
|
if (!held && (caught & sigbit(sig)) === 0) return false;
|
|
16999
17423
|
Atomics.or(thread.header, SAB_I_SIGNALS, sigbit(sig));
|
|
17000
|
-
if (held) return true;
|
|
17001
17424
|
Atomics.notify(thread.header, SAB_I_SIGNALS);
|
|
17425
|
+
if (held) return true;
|
|
17002
17426
|
const blocked2 = thread.interrupt;
|
|
17003
17427
|
thread.interrupt = new AbortController();
|
|
17004
17428
|
blocked2.abort();
|
|
@@ -17094,7 +17518,7 @@ function inherited(opts) {
|
|
|
17094
17518
|
...opts.cred ? { cred: opts.cred } : {}
|
|
17095
17519
|
};
|
|
17096
17520
|
}
|
|
17097
|
-
function holdingToken(opts,
|
|
17521
|
+
function holdingToken(opts, holds2, caller) {
|
|
17098
17522
|
return mintSyncFsToken({
|
|
17099
17523
|
...opts.owners ? caller : { umask: caller.umask },
|
|
17100
17524
|
...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
|
|
@@ -17105,13 +17529,13 @@ function holdingToken(opts, holds, caller) {
|
|
|
17105
17529
|
noLinks: opts.noLinks,
|
|
17106
17530
|
cwd: opts.cwd,
|
|
17107
17531
|
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
17108
|
-
hold: (path, on, open, real, handle) =>
|
|
17109
|
-
keptFor: (handle) =>
|
|
17110
|
-
unlinked: (path) =>
|
|
17111
|
-
gate: (path, op) => opts.unlinkGate &&
|
|
17112
|
-
own: (path, op) =>
|
|
17113
|
-
revoked: (path) =>
|
|
17114
|
-
renamed: (from, to) =>
|
|
17532
|
+
hold: (path, on, open, real, handle) => holds2.hold(path, on, open, real, handle),
|
|
17533
|
+
keptFor: (handle) => holds2.keptFor(handle),
|
|
17534
|
+
unlinked: (path) => holds2.keptAt(path),
|
|
17535
|
+
gate: (path, op) => opts.unlinkGate && holds2.holding(path) ? opts.unlinkGate.run(holds2.keyOf(path), op) : op(),
|
|
17536
|
+
own: (path, op) => holds2.own(path, op),
|
|
17537
|
+
revoked: (path) => holds2.isRevoked(path),
|
|
17538
|
+
renamed: (from, to) => holds2.renamed(from, to)
|
|
17115
17539
|
});
|
|
17116
17540
|
}
|
|
17117
17541
|
function linksOf(opts) {
|
|
@@ -17185,6 +17609,9 @@ function threadInit(opts, program, sab, cred, thread, main) {
|
|
|
17185
17609
|
signals: main
|
|
17186
17610
|
};
|
|
17187
17611
|
}
|
|
17612
|
+
function settleExit(exit, settle, code) {
|
|
17613
|
+
void exit.catch(() => void 0).then(() => settle(code & 255));
|
|
17614
|
+
}
|
|
17188
17615
|
function spawnWasmProcess(opts) {
|
|
17189
17616
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
17190
17617
|
const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
@@ -17211,19 +17638,20 @@ function spawnWasmProcess(opts) {
|
|
|
17211
17638
|
)
|
|
17212
17639
|
);
|
|
17213
17640
|
publishStops(process2, header4);
|
|
17214
|
-
const
|
|
17215
|
-
opts.held?.add(
|
|
17216
|
-
const token = holdingToken(opts,
|
|
17641
|
+
const holds2 = new HeldPaths();
|
|
17642
|
+
opts.held?.add(holds2);
|
|
17643
|
+
const token = holdingToken(opts, holds2, {
|
|
17217
17644
|
cred: () => process2.cred,
|
|
17218
17645
|
umask: () => process2.umask,
|
|
17219
17646
|
created: created3,
|
|
17220
|
-
holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (
|
|
17647
|
+
holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (holds2.keeps(path) || await process2.holds(path))
|
|
17221
17648
|
});
|
|
17222
|
-
process2.keptPath = (path) =>
|
|
17223
|
-
process2.keptHandle = (handle2) =>
|
|
17649
|
+
process2.keptPath = (path) => holds2.keptAt(path)?.hidden;
|
|
17650
|
+
process2.keptHandle = (handle2) => holds2.keptFor(handle2)?.hidden;
|
|
17224
17651
|
const worker = opts.createWorker();
|
|
17225
17652
|
const dying = new Dying();
|
|
17226
|
-
const dispatch2 = (req, block) => dying.
|
|
17653
|
+
const dispatch2 = (req, block) => dying.serve(
|
|
17654
|
+
req,
|
|
17227
17655
|
() => isWasmSyscall(req) ? process2.syscall(req, void 0, block) : dispatchSyncFs(req)
|
|
17228
17656
|
);
|
|
17229
17657
|
const clocks = new ProcessClocks(sab, opts.program.abi !== "js", process2);
|
|
@@ -17246,12 +17674,9 @@ function spawnWasmProcess(opts) {
|
|
|
17246
17674
|
responder.dispose();
|
|
17247
17675
|
lane?.dispose();
|
|
17248
17676
|
revokeSyncFsToken(token);
|
|
17249
|
-
opts.held?.delete(
|
|
17677
|
+
opts.held?.delete(holds2);
|
|
17250
17678
|
worker.terminate();
|
|
17251
|
-
|
|
17252
|
-
() => settle(code),
|
|
17253
|
-
() => settle(code)
|
|
17254
|
-
);
|
|
17679
|
+
settleExit(process2.exit(), settle, code);
|
|
17255
17680
|
};
|
|
17256
17681
|
const exitNow = (code) => {
|
|
17257
17682
|
queueMicrotask(() => finish(...dying.status(code)));
|
|
@@ -17295,7 +17720,7 @@ function spawnWasmProcess(opts) {
|
|
|
17295
17720
|
const tsignals = threadSignalsOf(tsab);
|
|
17296
17721
|
if (thread.blocked) storeBlocked(tsignals.header, thread.blocked);
|
|
17297
17722
|
threadSignals.set(thread.tid, tsignals);
|
|
17298
|
-
const tdispatch = (req, block) => dying.
|
|
17723
|
+
const tdispatch = (req, block) => dying.serve(req, () => threadCall(process2, req, threadCancel(tsignals), block));
|
|
17299
17724
|
const tresponder = attachSyncSabResponder(tw, tsab, token, {
|
|
17300
17725
|
dispatch: clocks.timed(clocks.thread(thread.tid, tsab), tdispatch)
|
|
17301
17726
|
});
|
|
@@ -17765,10 +18190,10 @@ var Automaton = class {
|
|
|
17765
18190
|
let node = 0;
|
|
17766
18191
|
for (const byte of bytes) {
|
|
17767
18192
|
const key = node * 256 + byte;
|
|
17768
|
-
let
|
|
17769
|
-
if (
|
|
17770
|
-
|
|
17771
|
-
this.edges.set(key,
|
|
18193
|
+
let next3 = this.edges.get(key);
|
|
18194
|
+
if (next3 === void 0) {
|
|
18195
|
+
next3 = this.depth.length;
|
|
18196
|
+
this.edges.set(key, next3);
|
|
17772
18197
|
this.fail.push(0);
|
|
17773
18198
|
this.depth.push(this.depth[node] + 1);
|
|
17774
18199
|
this.children.push(0);
|
|
@@ -17776,7 +18201,7 @@ var Automaton = class {
|
|
|
17776
18201
|
this.out.push([]);
|
|
17777
18202
|
this.dict.push(-1);
|
|
17778
18203
|
}
|
|
17779
|
-
node =
|
|
18204
|
+
node = next3;
|
|
17780
18205
|
}
|
|
17781
18206
|
const id2 = this.lengths.length;
|
|
17782
18207
|
this.lengths.push(bytes.length);
|
|
@@ -17812,8 +18237,8 @@ var Automaton = class {
|
|
|
17812
18237
|
step(state, byte) {
|
|
17813
18238
|
let current = state;
|
|
17814
18239
|
for (; ; ) {
|
|
17815
|
-
const
|
|
17816
|
-
if (
|
|
18240
|
+
const next3 = this.edges.get(current * 256 + byte);
|
|
18241
|
+
if (next3 !== void 0) return next3;
|
|
17817
18242
|
if (current === 0) return 0;
|
|
17818
18243
|
current = this.fail[current];
|
|
17819
18244
|
}
|
|
@@ -17841,7 +18266,7 @@ var RANK = {
|
|
|
17841
18266
|
};
|
|
17842
18267
|
var CR2 = 13;
|
|
17843
18268
|
var LF2 = 10;
|
|
17844
|
-
var
|
|
18269
|
+
var EMPTY3 = new Uint8Array(0);
|
|
17845
18270
|
function register(automaton, sources, ids, bytes, source) {
|
|
17846
18271
|
const key = Array.from(bytes).join(",");
|
|
17847
18272
|
let id2 = ids.get(key);
|
|
@@ -17967,7 +18392,7 @@ function pass(c, input, final) {
|
|
|
17967
18392
|
const partials = [];
|
|
17968
18393
|
scanMain(c, input, best, partials);
|
|
17969
18394
|
scanWrapped(c, input, best, partials);
|
|
17970
|
-
const
|
|
18395
|
+
const holds2 = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
|
|
17971
18396
|
const starts = [...best.keys()].sort((a, b) => a - b);
|
|
17972
18397
|
const parts2 = [];
|
|
17973
18398
|
const hits = /* @__PURE__ */ new Map();
|
|
@@ -17977,16 +18402,16 @@ function pass(c, input, final) {
|
|
|
17977
18402
|
let h = 0;
|
|
17978
18403
|
for (; ; ) {
|
|
17979
18404
|
while (s < starts.length && starts[s] < pos) s++;
|
|
17980
|
-
while (h <
|
|
17981
|
-
const hold = h <
|
|
17982
|
-
const
|
|
17983
|
-
if (hold <=
|
|
18405
|
+
while (h < holds2.length && holds2[h] < pos) h++;
|
|
18406
|
+
const hold = h < holds2.length ? holds2[h] : Infinity;
|
|
18407
|
+
const next3 = s < starts.length ? starts[s] : Infinity;
|
|
18408
|
+
if (hold <= next3) {
|
|
17984
18409
|
cut = Math.min(hold, input.length);
|
|
17985
18410
|
break;
|
|
17986
18411
|
}
|
|
17987
|
-
const candidate = best.get(
|
|
18412
|
+
const candidate = best.get(next3);
|
|
17988
18413
|
parts2.push(
|
|
17989
|
-
input.subarray(pos,
|
|
18414
|
+
input.subarray(pos, next3),
|
|
17990
18415
|
c.replacements[candidate.secret][candidate.form === "raw" ? 0 : 1]
|
|
17991
18416
|
);
|
|
17992
18417
|
count(c, hits, candidate);
|
|
@@ -18021,12 +18446,12 @@ function compile(secrets, options = {}) {
|
|
|
18021
18446
|
return { text: decoder4.decode(bytes), hits };
|
|
18022
18447
|
},
|
|
18023
18448
|
stream() {
|
|
18024
|
-
let pending =
|
|
18449
|
+
let pending = EMPTY3;
|
|
18025
18450
|
const hits = /* @__PURE__ */ new Map();
|
|
18026
18451
|
const run2 = (final) => {
|
|
18027
18452
|
if (c.secrets.length === 0 || pending.length === 0) {
|
|
18028
18453
|
const out = pending;
|
|
18029
|
-
pending =
|
|
18454
|
+
pending = EMPTY3;
|
|
18030
18455
|
return out;
|
|
18031
18456
|
}
|
|
18032
18457
|
const result = pass(c, pending, final);
|
|
@@ -18040,7 +18465,7 @@ function compile(secrets, options = {}) {
|
|
|
18040
18465
|
return run2(false);
|
|
18041
18466
|
},
|
|
18042
18467
|
idle() {
|
|
18043
|
-
return pending.length < FRAGMENT ? run2(true) :
|
|
18468
|
+
return pending.length < FRAGMENT ? run2(true) : EMPTY3;
|
|
18044
18469
|
},
|
|
18045
18470
|
end() {
|
|
18046
18471
|
return run2(true);
|
|
@@ -18082,7 +18507,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18082
18507
|
let timer;
|
|
18083
18508
|
let failed3;
|
|
18084
18509
|
const waiters = /* @__PURE__ */ new Set();
|
|
18085
|
-
const
|
|
18510
|
+
const quiet3 = () => !busy && pending === 0;
|
|
18086
18511
|
const wake = () => {
|
|
18087
18512
|
for (const waiter of [...waiters]) waiter();
|
|
18088
18513
|
};
|
|
@@ -18099,7 +18524,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18099
18524
|
if (failed3 === void 0) failed3 = err;
|
|
18100
18525
|
}).finally(() => {
|
|
18101
18526
|
pending -= 1;
|
|
18102
|
-
if (
|
|
18527
|
+
if (quiet3()) wake();
|
|
18103
18528
|
});
|
|
18104
18529
|
};
|
|
18105
18530
|
const settling = (signal) => new Promise((resolve2, reject) => {
|
|
@@ -18117,7 +18542,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18117
18542
|
signal?.addEventListener("abort", stop, { once: true });
|
|
18118
18543
|
});
|
|
18119
18544
|
const settled = async () => {
|
|
18120
|
-
while (!
|
|
18545
|
+
while (!quiet3()) await settling();
|
|
18121
18546
|
};
|
|
18122
18547
|
const changed = async (signal) => {
|
|
18123
18548
|
const round = new AbortController();
|
|
@@ -18133,7 +18558,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18133
18558
|
};
|
|
18134
18559
|
const turn = async (signal) => {
|
|
18135
18560
|
for (let waited = false; ; waited = true) {
|
|
18136
|
-
if (
|
|
18561
|
+
if (quiet3() && (pollFile(file).writable || !file.changed)) {
|
|
18137
18562
|
busy = true;
|
|
18138
18563
|
return;
|
|
18139
18564
|
}
|
|
@@ -18162,7 +18587,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18162
18587
|
...bound(file, "stat"),
|
|
18163
18588
|
poll: () => {
|
|
18164
18589
|
const state = pollFile(file);
|
|
18165
|
-
return
|
|
18590
|
+
return quiet3() ? state : { ...state, writable: false };
|
|
18166
18591
|
},
|
|
18167
18592
|
changed,
|
|
18168
18593
|
...file.tty ? { tty: file.tty } : {},
|
|
@@ -18178,7 +18603,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18178
18603
|
await send(stream2.push(taken), signal);
|
|
18179
18604
|
} finally {
|
|
18180
18605
|
busy = false;
|
|
18181
|
-
if (
|
|
18606
|
+
if (quiet3()) wake();
|
|
18182
18607
|
}
|
|
18183
18608
|
timer = setTimeout(release, idleMs);
|
|
18184
18609
|
return taken.length;
|
|
@@ -18279,15 +18704,15 @@ function isRecord(value) {
|
|
|
18279
18704
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18280
18705
|
}
|
|
18281
18706
|
function serialized(reply) {
|
|
18282
|
-
let
|
|
18707
|
+
let plain2;
|
|
18283
18708
|
try {
|
|
18284
18709
|
const text = JSON.stringify(reply);
|
|
18285
|
-
|
|
18710
|
+
plain2 = text === void 0 ? void 0 : JSON.parse(text);
|
|
18286
18711
|
} catch (err) {
|
|
18287
18712
|
return JSON.stringify(errorReply("EIO", lineOf2(err)));
|
|
18288
18713
|
}
|
|
18289
|
-
if (!isRecord(
|
|
18290
|
-
const { v: _, ...rest2 } =
|
|
18714
|
+
if (!isRecord(plain2)) return JSON.stringify(errorReply("EIO", "the vault gave no reply"));
|
|
18715
|
+
const { v: _, ...rest2 } = plain2;
|
|
18291
18716
|
return JSON.stringify({ v: 1, ...rest2 });
|
|
18292
18717
|
}
|
|
18293
18718
|
function lineOf2(err) {
|
|
@@ -19306,22 +19731,22 @@ function keepWatching(loop, signal) {
|
|
|
19306
19731
|
const stop = () => session2.abort();
|
|
19307
19732
|
signal.addEventListener("abort", stop);
|
|
19308
19733
|
let timer;
|
|
19309
|
-
const
|
|
19734
|
+
const quiet3 = () => {
|
|
19310
19735
|
clearTimeout(timer);
|
|
19311
19736
|
timer = setTimeout(stop, silenceMs);
|
|
19312
19737
|
};
|
|
19313
19738
|
let opened2 = false;
|
|
19314
19739
|
try {
|
|
19315
19740
|
const client = await loop.connect();
|
|
19316
|
-
|
|
19741
|
+
quiet3();
|
|
19317
19742
|
await client.watch(
|
|
19318
19743
|
session2.signal,
|
|
19319
19744
|
(event) => {
|
|
19320
|
-
|
|
19745
|
+
quiet3();
|
|
19321
19746
|
if (!event.ping) loop.event(event);
|
|
19322
19747
|
},
|
|
19323
19748
|
() => {
|
|
19324
|
-
|
|
19749
|
+
quiet3();
|
|
19325
19750
|
opened2 = true;
|
|
19326
19751
|
up = true;
|
|
19327
19752
|
loop.up(client);
|
|
@@ -19866,9 +20291,9 @@ function tmpfs() {
|
|
|
19866
20291
|
let node = root;
|
|
19867
20292
|
for (const name2 of parts2(path)) {
|
|
19868
20293
|
if (node.kind !== "directory") throw fsError2("ENOTDIR", path);
|
|
19869
|
-
const
|
|
19870
|
-
if (!
|
|
19871
|
-
node =
|
|
20294
|
+
const next3 = node.children.get(name2);
|
|
20295
|
+
if (!next3) throw fsError2("ENOENT", path);
|
|
20296
|
+
node = next3;
|
|
19872
20297
|
}
|
|
19873
20298
|
return node;
|
|
19874
20299
|
}
|
|
@@ -20174,6 +20599,28 @@ function foreignImports(bytes) {
|
|
|
20174
20599
|
return {};
|
|
20175
20600
|
}
|
|
20176
20601
|
|
|
20602
|
+
// src/refused-command.ts
|
|
20603
|
+
var REFUSED_PATH = "/usr/lib/slicc/refused";
|
|
20604
|
+
var REFUSED_SOURCE = [
|
|
20605
|
+
"export default async function refused(ctx) {",
|
|
20606
|
+
" await ctx.write(2, ctx.argv[1] + '\\n').catch(() => undefined);",
|
|
20607
|
+
" return 126;",
|
|
20608
|
+
"}"
|
|
20609
|
+
].join("\n");
|
|
20610
|
+
function refusing(command) {
|
|
20611
|
+
if (!command.refused) return command;
|
|
20612
|
+
return {
|
|
20613
|
+
name: command.name,
|
|
20614
|
+
abi: "js",
|
|
20615
|
+
glue: REFUSED_PATH,
|
|
20616
|
+
wasm: REFUSED_PATH,
|
|
20617
|
+
argv0: command.name,
|
|
20618
|
+
args: [`${command.name}: ${command.refused}`],
|
|
20619
|
+
refused: command.refused,
|
|
20620
|
+
shows: command.script ?? command.wasm
|
|
20621
|
+
};
|
|
20622
|
+
}
|
|
20623
|
+
|
|
20177
20624
|
// src/sudo.ts
|
|
20178
20625
|
var SUDOERS = "/etc/sudoers";
|
|
20179
20626
|
var SUDOERS_D = "/etc/sudoers.d";
|
|
@@ -20201,13 +20648,13 @@ function splitWords(text) {
|
|
|
20201
20648
|
while (piece.lastIndex < text.length) {
|
|
20202
20649
|
const m = piece.exec(text);
|
|
20203
20650
|
if (!m) return void 0;
|
|
20204
|
-
const [, single, double, escaped,
|
|
20651
|
+
const [, single, double, escaped, plain2, space] = m;
|
|
20205
20652
|
if (space !== void 0) {
|
|
20206
20653
|
if (word !== void 0) words2.push(word);
|
|
20207
20654
|
word = void 0;
|
|
20208
20655
|
continue;
|
|
20209
20656
|
}
|
|
20210
|
-
word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ??
|
|
20657
|
+
word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ?? plain2));
|
|
20211
20658
|
}
|
|
20212
20659
|
if (word !== void 0) words2.push(word);
|
|
20213
20660
|
return words2;
|
|
@@ -20239,7 +20686,7 @@ function parseRule(line) {
|
|
|
20239
20686
|
if (!cmnd?.[0]?.startsWith("/")) return void 0;
|
|
20240
20687
|
return { ...rule, cmnd };
|
|
20241
20688
|
}
|
|
20242
|
-
function flags(parsed2, arg,
|
|
20689
|
+
function flags(parsed2, arg, next3) {
|
|
20243
20690
|
for (let j = 1; j < arg.length; j++) {
|
|
20244
20691
|
const flag = arg[j];
|
|
20245
20692
|
if (flag === "n") parsed2.nonInteractive = true;
|
|
@@ -20247,7 +20694,7 @@ function flags(parsed2, arg, next2) {
|
|
|
20247
20694
|
else if (flag !== "u") return `sudo: invalid option -- '${flag}'
|
|
20248
20695
|
${USAGE}`;
|
|
20249
20696
|
else {
|
|
20250
|
-
const user = arg.slice(j + 1) ||
|
|
20697
|
+
const user = arg.slice(j + 1) || next3;
|
|
20251
20698
|
if (!user) return `sudo: option requires an argument -- 'u'
|
|
20252
20699
|
${USAGE}`;
|
|
20253
20700
|
parsed2.user = user;
|
|
@@ -20697,9 +21144,9 @@ function appendedRoots(given) {
|
|
|
20697
21144
|
return [...roots];
|
|
20698
21145
|
}
|
|
20699
21146
|
function plainEnv(words2) {
|
|
20700
|
-
const
|
|
20701
|
-
if (baseName2(words2[0] ?? "") !== "env" ||
|
|
20702
|
-
return
|
|
21147
|
+
const next3 = words2[1];
|
|
21148
|
+
if (baseName2(words2[0] ?? "") !== "env" || next3 === void 0) return false;
|
|
21149
|
+
return next3 === "-S" || !next3.startsWith("-") && !next3.includes("=");
|
|
20703
21150
|
}
|
|
20704
21151
|
function shebangCommand(words2) {
|
|
20705
21152
|
if (!plainEnv(words2)) {
|
|
@@ -20723,9 +21170,9 @@ function expandDefaults(defaults, env) {
|
|
|
20723
21170
|
for (const [key, value] of Object.entries(defaults ?? {})) {
|
|
20724
21171
|
let missing4 = false;
|
|
20725
21172
|
const expanded = value.replace(ENV_REFERENCE, (_, name2) => {
|
|
20726
|
-
const
|
|
20727
|
-
if (
|
|
20728
|
-
return
|
|
21173
|
+
const set3 = Object.hasOwn(env, name2) ? env[name2] : void 0;
|
|
21174
|
+
if (set3 === void 0) missing4 = true;
|
|
21175
|
+
return set3 ?? "";
|
|
20729
21176
|
});
|
|
20730
21177
|
if (!missing4) out[key] = expanded;
|
|
20731
21178
|
}
|
|
@@ -20950,7 +21397,7 @@ var Launcher = class {
|
|
|
20950
21397
|
const holders = [this.held, this.openFiles];
|
|
20951
21398
|
this.unlinked = new UnlinkedKeeper(
|
|
20952
21399
|
fs,
|
|
20953
|
-
{ [Symbol.iterator]: () => holders.flatMap((
|
|
21400
|
+
{ [Symbol.iterator]: () => holders.flatMap((set3) => [...set3]).values() },
|
|
20954
21401
|
(path) => this.mountRoot(path),
|
|
20955
21402
|
{
|
|
20956
21403
|
locks: webLocks(),
|
|
@@ -21035,11 +21482,21 @@ var Launcher = class {
|
|
|
21035
21482
|
found = this.trustedAppended().then(async (appended2) => {
|
|
21036
21483
|
const tiers = await this.tiers(scope, appended2);
|
|
21037
21484
|
return scanCommands(this.scanned, tiers, tiers.length - appended2.length);
|
|
21038
|
-
}).then((commands) => commands.set(SUDO_COMMAND.name, SUDO_COMMAND));
|
|
21485
|
+
}).then((commands) => this.refusals(commands).set(SUDO_COMMAND.name, SUDO_COMMAND));
|
|
21039
21486
|
this.catalogs.set(scope, found);
|
|
21040
21487
|
}
|
|
21041
21488
|
return found;
|
|
21042
21489
|
}
|
|
21490
|
+
refusals(commands) {
|
|
21491
|
+
for (const [name2, command] of commands) {
|
|
21492
|
+
if (!command.refused) continue;
|
|
21493
|
+
commands.set(name2, refusing(command));
|
|
21494
|
+
if (this.warned.has(command.refused)) continue;
|
|
21495
|
+
this.warned.add(command.refused);
|
|
21496
|
+
console.warn(`slicc-kernel: refusing the commands of ${command.refused}`);
|
|
21497
|
+
}
|
|
21498
|
+
return commands;
|
|
21499
|
+
}
|
|
21043
21500
|
ownCommands(scope) {
|
|
21044
21501
|
let found = this.ownCatalogs.get(scope);
|
|
21045
21502
|
if (!found) {
|
|
@@ -21114,7 +21571,8 @@ var Launcher = class {
|
|
|
21114
21571
|
);
|
|
21115
21572
|
return {
|
|
21116
21573
|
byUid: new Map(users.map((account, i) => [account.uid, homes[i]])),
|
|
21117
|
-
byBin: new Map(homes.map((home) => [`${home}/bin`, home]))
|
|
21574
|
+
byBin: new Map(homes.map((home) => [`${home}/bin`, home])),
|
|
21575
|
+
owners: new Map(homes.map((home, i) => [home, credOf(users[i])]))
|
|
21118
21576
|
};
|
|
21119
21577
|
},
|
|
21120
21578
|
() => ({ byUid: /* @__PURE__ */ new Map(), byBin: /* @__PURE__ */ new Map() })
|
|
@@ -21456,12 +21914,12 @@ var Launcher = class {
|
|
|
21456
21914
|
return `${path}:${st.size}:${st.mtime.getTime()}`;
|
|
21457
21915
|
}
|
|
21458
21916
|
verified(path, caller, fs = this.base) {
|
|
21459
|
-
const
|
|
21460
|
-
return this.integrity ? this.integrity.read(path, caller,
|
|
21917
|
+
const plain2 = () => fs.readFileBuffer(path);
|
|
21918
|
+
return this.integrity ? this.integrity.read(path, caller, plain2) : plain2();
|
|
21461
21919
|
}
|
|
21462
21920
|
keyed(path, caller, asked) {
|
|
21463
|
-
const
|
|
21464
|
-
return this.integrity ? this.integrity.readKeyed(path, caller,
|
|
21921
|
+
const plain2 = async () => this.base.readFileBuffer(path);
|
|
21922
|
+
return this.integrity ? this.integrity.readKeyed(path, caller, plain2, asked) : plain2().then((bytes) => ({ bytes }));
|
|
21465
21923
|
}
|
|
21466
21924
|
cached(cache, key, load) {
|
|
21467
21925
|
const hit = cache.get(key);
|
|
@@ -21532,6 +21990,9 @@ var Launcher = class {
|
|
|
21532
21990
|
if (target.abi === "js" && target.wasm === SUDO_PATH) {
|
|
21533
21991
|
return { abi: "js", glue: SUDO_SOURCE, path: SUDO_PATH };
|
|
21534
21992
|
}
|
|
21993
|
+
if (target.abi === "js" && target.wasm === REFUSED_PATH) {
|
|
21994
|
+
return { abi: "js", glue: REFUSED_SOURCE, path: REFUSED_PATH };
|
|
21995
|
+
}
|
|
21535
21996
|
const { asked } = target;
|
|
21536
21997
|
if (target.abi === "js") {
|
|
21537
21998
|
return { abi: "js", glue: await this.text(target.wasm, caller, asked), path: target.wasm };
|
|
@@ -21601,7 +22062,7 @@ var Launcher = class {
|
|
|
21601
22062
|
});
|
|
21602
22063
|
return {
|
|
21603
22064
|
source: {
|
|
21604
|
-
read: (path,
|
|
22065
|
+
read: (path, plain2) => integrity.readSource(path, caller(), plain2),
|
|
21605
22066
|
open: (path, real) => integrity.openSource(path, caller(), real)
|
|
21606
22067
|
}
|
|
21607
22068
|
};
|
|
@@ -22040,9 +22501,9 @@ var Launcher = class {
|
|
|
22040
22501
|
const members = this.jobs.list();
|
|
22041
22502
|
let image = pid;
|
|
22042
22503
|
for (; ; ) {
|
|
22043
|
-
const
|
|
22044
|
-
if (!
|
|
22045
|
-
image =
|
|
22504
|
+
const next3 = members.find((m) => m.execParent === image);
|
|
22505
|
+
if (!next3) return image;
|
|
22506
|
+
image = next3.pid;
|
|
22046
22507
|
}
|
|
22047
22508
|
}
|
|
22048
22509
|
credOf(pid) {
|
|
@@ -22329,7 +22790,7 @@ var Launcher = class {
|
|
|
22329
22790
|
this.pnpmStale();
|
|
22330
22791
|
if (!detach) return;
|
|
22331
22792
|
for (const nodes of this.openFiles) nodes.revoke(at);
|
|
22332
|
-
for (const
|
|
22793
|
+
for (const holds2 of this.held) holds2.revoke(at);
|
|
22333
22794
|
}
|
|
22334
22795
|
unmountAll() {
|
|
22335
22796
|
this.booting.abort();
|
|
@@ -22475,7 +22936,7 @@ var Launcher = class {
|
|
|
22475
22936
|
this.openFiles.add(nodes);
|
|
22476
22937
|
const unlinked = new UnlinkedKeeper(
|
|
22477
22938
|
fs,
|
|
22478
|
-
{ [Symbol.iterator]: () => [this.held, this.openFiles].flatMap((
|
|
22939
|
+
{ [Symbol.iterator]: () => [this.held, this.openFiles].flatMap((set3) => [...set3]).values() },
|
|
22479
22940
|
(path) => this.mountRoot(path),
|
|
22480
22941
|
{
|
|
22481
22942
|
locks: webLocks(),
|
|
@@ -22503,11 +22964,32 @@ var Launcher = class {
|
|
|
22503
22964
|
commandFs(root) {
|
|
22504
22965
|
return withCommandDirs(
|
|
22505
22966
|
root,
|
|
22506
|
-
async () =>
|
|
22967
|
+
async () => this.commandNames(await this.commands()),
|
|
22507
22968
|
(dir) => this.userCommandDir(dir),
|
|
22508
|
-
this.owners
|
|
22969
|
+
this.owners,
|
|
22970
|
+
(path) => this.entryTarget(path)
|
|
22509
22971
|
);
|
|
22510
22972
|
}
|
|
22973
|
+
named = /* @__PURE__ */ new WeakMap();
|
|
22974
|
+
commandNames(commands) {
|
|
22975
|
+
let names = this.named.get(commands);
|
|
22976
|
+
if (!names) {
|
|
22977
|
+
names = new Set(commands.keys());
|
|
22978
|
+
this.named.set(commands, names);
|
|
22979
|
+
}
|
|
22980
|
+
return names;
|
|
22981
|
+
}
|
|
22982
|
+
async entryTarget(path) {
|
|
22983
|
+
const system = COMMAND2.exec(path)?.[1];
|
|
22984
|
+
const slash = path.lastIndexOf("/");
|
|
22985
|
+
const scopes = await this.userScopes();
|
|
22986
|
+
const scope = system === void 0 ? scopes.byBin.get(path.slice(0, slash)) : "";
|
|
22987
|
+
const name2 = system ?? path.slice(slash + 1);
|
|
22988
|
+
const command = scope === void 0 ? void 0 : (await this.commands(scope)).get(name2);
|
|
22989
|
+
const owner = scope ? scopes.owners?.get(scope) : void 0;
|
|
22990
|
+
const target = command && (command.shows ?? command.script ?? command.wasm);
|
|
22991
|
+
return target === void 0 ? void 0 : { path: target, ...owner ? { owner } : {} };
|
|
22992
|
+
}
|
|
22511
22993
|
processChain(fs, nodes, unlinked) {
|
|
22512
22994
|
nodes.changed = (path) => this.changes.publish(path);
|
|
22513
22995
|
nodes.dirtied = (delta) => this.changes.dirtied(delta);
|
|
@@ -22634,11 +23116,11 @@ function ipv4Place(address) {
|
|
|
22634
23116
|
return void 0;
|
|
22635
23117
|
}
|
|
22636
23118
|
function placeOf(address) {
|
|
22637
|
-
const
|
|
22638
|
-
const kind = isIP(
|
|
22639
|
-
if (kind === 4) return ipv4Place(
|
|
23119
|
+
const plain2 = address.replace(/^\[(.*)\]$/, "$1").toLowerCase();
|
|
23120
|
+
const kind = isIP(plain2);
|
|
23121
|
+
if (kind === 4) return ipv4Place(plain2);
|
|
22640
23122
|
if (kind !== 6) return void 0;
|
|
22641
|
-
const words2 = hextets2(
|
|
23123
|
+
const words2 = hextets2(plain2);
|
|
22642
23124
|
const embedded2 = words2.slice(0, 5).every((w) => w === 0) && (words2[5] === 65535 || words2[5] === 0);
|
|
22643
23125
|
if (embedded2 && (words2[5] === 65535 || words2[6] !== 0)) return ipv4Place(ipv4Of(words2));
|
|
22644
23126
|
if (words2.slice(0, 7).every((w) => w === 0) && (words2[7] ?? 0) <= 1) return "loopback";
|
|
@@ -22687,10 +23169,10 @@ function connectRefusal(address, port, place) {
|
|
|
22687
23169
|
return Object.assign(new Error(why), { status: 403, code: "EACCES" });
|
|
22688
23170
|
}
|
|
22689
23171
|
async function addressesOf(host, resolve2) {
|
|
22690
|
-
const
|
|
22691
|
-
if (isIP(
|
|
22692
|
-
if (loopbackName2(
|
|
22693
|
-
return resolve2(
|
|
23172
|
+
const plain2 = host.replace(/^\[(.*)\]$/, "$1");
|
|
23173
|
+
if (isIP(plain2)) return [plain2];
|
|
23174
|
+
if (loopbackName2(plain2)) return ["127.0.0.1"];
|
|
23175
|
+
return resolve2(plain2).catch(() => []);
|
|
22694
23176
|
}
|
|
22695
23177
|
async function checkDestination(target, policy, resolve2 = resolveHost) {
|
|
22696
23178
|
const url = new URL(target);
|
|
@@ -22901,26 +23383,26 @@ var MemoryFile = class {
|
|
|
22901
23383
|
return new File(this.data.blobs, this.name, { lastModified: this.lastModified });
|
|
22902
23384
|
}
|
|
22903
23385
|
async createWritable({ keepExistingData = false } = {}) {
|
|
22904
|
-
const
|
|
23386
|
+
const next3 = keepExistingData ? new Chunks([...this.data.blobs], this.data.size) : new Chunks();
|
|
22905
23387
|
let position = 0;
|
|
22906
23388
|
const put = async (data) => {
|
|
22907
23389
|
const bytes = await bytesOf(data);
|
|
22908
|
-
await
|
|
23390
|
+
await next3.write(position, bytes);
|
|
22909
23391
|
position += bytes.length;
|
|
22910
23392
|
};
|
|
22911
23393
|
return {
|
|
22912
23394
|
write: async (data) => {
|
|
22913
23395
|
if (!isParams(data)) return put(data);
|
|
22914
|
-
if (data.type === "truncate") return
|
|
23396
|
+
if (data.type === "truncate") return next3.truncate(data.size ?? 0);
|
|
22915
23397
|
position = data.position ?? position;
|
|
22916
23398
|
if (data.type === "write") await put(data.data);
|
|
22917
23399
|
},
|
|
22918
23400
|
seek: async (at) => {
|
|
22919
23401
|
position = at;
|
|
22920
23402
|
},
|
|
22921
|
-
truncate: async (size) =>
|
|
23403
|
+
truncate: async (size) => next3.truncate(size),
|
|
22922
23404
|
close: async () => {
|
|
22923
|
-
this.data =
|
|
23405
|
+
this.data = next3;
|
|
22924
23406
|
this.lastModified = Date.now();
|
|
22925
23407
|
},
|
|
22926
23408
|
abort: async () => {
|
|
@@ -23118,12 +23600,17 @@ var RemoteTransport = class {
|
|
|
23118
23600
|
waiting = /* @__PURE__ */ new Map();
|
|
23119
23601
|
nextId = 0;
|
|
23120
23602
|
sockets = /* @__PURE__ */ new Map();
|
|
23603
|
+
uploads = /* @__PURE__ */ new Map();
|
|
23121
23604
|
failure;
|
|
23122
23605
|
constructor(port, traits) {
|
|
23123
23606
|
this.port = port;
|
|
23124
23607
|
this.traits = traits;
|
|
23125
23608
|
}
|
|
23126
23609
|
receive(reply) {
|
|
23610
|
+
if (reply.net === "body-pull") {
|
|
23611
|
+
void this.pull(reply.nid);
|
|
23612
|
+
return;
|
|
23613
|
+
}
|
|
23127
23614
|
const socket = this.sockets.get(reply.nid);
|
|
23128
23615
|
if (socket && this.toSocket(reply, socket)) return;
|
|
23129
23616
|
const waiter = this.waiting.get(reply.nid);
|
|
@@ -23142,8 +23629,35 @@ var RemoteTransport = class {
|
|
|
23142
23629
|
} else return false;
|
|
23143
23630
|
return true;
|
|
23144
23631
|
}
|
|
23632
|
+
async pull(nid) {
|
|
23633
|
+
const upload = this.uploads.get(nid);
|
|
23634
|
+
if (!upload) {
|
|
23635
|
+
this.port.postMessage({ net: "body-error", nid, message: "the request body is gone" });
|
|
23636
|
+
return;
|
|
23637
|
+
}
|
|
23638
|
+
try {
|
|
23639
|
+
const next3 = await upload.next();
|
|
23640
|
+
if (next3.done) {
|
|
23641
|
+
this.uploads.delete(nid);
|
|
23642
|
+
this.port.postMessage({ net: "body-end", nid });
|
|
23643
|
+
} else this.port.postMessage({ net: "body-chunk", nid, bytes: next3.value });
|
|
23644
|
+
} catch (e) {
|
|
23645
|
+
this.uploads.delete(nid);
|
|
23646
|
+
this.port.postMessage({
|
|
23647
|
+
net: "body-error",
|
|
23648
|
+
nid,
|
|
23649
|
+
message: e instanceof Error ? e.message : String(e)
|
|
23650
|
+
});
|
|
23651
|
+
}
|
|
23652
|
+
}
|
|
23653
|
+
dropUpload(nid) {
|
|
23654
|
+
const upload = this.uploads.get(nid);
|
|
23655
|
+
this.uploads.delete(nid);
|
|
23656
|
+
void upload?.return?.().catch(() => void 0);
|
|
23657
|
+
}
|
|
23145
23658
|
fail(error) {
|
|
23146
23659
|
this.failure = error;
|
|
23660
|
+
for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);
|
|
23147
23661
|
for (const waiter of this.waiting.values()) waiter.reject(error);
|
|
23148
23662
|
this.waiting.clear();
|
|
23149
23663
|
for (const socket of this.sockets.values())
|
|
@@ -23170,14 +23684,17 @@ var RemoteTransport = class {
|
|
|
23170
23684
|
let finished = false;
|
|
23171
23685
|
const abort = () => {
|
|
23172
23686
|
finished = true;
|
|
23687
|
+
this.dropUpload(nid);
|
|
23173
23688
|
this.cancel(nid);
|
|
23174
23689
|
};
|
|
23175
23690
|
signal.addEventListener("abort", abort, { once: true });
|
|
23176
23691
|
const finish = () => {
|
|
23692
|
+
this.dropUpload(nid);
|
|
23177
23693
|
if (finished) return;
|
|
23178
23694
|
finished = true;
|
|
23179
23695
|
signal.removeEventListener("abort", abort);
|
|
23180
23696
|
};
|
|
23697
|
+
if (request.bodyStream) this.uploads.set(nid, request.bodyStream[Symbol.asyncIterator]());
|
|
23181
23698
|
let head;
|
|
23182
23699
|
try {
|
|
23183
23700
|
head = await this.ask({
|
|
@@ -23186,7 +23703,7 @@ var RemoteTransport = class {
|
|
|
23186
23703
|
url: request.url,
|
|
23187
23704
|
method: request.method,
|
|
23188
23705
|
headers: request.headers,
|
|
23189
|
-
...request.body ? { body: request.body } : {}
|
|
23706
|
+
...request.bodyStream ? { streamed: true } : request.body ? { body: request.body } : {}
|
|
23190
23707
|
});
|
|
23191
23708
|
} catch (e) {
|
|
23192
23709
|
finish();
|
|
@@ -23455,11 +23972,11 @@ function stream(chunks2, socket, signal) {
|
|
|
23455
23972
|
},
|
|
23456
23973
|
async pull(controller) {
|
|
23457
23974
|
try {
|
|
23458
|
-
const
|
|
23459
|
-
if (
|
|
23975
|
+
const next3 = await chunks2.next();
|
|
23976
|
+
if (next3.done) {
|
|
23460
23977
|
controller.close();
|
|
23461
23978
|
socket.close();
|
|
23462
|
-
} else controller.enqueue(
|
|
23979
|
+
} else controller.enqueue(next3.value);
|
|
23463
23980
|
} catch (err) {
|
|
23464
23981
|
controller.error(err);
|
|
23465
23982
|
socket.close();
|
|
@@ -23816,9 +24333,9 @@ async function terminalOn(channel, argv, opts) {
|
|
|
23816
24333
|
get onData() {
|
|
23817
24334
|
return listener;
|
|
23818
24335
|
},
|
|
23819
|
-
set onData(
|
|
23820
|
-
listener =
|
|
23821
|
-
if (
|
|
24336
|
+
set onData(next3) {
|
|
24337
|
+
listener = next3;
|
|
24338
|
+
if (next3) for (const bytes of backlog.splice(0)) next3(bytes);
|
|
23822
24339
|
},
|
|
23823
24340
|
write: (data) => send({ action: "write", bytes: bytesOf2(data) }),
|
|
23824
24341
|
resize: (cols, rows) => send({ action: "resize", cols, rows }),
|
|
@@ -23964,7 +24481,12 @@ function hostfsFetchOf(options) {
|
|
|
23964
24481
|
};
|
|
23965
24482
|
}
|
|
23966
24483
|
function nodeTransport(options = {}) {
|
|
23967
|
-
const transport = fetchTransport({
|
|
24484
|
+
const transport = fetchTransport({
|
|
24485
|
+
webSocket: true,
|
|
24486
|
+
webSocketHeaders: true,
|
|
24487
|
+
redirect: "manual",
|
|
24488
|
+
streamingBodies: true
|
|
24489
|
+
});
|
|
23968
24490
|
const open = { ...transport, traits: { ...transport.traits, crossOrigin: "any" } };
|
|
23969
24491
|
return diagnosing(guardedLoopback(open, options.hostLoopback ?? false));
|
|
23970
24492
|
}
|
|
@@ -24110,9 +24632,9 @@ async function createNodeKernel(options = {}) {
|
|
|
24110
24632
|
get onData() {
|
|
24111
24633
|
return listener;
|
|
24112
24634
|
},
|
|
24113
|
-
set onData(
|
|
24114
|
-
listener =
|
|
24115
|
-
if (
|
|
24635
|
+
set onData(next3) {
|
|
24636
|
+
listener = next3;
|
|
24637
|
+
if (next3) for (const bytes of backlog.splice(0)) next3(bytes);
|
|
24116
24638
|
},
|
|
24117
24639
|
write: (data) => session.write(typeof data === "string" ? new TextEncoder().encode(data) : data),
|
|
24118
24640
|
resize: (cols, rows) => session.resize(cols, rows),
|