@ai-ecoverse/slicc-kernel 1.82.0 → 1.83.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -1
- package/dist/kernel-worker.js +940 -180
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node.js +948 -188
- package/dist/node.js.map +4 -4
- package/package.json +3 -2
package/dist/node.js
CHANGED
|
@@ -28,7 +28,7 @@ function serveCdpPort(port, hook, request, onDone) {
|
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
30
|
port.start?.();
|
|
31
|
-
new Promise((
|
|
31
|
+
new Promise((resolve2) => resolve2(hook(request))).then(
|
|
32
32
|
(opened2) => {
|
|
33
33
|
conn = opened2;
|
|
34
34
|
if (done4) return opened2.close();
|
|
@@ -51,7 +51,7 @@ function serveCdpPort(port, hook, request, onDone) {
|
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
function portCdpHook(ask, gone) {
|
|
54
|
-
return (request) => new Promise((
|
|
54
|
+
return (request) => new Promise((resolve2, reject) => {
|
|
55
55
|
const { port1, port2 } = new MessageChannel();
|
|
56
56
|
let closed = false;
|
|
57
57
|
const conn = {
|
|
@@ -69,7 +69,7 @@ function portCdpHook(ask, gone) {
|
|
|
69
69
|
};
|
|
70
70
|
port1.addEventListener("message", ({ data }) => {
|
|
71
71
|
if ("m" in data) conn.onmessage?.(data.m);
|
|
72
|
-
else if ("open" in data)
|
|
72
|
+
else if ("open" in data) resolve2(conn);
|
|
73
73
|
else if ("error" in data) {
|
|
74
74
|
closed = true;
|
|
75
75
|
port1.close();
|
|
@@ -671,9 +671,9 @@ var KernelPipe = class {
|
|
|
671
671
|
let filled = 0;
|
|
672
672
|
for (const chunk2 of this.chunks) {
|
|
673
673
|
if (filled === out.length) break;
|
|
674
|
-
const
|
|
675
|
-
out.set(chunk2.subarray(0,
|
|
676
|
-
filled +=
|
|
674
|
+
const count2 = Math.min(chunk2.length, out.length - filled);
|
|
675
|
+
out.set(chunk2.subarray(0, count2), filled);
|
|
676
|
+
filled += count2;
|
|
677
677
|
}
|
|
678
678
|
return out;
|
|
679
679
|
}
|
|
@@ -704,25 +704,25 @@ var KernelPipe = class {
|
|
|
704
704
|
let filled = 0;
|
|
705
705
|
while (filled < n) {
|
|
706
706
|
const head = this.chunks[0];
|
|
707
|
-
const
|
|
708
|
-
out.set(head.subarray(0,
|
|
709
|
-
filled +=
|
|
710
|
-
if (
|
|
711
|
-
else this.chunks[0] = head.subarray(
|
|
707
|
+
const count2 = Math.min(head.length, n - filled);
|
|
708
|
+
out.set(head.subarray(0, count2), filled);
|
|
709
|
+
filled += count2;
|
|
710
|
+
if (count2 === head.length) this.chunks.shift();
|
|
711
|
+
else this.chunks[0] = head.subarray(count2);
|
|
712
712
|
}
|
|
713
713
|
this.size -= n;
|
|
714
714
|
return out;
|
|
715
715
|
}
|
|
716
716
|
changed(signal) {
|
|
717
717
|
if (signal?.aborted) return Promise.reject(new PipeError("EINTR"));
|
|
718
|
-
return new Promise((
|
|
718
|
+
return new Promise((resolve2, reject) => {
|
|
719
719
|
const onAbort = () => {
|
|
720
720
|
this.waiters = this.waiters.filter((w) => w !== waiter);
|
|
721
721
|
reject(new PipeError("EINTR"));
|
|
722
722
|
};
|
|
723
723
|
const waiter = () => {
|
|
724
724
|
signal?.removeEventListener("abort", onAbort);
|
|
725
|
-
|
|
725
|
+
resolve2();
|
|
726
726
|
};
|
|
727
727
|
this.waiters.push(waiter);
|
|
728
728
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -731,7 +731,7 @@ var KernelPipe = class {
|
|
|
731
731
|
wake() {
|
|
732
732
|
const waiters = this.waiters;
|
|
733
733
|
this.waiters = [];
|
|
734
|
-
for (const
|
|
734
|
+
for (const resolve2 of waiters) resolve2();
|
|
735
735
|
}
|
|
736
736
|
};
|
|
737
737
|
|
|
@@ -1192,14 +1192,14 @@ var Changes = class {
|
|
|
1192
1192
|
waiters = [];
|
|
1193
1193
|
wait(signal) {
|
|
1194
1194
|
if (signal?.aborted) return Promise.reject(new KernelError("EINTR"));
|
|
1195
|
-
return new Promise((
|
|
1195
|
+
return new Promise((resolve2, reject) => {
|
|
1196
1196
|
const onAbort = () => {
|
|
1197
1197
|
this.waiters = this.waiters.filter((w) => w !== waiter);
|
|
1198
1198
|
reject(new KernelError("EINTR"));
|
|
1199
1199
|
};
|
|
1200
1200
|
const waiter = () => {
|
|
1201
1201
|
signal?.removeEventListener("abort", onAbort);
|
|
1202
|
-
|
|
1202
|
+
resolve2();
|
|
1203
1203
|
};
|
|
1204
1204
|
this.waiters.push(waiter);
|
|
1205
1205
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -1208,7 +1208,7 @@ var Changes = class {
|
|
|
1208
1208
|
wake() {
|
|
1209
1209
|
const waiters = this.waiters;
|
|
1210
1210
|
this.waiters = [];
|
|
1211
|
-
for (const
|
|
1211
|
+
for (const resolve2 of waiters) resolve2();
|
|
1212
1212
|
}
|
|
1213
1213
|
};
|
|
1214
1214
|
function link(a, b) {
|
|
@@ -1376,7 +1376,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
1376
1376
|
});
|
|
1377
1377
|
const { host, port } = addr;
|
|
1378
1378
|
const dialled = new Promise(
|
|
1379
|
-
(
|
|
1379
|
+
(resolve2) => resolve2(route.uplink.dial({ network: "tcp", host, port, signal: abort.signal }))
|
|
1380
1380
|
);
|
|
1381
1381
|
dialled.then(
|
|
1382
1382
|
(conn) => abort.signal.aborted && conn.close(),
|
|
@@ -1747,8 +1747,8 @@ var MessageQueue = class {
|
|
|
1747
1747
|
this.overflow = overflow;
|
|
1748
1748
|
this.limit = limit;
|
|
1749
1749
|
this.taken = taken;
|
|
1750
|
-
this.closed = new Promise((
|
|
1751
|
-
this.settle =
|
|
1750
|
+
this.closed = new Promise((resolve2) => {
|
|
1751
|
+
this.settle = resolve2;
|
|
1752
1752
|
});
|
|
1753
1753
|
}
|
|
1754
1754
|
push(message3) {
|
|
@@ -1787,8 +1787,8 @@ var MessageQueue = class {
|
|
|
1787
1787
|
continue;
|
|
1788
1788
|
}
|
|
1789
1789
|
if (this.ended) return;
|
|
1790
|
-
await new Promise((
|
|
1791
|
-
this.waiter =
|
|
1790
|
+
await new Promise((resolve2) => {
|
|
1791
|
+
this.waiter = resolve2;
|
|
1792
1792
|
});
|
|
1793
1793
|
}
|
|
1794
1794
|
}
|
|
@@ -1837,7 +1837,7 @@ function openWebSocket(Socket, request, withHeaders) {
|
|
|
1837
1837
|
}
|
|
1838
1838
|
socket.binaryType = "arraybuffer";
|
|
1839
1839
|
const queue = new MessageQueue(() => socket.close(1e3, "too many waiting messages"));
|
|
1840
|
-
return new Promise((
|
|
1840
|
+
return new Promise((resolve2, reject) => {
|
|
1841
1841
|
let open = false;
|
|
1842
1842
|
let settled = false;
|
|
1843
1843
|
const fail3 = (error) => {
|
|
@@ -1856,7 +1856,7 @@ function openWebSocket(Socket, request, withHeaders) {
|
|
|
1856
1856
|
open = true;
|
|
1857
1857
|
settled = true;
|
|
1858
1858
|
signal.removeEventListener("abort", abort);
|
|
1859
|
-
|
|
1859
|
+
resolve2({
|
|
1860
1860
|
protocol: socket.protocol,
|
|
1861
1861
|
get buffered() {
|
|
1862
1862
|
return socket.bufferedAmount;
|
|
@@ -2047,8 +2047,8 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
2047
2047
|
const relay = async (nid, socket) => {
|
|
2048
2048
|
let ending;
|
|
2049
2049
|
let late;
|
|
2050
|
-
const unanswered = new Promise((
|
|
2051
|
-
late = () =>
|
|
2050
|
+
const unanswered = new Promise((resolve2) => {
|
|
2051
|
+
late = () => resolve2("late");
|
|
2052
2052
|
});
|
|
2053
2053
|
const flow = {
|
|
2054
2054
|
inflight: 0,
|
|
@@ -2076,8 +2076,8 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
2076
2076
|
}
|
|
2077
2077
|
flow.inflight += payloadSize(data);
|
|
2078
2078
|
while (flow.inflight > INBOUND_LIMIT && !flow.closing) {
|
|
2079
|
-
await new Promise((
|
|
2080
|
-
flow.wake =
|
|
2079
|
+
await new Promise((resolve2) => {
|
|
2080
|
+
flow.wake = resolve2;
|
|
2081
2081
|
});
|
|
2082
2082
|
}
|
|
2083
2083
|
}
|
|
@@ -2096,7 +2096,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
2096
2096
|
if (!socket) return;
|
|
2097
2097
|
socket.send(call.data);
|
|
2098
2098
|
while (socket.buffered > SEND_BUFFER && sockets.has(call.nid)) {
|
|
2099
|
-
await new Promise((
|
|
2099
|
+
await new Promise((resolve2) => setTimeout(resolve2, 10));
|
|
2100
2100
|
}
|
|
2101
2101
|
peer.postMessage({ net: "ws-acked", nid: call.nid, n: payloadSize(call.data) });
|
|
2102
2102
|
};
|
|
@@ -3404,11 +3404,11 @@ var RemoteWatch = class {
|
|
|
3404
3404
|
const seq2 = ++this.seq;
|
|
3405
3405
|
this.channel.postMessage({ tab: this.tab, paths: this.mine, seq: seq2 });
|
|
3406
3406
|
if (this.peers.size === 0) return Promise.resolve();
|
|
3407
|
-
return new Promise((
|
|
3407
|
+
return new Promise((resolve2) => {
|
|
3408
3408
|
const done4 = () => {
|
|
3409
3409
|
clearTimeout(timer);
|
|
3410
3410
|
this.waiting.delete(seq2);
|
|
3411
|
-
|
|
3411
|
+
resolve2();
|
|
3412
3412
|
};
|
|
3413
3413
|
const timer = setTimeout(() => {
|
|
3414
3414
|
done4();
|
|
@@ -3504,7 +3504,7 @@ async function openSync(handle) {
|
|
|
3504
3504
|
const delay = SYNC_BACKOFF_MS[attempt];
|
|
3505
3505
|
if (!LOCKED.has(err?.name)) throw err;
|
|
3506
3506
|
if (delay === void 0) return void 0;
|
|
3507
|
-
await new Promise((
|
|
3507
|
+
await new Promise((resolve2) => setTimeout(resolve2, delay));
|
|
3508
3508
|
}
|
|
3509
3509
|
}
|
|
3510
3510
|
}
|
|
@@ -3957,7 +3957,7 @@ var OpfsFs = class {
|
|
|
3957
3957
|
const again = name2 === "NotReadableError" || locks && LOCKED.has(name2);
|
|
3958
3958
|
if (!again || attempt >= READ_ATTEMPTS)
|
|
3959
3959
|
throw translate(err, path, locks ? "write" : "read");
|
|
3960
|
-
await new Promise((
|
|
3960
|
+
await new Promise((resolve2) => setTimeout(resolve2, attempt * 10));
|
|
3961
3961
|
}
|
|
3962
3962
|
}
|
|
3963
3963
|
}
|
|
@@ -4014,8 +4014,8 @@ var OpfsFs = class {
|
|
|
4014
4014
|
}
|
|
4015
4015
|
async truncate(path, size) {
|
|
4016
4016
|
const handle = await this.existing(path, true);
|
|
4017
|
-
const
|
|
4018
|
-
const target =
|
|
4017
|
+
const resolve2 = this.ranged || this.remote?.watched();
|
|
4018
|
+
const target = resolve2 ? (await this.locate(path, true)).path : path;
|
|
4019
4019
|
await this.retrying(path, () => positioned(handle, (io) => io.truncate(size)), true);
|
|
4020
4020
|
this.written(target);
|
|
4021
4021
|
}
|
|
@@ -4455,12 +4455,12 @@ var PathGate = class {
|
|
|
4455
4455
|
tails = /* @__PURE__ */ new Map();
|
|
4456
4456
|
async acquire(path) {
|
|
4457
4457
|
const prev = this.tails.get(path) ?? Promise.resolve();
|
|
4458
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
4458
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
4459
4459
|
const tail = prev.then(() => promise);
|
|
4460
4460
|
this.tails.set(path, tail);
|
|
4461
4461
|
await prev;
|
|
4462
4462
|
return () => {
|
|
4463
|
-
|
|
4463
|
+
resolve2();
|
|
4464
4464
|
if (this.tails.get(path) === tail) this.tails.delete(path);
|
|
4465
4465
|
};
|
|
4466
4466
|
}
|
|
@@ -5224,7 +5224,7 @@ var CdpFacade = class {
|
|
|
5224
5224
|
const conn = await this.host(runtime);
|
|
5225
5225
|
try {
|
|
5226
5226
|
const reply = await new Promise(
|
|
5227
|
-
(
|
|
5227
|
+
(resolve2, reject) => {
|
|
5228
5228
|
const timer = setTimeout(
|
|
5229
5229
|
() => reject(new HttpError(504, "the CDP host did not answer Target.getTargets")),
|
|
5230
5230
|
this.options.listTimeout ?? LIST_TIMEOUT
|
|
@@ -5237,7 +5237,7 @@ var CdpFacade = class {
|
|
|
5237
5237
|
const parsed2 = JSON.parse(message3);
|
|
5238
5238
|
if (parsed2.id !== 1) return;
|
|
5239
5239
|
clearTimeout(timer);
|
|
5240
|
-
|
|
5240
|
+
resolve2(parsed2);
|
|
5241
5241
|
};
|
|
5242
5242
|
conn.send(JSON.stringify({ id: 1, method: "Target.getTargets" }));
|
|
5243
5243
|
}
|
|
@@ -5297,9 +5297,9 @@ var Relay = class {
|
|
|
5297
5297
|
}
|
|
5298
5298
|
async start(head) {
|
|
5299
5299
|
await this.send(head);
|
|
5300
|
-
const hostGone = new Promise((
|
|
5300
|
+
const hostGone = new Promise((resolve2) => {
|
|
5301
5301
|
this.host.onclose = (reason) => {
|
|
5302
|
-
void this.end(reason ? CLOSE.error : CLOSE.normal, reason ?? "").then(() =>
|
|
5302
|
+
void this.end(reason ? CLOSE.error : CLOSE.normal, reason ?? "").then(() => resolve2());
|
|
5303
5303
|
};
|
|
5304
5304
|
});
|
|
5305
5305
|
this.host.onmessage = (message3) => {
|
|
@@ -5313,8 +5313,8 @@ var Relay = class {
|
|
|
5313
5313
|
await Promise.race([pumping, hostGone]);
|
|
5314
5314
|
await this.writes;
|
|
5315
5315
|
let timer;
|
|
5316
|
-
const waited = new Promise((
|
|
5317
|
-
timer = setTimeout(
|
|
5316
|
+
const waited = new Promise((resolve2) => {
|
|
5317
|
+
timer = setTimeout(resolve2, this.closeWaitMs);
|
|
5318
5318
|
});
|
|
5319
5319
|
await Promise.race([pumping, waited]);
|
|
5320
5320
|
clearTimeout(timer);
|
|
@@ -5964,16 +5964,16 @@ var FreshModules = class {
|
|
|
5964
5964
|
if (head) await decide(path, head);
|
|
5965
5965
|
};
|
|
5966
5966
|
}
|
|
5967
|
-
const
|
|
5967
|
+
const bound2 = /* @__PURE__ */ new WeakMap();
|
|
5968
5968
|
return new Proxy(fs, {
|
|
5969
5969
|
get(target, key, receiver) {
|
|
5970
5970
|
if (Object.hasOwn(overrides, key)) return overrides[key];
|
|
5971
5971
|
const value = Reflect.get(target, key, receiver);
|
|
5972
5972
|
if (typeof value !== "function") return value;
|
|
5973
|
-
let method =
|
|
5973
|
+
let method = bound2.get(value);
|
|
5974
5974
|
if (method === void 0) {
|
|
5975
5975
|
method = value.bind(target);
|
|
5976
|
-
|
|
5976
|
+
bound2.set(value, method);
|
|
5977
5977
|
}
|
|
5978
5978
|
return method;
|
|
5979
5979
|
}
|
|
@@ -6302,7 +6302,7 @@ var ChildTable = class {
|
|
|
6302
6302
|
}
|
|
6303
6303
|
async nextChange(candidates, flags2, interrupt) {
|
|
6304
6304
|
let wake;
|
|
6305
|
-
const stateChange = new Promise((
|
|
6305
|
+
const stateChange = new Promise((resolve2) => wake = resolve2);
|
|
6306
6306
|
const watching = flags2.untraced || flags2.continued;
|
|
6307
6307
|
if (watching && wake) this.stateChanged.push(wake);
|
|
6308
6308
|
try {
|
|
@@ -6516,6 +6516,65 @@ var ClipboardBroker = class {
|
|
|
6516
6516
|
}
|
|
6517
6517
|
};
|
|
6518
6518
|
|
|
6519
|
+
// src/kernel/exec-ticket.ts
|
|
6520
|
+
var TICKET_ENV = "SLICC_SEALED_TICKET";
|
|
6521
|
+
var TICKET_TTL_MS = 3e4;
|
|
6522
|
+
var MAX_TICKETS = 256;
|
|
6523
|
+
var TICKET = /^[0-9a-f]{32}$/;
|
|
6524
|
+
async function argvDigest(argv) {
|
|
6525
|
+
const bytes = new TextEncoder().encode(JSON.stringify(argv));
|
|
6526
|
+
const hash = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
|
|
6527
|
+
return [...hash].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
6528
|
+
}
|
|
6529
|
+
function isStrings(value) {
|
|
6530
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
6531
|
+
}
|
|
6532
|
+
function stringRecord(value) {
|
|
6533
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
6534
|
+
const entries = Object.entries(value);
|
|
6535
|
+
return entries.every(([, v]) => typeof v === "string") ? Object.fromEntries(entries) : void 0;
|
|
6536
|
+
}
|
|
6537
|
+
var TicketBook = class {
|
|
6538
|
+
booked = /* @__PURE__ */ new Map();
|
|
6539
|
+
now;
|
|
6540
|
+
normalise = async (path) => path;
|
|
6541
|
+
constructor(now = Date.now) {
|
|
6542
|
+
this.now = now;
|
|
6543
|
+
}
|
|
6544
|
+
get size() {
|
|
6545
|
+
return this.booked.size;
|
|
6546
|
+
}
|
|
6547
|
+
async record(req, reply, pid) {
|
|
6548
|
+
const { ticket, error } = reply;
|
|
6549
|
+
if (error !== void 0 || typeof ticket !== "string" || !TICKET.test(ticket)) return;
|
|
6550
|
+
const { path, argv, cwd } = req;
|
|
6551
|
+
const entry = {
|
|
6552
|
+
pid,
|
|
6553
|
+
path: await this.normalise(path),
|
|
6554
|
+
requested: path,
|
|
6555
|
+
requestedCwd: cwd,
|
|
6556
|
+
argv: await argvDigest(argv),
|
|
6557
|
+
cwd: await this.normalise(cwd),
|
|
6558
|
+
at: this.now()
|
|
6559
|
+
};
|
|
6560
|
+
this.prune();
|
|
6561
|
+
while (this.booked.size >= MAX_TICKETS)
|
|
6562
|
+
this.booked.delete(this.booked.keys().next().value);
|
|
6563
|
+
this.booked.set(ticket, entry);
|
|
6564
|
+
}
|
|
6565
|
+
take(ticket) {
|
|
6566
|
+
const booked = this.booked.get(ticket);
|
|
6567
|
+
this.booked.delete(ticket);
|
|
6568
|
+
return booked && this.now() - booked.at < TICKET_TTL_MS ? booked : void 0;
|
|
6569
|
+
}
|
|
6570
|
+
prune() {
|
|
6571
|
+
const now = this.now();
|
|
6572
|
+
for (const [ticket, booked] of this.booked) {
|
|
6573
|
+
if (now - booked.at >= TICKET_TTL_MS) this.booked.delete(ticket);
|
|
6574
|
+
}
|
|
6575
|
+
}
|
|
6576
|
+
};
|
|
6577
|
+
|
|
6519
6578
|
// src/mount/protocol.ts
|
|
6520
6579
|
var DRIVER_PROTOCOL = [1, 2];
|
|
6521
6580
|
function driverVersionError(theirs) {
|
|
@@ -6586,7 +6645,7 @@ var DriverConnection = class _DriverConnection {
|
|
|
6586
6645
|
call(call, transfer = []) {
|
|
6587
6646
|
if (this.failure) return Promise.reject(this.failure);
|
|
6588
6647
|
const id2 = ++this.nextId;
|
|
6589
|
-
return new Promise((
|
|
6648
|
+
return new Promise((resolve2, reject) => {
|
|
6590
6649
|
const timer = unref(
|
|
6591
6650
|
setTimeout(() => {
|
|
6592
6651
|
this.waiting.delete(id2);
|
|
@@ -6599,7 +6658,7 @@ var DriverConnection = class _DriverConnection {
|
|
|
6599
6658
|
this.onFail?.(error);
|
|
6600
6659
|
}, this.timeoutMs)
|
|
6601
6660
|
);
|
|
6602
|
-
this.waiting.set(id2, { resolve, reject, timer });
|
|
6661
|
+
this.waiting.set(id2, { resolve: resolve2, reject, timer });
|
|
6603
6662
|
this.port.postMessage({ ...call, id: id2 }, transfer);
|
|
6604
6663
|
});
|
|
6605
6664
|
}
|
|
@@ -6742,8 +6801,8 @@ var HeldPaths = class extends Map {
|
|
|
6742
6801
|
this.keptHandles.delete(handle);
|
|
6743
6802
|
if (kept) this.letGo(kept);
|
|
6744
6803
|
}
|
|
6745
|
-
const
|
|
6746
|
-
if (
|
|
6804
|
+
const count2 = (this.opens.get(key) ?? 0) + (on ? 1 : -1);
|
|
6805
|
+
if (count2 > 0) this.opens.set(key, count2);
|
|
6747
6806
|
else {
|
|
6748
6807
|
this.opens.delete(key);
|
|
6749
6808
|
for (const id2 of this.handlesAt(key)) this.handles.delete(id2);
|
|
@@ -6757,8 +6816,8 @@ var HeldPaths = class extends Map {
|
|
|
6757
6816
|
return this.lastHandle;
|
|
6758
6817
|
}
|
|
6759
6818
|
holdWrite(path, on) {
|
|
6760
|
-
const
|
|
6761
|
-
if (
|
|
6819
|
+
const count2 = (this.get(path) ?? 0) + (on ? 1 : -1);
|
|
6820
|
+
if (count2 > 0) this.set(path, count2);
|
|
6762
6821
|
else {
|
|
6763
6822
|
this.delete(path);
|
|
6764
6823
|
this.revoked.delete(path);
|
|
@@ -6780,18 +6839,18 @@ var HeldPaths = class extends Map {
|
|
|
6780
6839
|
for (const path of this.keys()) if (within4(path, prefix)) this.revoked.add(path);
|
|
6781
6840
|
}
|
|
6782
6841
|
renamed(from, to) {
|
|
6783
|
-
for (const [path,
|
|
6842
|
+
for (const [path, count2] of [...this]) {
|
|
6784
6843
|
if (!within4(path, from)) continue;
|
|
6785
6844
|
const moved2 = to + path.slice(from.length);
|
|
6786
6845
|
this.delete(path);
|
|
6787
|
-
this.set(moved2, (this.get(moved2) ?? 0) +
|
|
6846
|
+
this.set(moved2, (this.get(moved2) ?? 0) + count2);
|
|
6788
6847
|
if (this.revoked.delete(path)) this.revoked.add(moved2);
|
|
6789
6848
|
}
|
|
6790
|
-
for (const [path,
|
|
6849
|
+
for (const [path, count2] of [...this.opens]) {
|
|
6791
6850
|
if (!within4(path, from)) continue;
|
|
6792
6851
|
const moved2 = to + path.slice(from.length);
|
|
6793
6852
|
this.opens.delete(path);
|
|
6794
|
-
this.opens.set(moved2, (this.opens.get(moved2) ?? 0) +
|
|
6853
|
+
this.opens.set(moved2, (this.opens.get(moved2) ?? 0) + count2);
|
|
6795
6854
|
}
|
|
6796
6855
|
for (const [id2, key] of this.handles) {
|
|
6797
6856
|
if (within4(key, from)) this.handles.set(id2, to + key.slice(from.length));
|
|
@@ -9112,7 +9171,7 @@ var AsyncOps = class {
|
|
|
9112
9171
|
this.wake();
|
|
9113
9172
|
}
|
|
9114
9173
|
sleep(timeoutMs, signal) {
|
|
9115
|
-
return new Promise((
|
|
9174
|
+
return new Promise((resolve2, reject) => {
|
|
9116
9175
|
let timer;
|
|
9117
9176
|
const cleanup = () => {
|
|
9118
9177
|
clearTimeout(timer);
|
|
@@ -9121,7 +9180,7 @@ var AsyncOps = class {
|
|
|
9121
9180
|
};
|
|
9122
9181
|
const wake = () => {
|
|
9123
9182
|
cleanup();
|
|
9124
|
-
|
|
9183
|
+
resolve2(true);
|
|
9125
9184
|
};
|
|
9126
9185
|
const abort = () => {
|
|
9127
9186
|
cleanup();
|
|
@@ -9132,7 +9191,7 @@ var AsyncOps = class {
|
|
|
9132
9191
|
if (timeoutMs !== void 0) {
|
|
9133
9192
|
timer = setTimeout(() => {
|
|
9134
9193
|
cleanup();
|
|
9135
|
-
|
|
9194
|
+
resolve2(false);
|
|
9136
9195
|
}, timeoutMs);
|
|
9137
9196
|
}
|
|
9138
9197
|
});
|
|
@@ -9216,10 +9275,10 @@ var Budget = class {
|
|
|
9216
9275
|
async acquire(n, signal) {
|
|
9217
9276
|
while (this.free < n) {
|
|
9218
9277
|
signal.throwIfAborted();
|
|
9219
|
-
await new Promise((
|
|
9278
|
+
await new Promise((resolve2) => {
|
|
9220
9279
|
const done4 = () => {
|
|
9221
9280
|
signal.removeEventListener("abort", done4);
|
|
9222
|
-
|
|
9281
|
+
resolve2();
|
|
9223
9282
|
};
|
|
9224
9283
|
this.waiters.push(done4);
|
|
9225
9284
|
signal.addEventListener("abort", done4, { once: true });
|
|
@@ -9361,14 +9420,14 @@ async function watchHangup(conn, abort, until) {
|
|
|
9361
9420
|
}
|
|
9362
9421
|
}
|
|
9363
9422
|
function untilAborted(response, signal) {
|
|
9364
|
-
return new Promise((
|
|
9423
|
+
return new Promise((resolve2, reject) => {
|
|
9365
9424
|
const onAbort = () => {
|
|
9366
9425
|
reject(signal.reason ?? new KernelError("EINTR"));
|
|
9367
9426
|
response.then((late) => late.cancel()).catch(() => void 0);
|
|
9368
9427
|
};
|
|
9369
9428
|
if (signal.aborted) return onAbort();
|
|
9370
9429
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
9371
|
-
response.then(
|
|
9430
|
+
response.then(resolve2, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
9372
9431
|
});
|
|
9373
9432
|
}
|
|
9374
9433
|
function plainResponse(status, message3) {
|
|
@@ -9401,8 +9460,8 @@ function wireCode(code) {
|
|
|
9401
9460
|
return sendableCode(code) ? code : 1011;
|
|
9402
9461
|
}
|
|
9403
9462
|
function quietly(ms) {
|
|
9404
|
-
return new Promise((
|
|
9405
|
-
AbortSignal.timeout(ms).addEventListener("abort", () =>
|
|
9463
|
+
return new Promise((resolve2) => {
|
|
9464
|
+
AbortSignal.timeout(ms).addEventListener("abort", () => resolve2(), { once: true });
|
|
9406
9465
|
});
|
|
9407
9466
|
}
|
|
9408
9467
|
var RealmProxy = class {
|
|
@@ -9500,7 +9559,7 @@ var RealmProxy = class {
|
|
|
9500
9559
|
return false;
|
|
9501
9560
|
}
|
|
9502
9561
|
const url = ctx.origin ? tunnelRequestUrl(req, ctx.origin) : requestUrl(req);
|
|
9503
|
-
const
|
|
9562
|
+
const keep2 = keepsAlive(req);
|
|
9504
9563
|
const framing = requestFraming(req.headers);
|
|
9505
9564
|
const reserve = framing.kind === "length" ? framing.length : framing.kind === "chunked" ? this.cap() : 0;
|
|
9506
9565
|
if (reserve > this.cap()) throw new HttpError(413, `request body over ${this.cap()} bytes`);
|
|
@@ -9523,7 +9582,7 @@ var RealmProxy = class {
|
|
|
9523
9582
|
} finally {
|
|
9524
9583
|
this.bodies.release(reserve);
|
|
9525
9584
|
}
|
|
9526
|
-
return await this.relay(conn, req.method, req.minor, response,
|
|
9585
|
+
return await this.relay(conn, req.method, req.minor, response, keep2);
|
|
9527
9586
|
} finally {
|
|
9528
9587
|
this.stop.signal.removeEventListener("abort", stopExchange);
|
|
9529
9588
|
abort.abort();
|
|
@@ -9571,8 +9630,8 @@ var RealmProxy = class {
|
|
|
9571
9630
|
bodiless: bodiless2
|
|
9572
9631
|
});
|
|
9573
9632
|
const chunked2 = !bodiless2 && minor >= 1;
|
|
9574
|
-
const
|
|
9575
|
-
headers.push(["Connection",
|
|
9633
|
+
const keep2 = keepAlive && (bodiless2 || chunked2);
|
|
9634
|
+
headers.push(["Connection", keep2 ? "keep-alive" : "close"]);
|
|
9576
9635
|
if (chunked2) headers.push(["Transfer-Encoding", "chunked"]);
|
|
9577
9636
|
const signal = this.stop.signal;
|
|
9578
9637
|
await conn.write(
|
|
@@ -9581,7 +9640,7 @@ var RealmProxy = class {
|
|
|
9581
9640
|
);
|
|
9582
9641
|
if (bodiless2) {
|
|
9583
9642
|
await response.cancel();
|
|
9584
|
-
return
|
|
9643
|
+
return keep2;
|
|
9585
9644
|
}
|
|
9586
9645
|
try {
|
|
9587
9646
|
for await (const piece of response.body) {
|
|
@@ -9592,7 +9651,7 @@ var RealmProxy = class {
|
|
|
9592
9651
|
return false;
|
|
9593
9652
|
}
|
|
9594
9653
|
if (chunked2) await conn.write(LAST_CHUNK, signal);
|
|
9595
|
-
return
|
|
9654
|
+
return keep2;
|
|
9596
9655
|
}
|
|
9597
9656
|
async connect(conn, incoming, req, idle) {
|
|
9598
9657
|
const target = tunnelTarget(req);
|
|
@@ -9815,10 +9874,10 @@ function header(der, at) {
|
|
|
9815
9874
|
let len = der[at + 1];
|
|
9816
9875
|
let start2 = at + 2;
|
|
9817
9876
|
if (len & 128) {
|
|
9818
|
-
const
|
|
9877
|
+
const count2 = len & 127;
|
|
9819
9878
|
len = 0;
|
|
9820
|
-
for (let i = 0; i <
|
|
9821
|
-
start2 +=
|
|
9879
|
+
for (let i = 0; i < count2; i++) len = len * 256 + der[start2 + i];
|
|
9880
|
+
start2 += count2;
|
|
9822
9881
|
}
|
|
9823
9882
|
if (start2 + len > der.length) throw new Error("truncated DER");
|
|
9824
9883
|
return [tag, start2, start2 + len];
|
|
@@ -10875,7 +10934,7 @@ var Resolver = class {
|
|
|
10875
10934
|
};
|
|
10876
10935
|
function waitFor(lookup2, signal) {
|
|
10877
10936
|
lookup2.waiters++;
|
|
10878
|
-
return new Promise((
|
|
10937
|
+
return new Promise((resolve2, reject) => {
|
|
10879
10938
|
const abort = () => {
|
|
10880
10939
|
if (--lookup2.waiters === 0) lookup2.abort.abort(new KernelError("EINTR"));
|
|
10881
10940
|
reject(new KernelError("EINTR"));
|
|
@@ -10885,7 +10944,7 @@ function waitFor(lookup2, signal) {
|
|
|
10885
10944
|
if (signal?.aborted) return;
|
|
10886
10945
|
lookup2.waiters--;
|
|
10887
10946
|
signal?.removeEventListener("abort", abort);
|
|
10888
|
-
|
|
10947
|
+
resolve2(value);
|
|
10889
10948
|
});
|
|
10890
10949
|
});
|
|
10891
10950
|
}
|
|
@@ -11066,8 +11125,8 @@ var KernelTty = class {
|
|
|
11066
11125
|
}
|
|
11067
11126
|
rubOut(n) {
|
|
11068
11127
|
const dropped2 = this.line.splice(this.line.length - n, n);
|
|
11069
|
-
const
|
|
11070
|
-
const cells =
|
|
11128
|
+
const utf83 = (this.termios.c_iflag & IUTF8) !== 0;
|
|
11129
|
+
const cells = utf83 ? dropped2.filter((b) => !isContinuation(b)).length : dropped2.length;
|
|
11071
11130
|
if (cells > 0 && this.termios.c_lflag & ECHO) {
|
|
11072
11131
|
this.output(encoder3.encode("\b \b".repeat(cells)), false);
|
|
11073
11132
|
}
|
|
@@ -11137,14 +11196,14 @@ var KernelTty = class {
|
|
|
11137
11196
|
}
|
|
11138
11197
|
changed(signal) {
|
|
11139
11198
|
if (signal?.aborted) return Promise.reject(new KernelError("EINTR"));
|
|
11140
|
-
return new Promise((
|
|
11199
|
+
return new Promise((resolve2, reject) => {
|
|
11141
11200
|
const onAbort = () => {
|
|
11142
11201
|
this.waiters = this.waiters.filter((w) => w !== waiter);
|
|
11143
11202
|
reject(new KernelError("EINTR"));
|
|
11144
11203
|
};
|
|
11145
11204
|
const waiter = () => {
|
|
11146
11205
|
signal?.removeEventListener("abort", onAbort);
|
|
11147
|
-
|
|
11206
|
+
resolve2();
|
|
11148
11207
|
};
|
|
11149
11208
|
this.waiters.push(waiter);
|
|
11150
11209
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -11153,7 +11212,7 @@ var KernelTty = class {
|
|
|
11153
11212
|
wake() {
|
|
11154
11213
|
const waiters = this.waiters;
|
|
11155
11214
|
this.waiters = [];
|
|
11156
|
-
for (const
|
|
11215
|
+
for (const resolve2 of waiters) resolve2();
|
|
11157
11216
|
}
|
|
11158
11217
|
};
|
|
11159
11218
|
|
|
@@ -11252,14 +11311,14 @@ var PtyPair = class {
|
|
|
11252
11311
|
}
|
|
11253
11312
|
changed(signal) {
|
|
11254
11313
|
if (signal?.aborted) return Promise.reject(new KernelError("EINTR"));
|
|
11255
|
-
return new Promise((
|
|
11314
|
+
return new Promise((resolve2, reject) => {
|
|
11256
11315
|
const onAbort = () => {
|
|
11257
11316
|
this.waiters = this.waiters.filter((w) => w !== waiter);
|
|
11258
11317
|
reject(new KernelError("EINTR"));
|
|
11259
11318
|
};
|
|
11260
11319
|
const waiter = () => {
|
|
11261
11320
|
signal?.removeEventListener("abort", onAbort);
|
|
11262
|
-
|
|
11321
|
+
resolve2();
|
|
11263
11322
|
};
|
|
11264
11323
|
this.waiters.push(waiter);
|
|
11265
11324
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -11268,7 +11327,7 @@ var PtyPair = class {
|
|
|
11268
11327
|
wake() {
|
|
11269
11328
|
const waiters = this.waiters;
|
|
11270
11329
|
this.waiters = [];
|
|
11271
|
-
for (const
|
|
11330
|
+
for (const resolve2 of waiters) resolve2();
|
|
11272
11331
|
}
|
|
11273
11332
|
};
|
|
11274
11333
|
var PtyTable = class {
|
|
@@ -11333,7 +11392,8 @@ function ptySyscall(req, ctx) {
|
|
|
11333
11392
|
if (!ctx.ptys) throw new KernelError("ENOENT");
|
|
11334
11393
|
const pair = ctx.ptys.get(req.n);
|
|
11335
11394
|
ttyOpenable(ctx.guard, pair.slave);
|
|
11336
|
-
const
|
|
11395
|
+
const slave = pair.openSlave();
|
|
11396
|
+
const fd = ctx.fds.install(ctx.ttyFilter?.(slave) ?? slave, 3);
|
|
11337
11397
|
if (!req.noctty) ctx.jobs?.acquireTerminal(ctx.pid, pair.slave);
|
|
11338
11398
|
return json4(fd);
|
|
11339
11399
|
}
|
|
@@ -11406,8 +11466,8 @@ async function runChild(req, deps) {
|
|
|
11406
11466
|
};
|
|
11407
11467
|
const controls = [];
|
|
11408
11468
|
const capture = () => {
|
|
11409
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
11410
|
-
const control = { shut: false, ended:
|
|
11469
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
11470
|
+
const control = { shut: false, ended: resolve2, eof: promise };
|
|
11411
11471
|
controls.push(control);
|
|
11412
11472
|
return { capture: true, max, overflow: () => stop("ENOBUFS"), control };
|
|
11413
11473
|
};
|
|
@@ -11500,7 +11560,7 @@ async function waitReady(fds, read, write, deadline, interrupted2) {
|
|
|
11500
11560
|
return file.changed === void 0 ? [] : [file.changed(round.signal).catch(() => void 0)];
|
|
11501
11561
|
});
|
|
11502
11562
|
let timer;
|
|
11503
|
-
const expiry = deadline === Number.POSITIVE_INFINITY ? [] : [new Promise((
|
|
11563
|
+
const expiry = deadline === Number.POSITIVE_INFINITY ? [] : [new Promise((resolve2) => timer = setTimeout(resolve2, deadline - Date.now()))];
|
|
11504
11564
|
try {
|
|
11505
11565
|
await Promise.race([...changes, ...expiry, interrupted2]);
|
|
11506
11566
|
} finally {
|
|
@@ -11584,10 +11644,10 @@ async function socketSyscall(req, proc) {
|
|
|
11584
11644
|
}
|
|
11585
11645
|
}
|
|
11586
11646
|
function interruptible2(dialing, signal) {
|
|
11587
|
-
return new Promise((
|
|
11647
|
+
return new Promise((resolve2, reject) => {
|
|
11588
11648
|
const abort = () => reject(new KernelError("EINTR"));
|
|
11589
11649
|
signal.addEventListener("abort", abort, { once: true });
|
|
11590
|
-
dialing.then(
|
|
11650
|
+
dialing.then(resolve2, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
11591
11651
|
});
|
|
11592
11652
|
}
|
|
11593
11653
|
function unnamed(domain) {
|
|
@@ -12434,7 +12494,7 @@ var WasmProcess = class {
|
|
|
12434
12494
|
if (this.stopped) return "stop";
|
|
12435
12495
|
this.stopped = sig;
|
|
12436
12496
|
this.stops++;
|
|
12437
|
-
this.resumed = new Promise((
|
|
12497
|
+
this.resumed = new Promise((resolve2) => this.wake = resolve2);
|
|
12438
12498
|
const blocked = this.interrupt;
|
|
12439
12499
|
this.interrupt = new AbortController();
|
|
12440
12500
|
blocked.abort();
|
|
@@ -12499,7 +12559,9 @@ var WasmProcess = class {
|
|
|
12499
12559
|
const { ptys, jobs } = this.options;
|
|
12500
12560
|
const owner = this.options.owners ? this.ttyOwner() : void 0;
|
|
12501
12561
|
const guard2 = this.guarded();
|
|
12502
|
-
|
|
12562
|
+
const { ttyFilter } = this.options;
|
|
12563
|
+
const ctx = { pid: this.pid, fds: this.fds, ptys, jobs, guard: guard2, owner, ttyFilter };
|
|
12564
|
+
return ptySyscall(req, ctx);
|
|
12503
12565
|
}
|
|
12504
12566
|
return await this.procSyscall(req, cancelled);
|
|
12505
12567
|
} catch (e) {
|
|
@@ -12674,7 +12736,8 @@ var WasmProcess = class {
|
|
|
12674
12736
|
const tty = name2 === void 0 ? this.controllingTerminal() : this.options.jobs?.terminalNamed(name2);
|
|
12675
12737
|
if (!tty) throw new KernelError("ENXIO");
|
|
12676
12738
|
if (name2 !== void 0) ttyOpenable(this.guarded(), tty);
|
|
12677
|
-
|
|
12739
|
+
const file = tty.file();
|
|
12740
|
+
return this.fds.install(this.options.ttyFilter?.(file) ?? file, 3);
|
|
12678
12741
|
}
|
|
12679
12742
|
openSealed() {
|
|
12680
12743
|
const broker = this.options.sealed;
|
|
@@ -12714,15 +12777,8 @@ var WasmProcess = class {
|
|
|
12714
12777
|
async sealedCaller() {
|
|
12715
12778
|
const shown = await this.options.identity?.();
|
|
12716
12779
|
const broker = this.options.sealed;
|
|
12717
|
-
const
|
|
12718
|
-
return
|
|
12719
|
-
pid: shown?.pid ?? this.pid,
|
|
12720
|
-
ppid: shown?.ppid ?? 0,
|
|
12721
|
-
uid: this.cred.euid,
|
|
12722
|
-
gid: this.cred.egid,
|
|
12723
|
-
...tag !== void 0 ? { tag } : {},
|
|
12724
|
-
users: broker.users
|
|
12725
|
-
};
|
|
12780
|
+
const ids = { pid: shown?.pid ?? this.pid, ppid: shown?.ppid ?? 0 };
|
|
12781
|
+
return broker.stamp(ids, this.cred, broker.tagOf(this.pid));
|
|
12726
12782
|
}
|
|
12727
12783
|
guarded() {
|
|
12728
12784
|
const { guard: guard2 } = this.options;
|
|
@@ -13230,13 +13286,13 @@ var WasmProcess = class {
|
|
|
13230
13286
|
while (this.dlLock.depth > 0 && this.dlLock.owner !== owner) {
|
|
13231
13287
|
if (this.dying) throw new KernelError("EINTR");
|
|
13232
13288
|
const interrupt = this.interrupt.signal;
|
|
13233
|
-
const gone = await new Promise((
|
|
13289
|
+
const gone = await new Promise((resolve2) => {
|
|
13234
13290
|
const waiter = {
|
|
13235
13291
|
owner,
|
|
13236
13292
|
wake: (ended) => {
|
|
13237
13293
|
this.dlLock.waiters.delete(waiter);
|
|
13238
13294
|
interrupt.removeEventListener("abort", recheck);
|
|
13239
|
-
|
|
13295
|
+
resolve2(ended);
|
|
13240
13296
|
}
|
|
13241
13297
|
};
|
|
13242
13298
|
const recheck = () => waiter.wake(false);
|
|
@@ -13492,6 +13548,7 @@ function processOptions(opts, header4, hooks, created3) {
|
|
|
13492
13548
|
...inherited(opts),
|
|
13493
13549
|
...opts.owners ? { owners: true } : {},
|
|
13494
13550
|
...opts.sealed ? { sealed: opts.sealed } : {},
|
|
13551
|
+
...opts.ttyFilter ? { ttyFilter: opts.ttyFilter } : {},
|
|
13495
13552
|
...opts.clipboard ? { clipboard: opts.clipboard, ...clipboardName(opts) } : {},
|
|
13496
13553
|
...opts.readonlyAt ? { readonlyAt: opts.readonlyAt } : {},
|
|
13497
13554
|
...opts.dac ? { guard: { dac: opts.dac, fs: opts.fs, created: created3 } } : {},
|
|
@@ -13986,6 +14043,523 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
13986
14043
|
};
|
|
13987
14044
|
}
|
|
13988
14045
|
|
|
14046
|
+
// node_modules/@ai-ecoverse/slicc-scrub/dist/index.js
|
|
14047
|
+
var FRAGMENT = 16;
|
|
14048
|
+
var MIN_VALUE = 8;
|
|
14049
|
+
var MIN_BASE64 = 8;
|
|
14050
|
+
var encoder4 = new TextEncoder();
|
|
14051
|
+
var STD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
14052
|
+
function utf82(text) {
|
|
14053
|
+
return encoder4.encode(text);
|
|
14054
|
+
}
|
|
14055
|
+
function base642(bytes, padded = true) {
|
|
14056
|
+
let out = "";
|
|
14057
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
14058
|
+
const a = bytes[i];
|
|
14059
|
+
const b = i + 1 < bytes.length ? bytes[i + 1] : 0;
|
|
14060
|
+
const c = i + 2 < bytes.length ? bytes[i + 2] : 0;
|
|
14061
|
+
const triple = a << 16 | b << 8 | c;
|
|
14062
|
+
const left = bytes.length - i;
|
|
14063
|
+
out += STD[triple >> 18 & 63] + STD[triple >> 12 & 63];
|
|
14064
|
+
out += left > 1 ? STD[triple >> 6 & 63] : padded ? "=" : "";
|
|
14065
|
+
out += left > 2 ? STD[triple & 63] : padded ? "=" : "";
|
|
14066
|
+
}
|
|
14067
|
+
return out;
|
|
14068
|
+
}
|
|
14069
|
+
function urlSafe(text) {
|
|
14070
|
+
return text.replace(/\+/g, "-").replace(/\//g, "_");
|
|
14071
|
+
}
|
|
14072
|
+
function hex2(bytes) {
|
|
14073
|
+
let out = "";
|
|
14074
|
+
for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
|
|
14075
|
+
return out;
|
|
14076
|
+
}
|
|
14077
|
+
function embedded(bytes, offset) {
|
|
14078
|
+
const shifted = new Uint8Array(offset + bytes.length);
|
|
14079
|
+
shifted.set(bytes, offset);
|
|
14080
|
+
const encoded = base642(shifted);
|
|
14081
|
+
const first = Math.ceil(8 * offset / 6);
|
|
14082
|
+
const last = Math.floor(8 * (offset + bytes.length) / 6);
|
|
14083
|
+
return encoded.slice(first, last);
|
|
14084
|
+
}
|
|
14085
|
+
function unicode(value, upper) {
|
|
14086
|
+
let out = "";
|
|
14087
|
+
for (let i = 0; i < value.length; i++) {
|
|
14088
|
+
const unit = value.charCodeAt(i);
|
|
14089
|
+
if (unit === 34) out += '\\"';
|
|
14090
|
+
else if (unit === 92) out += "\\\\";
|
|
14091
|
+
else if (unit < 32 || unit > 126) {
|
|
14092
|
+
const code = unit.toString(16).padStart(4, "0");
|
|
14093
|
+
out += `\\u${upper ? code.toUpperCase() : code}`;
|
|
14094
|
+
} else out += value[i];
|
|
14095
|
+
}
|
|
14096
|
+
return out;
|
|
14097
|
+
}
|
|
14098
|
+
function percent(value) {
|
|
14099
|
+
let component;
|
|
14100
|
+
try {
|
|
14101
|
+
component = encodeURIComponent(value);
|
|
14102
|
+
} catch {
|
|
14103
|
+
return [];
|
|
14104
|
+
}
|
|
14105
|
+
const lower = component.replace(/%[0-9A-F]{2}/g, (escape) => escape.toLowerCase());
|
|
14106
|
+
const plus = component.replace(/%20/g, "+");
|
|
14107
|
+
let form = "";
|
|
14108
|
+
for (const byte of utf82(value)) {
|
|
14109
|
+
const char = String.fromCharCode(byte);
|
|
14110
|
+
if (/[A-Za-z0-9*\-._]/.test(char)) form += char;
|
|
14111
|
+
else if (byte === 32) form += "+";
|
|
14112
|
+
else form += `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
14113
|
+
}
|
|
14114
|
+
return [component, lower, plus, form];
|
|
14115
|
+
}
|
|
14116
|
+
function html(value, apostrophe) {
|
|
14117
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, apostrophe);
|
|
14118
|
+
}
|
|
14119
|
+
function encodings(bytes) {
|
|
14120
|
+
const standard = [base642(bytes), base642(bytes, false)];
|
|
14121
|
+
for (const offset of [0, 1, 2]) {
|
|
14122
|
+
const run2 = embedded(bytes, offset);
|
|
14123
|
+
if (run2.length >= MIN_BASE64) standard.push(run2);
|
|
14124
|
+
}
|
|
14125
|
+
return [...standard, ...standard.map(urlSafe)];
|
|
14126
|
+
}
|
|
14127
|
+
function shapes(value) {
|
|
14128
|
+
const raw = utf82(value);
|
|
14129
|
+
const seen = /* @__PURE__ */ new Set([value]);
|
|
14130
|
+
const out = [];
|
|
14131
|
+
if (raw.length < FRAGMENT) out.push({ bytes: raw, form: "raw" });
|
|
14132
|
+
for (let offset = 0; raw.length >= FRAGMENT && offset + FRAGMENT <= raw.length; offset++) {
|
|
14133
|
+
out.push({ bytes: raw.subarray(offset, offset + FRAGMENT), form: "fragment", offset });
|
|
14134
|
+
}
|
|
14135
|
+
const add = (text, form) => {
|
|
14136
|
+
if (seen.has(text)) return;
|
|
14137
|
+
seen.add(text);
|
|
14138
|
+
out.push({ bytes: utf82(text), form });
|
|
14139
|
+
};
|
|
14140
|
+
const json5 = JSON.stringify(value).slice(1, -1);
|
|
14141
|
+
for (const text of [
|
|
14142
|
+
json5,
|
|
14143
|
+
json5.replace(/\//g, "\\/"),
|
|
14144
|
+
unicode(value, false),
|
|
14145
|
+
unicode(value, true)
|
|
14146
|
+
]) {
|
|
14147
|
+
add(text, "json");
|
|
14148
|
+
}
|
|
14149
|
+
for (const text of percent(value)) add(text, "percent");
|
|
14150
|
+
for (const text of [html(value, "'"), html(value, "'")]) add(text, "html");
|
|
14151
|
+
for (const text of encodings(raw)) add(text, "base64");
|
|
14152
|
+
add(hex2(raw), "hex");
|
|
14153
|
+
add(hex2(raw).toUpperCase(), "hex");
|
|
14154
|
+
return out;
|
|
14155
|
+
}
|
|
14156
|
+
function wrappable(form) {
|
|
14157
|
+
return form === "base64" || form === "hex";
|
|
14158
|
+
}
|
|
14159
|
+
var Automaton = class {
|
|
14160
|
+
edges = /* @__PURE__ */ new Map();
|
|
14161
|
+
fail = [0];
|
|
14162
|
+
depth = [0];
|
|
14163
|
+
children = [0];
|
|
14164
|
+
out = [[]];
|
|
14165
|
+
dict = [-1];
|
|
14166
|
+
lengths = [];
|
|
14167
|
+
add(bytes) {
|
|
14168
|
+
let node = 0;
|
|
14169
|
+
for (const byte of bytes) {
|
|
14170
|
+
const key = node * 256 + byte;
|
|
14171
|
+
let next2 = this.edges.get(key);
|
|
14172
|
+
if (next2 === void 0) {
|
|
14173
|
+
next2 = this.depth.length;
|
|
14174
|
+
this.edges.set(key, next2);
|
|
14175
|
+
this.fail.push(0);
|
|
14176
|
+
this.depth.push(this.depth[node] + 1);
|
|
14177
|
+
this.children.push(0);
|
|
14178
|
+
this.children[node] += 1;
|
|
14179
|
+
this.out.push([]);
|
|
14180
|
+
this.dict.push(-1);
|
|
14181
|
+
}
|
|
14182
|
+
node = next2;
|
|
14183
|
+
}
|
|
14184
|
+
const id2 = this.lengths.length;
|
|
14185
|
+
this.lengths.push(bytes.length);
|
|
14186
|
+
this.out[node].push(id2);
|
|
14187
|
+
return id2;
|
|
14188
|
+
}
|
|
14189
|
+
build() {
|
|
14190
|
+
const queue = [];
|
|
14191
|
+
const byNode = /* @__PURE__ */ new Map();
|
|
14192
|
+
for (const [key, child] of this.edges) {
|
|
14193
|
+
const parent = Math.floor(key / 256);
|
|
14194
|
+
const list = byNode.get(parent) ?? [];
|
|
14195
|
+
list.push([key % 256, child]);
|
|
14196
|
+
byNode.set(parent, list);
|
|
14197
|
+
}
|
|
14198
|
+
for (const [, child] of byNode.get(0) ?? []) queue.push(child);
|
|
14199
|
+
for (let head = 0; head < queue.length; head++) {
|
|
14200
|
+
const node = queue[head];
|
|
14201
|
+
const fallback = this.fail[node];
|
|
14202
|
+
this.dict[node] = this.out[fallback].length > 0 ? fallback : this.dict[fallback];
|
|
14203
|
+
for (const [byte, child] of byNode.get(node) ?? []) {
|
|
14204
|
+
let state = fallback;
|
|
14205
|
+
let target = this.edges.get(state * 256 + byte);
|
|
14206
|
+
while (target === void 0 && state > 0) {
|
|
14207
|
+
state = this.fail[state];
|
|
14208
|
+
target = this.edges.get(state * 256 + byte);
|
|
14209
|
+
}
|
|
14210
|
+
this.fail[child] = target ?? 0;
|
|
14211
|
+
queue.push(child);
|
|
14212
|
+
}
|
|
14213
|
+
}
|
|
14214
|
+
}
|
|
14215
|
+
step(state, byte) {
|
|
14216
|
+
let current = state;
|
|
14217
|
+
for (; ; ) {
|
|
14218
|
+
const next2 = this.edges.get(current * 256 + byte);
|
|
14219
|
+
if (next2 !== void 0) return next2;
|
|
14220
|
+
if (current === 0) return 0;
|
|
14221
|
+
current = this.fail[current];
|
|
14222
|
+
}
|
|
14223
|
+
}
|
|
14224
|
+
matches(state, visit) {
|
|
14225
|
+
for (let node = state; node > 0; node = this.dict[node]) {
|
|
14226
|
+
for (const id2 of this.out[node]) visit(id2);
|
|
14227
|
+
}
|
|
14228
|
+
}
|
|
14229
|
+
partials(state, length2, visit) {
|
|
14230
|
+
for (let node = state; node > 0; node = this.fail[node]) {
|
|
14231
|
+
if (this.children[node] > 0) visit(length2 - this.depth[node]);
|
|
14232
|
+
}
|
|
14233
|
+
}
|
|
14234
|
+
};
|
|
14235
|
+
var RANK = {
|
|
14236
|
+
raw: 0,
|
|
14237
|
+
fragment: 1,
|
|
14238
|
+
json: 2,
|
|
14239
|
+
percent: 3,
|
|
14240
|
+
html: 4,
|
|
14241
|
+
base64: 5,
|
|
14242
|
+
hex: 6,
|
|
14243
|
+
wrapped: 7
|
|
14244
|
+
};
|
|
14245
|
+
var CR2 = 13;
|
|
14246
|
+
var LF2 = 10;
|
|
14247
|
+
var EMPTY2 = new Uint8Array(0);
|
|
14248
|
+
function register(automaton, sources, ids, bytes, source) {
|
|
14249
|
+
const key = Array.from(bytes).join(",");
|
|
14250
|
+
let id2 = ids.get(key);
|
|
14251
|
+
if (id2 === void 0) {
|
|
14252
|
+
id2 = automaton.add(bytes);
|
|
14253
|
+
ids.set(key, id2);
|
|
14254
|
+
sources[id2] = [];
|
|
14255
|
+
}
|
|
14256
|
+
sources[id2].push(source);
|
|
14257
|
+
}
|
|
14258
|
+
function prepare(secrets) {
|
|
14259
|
+
const main = new Automaton();
|
|
14260
|
+
const wrap = new Automaton();
|
|
14261
|
+
const sources = [];
|
|
14262
|
+
const wrapSources = [];
|
|
14263
|
+
const ids = /* @__PURE__ */ new Map();
|
|
14264
|
+
const wrapIds = /* @__PURE__ */ new Map();
|
|
14265
|
+
const values = secrets.map((secret) => utf82(secret.value));
|
|
14266
|
+
secrets.forEach((secret, index) => {
|
|
14267
|
+
if (typeof secret.value !== "string" || values[index].length < MIN_VALUE) {
|
|
14268
|
+
throw new RangeError(`the value of ${secret.name} is shorter than ${MIN_VALUE} bytes`);
|
|
14269
|
+
}
|
|
14270
|
+
for (const shape of shapes(secret.value)) {
|
|
14271
|
+
const source = { secret: index, form: shape.form, offset: shape.offset };
|
|
14272
|
+
register(main, sources, ids, shape.bytes, source);
|
|
14273
|
+
if (wrappable(shape.form)) register(wrap, wrapSources, wrapIds, shape.bytes, source);
|
|
14274
|
+
}
|
|
14275
|
+
});
|
|
14276
|
+
main.build();
|
|
14277
|
+
wrap.build();
|
|
14278
|
+
const replacements = secrets.map((secret) => [
|
|
14279
|
+
utf82(secret.placeholder),
|
|
14280
|
+
utf82(`[redacted:${secret.name}]`)
|
|
14281
|
+
]);
|
|
14282
|
+
return { secrets, values, main, wrap, sources, wrapSources, replacements };
|
|
14283
|
+
}
|
|
14284
|
+
function better(a, b) {
|
|
14285
|
+
if (!b) return true;
|
|
14286
|
+
if (a.end !== b.end) return a.end > b.end;
|
|
14287
|
+
if (a.rank !== b.rank) return a.rank < b.rank;
|
|
14288
|
+
return a.secret < b.secret;
|
|
14289
|
+
}
|
|
14290
|
+
function resolve(c, input, start2, end, source) {
|
|
14291
|
+
if (source.form !== "fragment") {
|
|
14292
|
+
return {
|
|
14293
|
+
start: start2,
|
|
14294
|
+
end,
|
|
14295
|
+
secret: source.secret,
|
|
14296
|
+
form: source.form,
|
|
14297
|
+
rank: RANK[source.form],
|
|
14298
|
+
growing: false
|
|
14299
|
+
};
|
|
14300
|
+
}
|
|
14301
|
+
const value = c.values[source.secret];
|
|
14302
|
+
let stop = end;
|
|
14303
|
+
let at = source.offset + FRAGMENT;
|
|
14304
|
+
while (stop < input.length && at < value.length && input[stop] === value[at]) {
|
|
14305
|
+
stop++;
|
|
14306
|
+
at++;
|
|
14307
|
+
}
|
|
14308
|
+
const form = source.offset === 0 && at === value.length ? "raw" : "fragment";
|
|
14309
|
+
const growing = stop === input.length && at < value.length;
|
|
14310
|
+
return { start: start2, end: stop, secret: source.secret, form, rank: RANK[form], growing };
|
|
14311
|
+
}
|
|
14312
|
+
function keep(best, candidate) {
|
|
14313
|
+
if (better(candidate, best.get(candidate.start))) best.set(candidate.start, candidate);
|
|
14314
|
+
}
|
|
14315
|
+
function scanMain(c, input, best, partials) {
|
|
14316
|
+
let state = 0;
|
|
14317
|
+
for (let i = 0; i < input.length; i++) {
|
|
14318
|
+
state = c.main.step(state, input[i]);
|
|
14319
|
+
c.main.matches(state, (id2) => {
|
|
14320
|
+
const start2 = i + 1 - c.main.lengths[id2];
|
|
14321
|
+
for (const source of c.sources[id2]) {
|
|
14322
|
+
const candidate = resolve(c, input, start2, i + 1, source);
|
|
14323
|
+
if (candidate.growing) partials.push(candidate.start);
|
|
14324
|
+
keep(best, candidate);
|
|
14325
|
+
}
|
|
14326
|
+
});
|
|
14327
|
+
}
|
|
14328
|
+
c.main.partials(state, input.length, (start2) => partials.push(start2));
|
|
14329
|
+
}
|
|
14330
|
+
function scanWrapped(c, input, best, partials) {
|
|
14331
|
+
const map = [];
|
|
14332
|
+
for (let i = 0; i < input.length; i++) if (input[i] !== CR2 && input[i] !== LF2) map.push(i);
|
|
14333
|
+
if (map.length === input.length) return;
|
|
14334
|
+
let state = 0;
|
|
14335
|
+
for (let v = 0; v < map.length; v++) {
|
|
14336
|
+
state = c.wrap.step(state, input[map[v]]);
|
|
14337
|
+
c.wrap.matches(state, (id2) => {
|
|
14338
|
+
const first = v + 1 - c.wrap.lengths[id2];
|
|
14339
|
+
const start2 = map[first];
|
|
14340
|
+
const end = map[v] + 1;
|
|
14341
|
+
const wrapped = end - start2 !== c.wrap.lengths[id2];
|
|
14342
|
+
for (const source of c.wrapSources[id2]) {
|
|
14343
|
+
const form = wrapped ? "wrapped" : source.form;
|
|
14344
|
+
keep(best, { start: start2, end, secret: source.secret, form, rank: RANK[form], growing: false });
|
|
14345
|
+
}
|
|
14346
|
+
});
|
|
14347
|
+
}
|
|
14348
|
+
c.wrap.partials(state, map.length, (start2) => partials.push(map[start2]));
|
|
14349
|
+
}
|
|
14350
|
+
function count(c, hits, candidate) {
|
|
14351
|
+
const name2 = c.secrets[candidate.secret].name;
|
|
14352
|
+
const key = `${name2}\0${candidate.form}`;
|
|
14353
|
+
const hit = hits.get(key) ?? { name: name2, form: candidate.form, count: 0 };
|
|
14354
|
+
hit.count += 1;
|
|
14355
|
+
hits.set(key, hit);
|
|
14356
|
+
}
|
|
14357
|
+
function concat5(parts2) {
|
|
14358
|
+
let length2 = 0;
|
|
14359
|
+
for (const part of parts2) length2 += part.length;
|
|
14360
|
+
const out = new Uint8Array(length2);
|
|
14361
|
+
let at = 0;
|
|
14362
|
+
for (const part of parts2) {
|
|
14363
|
+
out.set(part, at);
|
|
14364
|
+
at += part.length;
|
|
14365
|
+
}
|
|
14366
|
+
return out;
|
|
14367
|
+
}
|
|
14368
|
+
function pass(c, input, final) {
|
|
14369
|
+
const best = /* @__PURE__ */ new Map();
|
|
14370
|
+
const partials = [];
|
|
14371
|
+
scanMain(c, input, best, partials);
|
|
14372
|
+
scanWrapped(c, input, best, partials);
|
|
14373
|
+
const holds = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
|
|
14374
|
+
const starts = [...best.keys()].sort((a, b) => a - b);
|
|
14375
|
+
const parts2 = [];
|
|
14376
|
+
const hits = /* @__PURE__ */ new Map();
|
|
14377
|
+
let pos = 0;
|
|
14378
|
+
let cut = input.length;
|
|
14379
|
+
let s = 0;
|
|
14380
|
+
let h = 0;
|
|
14381
|
+
for (; ; ) {
|
|
14382
|
+
while (s < starts.length && starts[s] < pos) s++;
|
|
14383
|
+
while (h < holds.length && holds[h] < pos) h++;
|
|
14384
|
+
const hold = h < holds.length ? holds[h] : Infinity;
|
|
14385
|
+
const next2 = s < starts.length ? starts[s] : Infinity;
|
|
14386
|
+
if (hold <= next2) {
|
|
14387
|
+
cut = Math.min(hold, input.length);
|
|
14388
|
+
break;
|
|
14389
|
+
}
|
|
14390
|
+
const candidate = best.get(next2);
|
|
14391
|
+
parts2.push(
|
|
14392
|
+
input.subarray(pos, next2),
|
|
14393
|
+
c.replacements[candidate.secret][candidate.form === "raw" ? 0 : 1]
|
|
14394
|
+
);
|
|
14395
|
+
count(c, hits, candidate);
|
|
14396
|
+
pos = candidate.end;
|
|
14397
|
+
}
|
|
14398
|
+
parts2.push(input.subarray(pos, cut));
|
|
14399
|
+
return { output: concat5(parts2), cut, hits };
|
|
14400
|
+
}
|
|
14401
|
+
function merge(into, from) {
|
|
14402
|
+
for (const [key, hit] of from) {
|
|
14403
|
+
const known = into.get(key);
|
|
14404
|
+
if (known) known.count += hit.count;
|
|
14405
|
+
else into.set(key, { ...hit });
|
|
14406
|
+
}
|
|
14407
|
+
}
|
|
14408
|
+
function compile(secrets, options = {}) {
|
|
14409
|
+
const c = prepare(secrets.map((secret) => ({ ...secret })));
|
|
14410
|
+
const decoder4 = new TextDecoder();
|
|
14411
|
+
const idleMs = options.idleMs ?? 250;
|
|
14412
|
+
const scrubBytes = (input) => {
|
|
14413
|
+
if (c.secrets.length === 0) return { bytes: input.slice(), hits: [] };
|
|
14414
|
+
const result = pass(c, input, true);
|
|
14415
|
+
return { bytes: result.output, hits: [...result.hits.values()] };
|
|
14416
|
+
};
|
|
14417
|
+
return {
|
|
14418
|
+
version: options.version ?? 0,
|
|
14419
|
+
idleMs,
|
|
14420
|
+
size: c.main.lengths.length,
|
|
14421
|
+
bytes: scrubBytes,
|
|
14422
|
+
text(input) {
|
|
14423
|
+
const { bytes, hits } = scrubBytes(utf82(input));
|
|
14424
|
+
return { text: decoder4.decode(bytes), hits };
|
|
14425
|
+
},
|
|
14426
|
+
stream() {
|
|
14427
|
+
let pending = EMPTY2;
|
|
14428
|
+
const hits = /* @__PURE__ */ new Map();
|
|
14429
|
+
const run2 = (final) => {
|
|
14430
|
+
if (c.secrets.length === 0 || pending.length === 0) {
|
|
14431
|
+
const out = pending;
|
|
14432
|
+
pending = EMPTY2;
|
|
14433
|
+
return out;
|
|
14434
|
+
}
|
|
14435
|
+
const result = pass(c, pending, final);
|
|
14436
|
+
merge(hits, result.hits);
|
|
14437
|
+
pending = pending.slice(result.cut);
|
|
14438
|
+
return result.output;
|
|
14439
|
+
};
|
|
14440
|
+
return {
|
|
14441
|
+
push(chunk2) {
|
|
14442
|
+
pending = concat5([pending, chunk2]);
|
|
14443
|
+
return run2(false);
|
|
14444
|
+
},
|
|
14445
|
+
idle() {
|
|
14446
|
+
return pending.length < FRAGMENT ? run2(true) : EMPTY2;
|
|
14447
|
+
},
|
|
14448
|
+
end() {
|
|
14449
|
+
return run2(true);
|
|
14450
|
+
},
|
|
14451
|
+
get hits() {
|
|
14452
|
+
return [...hits.values()];
|
|
14453
|
+
}
|
|
14454
|
+
};
|
|
14455
|
+
}
|
|
14456
|
+
};
|
|
14457
|
+
}
|
|
14458
|
+
|
|
14459
|
+
// src/kernel/scrub-file.ts
|
|
14460
|
+
var SCRUB_IDLE_MS = 50;
|
|
14461
|
+
var encoder5 = new TextEncoder();
|
|
14462
|
+
function scrubberOf(secrets) {
|
|
14463
|
+
const usable = secrets.filter((s) => encoder5.encode(s.value).length >= MIN_VALUE);
|
|
14464
|
+
return usable.length > 0 ? compile(usable, { idleMs: SCRUB_IDLE_MS }) : void 0;
|
|
14465
|
+
}
|
|
14466
|
+
async function writeAll2(file, bytes, signal) {
|
|
14467
|
+
const write = file.write;
|
|
14468
|
+
for (let at = 0; at < bytes.length; ) {
|
|
14469
|
+
at += await write.call(file, bytes.subarray(at), at === 0 ? signal : void 0);
|
|
14470
|
+
}
|
|
14471
|
+
}
|
|
14472
|
+
function bound(file, key) {
|
|
14473
|
+
const method = file[key];
|
|
14474
|
+
return typeof method === "function" ? { [key]: method.bind(file) } : {};
|
|
14475
|
+
}
|
|
14476
|
+
function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
14477
|
+
const file = inner.file;
|
|
14478
|
+
const stream2 = scrubber.stream();
|
|
14479
|
+
let queue = Promise.resolve();
|
|
14480
|
+
let timer;
|
|
14481
|
+
let failed3;
|
|
14482
|
+
const raise = () => {
|
|
14483
|
+
if (failed3 === void 0) return;
|
|
14484
|
+
const err = failed3;
|
|
14485
|
+
failed3 = void 0;
|
|
14486
|
+
throw err;
|
|
14487
|
+
};
|
|
14488
|
+
const enqueue = (bytes, signal) => {
|
|
14489
|
+
const next2 = queue.then(() => bytes.length > 0 ? writeAll2(file, bytes, signal) : void 0);
|
|
14490
|
+
queue = next2.catch(() => void 0);
|
|
14491
|
+
return next2;
|
|
14492
|
+
};
|
|
14493
|
+
const release = () => {
|
|
14494
|
+
timer = void 0;
|
|
14495
|
+
enqueue(stream2.idle()).catch((err) => {
|
|
14496
|
+
failed3 = err;
|
|
14497
|
+
});
|
|
14498
|
+
};
|
|
14499
|
+
return new OpenFile({
|
|
14500
|
+
...bound(file, "read"),
|
|
14501
|
+
...bound(file, "peek"),
|
|
14502
|
+
...bound(file, "poll"),
|
|
14503
|
+
...bound(file, "changed"),
|
|
14504
|
+
...bound(file, "stat"),
|
|
14505
|
+
...file.tty ? { tty: file.tty } : {},
|
|
14506
|
+
...file.clipboard ? { clipboard: file.clipboard } : {},
|
|
14507
|
+
...file.write ? {
|
|
14508
|
+
write: async (bytes, signal) => {
|
|
14509
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
14510
|
+
raise();
|
|
14511
|
+
await enqueue(stream2.push(bytes), signal);
|
|
14512
|
+
timer = setTimeout(release, idleMs);
|
|
14513
|
+
return bytes.length;
|
|
14514
|
+
}
|
|
14515
|
+
} : {},
|
|
14516
|
+
flush: async () => {
|
|
14517
|
+
await queue;
|
|
14518
|
+
raise();
|
|
14519
|
+
await file.flush?.();
|
|
14520
|
+
},
|
|
14521
|
+
close: async () => {
|
|
14522
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
14523
|
+
let failure;
|
|
14524
|
+
try {
|
|
14525
|
+
await enqueue(stream2.end());
|
|
14526
|
+
raise();
|
|
14527
|
+
} catch (err) {
|
|
14528
|
+
failure = { err };
|
|
14529
|
+
}
|
|
14530
|
+
await inner.release();
|
|
14531
|
+
if (failure) throw failure.err;
|
|
14532
|
+
}
|
|
14533
|
+
});
|
|
14534
|
+
}
|
|
14535
|
+
function scrubbedAll(file, scrubbers) {
|
|
14536
|
+
return scrubbers.reduce((inner, scrubber) => scrubbed(inner, scrubber), file);
|
|
14537
|
+
}
|
|
14538
|
+
function stdioFiles(fds) {
|
|
14539
|
+
const files = /* @__PURE__ */ new Set();
|
|
14540
|
+
for (const fd of [1, 2]) {
|
|
14541
|
+
try {
|
|
14542
|
+
files.add(fds.get(fd));
|
|
14543
|
+
} catch {
|
|
14544
|
+
}
|
|
14545
|
+
}
|
|
14546
|
+
return files;
|
|
14547
|
+
}
|
|
14548
|
+
function scrubStdio(fds, scrubber) {
|
|
14549
|
+
const wrapped = /* @__PURE__ */ new Map();
|
|
14550
|
+
const stdio = stdioFiles(fds);
|
|
14551
|
+
for (const fd of fds.numbers()) {
|
|
14552
|
+
const original = fds.get(fd);
|
|
14553
|
+
if (!stdio.has(original) && !original.file.tty) continue;
|
|
14554
|
+
const known = wrapped.get(original);
|
|
14555
|
+
const flags2 = fds.statusFlags(fd);
|
|
14556
|
+
const wrapper = known ? known.retain() : scrubbed(original.retain(), scrubber);
|
|
14557
|
+
wrapped.set(original, wrapper);
|
|
14558
|
+
fds.installAt(fd, wrapper);
|
|
14559
|
+
if (flags2 !== void 0) fds.setStatusFlags(fd, flags2);
|
|
14560
|
+
}
|
|
14561
|
+
}
|
|
14562
|
+
|
|
13989
14563
|
// src/kernel/sealed.ts
|
|
13990
14564
|
var SEALED_MAX_BYTES = 64 * 1024;
|
|
13991
14565
|
var SEALED_TIMEOUT_MS = 1e4;
|
|
@@ -13999,7 +14573,7 @@ var SEALED_OPS = /* @__PURE__ */ new Set([
|
|
|
13999
14573
|
"cancel",
|
|
14000
14574
|
"materialize"
|
|
14001
14575
|
]);
|
|
14002
|
-
var
|
|
14576
|
+
var encoder6 = new TextEncoder();
|
|
14003
14577
|
var decoder3 = new TextDecoder("utf-8", { fatal: true });
|
|
14004
14578
|
function parseSealed(bytes) {
|
|
14005
14579
|
try {
|
|
@@ -14015,11 +14589,16 @@ function parseSealed(bytes) {
|
|
|
14015
14589
|
const req = parsed2;
|
|
14016
14590
|
if (req.v !== 1 || typeof req.op !== "string" || !SEALED_OPS.has(req.op))
|
|
14017
14591
|
throw new KernelError("EINVAL");
|
|
14592
|
+
if (req.op === "materialize" && !materializable(req)) throw new KernelError("EINVAL");
|
|
14018
14593
|
return req;
|
|
14019
14594
|
} finally {
|
|
14020
14595
|
bytes.fill(0);
|
|
14021
14596
|
}
|
|
14022
14597
|
}
|
|
14598
|
+
function materializable(req) {
|
|
14599
|
+
if (req.shellGrants !== true && !isStrings(req.names)) return false;
|
|
14600
|
+
return isStrings(req.argv) && typeof req.path === "string" && typeof req.cwd === "string";
|
|
14601
|
+
}
|
|
14023
14602
|
function errorReply(code, message3) {
|
|
14024
14603
|
return { v: 1, error: { code, message: message3 } };
|
|
14025
14604
|
}
|
|
@@ -14063,12 +14642,14 @@ var SealedChannel = class {
|
|
|
14063
14642
|
const timer = setTimeout(() => control.abort("timeout"), this.broker.timeoutMs);
|
|
14064
14643
|
const req = { ...fields, v: 1, op: fields.op, caller };
|
|
14065
14644
|
const flight = { control, done: Promise.resolve() };
|
|
14066
|
-
flight.done = this.answer(req, control.signal).then((reply) => {
|
|
14645
|
+
flight.done = this.answer(req, control.signal).then(async (reply) => {
|
|
14067
14646
|
clearTimeout(timer);
|
|
14068
14647
|
gone.removeEventListener("abort", withdraw);
|
|
14648
|
+
if (reply && req.op === "materialize")
|
|
14649
|
+
await this.broker.tickets.record(req, reply, caller.pid);
|
|
14069
14650
|
if (this.inflight !== flight) return;
|
|
14070
14651
|
this.inflight = void 0;
|
|
14071
|
-
if (reply) this.reply =
|
|
14652
|
+
if (reply) this.reply = encoder6.encode(serialized(reply));
|
|
14072
14653
|
});
|
|
14073
14654
|
this.inflight = flight;
|
|
14074
14655
|
return length2;
|
|
@@ -14076,8 +14657,8 @@ var SealedChannel = class {
|
|
|
14076
14657
|
async answer(req, signal) {
|
|
14077
14658
|
const hook = this.broker.hook;
|
|
14078
14659
|
if (!hook) return errorReply("ENOTCONN", "no vault is connected");
|
|
14079
|
-
const stopped = new Promise((
|
|
14080
|
-
signal.addEventListener("abort", () =>
|
|
14660
|
+
const stopped = new Promise((resolve2) => {
|
|
14661
|
+
signal.addEventListener("abort", () => resolve2(void 0), { once: true });
|
|
14081
14662
|
});
|
|
14082
14663
|
if (signal.aborted) return void 0;
|
|
14083
14664
|
const asked = Promise.resolve().then(() => hook(req, { signal })).then(
|
|
@@ -14132,17 +14713,60 @@ var SealedChannel = class {
|
|
|
14132
14713
|
this.reply = void 0;
|
|
14133
14714
|
}
|
|
14134
14715
|
};
|
|
14716
|
+
function swapOf(reply) {
|
|
14717
|
+
if (!isRecord(reply) || reply.error !== void 0) return void 0;
|
|
14718
|
+
const values = stringRecord(reply.values);
|
|
14719
|
+
const placeholders = stringRecord(reply.placeholders);
|
|
14720
|
+
return values && placeholders ? { values, placeholders } : void 0;
|
|
14721
|
+
}
|
|
14135
14722
|
var SealedBroker = class {
|
|
14136
14723
|
hook;
|
|
14137
14724
|
users;
|
|
14138
14725
|
timeoutMs;
|
|
14139
14726
|
tagOf;
|
|
14727
|
+
tickets = new TicketBook();
|
|
14728
|
+
userOf = async () => void 0;
|
|
14140
14729
|
constructor(hook, users, timeoutMs = SEALED_TIMEOUT_MS, tagOf = () => void 0) {
|
|
14141
14730
|
this.hook = hook;
|
|
14142
14731
|
this.users = users;
|
|
14143
14732
|
this.timeoutMs = timeoutMs;
|
|
14144
14733
|
this.tagOf = tagOf;
|
|
14145
14734
|
}
|
|
14735
|
+
async stamp(ids, cred, tag) {
|
|
14736
|
+
const user = await this.userOf(cred.euid).catch(() => void 0);
|
|
14737
|
+
return {
|
|
14738
|
+
pid: ids.pid,
|
|
14739
|
+
ppid: ids.ppid,
|
|
14740
|
+
uid: cred.euid,
|
|
14741
|
+
gid: cred.egid,
|
|
14742
|
+
...user !== void 0 ? { user } : {},
|
|
14743
|
+
groups: [...cred.groups],
|
|
14744
|
+
users: this.users,
|
|
14745
|
+
...tag !== void 0 ? { tag } : {}
|
|
14746
|
+
};
|
|
14747
|
+
}
|
|
14748
|
+
async consume(fields) {
|
|
14749
|
+
const { hook } = this;
|
|
14750
|
+
if (!hook) return void 0;
|
|
14751
|
+
const control = new AbortController();
|
|
14752
|
+
const timer = setTimeout(() => control.abort("timeout"), this.timeoutMs);
|
|
14753
|
+
const stopped = new Promise((resolve2) => {
|
|
14754
|
+
control.signal.addEventListener("abort", () => resolve2(void 0), { once: true });
|
|
14755
|
+
});
|
|
14756
|
+
const req = {
|
|
14757
|
+
...fields,
|
|
14758
|
+
v: 1,
|
|
14759
|
+
op: "materializeConsume",
|
|
14760
|
+
caller: fields.stamp
|
|
14761
|
+
};
|
|
14762
|
+
try {
|
|
14763
|
+
const asked = Promise.resolve().then(() => hook(req, { signal: control.signal })).then(swapOf, () => void 0);
|
|
14764
|
+
return await Promise.race([asked, stopped]);
|
|
14765
|
+
} finally {
|
|
14766
|
+
clearTimeout(timer);
|
|
14767
|
+
control.abort("done");
|
|
14768
|
+
}
|
|
14769
|
+
}
|
|
14146
14770
|
open() {
|
|
14147
14771
|
const channel = new SealedChannel(this);
|
|
14148
14772
|
return new OpenFile({
|
|
@@ -14641,11 +15265,11 @@ function codeOf3(err) {
|
|
|
14641
15265
|
}
|
|
14642
15266
|
function wait(ms, signal) {
|
|
14643
15267
|
if (signal.aborted) return Promise.resolve();
|
|
14644
|
-
return new Promise((
|
|
15268
|
+
return new Promise((resolve2) => {
|
|
14645
15269
|
const done4 = () => {
|
|
14646
15270
|
clearTimeout(timer);
|
|
14647
15271
|
signal.removeEventListener("abort", done4);
|
|
14648
|
-
|
|
15272
|
+
resolve2();
|
|
14649
15273
|
};
|
|
14650
15274
|
const timer = setTimeout(done4, ms);
|
|
14651
15275
|
signal.addEventListener("abort", done4, { once: true });
|
|
@@ -14972,11 +15596,11 @@ async function resize(h, path, size) {
|
|
|
14972
15596
|
}
|
|
14973
15597
|
}
|
|
14974
15598
|
function sleep(ms, signal) {
|
|
14975
|
-
return new Promise((
|
|
15599
|
+
return new Promise((resolve2) => {
|
|
14976
15600
|
const done4 = () => {
|
|
14977
15601
|
clearTimeout(timer);
|
|
14978
15602
|
signal.removeEventListener("abort", done4);
|
|
14979
|
-
|
|
15603
|
+
resolve2();
|
|
14980
15604
|
};
|
|
14981
15605
|
const timer = setTimeout(done4, ms);
|
|
14982
15606
|
signal.addEventListener("abort", done4);
|
|
@@ -15059,7 +15683,7 @@ var PORT_DEAD_MS = 1e4;
|
|
|
15059
15683
|
var PORT_LINGER_MS = 1e3;
|
|
15060
15684
|
function timed(transport, ms) {
|
|
15061
15685
|
const inflight = /* @__PURE__ */ new Set();
|
|
15062
|
-
const guard2 = (name2, run2, late, expire) => new Promise((
|
|
15686
|
+
const guard2 = (name2, run2, late, expire) => new Promise((resolve2, reject) => {
|
|
15063
15687
|
let expired = false;
|
|
15064
15688
|
const running = run2();
|
|
15065
15689
|
inflight.add(running);
|
|
@@ -15076,7 +15700,7 @@ function timed(transport, ms) {
|
|
|
15076
15700
|
(value) => {
|
|
15077
15701
|
clearTimeout(timer);
|
|
15078
15702
|
if (expired) late?.(value);
|
|
15079
|
-
|
|
15703
|
+
resolve2(value);
|
|
15080
15704
|
},
|
|
15081
15705
|
(err) => {
|
|
15082
15706
|
clearTimeout(timer);
|
|
@@ -15211,7 +15835,7 @@ var PortTransport = class {
|
|
|
15211
15835
|
ask(message3, bytes = 0, transfer = []) {
|
|
15212
15836
|
const id2 = ++this.next;
|
|
15213
15837
|
if (this.dead) return Promise.reject(fsError2("ENOTCONN", this.dead));
|
|
15214
|
-
return new Promise((
|
|
15838
|
+
return new Promise((resolve2, reject) => {
|
|
15215
15839
|
const timer = setTimeout(
|
|
15216
15840
|
() => {
|
|
15217
15841
|
this.waiting.delete(id2);
|
|
@@ -15225,7 +15849,7 @@ var PortTransport = class {
|
|
|
15225
15849
|
clearTimeout(timer);
|
|
15226
15850
|
this.waiting.delete(id2);
|
|
15227
15851
|
if (reply.error) reject(fsError2(reply.error.code ?? "EIO", reply.error.message ?? ""));
|
|
15228
|
-
else
|
|
15852
|
+
else resolve2(reply);
|
|
15229
15853
|
});
|
|
15230
15854
|
try {
|
|
15231
15855
|
this.port.postMessage({ id: id2, ...message3 }, transfer);
|
|
@@ -15254,7 +15878,7 @@ var PortTransport = class {
|
|
|
15254
15878
|
this.fail("the folder's watch ended");
|
|
15255
15879
|
return Promise.resolve();
|
|
15256
15880
|
}
|
|
15257
|
-
return new Promise((
|
|
15881
|
+
return new Promise((resolve2, reject) => {
|
|
15258
15882
|
const finish = () => {
|
|
15259
15883
|
this.waiting.delete(id2);
|
|
15260
15884
|
signal.removeEventListener("abort", stop);
|
|
@@ -15265,7 +15889,7 @@ var PortTransport = class {
|
|
|
15265
15889
|
this.port.postMessage({ id: id2, op: "unwatch" });
|
|
15266
15890
|
} catch {
|
|
15267
15891
|
}
|
|
15268
|
-
|
|
15892
|
+
resolve2();
|
|
15269
15893
|
};
|
|
15270
15894
|
this.watchBeat();
|
|
15271
15895
|
this.waiting.set(id2, (reply) => {
|
|
@@ -15273,7 +15897,7 @@ var PortTransport = class {
|
|
|
15273
15897
|
if (reply.event) return onEvent(reply.event);
|
|
15274
15898
|
finish();
|
|
15275
15899
|
if (reply.error) reject(fsError2(reply.error.code ?? "ENOTCONN", reply.error.message ?? ""));
|
|
15276
|
-
else
|
|
15900
|
+
else resolve2();
|
|
15277
15901
|
});
|
|
15278
15902
|
signal.addEventListener("abort", stop, { once: true });
|
|
15279
15903
|
try {
|
|
@@ -15489,10 +16113,10 @@ var ChunkedBytes = class {
|
|
|
15489
16113
|
}
|
|
15490
16114
|
truncate(size) {
|
|
15491
16115
|
if (size < this.size) {
|
|
15492
|
-
const
|
|
15493
|
-
this.chunks.length = Math.min(this.chunks.length,
|
|
15494
|
-
const tail = this.chunks[
|
|
15495
|
-
const from = size - (
|
|
16116
|
+
const keep2 = Math.ceil(size / CHUNK3);
|
|
16117
|
+
this.chunks.length = Math.min(this.chunks.length, keep2);
|
|
16118
|
+
const tail = this.chunks[keep2 - 1];
|
|
16119
|
+
const from = size - (keep2 - 1) * CHUNK3;
|
|
15496
16120
|
if (tail && from < tail.length) tail.fill(0, from);
|
|
15497
16121
|
}
|
|
15498
16122
|
this.size = size;
|
|
@@ -15737,8 +16361,8 @@ function importedMemory(bytes) {
|
|
|
15737
16361
|
at = end;
|
|
15738
16362
|
continue;
|
|
15739
16363
|
}
|
|
15740
|
-
const
|
|
15741
|
-
for (let i = 0; i <
|
|
16364
|
+
const count2 = u32();
|
|
16365
|
+
for (let i = 0; i < count2; i++) {
|
|
15742
16366
|
const module = name2();
|
|
15743
16367
|
const field3 = name2();
|
|
15744
16368
|
const kind = bytes[at++];
|
|
@@ -16167,7 +16791,7 @@ ${lines2}
|
|
|
16167
16791
|
const withdraw = () => control.abort("withdrawn");
|
|
16168
16792
|
requester.addEventListener("abort", withdraw, { once: true });
|
|
16169
16793
|
const aborted2 = new Promise(
|
|
16170
|
-
(
|
|
16794
|
+
(resolve2) => control.signal.addEventListener("abort", () => resolve2("aborted"), { once: true })
|
|
16171
16795
|
);
|
|
16172
16796
|
try {
|
|
16173
16797
|
const answered = Promise.resolve().then(() => approve(req, { signal: control.signal })).catch(() => "deny");
|
|
@@ -16293,7 +16917,7 @@ var LAYOUT = [
|
|
|
16293
16917
|
];
|
|
16294
16918
|
var LOAD_SAMPLE_MS = 5e3;
|
|
16295
16919
|
var LOAD_WINDOWS_MS = [6e4, 3e5, 9e5];
|
|
16296
|
-
var
|
|
16920
|
+
var encoder7 = new TextEncoder();
|
|
16297
16921
|
var USERS_MODES = ["off", "report", "enforce"];
|
|
16298
16922
|
function usersMode(mode = "off") {
|
|
16299
16923
|
if (USERS_MODES.includes(mode)) return mode;
|
|
@@ -16324,6 +16948,30 @@ function shebang(head) {
|
|
|
16324
16948
|
if (head[0] !== 35 || head[1] !== 33) return void 0;
|
|
16325
16949
|
return new TextDecoder().decode(head.subarray(0, SHEBANG_MAX)).slice(2).split("\n")[0].trim().split(/[ \t]+/);
|
|
16326
16950
|
}
|
|
16951
|
+
async function rootOnly(fs, path) {
|
|
16952
|
+
const names = chain(path);
|
|
16953
|
+
for (const [i, at] of names.entries()) {
|
|
16954
|
+
const st = await fs.lstat(at).catch(() => void 0);
|
|
16955
|
+
const kind = i === names.length - 1 ? st?.isFile : st?.isDirectory;
|
|
16956
|
+
if (!kind || st?.uid !== 0 || (st.mode & 18) !== 0) return false;
|
|
16957
|
+
}
|
|
16958
|
+
return true;
|
|
16959
|
+
}
|
|
16960
|
+
function plainEnv(words2) {
|
|
16961
|
+
const next2 = words2[1];
|
|
16962
|
+
if (baseName(words2[0] ?? "") !== "env" || next2 === void 0) return false;
|
|
16963
|
+
return next2 === "-S" || !next2.startsWith("-") && !next2.includes("=");
|
|
16964
|
+
}
|
|
16965
|
+
function shebangCommand(words2) {
|
|
16966
|
+
if (!plainEnv(words2)) {
|
|
16967
|
+
const arg2 = words2.slice(1).join(" ");
|
|
16968
|
+
return { interp: words2[0], args: arg2 ? [arg2] : [] };
|
|
16969
|
+
}
|
|
16970
|
+
const split2 = words2[1] === "-S";
|
|
16971
|
+
const [interp, ...rest2] = words2.slice(split2 ? 2 : 1);
|
|
16972
|
+
const arg = rest2.join(" ");
|
|
16973
|
+
return { interp, args: split2 ? rest2 : arg ? [arg] : [] };
|
|
16974
|
+
}
|
|
16327
16975
|
function interpreter(head) {
|
|
16328
16976
|
const words2 = shebang(head);
|
|
16329
16977
|
if (!words2) return "node";
|
|
@@ -16377,7 +17025,7 @@ function childHandle(handle) {
|
|
|
16377
17025
|
onState: (listener) => handle.onState(listener)
|
|
16378
17026
|
};
|
|
16379
17027
|
}
|
|
16380
|
-
function
|
|
17028
|
+
function concat6(chunks2) {
|
|
16381
17029
|
const out = new Uint8Array(chunks2.reduce((n, chunk2) => n + chunk2.length, 0));
|
|
16382
17030
|
let offset = 0;
|
|
16383
17031
|
for (const chunk2 of chunks2) {
|
|
@@ -16463,6 +17111,7 @@ var Launcher = class {
|
|
|
16463
17111
|
usersMode;
|
|
16464
17112
|
dac;
|
|
16465
17113
|
sealed;
|
|
17114
|
+
scrubs = /* @__PURE__ */ new Map();
|
|
16466
17115
|
clipboard;
|
|
16467
17116
|
rootFs;
|
|
16468
17117
|
fileWatches;
|
|
@@ -16486,6 +17135,8 @@ var Launcher = class {
|
|
|
16486
17135
|
void 0,
|
|
16487
17136
|
(pid) => this.tagOf(pid)
|
|
16488
17137
|
);
|
|
17138
|
+
this.sealed.tickets.normalise = (path) => physicalPathAsync(this.base, path);
|
|
17139
|
+
this.sealed.userOf = async (uid) => (await this.users.lookup(uid))?.name;
|
|
16489
17140
|
if (this.owners) options.fs.trackOwners?.();
|
|
16490
17141
|
this.mounts = new MountTable({
|
|
16491
17142
|
open: (type, spec) => this.driver(type, spec),
|
|
@@ -16734,13 +17385,12 @@ var Launcher = class {
|
|
|
16734
17385
|
const binfmt = isWasm(head) ? void 0 : binfmtOf(await this.interpreters(scope), script);
|
|
16735
17386
|
const words2 = shebang(head) ?? (binfmt ? [binfmt] : void 0);
|
|
16736
17387
|
if (!words2) return void 0;
|
|
16737
|
-
|
|
16738
|
-
const [
|
|
16739
|
-
|
|
16740
|
-
const
|
|
16741
|
-
const found = interp ? await this.resolve(interp, interp, cwd, scope) : void 0;
|
|
17388
|
+
const { interp, args } = shebangCommand(words2);
|
|
17389
|
+
const passed = [...args, command ? script : file, ...argv.slice(1)];
|
|
17390
|
+
if (!interp) return void 0;
|
|
17391
|
+
const found = await this.resolve(interp, interp, cwd, scope);
|
|
16742
17392
|
if (!found) {
|
|
16743
|
-
if (
|
|
17393
|
+
if (depth >= MAX_INTERPRETERS || !await this.scriptCommand(interp, cwd, scope)) {
|
|
16744
17394
|
return void 0;
|
|
16745
17395
|
}
|
|
16746
17396
|
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
@@ -16780,6 +17430,99 @@ var Launcher = class {
|
|
|
16780
17430
|
await need(g, "exec", this.fs.resolvePath(req.cwd, file), want);
|
|
16781
17431
|
}
|
|
16782
17432
|
}
|
|
17433
|
+
async checkedPlan(req, { ppid, cred, scope }, fds) {
|
|
17434
|
+
const planned = await this.plan(req.file, req.argv, req.cwd, scope, req.argv0);
|
|
17435
|
+
try {
|
|
17436
|
+
await this.mayExec(cred, { ...req, pid: ppid }, planned);
|
|
17437
|
+
} catch (err) {
|
|
17438
|
+
await fds.closeAll();
|
|
17439
|
+
throw err.code === "EACCES" ? new SpawnError("EACCES") : err;
|
|
17440
|
+
}
|
|
17441
|
+
if (planned) return planned;
|
|
17442
|
+
await fds.closeAll();
|
|
17443
|
+
throw new SpawnError(await this.unrunnable(req.file, req.cwd, scope));
|
|
17444
|
+
}
|
|
17445
|
+
async ticketFile(req, fds) {
|
|
17446
|
+
if (req.file.startsWith("/")) return physicalPathAsync(this.base, req.file);
|
|
17447
|
+
await fds.closeAll();
|
|
17448
|
+
throw new SpawnError("EACCES");
|
|
17449
|
+
}
|
|
17450
|
+
takeTicket(req) {
|
|
17451
|
+
if (!(TICKET_ENV in req.env)) return void 0;
|
|
17452
|
+
return this.sealed.tickets.take(req.env[TICKET_ENV] ?? "") ?? null;
|
|
17453
|
+
}
|
|
17454
|
+
async redeemed(req, who, planned, fds) {
|
|
17455
|
+
if (who.booked === void 0) return { env: req.env };
|
|
17456
|
+
try {
|
|
17457
|
+
const redeemed = await this.redeem(req, who, planned);
|
|
17458
|
+
if (redeemed.scrub) scrubStdio(fds, redeemed.scrub);
|
|
17459
|
+
return redeemed;
|
|
17460
|
+
} catch {
|
|
17461
|
+
await fds.closeAll();
|
|
17462
|
+
throw new SpawnError("EACCES");
|
|
17463
|
+
}
|
|
17464
|
+
}
|
|
17465
|
+
async redeem(req, { ppid, cred, scope, booked }, planned) {
|
|
17466
|
+
const { [TICKET_ENV]: ticket = "", ...env } = req.env;
|
|
17467
|
+
const caller = this.jobs.shown(ppid);
|
|
17468
|
+
const named = typeof req.argv0 === "string" && !planned.script && !planned.target.fixed;
|
|
17469
|
+
const argv = named ? [req.argv0, ...req.argv.slice(1)] : req.argv;
|
|
17470
|
+
const exact = booked?.pid === caller && req.file === booked.path && await physicalPathAsync(this.base, req.cwd) === booked.cwd && await argvDigest(argv) === booked.argv;
|
|
17471
|
+
if (!exact) throw new SpawnError("EACCES");
|
|
17472
|
+
const { requested: path, requestedCwd: cwd, path: resolved2 } = booked;
|
|
17473
|
+
const pid = this.nextPid++;
|
|
17474
|
+
const ids = { pid: req.exec ? caller : pid, ppid: caller };
|
|
17475
|
+
const stamp = await this.sealed.stamp(ids, cred, this.tagOf(ppid));
|
|
17476
|
+
const interpreters = await this.interpreterChain(planned, booked.cwd, scope);
|
|
17477
|
+
const trusted = this.usersMode === "enforce" && await this.trustedFiles(planned, req.file, booked.cwd, scope);
|
|
17478
|
+
const swap = await this.sealed.consume({
|
|
17479
|
+
ticket,
|
|
17480
|
+
stamp,
|
|
17481
|
+
path,
|
|
17482
|
+
resolved: resolved2,
|
|
17483
|
+
argv,
|
|
17484
|
+
cwd,
|
|
17485
|
+
interpreters,
|
|
17486
|
+
trusted
|
|
17487
|
+
});
|
|
17488
|
+
if (!swap) throw new SpawnError("EACCES");
|
|
17489
|
+
const secrets = [];
|
|
17490
|
+
for (const [name2, placeholder] of Object.entries(swap.placeholders)) {
|
|
17491
|
+
const value = swap.values[name2];
|
|
17492
|
+
if (value === void 0 || env[name2] !== placeholder) continue;
|
|
17493
|
+
env[name2] = value;
|
|
17494
|
+
secrets.push({ name: name2, value, placeholder });
|
|
17495
|
+
}
|
|
17496
|
+
const scrub = scrubberOf(secrets);
|
|
17497
|
+
return { env, pid, cwd: booked.cwd, ...scrub ? { scrub } : {} };
|
|
17498
|
+
}
|
|
17499
|
+
async interpreterChain(planned, cwd, scope) {
|
|
17500
|
+
const out = [];
|
|
17501
|
+
for (const entry of planned.via ?? []) {
|
|
17502
|
+
if (entry.includes("/")) {
|
|
17503
|
+
out.push(await physicalPathAsync(this.base, this.fs.resolvePath(cwd, entry)));
|
|
17504
|
+
continue;
|
|
17505
|
+
}
|
|
17506
|
+
const script = (await this.scriptCommand(entry, cwd, scope))?.script;
|
|
17507
|
+
out.push(
|
|
17508
|
+
await physicalPathAsync(this.base, script ?? await this.commandFile(entry, cwd, scope))
|
|
17509
|
+
);
|
|
17510
|
+
}
|
|
17511
|
+
return out;
|
|
17512
|
+
}
|
|
17513
|
+
async commandFile(name2, cwd, scope) {
|
|
17514
|
+
const scoped = await this.resolve(name2, name2, cwd, scope);
|
|
17515
|
+
const system = scope === "" ? scoped : await this.resolve(name2, name2, cwd, "");
|
|
17516
|
+
if (!scoped || system?.glue === scoped.glue) return `/usr/bin/${name2}`;
|
|
17517
|
+
return scoped.glue;
|
|
17518
|
+
}
|
|
17519
|
+
async trustedFiles(planned, file, cwd, scope) {
|
|
17520
|
+
const files = await this.backingOf(planned, file, cwd, scope);
|
|
17521
|
+
for (const at of files) {
|
|
17522
|
+
if (!await rootOnly(this.base, await physicalPathAsync(this.base, at))) return false;
|
|
17523
|
+
}
|
|
17524
|
+
return true;
|
|
17525
|
+
}
|
|
16783
17526
|
async grantedCwd(caller, cwd) {
|
|
16784
17527
|
const real = await physicalPathAsync(this.base, cwd).catch(() => void 0);
|
|
16785
17528
|
return real === cwd && await this.sudoer.reachable(caller, cwd);
|
|
@@ -16798,13 +17541,15 @@ var Launcher = class {
|
|
|
16798
17541
|
}
|
|
16799
17542
|
async backing(file, cwd) {
|
|
16800
17543
|
const planned = await this.plan(file, [file], cwd, "");
|
|
16801
|
-
|
|
17544
|
+
return planned && this.backingOf(planned, file, cwd, "");
|
|
17545
|
+
}
|
|
17546
|
+
async backingOf(planned, file, cwd, scope) {
|
|
16802
17547
|
const { glue, wasm, imports } = planned.target;
|
|
16803
17548
|
const files = [glue, wasm, ...imports ? [imports] : []];
|
|
16804
17549
|
const scripts = [];
|
|
16805
17550
|
for (const name2 of [file, ...planned.via ?? []]) {
|
|
16806
17551
|
if (name2.includes("/") && !COMMAND2.test(name2)) scripts.push(this.fs.resolvePath(cwd, name2));
|
|
16807
|
-
const script = (await this.scriptCommand(name2, cwd,
|
|
17552
|
+
const script = (await this.scriptCommand(name2, cwd, scope))?.script;
|
|
16808
17553
|
if (script) scripts.push(script);
|
|
16809
17554
|
}
|
|
16810
17555
|
files.push(...scripts, ...await this.binfmtManifests(scripts));
|
|
@@ -16933,6 +17678,7 @@ var Launcher = class {
|
|
|
16933
17678
|
const seen = { ...req.env, HOSTNAME: this.hostname, cwd };
|
|
16934
17679
|
const env = { ...expandDefaults(target.env, seen), ...req.env };
|
|
16935
17680
|
for (const key of target.unset ?? []) delete env[key];
|
|
17681
|
+
delete env[TICKET_ENV];
|
|
16936
17682
|
env.HOSTNAME = this.hostname;
|
|
16937
17683
|
let program;
|
|
16938
17684
|
try {
|
|
@@ -16948,16 +17694,23 @@ var Launcher = class {
|
|
|
16948
17694
|
groupSession(pgid) {
|
|
16949
17695
|
return this.jobs.sessionOf(pgid);
|
|
16950
17696
|
}
|
|
17697
|
+
treeScrubs(pid, req) {
|
|
17698
|
+
const inherited2 = req.ppid !== void 0 ? this.scrubs.get(req.ppid) : void 0;
|
|
17699
|
+
const scrubs = req.scrub ? [...inherited2 ?? [], req.scrub] : inherited2;
|
|
17700
|
+
if (scrubs) this.scrubs.set(pid, scrubs);
|
|
17701
|
+
return scrubs;
|
|
17702
|
+
}
|
|
16951
17703
|
start(req) {
|
|
16952
17704
|
this.sampling();
|
|
16953
17705
|
if (req.pgid !== void 0 && this.jobs.sessionOf(req.pgid) === void 0) {
|
|
16954
17706
|
throw new SpawnError("ESRCH");
|
|
16955
17707
|
}
|
|
16956
|
-
const pid = this.nextPid++;
|
|
17708
|
+
const pid = req.pid ?? this.nextPid++;
|
|
17709
|
+
const scrubs = this.treeScrubs(pid, req);
|
|
16957
17710
|
const stack = this.stackFor(req.tag);
|
|
16958
17711
|
const terminal = req.fds.stdioTerminal();
|
|
16959
17712
|
const decided = req.decided ?? Promise.resolve(true);
|
|
16960
|
-
const
|
|
17713
|
+
const count2 = (byParent) => {
|
|
16961
17714
|
this.identities.asked++;
|
|
16962
17715
|
if (!byParent) this.identities.timedOut++;
|
|
16963
17716
|
};
|
|
@@ -16965,7 +17718,7 @@ var Launcher = class {
|
|
|
16965
17718
|
const handle = spawnWasmProcess({
|
|
16966
17719
|
pid,
|
|
16967
17720
|
identity: async () => {
|
|
16968
|
-
await (asked ??= decided.then(
|
|
17721
|
+
await (asked ??= decided.then(count2));
|
|
16969
17722
|
return this.identityOf(pid);
|
|
16970
17723
|
},
|
|
16971
17724
|
onSyscall: (call) => {
|
|
@@ -16979,6 +17732,7 @@ var Launcher = class {
|
|
|
16979
17732
|
...this.owners && req.program.abi === "wasi" ? { fresh: (path, umask) => this.freshModules.add(path, umask, pid) } : {},
|
|
16980
17733
|
...this.owners ? { owners: true } : {},
|
|
16981
17734
|
sealed: this.sealed,
|
|
17735
|
+
...scrubs ? { ttyFilter: (file) => scrubbedAll(file, scrubs) } : {},
|
|
16982
17736
|
clipboard: this.clipboard,
|
|
16983
17737
|
...this.dac ? { dac: this.dac } : {},
|
|
16984
17738
|
program: req.program,
|
|
@@ -17045,6 +17799,7 @@ var Launcher = class {
|
|
|
17045
17799
|
if (spent) addTimes(this.imageTimes, this.jobs.shown(pid), spent);
|
|
17046
17800
|
this.stopped.delete(pid);
|
|
17047
17801
|
this.processes.delete(pid);
|
|
17802
|
+
this.scrubs.delete(pid);
|
|
17048
17803
|
if (this.processes.size === 0) {
|
|
17049
17804
|
clearInterval(this.sampler);
|
|
17050
17805
|
this.sampler = void 0;
|
|
@@ -17216,6 +17971,7 @@ var Launcher = class {
|
|
|
17216
17971
|
}
|
|
17217
17972
|
spawner(ppid, report) {
|
|
17218
17973
|
return async (req, fds, grant) => {
|
|
17974
|
+
const booked = this.takeTicket(req);
|
|
17219
17975
|
if (grant && !await this.grantedCwd(grant.caller, req.cwd)) {
|
|
17220
17976
|
await fds.closeAll();
|
|
17221
17977
|
throw new SpawnError("EACCES");
|
|
@@ -17227,23 +17983,20 @@ var Launcher = class {
|
|
|
17227
17983
|
}
|
|
17228
17984
|
const cred = grant ? grant.cred : this.credOf(ppid);
|
|
17229
17985
|
const scope = grant ? "" : await this.scopeOf(cred.euid);
|
|
17230
|
-
const
|
|
17231
|
-
|
|
17232
|
-
|
|
17233
|
-
|
|
17234
|
-
|
|
17235
|
-
|
|
17236
|
-
|
|
17237
|
-
|
|
17238
|
-
await fds.closeAll();
|
|
17239
|
-
throw new SpawnError(await this.unrunnable(req.file, req.cwd, scope));
|
|
17240
|
-
}
|
|
17986
|
+
const file = booked === void 0 ? req.file : await this.ticketFile(req, fds);
|
|
17987
|
+
const planned = await this.checkedPlan({ ...req, file }, { ppid, cred, scope }, fds);
|
|
17988
|
+
const redeemed = await this.redeemed(
|
|
17989
|
+
{ ...req, file },
|
|
17990
|
+
{ ppid, cred, scope, booked },
|
|
17991
|
+
planned,
|
|
17992
|
+
fds
|
|
17993
|
+
);
|
|
17241
17994
|
const exec = req.exec ? { exec: true } : {};
|
|
17242
17995
|
const deciding = req.exec ? void 0 : this.undecided(ppid);
|
|
17243
17996
|
const handle = await this.launch(planned, {
|
|
17244
17997
|
...deciding ? { decided: deciding.promise } : {},
|
|
17245
|
-
env: req.env,
|
|
17246
17998
|
cwd: req.cwd,
|
|
17999
|
+
...redeemed,
|
|
17247
18000
|
fds,
|
|
17248
18001
|
report,
|
|
17249
18002
|
ppid,
|
|
@@ -17296,11 +18049,11 @@ var Launcher = class {
|
|
|
17296
18049
|
if (!waiting) return;
|
|
17297
18050
|
this.deciding.delete(ppid);
|
|
17298
18051
|
setTimeout(() => {
|
|
17299
|
-
for (const
|
|
18052
|
+
for (const resolve2 of waiting) resolve2(true);
|
|
17300
18053
|
}, 0);
|
|
17301
18054
|
}
|
|
17302
18055
|
forker(ppid, parent) {
|
|
17303
|
-
const { exec: _exec, pgid: _pgid, group: _group, ...image } = parent;
|
|
18056
|
+
const { exec: _exec, pgid: _pgid, group: _group, pid: _pid, scrub: _scrub, ...image } = parent;
|
|
17304
18057
|
return async (state, fds) => childHandle(
|
|
17305
18058
|
this.start({
|
|
17306
18059
|
...image,
|
|
@@ -17677,7 +18430,14 @@ var Launcher = class {
|
|
|
17677
18430
|
);
|
|
17678
18431
|
}
|
|
17679
18432
|
environment(cwd, extra, account) {
|
|
17680
|
-
|
|
18433
|
+
const env = {
|
|
18434
|
+
...this.env,
|
|
18435
|
+
...userEnv(account, this.pnpmHome),
|
|
18436
|
+
PWD: cwd,
|
|
18437
|
+
...extra
|
|
18438
|
+
};
|
|
18439
|
+
delete env[TICKET_ENV];
|
|
18440
|
+
return env;
|
|
17681
18441
|
}
|
|
17682
18442
|
async account(user) {
|
|
17683
18443
|
if (typeof user === "object") return user;
|
|
@@ -17773,7 +18533,7 @@ var Launcher = class {
|
|
|
17773
18533
|
},
|
|
17774
18534
|
account
|
|
17775
18535
|
);
|
|
17776
|
-
const report = (message3) => options.onData(
|
|
18536
|
+
const report = (message3) => options.onData(encoder7.encode(`${message3}\r
|
|
17777
18537
|
`));
|
|
17778
18538
|
const handle = await this.launch(planned, {
|
|
17779
18539
|
env,
|
|
@@ -17804,18 +18564,18 @@ var Launcher = class {
|
|
|
17804
18564
|
const env = this.environment(cwd, options.env, account);
|
|
17805
18565
|
const out = [];
|
|
17806
18566
|
const err = [];
|
|
17807
|
-
const
|
|
18567
|
+
const keep2 = options.collect !== false;
|
|
17808
18568
|
const collect = (chunks2, tee) => (bytes) => {
|
|
17809
|
-
if (
|
|
18569
|
+
if (keep2) chunks2.push(bytes);
|
|
17810
18570
|
tee?.(bytes);
|
|
17811
18571
|
};
|
|
17812
18572
|
const stdout = collect(out, options.onStdout);
|
|
17813
18573
|
const stderr = collect(err, options.onStderr);
|
|
17814
|
-
const report = (message3) => stderr(
|
|
18574
|
+
const report = (message3) => stderr(encoder7.encode(`${message3}
|
|
17815
18575
|
`));
|
|
17816
18576
|
if (!planned) {
|
|
17817
18577
|
report(`${file}: command not found`);
|
|
17818
|
-
return { status: NOT_FOUND, stdout:
|
|
18578
|
+
return { status: NOT_FOUND, stdout: concat6(out), stderr: concat6(err) };
|
|
17819
18579
|
}
|
|
17820
18580
|
const fds = new FdTable();
|
|
17821
18581
|
fds.installAt(0, options.stdin ? bytesSource(options.stdin) : deviceFile("null"));
|
|
@@ -17833,7 +18593,7 @@ var Launcher = class {
|
|
|
17833
18593
|
options.onStarted?.(handle.pid);
|
|
17834
18594
|
const status = await handle.exited;
|
|
17835
18595
|
const signal = handle.termsig();
|
|
17836
|
-
return { status, ...signal ? { signal } : {}, stdout:
|
|
18596
|
+
return { status, ...signal ? { signal } : {}, stdout: concat6(out), stderr: concat6(err) };
|
|
17837
18597
|
}
|
|
17838
18598
|
};
|
|
17839
18599
|
|
|
@@ -17902,10 +18662,10 @@ var Chunks = class {
|
|
|
17902
18662
|
this.grow(size);
|
|
17903
18663
|
return;
|
|
17904
18664
|
}
|
|
17905
|
-
const
|
|
17906
|
-
this.blobs.length =
|
|
17907
|
-
if (
|
|
17908
|
-
this.blobs[
|
|
18665
|
+
const keep2 = Math.ceil(size / CHUNK4);
|
|
18666
|
+
this.blobs.length = keep2;
|
|
18667
|
+
if (keep2 > 0)
|
|
18668
|
+
this.blobs[keep2 - 1] = this.blobs[keep2 - 1].slice(0, size - (keep2 - 1) * CHUNK4);
|
|
17909
18669
|
this.size = size;
|
|
17910
18670
|
}
|
|
17911
18671
|
};
|
|
@@ -18054,12 +18814,12 @@ function codeOf5(e) {
|
|
|
18054
18814
|
return typeof code === "string" ? code : void 0;
|
|
18055
18815
|
}
|
|
18056
18816
|
function probe(secure, host, port, ms) {
|
|
18057
|
-
return new Promise((
|
|
18817
|
+
return new Promise((resolve2) => {
|
|
18058
18818
|
const socket = secure ? tls({ host, port, ...isIP(host) ? {} : { servername: host } }) : tcp({ host, port });
|
|
18059
18819
|
const done4 = (code) => {
|
|
18060
18820
|
clearTimeout(timer);
|
|
18061
18821
|
socket.destroy();
|
|
18062
|
-
|
|
18822
|
+
resolve2(code);
|
|
18063
18823
|
};
|
|
18064
18824
|
const timer = setTimeout(() => done4("ETIMEDOUT"), ms);
|
|
18065
18825
|
socket.once(secure ? "secureConnect" : "connect", () => done4("EPROTO"));
|
|
@@ -18151,8 +18911,8 @@ var RemoteTransport = class {
|
|
|
18151
18911
|
}
|
|
18152
18912
|
ask(call) {
|
|
18153
18913
|
if (this.failure) return Promise.reject(this.failure);
|
|
18154
|
-
return new Promise((
|
|
18155
|
-
this.waiting.set(call.nid, { resolve, reject });
|
|
18914
|
+
return new Promise((resolve2, reject) => {
|
|
18915
|
+
this.waiting.set(call.nid, { resolve: resolve2, reject });
|
|
18156
18916
|
this.port.postMessage(call);
|
|
18157
18917
|
});
|
|
18158
18918
|
}
|
|
@@ -18332,7 +19092,7 @@ function dialStream(port, onClose) {
|
|
|
18332
19092
|
write(chunk2) {
|
|
18333
19093
|
if (closed) throw errorWithCode("EPIPE: the connection is closed");
|
|
18334
19094
|
const copy = fresh(chunk2);
|
|
18335
|
-
const acked = new Promise((
|
|
19095
|
+
const acked = new Promise((resolve2, reject) => acks.push({ resolve: resolve2, reject }));
|
|
18336
19096
|
port.postMessage(copy, [copy.buffer]);
|
|
18337
19097
|
return acked;
|
|
18338
19098
|
},
|
|
@@ -18352,7 +19112,7 @@ function dialStream(port, onClose) {
|
|
|
18352
19112
|
|
|
18353
19113
|
// src/client/loopback-fetch.ts
|
|
18354
19114
|
var OWN_HEADERS = /* @__PURE__ */ new Set(["host", "connection", "content-length", "transfer-encoding"]);
|
|
18355
|
-
var
|
|
19115
|
+
var encoder8 = new TextEncoder();
|
|
18356
19116
|
var latin12 = new TextDecoder("latin1");
|
|
18357
19117
|
var ByteSource = class {
|
|
18358
19118
|
buffered = new Uint8Array(0);
|
|
@@ -18370,7 +19130,7 @@ var ByteSource = class {
|
|
|
18370
19130
|
return true;
|
|
18371
19131
|
}
|
|
18372
19132
|
async until(marker) {
|
|
18373
|
-
const needle =
|
|
19133
|
+
const needle = encoder8.encode(marker);
|
|
18374
19134
|
for (; ; ) {
|
|
18375
19135
|
const at = indexOf(this.buffered, needle);
|
|
18376
19136
|
if (at >= 0) return this.take(at + needle.length);
|
|
@@ -18381,13 +19141,13 @@ var ByteSource = class {
|
|
|
18381
19141
|
if (this.buffered.length === 0 && !await this.more()) return void 0;
|
|
18382
19142
|
return this.take(Math.min(max, this.buffered.length));
|
|
18383
19143
|
}
|
|
18384
|
-
async exactly(
|
|
18385
|
-
while (this.buffered.length <
|
|
18386
|
-
return this.take(
|
|
19144
|
+
async exactly(count2) {
|
|
19145
|
+
while (this.buffered.length < count2) if (!await this.more()) return void 0;
|
|
19146
|
+
return this.take(count2);
|
|
18387
19147
|
}
|
|
18388
|
-
take(
|
|
18389
|
-
const out = this.buffered.slice(0,
|
|
18390
|
-
this.buffered = this.buffered.slice(
|
|
19148
|
+
take(count2) {
|
|
19149
|
+
const out = this.buffered.slice(0, count2);
|
|
19150
|
+
this.buffered = this.buffered.slice(count2);
|
|
18391
19151
|
return out;
|
|
18392
19152
|
}
|
|
18393
19153
|
};
|
|
@@ -18478,7 +19238,7 @@ async function requestBytes(request) {
|
|
|
18478
19238
|
});
|
|
18479
19239
|
if (body) lines2.push(`Content-Length: ${body.length}`);
|
|
18480
19240
|
lines2.push("Connection: close", "", "");
|
|
18481
|
-
const head =
|
|
19241
|
+
const head = encoder8.encode(lines2.join("\r\n"));
|
|
18482
19242
|
const out = new Uint8Array(head.length + (body?.length ?? 0));
|
|
18483
19243
|
out.set(head);
|
|
18484
19244
|
if (body) out.set(body, head.length);
|
|
@@ -18532,8 +19292,8 @@ var KernelCallError = class extends Error {
|
|
|
18532
19292
|
this.code = code;
|
|
18533
19293
|
}
|
|
18534
19294
|
};
|
|
18535
|
-
var
|
|
18536
|
-
var bytesOf2 = (data) => typeof data === "string" ?
|
|
19295
|
+
var encoder9 = new TextEncoder();
|
|
19296
|
+
var bytesOf2 = (data) => typeof data === "string" ? encoder9.encode(data) : data;
|
|
18537
19297
|
var UNAVAILABLE = {
|
|
18538
19298
|
manualRedirects: false,
|
|
18539
19299
|
encodedBodies: false,
|
|
@@ -18553,7 +19313,7 @@ async function holdLock(locks) {
|
|
|
18553
19313
|
await granted2.promise;
|
|
18554
19314
|
return { name: name2, release: () => held.resolve() };
|
|
18555
19315
|
}
|
|
18556
|
-
function
|
|
19316
|
+
function concat7(chunks2) {
|
|
18557
19317
|
const out = new Uint8Array(chunks2.reduce((n, c) => n + c.length, 0));
|
|
18558
19318
|
let at = 0;
|
|
18559
19319
|
for (const chunk2 of chunks2) {
|
|
@@ -18604,8 +19364,8 @@ var Channel = class {
|
|
|
18604
19364
|
const id2 = ++this.nextId;
|
|
18605
19365
|
const { failure } = this;
|
|
18606
19366
|
if (failure) return { id: id2, done: Promise.reject(failure) };
|
|
18607
|
-
const done4 = new Promise((
|
|
18608
|
-
this.pending.set(id2, { resolve, reject, ...handlers });
|
|
19367
|
+
const done4 = new Promise((resolve2, reject) => {
|
|
19368
|
+
this.pending.set(id2, { resolve: resolve2, reject, ...handlers });
|
|
18609
19369
|
this.port.postMessage({ ...call, id: id2 });
|
|
18610
19370
|
});
|
|
18611
19371
|
return { id: id2, done: done4 };
|
|
@@ -18743,7 +19503,7 @@ async function runOn(channel, argv, opts) {
|
|
|
18743
19503
|
onStderr: tee(2, onStderr)
|
|
18744
19504
|
});
|
|
18745
19505
|
const { status, signal } = await child.ended;
|
|
18746
|
-
const text = (fd) => new TextDecoder().decode(
|
|
19506
|
+
const text = (fd) => new TextDecoder().decode(concat7(chunks2[fd]));
|
|
18747
19507
|
return {
|
|
18748
19508
|
pid: child.pid,
|
|
18749
19509
|
status,
|
|
@@ -19022,10 +19782,10 @@ async function createNodeKernel(options = {}) {
|
|
|
19022
19782
|
...options.approve ? { approve: options.approve } : {}
|
|
19023
19783
|
});
|
|
19024
19784
|
await launcher.prepare();
|
|
19025
|
-
const guard2 = (work) => new Promise((
|
|
19785
|
+
const guard2 = (work) => new Promise((resolve2, reject) => {
|
|
19026
19786
|
if (terminated) return reject(new Error(TERMINATED));
|
|
19027
19787
|
pending.add(reject);
|
|
19028
|
-
work().then(
|
|
19788
|
+
work().then(resolve2, reject).finally(() => pending.delete(reject));
|
|
19029
19789
|
});
|
|
19030
19790
|
const decoder4 = new TextDecoder();
|
|
19031
19791
|
return {
|