@ai-ecoverse/slicc-kernel 1.82.0 → 1.84.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 +26 -4
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +1025 -218
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +27 -5
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +1163 -250
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +27 -5
- package/dist/process-worker.js.map +3 -3
- 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();
|
|
@@ -448,8 +448,8 @@ async function inParent(g, op, path, old = false) {
|
|
|
448
448
|
if (!old) return void await need(g, op, parentOf(path), W_OK | X_OK, DIR, path);
|
|
449
449
|
const dir = await access(g.fs, g.cred, parentOf(path), W_OK | X_OK, DIR);
|
|
450
450
|
if (dir.denied === void 0) return stickyEntry(g, op, path, dir);
|
|
451
|
-
const
|
|
452
|
-
if (!
|
|
451
|
+
const lookup3 = dir.denied === dir.path && dir.perm && permits(g.cred, dir.perm, X_OK);
|
|
452
|
+
if (!lookup3 || await present(g.fs, entryIn(dir, path), false)) deny(g, op, path);
|
|
453
453
|
}
|
|
454
454
|
async function makeIn(g, op, path) {
|
|
455
455
|
for (let dir = parentOf(path); ; dir = parentOf(dir)) {
|
|
@@ -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();
|
|
@@ -3467,10 +3467,10 @@ function translate(err, path, op = "lookup", mapped = true) {
|
|
|
3467
3467
|
var META_OPS = ["get", "update", "move", "remove", "links", "under", "all"];
|
|
3468
3468
|
function sidecar(meta) {
|
|
3469
3469
|
const pathOf = ([first]) => [first, "/"].flat().find((p) => typeof p === "string");
|
|
3470
|
-
const
|
|
3470
|
+
const guarded3 = (op) => (...args) => meta[op].apply(meta, args).catch((err) => {
|
|
3471
3471
|
throw translate(err, pathOf(args), "sidecar", false);
|
|
3472
3472
|
});
|
|
3473
|
-
return Object.fromEntries(META_OPS.map((op) => [op,
|
|
3473
|
+
return Object.fromEntries(META_OPS.map((op) => [op, guarded3(op)]));
|
|
3474
3474
|
}
|
|
3475
3475
|
function missing2(err) {
|
|
3476
3476
|
const code = err?.code;
|
|
@@ -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);
|
|
@@ -5907,9 +5907,13 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
5907
5907
|
// src/fs/fresh-modules.ts
|
|
5908
5908
|
var MAGIC = [0, 97, 115, 109];
|
|
5909
5909
|
var MAX_FRESH = 65536;
|
|
5910
|
+
var DEFAULT_UMASK = 18;
|
|
5910
5911
|
function isModule(bytes) {
|
|
5911
5912
|
return MAGIC.every((b, i) => bytes[i] === b);
|
|
5912
5913
|
}
|
|
5914
|
+
function within4(path, dir) {
|
|
5915
|
+
return path.startsWith(dir === "/" ? "/" : `${dir}/`);
|
|
5916
|
+
}
|
|
5913
5917
|
var FreshModules = class {
|
|
5914
5918
|
fresh = /* @__PURE__ */ new Map();
|
|
5915
5919
|
add(path, umask, pid) {
|
|
@@ -5917,17 +5921,40 @@ var FreshModules = class {
|
|
|
5917
5921
|
this.fresh.delete(key);
|
|
5918
5922
|
const oldest = this.fresh.size >= MAX_FRESH ? this.fresh.keys().next().value : void 0;
|
|
5919
5923
|
if (oldest !== void 0) this.fresh.delete(oldest);
|
|
5920
|
-
|
|
5924
|
+
const mask = umask & 511;
|
|
5925
|
+
this.fresh.set(key, { umask: mask, pid, added: 0, setup: mask !== DEFAULT_UMASK });
|
|
5921
5926
|
}
|
|
5922
5927
|
forget(pid) {
|
|
5923
5928
|
for (const [path, fresh2] of this.fresh) if (fresh2.pid === pid) this.fresh.delete(path);
|
|
5924
5929
|
}
|
|
5930
|
+
drop(fresh2) {
|
|
5931
|
+
for (const [key, note] of [...this.fresh]) if (note === fresh2) this.fresh.delete(key);
|
|
5932
|
+
}
|
|
5933
|
+
moved(from, to) {
|
|
5934
|
+
const source = normalizePath(from);
|
|
5935
|
+
const target = normalizePath(to);
|
|
5936
|
+
if (source === target) return;
|
|
5937
|
+
for (const key of [...this.fresh.keys()]) {
|
|
5938
|
+
if (key === target || within4(key, target)) this.fresh.delete(key);
|
|
5939
|
+
}
|
|
5940
|
+
for (const [key, fresh2] of [...this.fresh]) {
|
|
5941
|
+
if (key !== source && !within4(key, source)) continue;
|
|
5942
|
+
this.fresh.delete(key);
|
|
5943
|
+
this.fresh.set(target + key.slice(source.length), fresh2);
|
|
5944
|
+
}
|
|
5945
|
+
}
|
|
5925
5946
|
wrap(fs) {
|
|
5926
|
-
const
|
|
5947
|
+
const head = async (path) => {
|
|
5948
|
+
if (fs.pread) return fs.pread(path, 0, MAGIC.length);
|
|
5949
|
+
return (await fs.readFileBuffer(path)).subarray(0, MAGIC.length);
|
|
5950
|
+
};
|
|
5951
|
+
const decide = async (given, known) => {
|
|
5927
5952
|
const path = normalizePath(given);
|
|
5928
5953
|
const fresh2 = this.fresh.get(path);
|
|
5929
|
-
if (!fresh2
|
|
5954
|
+
if (!fresh2) return;
|
|
5955
|
+
const bytes = known && known.length >= MAGIC.length ? known : await head(path);
|
|
5930
5956
|
const want = isModule(bytes) ? 73 & ~fresh2.umask : 0;
|
|
5957
|
+
fresh2.setup = false;
|
|
5931
5958
|
if (want === fresh2.added) return;
|
|
5932
5959
|
const mode = (await fs.stat(path)).mode & 4095;
|
|
5933
5960
|
await fs.chmod(path, mode & ~fresh2.added | want);
|
|
@@ -5936,44 +5963,59 @@ var FreshModules = class {
|
|
|
5936
5963
|
const overrides = {
|
|
5937
5964
|
writeFile: async (path, content, owner) => {
|
|
5938
5965
|
await fs.writeFile(path, content, owner);
|
|
5939
|
-
|
|
5966
|
+
if (this.fresh.has(normalizePath(path))) {
|
|
5967
|
+
await decide(
|
|
5968
|
+
path,
|
|
5969
|
+
typeof content === "string" ? new TextEncoder().encode(content) : content
|
|
5970
|
+
);
|
|
5971
|
+
}
|
|
5940
5972
|
},
|
|
5941
5973
|
chmod: async (path, mode) => {
|
|
5942
5974
|
const fresh2 = this.fresh.get(normalizePath(path));
|
|
5943
|
-
|
|
5944
|
-
if (
|
|
5975
|
+
if (fresh2?.setup && (mode & 4095) === (438 & ~fresh2.umask)) fresh2.setup = false;
|
|
5976
|
+
else if (fresh2) this.drop(fresh2);
|
|
5945
5977
|
await fs.chmod(path, mode);
|
|
5946
5978
|
},
|
|
5947
5979
|
rm: async (path, options) => {
|
|
5948
|
-
this.fresh.delete(normalizePath(path));
|
|
5949
5980
|
await fs.rm(path, options);
|
|
5981
|
+
const at = normalizePath(path);
|
|
5982
|
+
for (const key of [...this.fresh.keys()]) {
|
|
5983
|
+
if (key === at || within4(key, at)) this.fresh.delete(key);
|
|
5984
|
+
}
|
|
5950
5985
|
},
|
|
5951
5986
|
rename: async (from, to) => {
|
|
5952
5987
|
await fs.rename(from, to);
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5988
|
+
this.moved(from, to);
|
|
5989
|
+
},
|
|
5990
|
+
link: async (from, to, follow2) => {
|
|
5991
|
+
await fs.link(from, to, follow2);
|
|
5992
|
+
const source = follow2 && fs.realpath ? await fs.realpath(from, true) : from;
|
|
5993
|
+
const fresh2 = this.fresh.get(normalizePath(source));
|
|
5956
5994
|
if (fresh2) this.fresh.set(normalizePath(to), fresh2);
|
|
5957
5995
|
}
|
|
5958
5996
|
};
|
|
5959
5997
|
const ranged2 = rangedOps(fs);
|
|
5960
5998
|
if (ranged2) {
|
|
5961
5999
|
overrides.pwrite = async (path, at, bytes, transfer) => {
|
|
5962
|
-
const
|
|
6000
|
+
const touches2 = at < MAGIC.length && this.fresh.has(normalizePath(path));
|
|
5963
6001
|
await ranged2.pwrite(path, at, bytes, transfer);
|
|
5964
|
-
if (
|
|
6002
|
+
if (touches2) await decide(path);
|
|
6003
|
+
};
|
|
6004
|
+
overrides.truncate = async (path, size) => {
|
|
6005
|
+
await ranged2.truncate(path, size);
|
|
6006
|
+
if (size < MAGIC.length && this.fresh.has(normalizePath(path))) await decide(path);
|
|
5965
6007
|
};
|
|
5966
6008
|
}
|
|
5967
|
-
const
|
|
6009
|
+
const bound2 = /* @__PURE__ */ new WeakMap();
|
|
5968
6010
|
return new Proxy(fs, {
|
|
5969
6011
|
get(target, key, receiver) {
|
|
5970
6012
|
if (Object.hasOwn(overrides, key)) return overrides[key];
|
|
5971
6013
|
const value = Reflect.get(target, key, receiver);
|
|
5972
6014
|
if (typeof value !== "function") return value;
|
|
5973
|
-
let method =
|
|
6015
|
+
let method = bound2.get(value);
|
|
5974
6016
|
if (method === void 0) {
|
|
5975
6017
|
method = value.bind(target);
|
|
5976
|
-
|
|
6018
|
+
bound2.set(value, method);
|
|
5977
6019
|
}
|
|
5978
6020
|
return method;
|
|
5979
6021
|
}
|
|
@@ -6302,7 +6344,7 @@ var ChildTable = class {
|
|
|
6302
6344
|
}
|
|
6303
6345
|
async nextChange(candidates, flags2, interrupt) {
|
|
6304
6346
|
let wake;
|
|
6305
|
-
const stateChange = new Promise((
|
|
6347
|
+
const stateChange = new Promise((resolve2) => wake = resolve2);
|
|
6306
6348
|
const watching = flags2.untraced || flags2.continued;
|
|
6307
6349
|
if (watching && wake) this.stateChanged.push(wake);
|
|
6308
6350
|
try {
|
|
@@ -6516,6 +6558,65 @@ var ClipboardBroker = class {
|
|
|
6516
6558
|
}
|
|
6517
6559
|
};
|
|
6518
6560
|
|
|
6561
|
+
// src/kernel/exec-ticket.ts
|
|
6562
|
+
var TICKET_ENV = "SLICC_SEALED_TICKET";
|
|
6563
|
+
var TICKET_TTL_MS = 3e4;
|
|
6564
|
+
var MAX_TICKETS = 256;
|
|
6565
|
+
var TICKET = /^[0-9a-f]{32}$/;
|
|
6566
|
+
async function argvDigest(argv) {
|
|
6567
|
+
const bytes = new TextEncoder().encode(JSON.stringify(argv));
|
|
6568
|
+
const hash = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
|
|
6569
|
+
return [...hash].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
6570
|
+
}
|
|
6571
|
+
function isStrings(value) {
|
|
6572
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
6573
|
+
}
|
|
6574
|
+
function stringRecord(value) {
|
|
6575
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
6576
|
+
const entries = Object.entries(value);
|
|
6577
|
+
return entries.every(([, v]) => typeof v === "string") ? Object.fromEntries(entries) : void 0;
|
|
6578
|
+
}
|
|
6579
|
+
var TicketBook = class {
|
|
6580
|
+
booked = /* @__PURE__ */ new Map();
|
|
6581
|
+
now;
|
|
6582
|
+
normalise = async (path) => path;
|
|
6583
|
+
constructor(now = Date.now) {
|
|
6584
|
+
this.now = now;
|
|
6585
|
+
}
|
|
6586
|
+
get size() {
|
|
6587
|
+
return this.booked.size;
|
|
6588
|
+
}
|
|
6589
|
+
async record(req, reply, pid) {
|
|
6590
|
+
const { ticket, error } = reply;
|
|
6591
|
+
if (error !== void 0 || typeof ticket !== "string" || !TICKET.test(ticket)) return;
|
|
6592
|
+
const { path, argv, cwd } = req;
|
|
6593
|
+
const entry = {
|
|
6594
|
+
pid,
|
|
6595
|
+
path: await this.normalise(path),
|
|
6596
|
+
requested: path,
|
|
6597
|
+
requestedCwd: cwd,
|
|
6598
|
+
argv: await argvDigest(argv),
|
|
6599
|
+
cwd: await this.normalise(cwd),
|
|
6600
|
+
at: this.now()
|
|
6601
|
+
};
|
|
6602
|
+
this.prune();
|
|
6603
|
+
while (this.booked.size >= MAX_TICKETS)
|
|
6604
|
+
this.booked.delete(this.booked.keys().next().value);
|
|
6605
|
+
this.booked.set(ticket, entry);
|
|
6606
|
+
}
|
|
6607
|
+
take(ticket) {
|
|
6608
|
+
const booked = this.booked.get(ticket);
|
|
6609
|
+
this.booked.delete(ticket);
|
|
6610
|
+
return booked && this.now() - booked.at < TICKET_TTL_MS ? booked : void 0;
|
|
6611
|
+
}
|
|
6612
|
+
prune() {
|
|
6613
|
+
const now = this.now();
|
|
6614
|
+
for (const [ticket, booked] of this.booked) {
|
|
6615
|
+
if (now - booked.at >= TICKET_TTL_MS) this.booked.delete(ticket);
|
|
6616
|
+
}
|
|
6617
|
+
}
|
|
6618
|
+
};
|
|
6619
|
+
|
|
6519
6620
|
// src/mount/protocol.ts
|
|
6520
6621
|
var DRIVER_PROTOCOL = [1, 2];
|
|
6521
6622
|
function driverVersionError(theirs) {
|
|
@@ -6586,7 +6687,7 @@ var DriverConnection = class _DriverConnection {
|
|
|
6586
6687
|
call(call, transfer = []) {
|
|
6587
6688
|
if (this.failure) return Promise.reject(this.failure);
|
|
6588
6689
|
const id2 = ++this.nextId;
|
|
6589
|
-
return new Promise((
|
|
6690
|
+
return new Promise((resolve2, reject) => {
|
|
6590
6691
|
const timer = unref(
|
|
6591
6692
|
setTimeout(() => {
|
|
6592
6693
|
this.waiting.delete(id2);
|
|
@@ -6599,7 +6700,7 @@ var DriverConnection = class _DriverConnection {
|
|
|
6599
6700
|
this.onFail?.(error);
|
|
6600
6701
|
}, this.timeoutMs)
|
|
6601
6702
|
);
|
|
6602
|
-
this.waiting.set(id2, { resolve, reject, timer });
|
|
6703
|
+
this.waiting.set(id2, { resolve: resolve2, reject, timer });
|
|
6603
6704
|
this.port.postMessage({ ...call, id: id2 }, transfer);
|
|
6604
6705
|
});
|
|
6605
6706
|
}
|
|
@@ -6642,7 +6743,7 @@ function parseSize(text) {
|
|
|
6642
6743
|
if (!match) throw errnoError("EINVAL", `not a size: ${text}`);
|
|
6643
6744
|
return Math.floor(Number(match[1]) * UNITS[match[2].toLowerCase()]);
|
|
6644
6745
|
}
|
|
6645
|
-
var
|
|
6746
|
+
var within5 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
6646
6747
|
var HeldSet = class extends Set {
|
|
6647
6748
|
idle;
|
|
6648
6749
|
constructor(idle) {
|
|
@@ -6661,7 +6762,7 @@ var HeldSet = class extends Set {
|
|
|
6661
6762
|
}
|
|
6662
6763
|
};
|
|
6663
6764
|
function heldUnder(held, target) {
|
|
6664
|
-
for (const paths of held) for (const path of paths.keys()) if (
|
|
6765
|
+
for (const paths of held) for (const path of paths.keys()) if (within5(path, target)) return true;
|
|
6665
6766
|
return false;
|
|
6666
6767
|
}
|
|
6667
6768
|
var HeldPaths = class extends Map {
|
|
@@ -6742,8 +6843,8 @@ var HeldPaths = class extends Map {
|
|
|
6742
6843
|
this.keptHandles.delete(handle);
|
|
6743
6844
|
if (kept) this.letGo(kept);
|
|
6744
6845
|
}
|
|
6745
|
-
const
|
|
6746
|
-
if (
|
|
6846
|
+
const count2 = (this.opens.get(key) ?? 0) + (on ? 1 : -1);
|
|
6847
|
+
if (count2 > 0) this.opens.set(key, count2);
|
|
6747
6848
|
else {
|
|
6748
6849
|
this.opens.delete(key);
|
|
6749
6850
|
for (const id2 of this.handlesAt(key)) this.handles.delete(id2);
|
|
@@ -6757,8 +6858,8 @@ var HeldPaths = class extends Map {
|
|
|
6757
6858
|
return this.lastHandle;
|
|
6758
6859
|
}
|
|
6759
6860
|
holdWrite(path, on) {
|
|
6760
|
-
const
|
|
6761
|
-
if (
|
|
6861
|
+
const count2 = (this.get(path) ?? 0) + (on ? 1 : -1);
|
|
6862
|
+
if (count2 > 0) this.set(path, count2);
|
|
6762
6863
|
else {
|
|
6763
6864
|
this.delete(path);
|
|
6764
6865
|
this.revoked.delete(path);
|
|
@@ -6777,24 +6878,24 @@ var HeldPaths = class extends Map {
|
|
|
6777
6878
|
return this.owning === path;
|
|
6778
6879
|
}
|
|
6779
6880
|
revoke(prefix) {
|
|
6780
|
-
for (const path of this.keys()) if (
|
|
6881
|
+
for (const path of this.keys()) if (within5(path, prefix)) this.revoked.add(path);
|
|
6781
6882
|
}
|
|
6782
6883
|
renamed(from, to) {
|
|
6783
|
-
for (const [path,
|
|
6784
|
-
if (!
|
|
6884
|
+
for (const [path, count2] of [...this]) {
|
|
6885
|
+
if (!within5(path, from)) continue;
|
|
6785
6886
|
const moved2 = to + path.slice(from.length);
|
|
6786
6887
|
this.delete(path);
|
|
6787
|
-
this.set(moved2, (this.get(moved2) ?? 0) +
|
|
6888
|
+
this.set(moved2, (this.get(moved2) ?? 0) + count2);
|
|
6788
6889
|
if (this.revoked.delete(path)) this.revoked.add(moved2);
|
|
6789
6890
|
}
|
|
6790
|
-
for (const [path,
|
|
6791
|
-
if (!
|
|
6891
|
+
for (const [path, count2] of [...this.opens]) {
|
|
6892
|
+
if (!within5(path, from)) continue;
|
|
6792
6893
|
const moved2 = to + path.slice(from.length);
|
|
6793
6894
|
this.opens.delete(path);
|
|
6794
|
-
this.opens.set(moved2, (this.opens.get(moved2) ?? 0) +
|
|
6895
|
+
this.opens.set(moved2, (this.opens.get(moved2) ?? 0) + count2);
|
|
6795
6896
|
}
|
|
6796
6897
|
for (const [id2, key] of this.handles) {
|
|
6797
|
-
if (
|
|
6898
|
+
if (within5(key, from)) this.handles.set(id2, to + key.slice(from.length));
|
|
6798
6899
|
}
|
|
6799
6900
|
}
|
|
6800
6901
|
isRevoked(path) {
|
|
@@ -6901,7 +7002,7 @@ var MountTable = class {
|
|
|
6901
7002
|
locate(path) {
|
|
6902
7003
|
let best;
|
|
6903
7004
|
for (const mount of this.mounts.values()) {
|
|
6904
|
-
if (
|
|
7005
|
+
if (within5(path, mount.target) && (!best || mount.target.length > best.target.length))
|
|
6905
7006
|
best = mount;
|
|
6906
7007
|
}
|
|
6907
7008
|
if (!best) return void 0;
|
|
@@ -7044,7 +7145,7 @@ var MountTable = class {
|
|
|
7044
7145
|
async commitUnder(prefix) {
|
|
7045
7146
|
const at = normalizePath(prefix);
|
|
7046
7147
|
await Promise.all(
|
|
7047
|
-
[...this.sessions.keys()].filter((p) =>
|
|
7148
|
+
[...this.sessions.keys()].filter((p) => within5(p, at)).map((p) => this.commit(p))
|
|
7048
7149
|
);
|
|
7049
7150
|
}
|
|
7050
7151
|
async commitOverlapping(real, offset, length2) {
|
|
@@ -7079,10 +7180,10 @@ var MountTable = class {
|
|
|
7079
7180
|
}
|
|
7080
7181
|
forget(mount, path) {
|
|
7081
7182
|
mount.epoch++;
|
|
7082
|
-
for (const key of [...mount.attrs.keys()]) if (
|
|
7183
|
+
for (const key of [...mount.attrs.keys()]) if (within5(key, path)) mount.attrs.delete(key);
|
|
7083
7184
|
mount.lists.delete(path);
|
|
7084
7185
|
mount.lists.delete(parentOf7(path));
|
|
7085
|
-
for (const key of [...mount.lists.keys()]) if (
|
|
7186
|
+
for (const key of [...mount.lists.keys()]) if (within5(key, path)) mount.lists.delete(key);
|
|
7086
7187
|
}
|
|
7087
7188
|
async getattr(mount, path, rel2, settled = false) {
|
|
7088
7189
|
for (let round = 1; ; round++) {
|
|
@@ -7717,6 +7818,11 @@ function statJson(s) {
|
|
|
7717
7818
|
async function readdirStat(fs, dir) {
|
|
7718
7819
|
return (await fs.readdirStat(dir)).map(([name2, stat]) => [name2, stat && statJson(stat)]);
|
|
7719
7820
|
}
|
|
7821
|
+
async function usageAt(entry, path) {
|
|
7822
|
+
if (!entry.statfs) return void 0;
|
|
7823
|
+
const real = await realTarget(entry.fs, path).catch(() => path);
|
|
7824
|
+
return entry.statfs(real);
|
|
7825
|
+
}
|
|
7720
7826
|
async function storageUsage() {
|
|
7721
7827
|
const estimate = await globalThis.navigator?.storage?.estimate?.();
|
|
7722
7828
|
if (typeof estimate?.quota !== "number") return null;
|
|
@@ -7937,8 +8043,8 @@ async function guarded(entry, path, req) {
|
|
|
7937
8043
|
await guard(g, path, req, entry.cwd);
|
|
7938
8044
|
return void 0;
|
|
7939
8045
|
} catch (err) {
|
|
7940
|
-
const
|
|
7941
|
-
return req.op === "exists" &&
|
|
8046
|
+
const refusal2 = err.code === "EACCES";
|
|
8047
|
+
return req.op === "exists" && refusal2 ? json2(false) : toErrno(err);
|
|
7942
8048
|
}
|
|
7943
8049
|
}
|
|
7944
8050
|
async function createExclusive(fs, path, owner) {
|
|
@@ -8033,7 +8139,7 @@ async function dispatchOne(entry, req) {
|
|
|
8033
8139
|
if (req.op === "hold") return await holdOp(entry, path, req);
|
|
8034
8140
|
const refused2 = await guarded(entry, path, req);
|
|
8035
8141
|
if (refused2) return refused2;
|
|
8036
|
-
if (req.op === "statfs") return json2(await entry
|
|
8142
|
+
if (req.op === "statfs") return json2(await usageAt(entry, path) ?? await storageUsage());
|
|
8037
8143
|
if (entry.revoked?.(path)) return { ok: false, errno: "EIO", message: `${path} was unmounted` };
|
|
8038
8144
|
if (req.op === "write" && req.mode === 1 || UNLINKED_OPS.has(req.op)) {
|
|
8039
8145
|
const serve = async () => run(entry, await keptOr(entry, path, req.handle), req);
|
|
@@ -9112,7 +9218,7 @@ var AsyncOps = class {
|
|
|
9112
9218
|
this.wake();
|
|
9113
9219
|
}
|
|
9114
9220
|
sleep(timeoutMs, signal) {
|
|
9115
|
-
return new Promise((
|
|
9221
|
+
return new Promise((resolve2, reject) => {
|
|
9116
9222
|
let timer;
|
|
9117
9223
|
const cleanup = () => {
|
|
9118
9224
|
clearTimeout(timer);
|
|
@@ -9121,7 +9227,7 @@ var AsyncOps = class {
|
|
|
9121
9227
|
};
|
|
9122
9228
|
const wake = () => {
|
|
9123
9229
|
cleanup();
|
|
9124
|
-
|
|
9230
|
+
resolve2(true);
|
|
9125
9231
|
};
|
|
9126
9232
|
const abort = () => {
|
|
9127
9233
|
cleanup();
|
|
@@ -9132,7 +9238,7 @@ var AsyncOps = class {
|
|
|
9132
9238
|
if (timeoutMs !== void 0) {
|
|
9133
9239
|
timer = setTimeout(() => {
|
|
9134
9240
|
cleanup();
|
|
9135
|
-
|
|
9241
|
+
resolve2(false);
|
|
9136
9242
|
}, timeoutMs);
|
|
9137
9243
|
}
|
|
9138
9244
|
});
|
|
@@ -9216,10 +9322,10 @@ var Budget = class {
|
|
|
9216
9322
|
async acquire(n, signal) {
|
|
9217
9323
|
while (this.free < n) {
|
|
9218
9324
|
signal.throwIfAborted();
|
|
9219
|
-
await new Promise((
|
|
9325
|
+
await new Promise((resolve2) => {
|
|
9220
9326
|
const done4 = () => {
|
|
9221
9327
|
signal.removeEventListener("abort", done4);
|
|
9222
|
-
|
|
9328
|
+
resolve2();
|
|
9223
9329
|
};
|
|
9224
9330
|
this.waiters.push(done4);
|
|
9225
9331
|
signal.addEventListener("abort", done4, { once: true });
|
|
@@ -9361,14 +9467,14 @@ async function watchHangup(conn, abort, until) {
|
|
|
9361
9467
|
}
|
|
9362
9468
|
}
|
|
9363
9469
|
function untilAborted(response, signal) {
|
|
9364
|
-
return new Promise((
|
|
9470
|
+
return new Promise((resolve2, reject) => {
|
|
9365
9471
|
const onAbort = () => {
|
|
9366
9472
|
reject(signal.reason ?? new KernelError("EINTR"));
|
|
9367
9473
|
response.then((late) => late.cancel()).catch(() => void 0);
|
|
9368
9474
|
};
|
|
9369
9475
|
if (signal.aborted) return onAbort();
|
|
9370
9476
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
9371
|
-
response.then(
|
|
9477
|
+
response.then(resolve2, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
9372
9478
|
});
|
|
9373
9479
|
}
|
|
9374
9480
|
function plainResponse(status, message3) {
|
|
@@ -9401,8 +9507,8 @@ function wireCode(code) {
|
|
|
9401
9507
|
return sendableCode(code) ? code : 1011;
|
|
9402
9508
|
}
|
|
9403
9509
|
function quietly(ms) {
|
|
9404
|
-
return new Promise((
|
|
9405
|
-
AbortSignal.timeout(ms).addEventListener("abort", () =>
|
|
9510
|
+
return new Promise((resolve2) => {
|
|
9511
|
+
AbortSignal.timeout(ms).addEventListener("abort", () => resolve2(), { once: true });
|
|
9406
9512
|
});
|
|
9407
9513
|
}
|
|
9408
9514
|
var RealmProxy = class {
|
|
@@ -9500,7 +9606,7 @@ var RealmProxy = class {
|
|
|
9500
9606
|
return false;
|
|
9501
9607
|
}
|
|
9502
9608
|
const url = ctx.origin ? tunnelRequestUrl(req, ctx.origin) : requestUrl(req);
|
|
9503
|
-
const
|
|
9609
|
+
const keep2 = keepsAlive(req);
|
|
9504
9610
|
const framing = requestFraming(req.headers);
|
|
9505
9611
|
const reserve = framing.kind === "length" ? framing.length : framing.kind === "chunked" ? this.cap() : 0;
|
|
9506
9612
|
if (reserve > this.cap()) throw new HttpError(413, `request body over ${this.cap()} bytes`);
|
|
@@ -9523,7 +9629,7 @@ var RealmProxy = class {
|
|
|
9523
9629
|
} finally {
|
|
9524
9630
|
this.bodies.release(reserve);
|
|
9525
9631
|
}
|
|
9526
|
-
return await this.relay(conn, req.method, req.minor, response,
|
|
9632
|
+
return await this.relay(conn, req.method, req.minor, response, keep2);
|
|
9527
9633
|
} finally {
|
|
9528
9634
|
this.stop.signal.removeEventListener("abort", stopExchange);
|
|
9529
9635
|
abort.abort();
|
|
@@ -9571,8 +9677,8 @@ var RealmProxy = class {
|
|
|
9571
9677
|
bodiless: bodiless2
|
|
9572
9678
|
});
|
|
9573
9679
|
const chunked2 = !bodiless2 && minor >= 1;
|
|
9574
|
-
const
|
|
9575
|
-
headers.push(["Connection",
|
|
9680
|
+
const keep2 = keepAlive && (bodiless2 || chunked2);
|
|
9681
|
+
headers.push(["Connection", keep2 ? "keep-alive" : "close"]);
|
|
9576
9682
|
if (chunked2) headers.push(["Transfer-Encoding", "chunked"]);
|
|
9577
9683
|
const signal = this.stop.signal;
|
|
9578
9684
|
await conn.write(
|
|
@@ -9581,7 +9687,7 @@ var RealmProxy = class {
|
|
|
9581
9687
|
);
|
|
9582
9688
|
if (bodiless2) {
|
|
9583
9689
|
await response.cancel();
|
|
9584
|
-
return
|
|
9690
|
+
return keep2;
|
|
9585
9691
|
}
|
|
9586
9692
|
try {
|
|
9587
9693
|
for await (const piece of response.body) {
|
|
@@ -9592,7 +9698,7 @@ var RealmProxy = class {
|
|
|
9592
9698
|
return false;
|
|
9593
9699
|
}
|
|
9594
9700
|
if (chunked2) await conn.write(LAST_CHUNK, signal);
|
|
9595
|
-
return
|
|
9701
|
+
return keep2;
|
|
9596
9702
|
}
|
|
9597
9703
|
async connect(conn, incoming, req, idle) {
|
|
9598
9704
|
const target = tunnelTarget(req);
|
|
@@ -9815,10 +9921,10 @@ function header(der, at) {
|
|
|
9815
9921
|
let len = der[at + 1];
|
|
9816
9922
|
let start2 = at + 2;
|
|
9817
9923
|
if (len & 128) {
|
|
9818
|
-
const
|
|
9924
|
+
const count2 = len & 127;
|
|
9819
9925
|
len = 0;
|
|
9820
|
-
for (let i = 0; i <
|
|
9821
|
-
start2 +=
|
|
9926
|
+
for (let i = 0; i < count2; i++) len = len * 256 + der[start2 + i];
|
|
9927
|
+
start2 += count2;
|
|
9822
9928
|
}
|
|
9823
9929
|
if (start2 + len > der.length) throw new Error("truncated DER");
|
|
9824
9930
|
return [tag, start2, start2 + len];
|
|
@@ -10717,7 +10823,7 @@ function parsePrefix(text) {
|
|
|
10717
10823
|
if (length2 < 0 || length2 > max) return void 0;
|
|
10718
10824
|
return { ...parsed2, length: length2 };
|
|
10719
10825
|
}
|
|
10720
|
-
function
|
|
10826
|
+
function within6(prefix, addr) {
|
|
10721
10827
|
if (prefix.v6 !== addr.v6) return false;
|
|
10722
10828
|
const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);
|
|
10723
10829
|
return addr.bits >> shift === prefix.bits >> shift;
|
|
@@ -10757,9 +10863,9 @@ var Routes = class {
|
|
|
10757
10863
|
if (!addr) return "unreachable";
|
|
10758
10864
|
if (addr.v6 && addr.bits === 1n) return "loopback";
|
|
10759
10865
|
if (!addr.v6 && addr.bits >> 24n === 127n) return "loopback";
|
|
10760
|
-
if (RESERVED.some((p) =>
|
|
10866
|
+
if (RESERVED.some((p) => within6(p, addr))) return "reserved";
|
|
10761
10867
|
if (addr.v6 && !this.ipv6) return "unreachable";
|
|
10762
|
-
if (this.exit || this.table.some((p) =>
|
|
10868
|
+
if (this.exit || this.table.some((p) => within6(p, addr))) return "uplink";
|
|
10763
10869
|
return "unreachable";
|
|
10764
10870
|
}
|
|
10765
10871
|
};
|
|
@@ -10825,14 +10931,14 @@ var Resolver = class {
|
|
|
10825
10931
|
if (hit && hit.expires > this.now()) return hit.addresses;
|
|
10826
10932
|
const signal = blocking?.();
|
|
10827
10933
|
if (signal?.aborted) throw new KernelError("EINTR");
|
|
10828
|
-
let
|
|
10829
|
-
if (!
|
|
10934
|
+
let lookup3 = this.pending.get(id2);
|
|
10935
|
+
if (!lookup3) {
|
|
10830
10936
|
const abort = new AbortController();
|
|
10831
|
-
|
|
10832
|
-
this.pending.set(id2,
|
|
10833
|
-
void
|
|
10937
|
+
lookup3 = { work: this.lookup(key, asked, id2, abort.signal), abort, waiters: 0 };
|
|
10938
|
+
this.pending.set(id2, lookup3);
|
|
10939
|
+
void lookup3.work.then(() => this.pending.delete(id2));
|
|
10834
10940
|
}
|
|
10835
|
-
return waitFor(
|
|
10941
|
+
return waitFor(lookup3, signal);
|
|
10836
10942
|
}
|
|
10837
10943
|
async lookup(name2, family, id2, abandoned) {
|
|
10838
10944
|
const uplink = this.uplink;
|
|
@@ -10873,19 +10979,19 @@ var Resolver = class {
|
|
|
10873
10979
|
}
|
|
10874
10980
|
}
|
|
10875
10981
|
};
|
|
10876
|
-
function waitFor(
|
|
10877
|
-
|
|
10878
|
-
return new Promise((
|
|
10982
|
+
function waitFor(lookup3, signal) {
|
|
10983
|
+
lookup3.waiters++;
|
|
10984
|
+
return new Promise((resolve2, reject) => {
|
|
10879
10985
|
const abort = () => {
|
|
10880
|
-
if (--
|
|
10986
|
+
if (--lookup3.waiters === 0) lookup3.abort.abort(new KernelError("EINTR"));
|
|
10881
10987
|
reject(new KernelError("EINTR"));
|
|
10882
10988
|
};
|
|
10883
10989
|
signal?.addEventListener("abort", abort, { once: true });
|
|
10884
|
-
void
|
|
10990
|
+
void lookup3.work.then((value) => {
|
|
10885
10991
|
if (signal?.aborted) return;
|
|
10886
|
-
|
|
10992
|
+
lookup3.waiters--;
|
|
10887
10993
|
signal?.removeEventListener("abort", abort);
|
|
10888
|
-
|
|
10994
|
+
resolve2(value);
|
|
10889
10995
|
});
|
|
10890
10996
|
});
|
|
10891
10997
|
}
|
|
@@ -11066,8 +11172,8 @@ var KernelTty = class {
|
|
|
11066
11172
|
}
|
|
11067
11173
|
rubOut(n) {
|
|
11068
11174
|
const dropped2 = this.line.splice(this.line.length - n, n);
|
|
11069
|
-
const
|
|
11070
|
-
const cells =
|
|
11175
|
+
const utf83 = (this.termios.c_iflag & IUTF8) !== 0;
|
|
11176
|
+
const cells = utf83 ? dropped2.filter((b) => !isContinuation(b)).length : dropped2.length;
|
|
11071
11177
|
if (cells > 0 && this.termios.c_lflag & ECHO) {
|
|
11072
11178
|
this.output(encoder3.encode("\b \b".repeat(cells)), false);
|
|
11073
11179
|
}
|
|
@@ -11137,14 +11243,14 @@ var KernelTty = class {
|
|
|
11137
11243
|
}
|
|
11138
11244
|
changed(signal) {
|
|
11139
11245
|
if (signal?.aborted) return Promise.reject(new KernelError("EINTR"));
|
|
11140
|
-
return new Promise((
|
|
11246
|
+
return new Promise((resolve2, reject) => {
|
|
11141
11247
|
const onAbort = () => {
|
|
11142
11248
|
this.waiters = this.waiters.filter((w) => w !== waiter);
|
|
11143
11249
|
reject(new KernelError("EINTR"));
|
|
11144
11250
|
};
|
|
11145
11251
|
const waiter = () => {
|
|
11146
11252
|
signal?.removeEventListener("abort", onAbort);
|
|
11147
|
-
|
|
11253
|
+
resolve2();
|
|
11148
11254
|
};
|
|
11149
11255
|
this.waiters.push(waiter);
|
|
11150
11256
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -11153,7 +11259,7 @@ var KernelTty = class {
|
|
|
11153
11259
|
wake() {
|
|
11154
11260
|
const waiters = this.waiters;
|
|
11155
11261
|
this.waiters = [];
|
|
11156
|
-
for (const
|
|
11262
|
+
for (const resolve2 of waiters) resolve2();
|
|
11157
11263
|
}
|
|
11158
11264
|
};
|
|
11159
11265
|
|
|
@@ -11252,14 +11358,14 @@ var PtyPair = class {
|
|
|
11252
11358
|
}
|
|
11253
11359
|
changed(signal) {
|
|
11254
11360
|
if (signal?.aborted) return Promise.reject(new KernelError("EINTR"));
|
|
11255
|
-
return new Promise((
|
|
11361
|
+
return new Promise((resolve2, reject) => {
|
|
11256
11362
|
const onAbort = () => {
|
|
11257
11363
|
this.waiters = this.waiters.filter((w) => w !== waiter);
|
|
11258
11364
|
reject(new KernelError("EINTR"));
|
|
11259
11365
|
};
|
|
11260
11366
|
const waiter = () => {
|
|
11261
11367
|
signal?.removeEventListener("abort", onAbort);
|
|
11262
|
-
|
|
11368
|
+
resolve2();
|
|
11263
11369
|
};
|
|
11264
11370
|
this.waiters.push(waiter);
|
|
11265
11371
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -11268,7 +11374,7 @@ var PtyPair = class {
|
|
|
11268
11374
|
wake() {
|
|
11269
11375
|
const waiters = this.waiters;
|
|
11270
11376
|
this.waiters = [];
|
|
11271
|
-
for (const
|
|
11377
|
+
for (const resolve2 of waiters) resolve2();
|
|
11272
11378
|
}
|
|
11273
11379
|
};
|
|
11274
11380
|
var PtyTable = class {
|
|
@@ -11333,7 +11439,8 @@ function ptySyscall(req, ctx) {
|
|
|
11333
11439
|
if (!ctx.ptys) throw new KernelError("ENOENT");
|
|
11334
11440
|
const pair = ctx.ptys.get(req.n);
|
|
11335
11441
|
ttyOpenable(ctx.guard, pair.slave);
|
|
11336
|
-
const
|
|
11442
|
+
const slave = pair.openSlave();
|
|
11443
|
+
const fd = ctx.fds.install(ctx.ttyFilter?.(slave) ?? slave, 3);
|
|
11337
11444
|
if (!req.noctty) ctx.jobs?.acquireTerminal(ctx.pid, pair.slave);
|
|
11338
11445
|
return json4(fd);
|
|
11339
11446
|
}
|
|
@@ -11406,8 +11513,8 @@ async function runChild(req, deps) {
|
|
|
11406
11513
|
};
|
|
11407
11514
|
const controls = [];
|
|
11408
11515
|
const capture = () => {
|
|
11409
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
11410
|
-
const control = { shut: false, ended:
|
|
11516
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
11517
|
+
const control = { shut: false, ended: resolve2, eof: promise };
|
|
11411
11518
|
controls.push(control);
|
|
11412
11519
|
return { capture: true, max, overflow: () => stop("ENOBUFS"), control };
|
|
11413
11520
|
};
|
|
@@ -11500,7 +11607,7 @@ async function waitReady(fds, read, write, deadline, interrupted2) {
|
|
|
11500
11607
|
return file.changed === void 0 ? [] : [file.changed(round.signal).catch(() => void 0)];
|
|
11501
11608
|
});
|
|
11502
11609
|
let timer;
|
|
11503
|
-
const expiry = deadline === Number.POSITIVE_INFINITY ? [] : [new Promise((
|
|
11610
|
+
const expiry = deadline === Number.POSITIVE_INFINITY ? [] : [new Promise((resolve2) => timer = setTimeout(resolve2, deadline - Date.now()))];
|
|
11504
11611
|
try {
|
|
11505
11612
|
await Promise.race([...changes, ...expiry, interrupted2]);
|
|
11506
11613
|
} finally {
|
|
@@ -11584,10 +11691,10 @@ async function socketSyscall(req, proc) {
|
|
|
11584
11691
|
}
|
|
11585
11692
|
}
|
|
11586
11693
|
function interruptible2(dialing, signal) {
|
|
11587
|
-
return new Promise((
|
|
11694
|
+
return new Promise((resolve2, reject) => {
|
|
11588
11695
|
const abort = () => reject(new KernelError("EINTR"));
|
|
11589
11696
|
signal.addEventListener("abort", abort, { once: true });
|
|
11590
|
-
dialing.then(
|
|
11697
|
+
dialing.then(resolve2, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
11591
11698
|
});
|
|
11592
11699
|
}
|
|
11593
11700
|
function unnamed(domain) {
|
|
@@ -11614,7 +11721,7 @@ function isMissing(err) {
|
|
|
11614
11721
|
if (err?.code === "ENOENT") return true;
|
|
11615
11722
|
return err instanceof Error && err.message.startsWith("ENOENT");
|
|
11616
11723
|
}
|
|
11617
|
-
function
|
|
11724
|
+
function within7(path, root) {
|
|
11618
11725
|
return path === root || path.startsWith(root.endsWith("/") ? root : `${root}/`);
|
|
11619
11726
|
}
|
|
11620
11727
|
var VfsNode = class {
|
|
@@ -11935,12 +12042,12 @@ var VfsNodes = class {
|
|
|
11935
12042
|
return node;
|
|
11936
12043
|
}
|
|
11937
12044
|
holds(prefix) {
|
|
11938
|
-
for (const path of this.byPath.keys()) if (
|
|
12045
|
+
for (const path of this.byPath.keys()) if (within7(path, prefix)) return true;
|
|
11939
12046
|
return false;
|
|
11940
12047
|
}
|
|
11941
12048
|
writes(prefix) {
|
|
11942
12049
|
for (const [path, node] of this.byPath)
|
|
11943
|
-
if (node.writers > 0 &&
|
|
12050
|
+
if (node.writers > 0 && within7(path, prefix)) return true;
|
|
11944
12051
|
return false;
|
|
11945
12052
|
}
|
|
11946
12053
|
closed(node, writable2 = false) {
|
|
@@ -11984,11 +12091,11 @@ var VfsNodes = class {
|
|
|
11984
12091
|
this.kept.delete(node);
|
|
11985
12092
|
}
|
|
11986
12093
|
async flush(path) {
|
|
11987
|
-
for (const [p, node] of this.byPath) if (
|
|
12094
|
+
for (const [p, node] of this.byPath) if (within7(p, path)) await node.serial(() => node.flush());
|
|
11988
12095
|
}
|
|
11989
12096
|
async unlinking(path) {
|
|
11990
12097
|
for (const [held, node] of [...this.byPath]) {
|
|
11991
|
-
if (!
|
|
12098
|
+
if (!within7(held, path)) continue;
|
|
11992
12099
|
await node.serial(async () => {
|
|
11993
12100
|
await Promise.all([this.keepsOnDisk || node.keep(), node.limit()]);
|
|
11994
12101
|
});
|
|
@@ -11996,14 +12103,14 @@ var VfsNodes = class {
|
|
|
11996
12103
|
}
|
|
11997
12104
|
revoke(prefix) {
|
|
11998
12105
|
for (const [path, node] of [...this.byPath]) {
|
|
11999
|
-
if (!
|
|
12106
|
+
if (!within7(path, prefix)) continue;
|
|
12000
12107
|
node.revoke();
|
|
12001
12108
|
this.forget(node);
|
|
12002
12109
|
}
|
|
12003
12110
|
}
|
|
12004
12111
|
unlinked(path) {
|
|
12005
12112
|
for (const [held, node] of [...this.byPath]) {
|
|
12006
|
-
if (!
|
|
12113
|
+
if (!within7(held, path) || this.byPath.get(held) !== node) continue;
|
|
12007
12114
|
if (!this.dropName(held, node)) this.orphan(node);
|
|
12008
12115
|
}
|
|
12009
12116
|
}
|
|
@@ -12011,8 +12118,8 @@ var VfsNodes = class {
|
|
|
12011
12118
|
if (from === to) return;
|
|
12012
12119
|
const moved2 = [];
|
|
12013
12120
|
for (const [p, node] of [...this.byPath]) {
|
|
12014
|
-
if (
|
|
12015
|
-
else if (
|
|
12121
|
+
if (within7(p, from)) moved2.push([p, node]);
|
|
12122
|
+
else if (within7(p, to) && this.byPath.get(p) === node && !this.dropName(p, node)) {
|
|
12016
12123
|
this.orphan(node);
|
|
12017
12124
|
}
|
|
12018
12125
|
}
|
|
@@ -12291,7 +12398,7 @@ function isWasmSyscall(req) {
|
|
|
12291
12398
|
var MAX_READ = 1024 * 1024;
|
|
12292
12399
|
var WRITE_ACCESS = 3;
|
|
12293
12400
|
var KEYBOARD = /* @__PURE__ */ new Set([SIG.INT, SIG.QUIT, SIG.TSTP]);
|
|
12294
|
-
var
|
|
12401
|
+
var DEFAULT_UMASK2 = 18;
|
|
12295
12402
|
function words(value) {
|
|
12296
12403
|
if (!Array.isArray(value) || !value.every((w) => typeof w === "string")) {
|
|
12297
12404
|
throw new KernelError("EINVAL");
|
|
@@ -12319,7 +12426,7 @@ var WasmProcess = class {
|
|
|
12319
12426
|
interrupt = new AbortController();
|
|
12320
12427
|
gone = new AbortController();
|
|
12321
12428
|
dying = false;
|
|
12322
|
-
umask =
|
|
12429
|
+
umask = DEFAULT_UMASK2;
|
|
12323
12430
|
cred;
|
|
12324
12431
|
execChild;
|
|
12325
12432
|
killed = false;
|
|
@@ -12341,7 +12448,7 @@ var WasmProcess = class {
|
|
|
12341
12448
|
this.fds = fds;
|
|
12342
12449
|
this.options = options;
|
|
12343
12450
|
this.inherited = options.ignored ?? 0;
|
|
12344
|
-
this.umask = options.umask ??
|
|
12451
|
+
this.umask = options.umask ?? DEFAULT_UMASK2;
|
|
12345
12452
|
this.cred = copyCred(options.cred ?? ROOT);
|
|
12346
12453
|
this.children = new ChildTable(fds, options.spawner, options.forker);
|
|
12347
12454
|
this.nodes = options.nodes ?? new VfsNodes(options.fs);
|
|
@@ -12434,7 +12541,7 @@ var WasmProcess = class {
|
|
|
12434
12541
|
if (this.stopped) return "stop";
|
|
12435
12542
|
this.stopped = sig;
|
|
12436
12543
|
this.stops++;
|
|
12437
|
-
this.resumed = new Promise((
|
|
12544
|
+
this.resumed = new Promise((resolve2) => this.wake = resolve2);
|
|
12438
12545
|
const blocked = this.interrupt;
|
|
12439
12546
|
this.interrupt = new AbortController();
|
|
12440
12547
|
blocked.abort();
|
|
@@ -12499,7 +12606,9 @@ var WasmProcess = class {
|
|
|
12499
12606
|
const { ptys, jobs } = this.options;
|
|
12500
12607
|
const owner = this.options.owners ? this.ttyOwner() : void 0;
|
|
12501
12608
|
const guard2 = this.guarded();
|
|
12502
|
-
|
|
12609
|
+
const { ttyFilter } = this.options;
|
|
12610
|
+
const ctx = { pid: this.pid, fds: this.fds, ptys, jobs, guard: guard2, owner, ttyFilter };
|
|
12611
|
+
return ptySyscall(req, ctx);
|
|
12503
12612
|
}
|
|
12504
12613
|
return await this.procSyscall(req, cancelled);
|
|
12505
12614
|
} catch (e) {
|
|
@@ -12674,7 +12783,8 @@ var WasmProcess = class {
|
|
|
12674
12783
|
const tty = name2 === void 0 ? this.controllingTerminal() : this.options.jobs?.terminalNamed(name2);
|
|
12675
12784
|
if (!tty) throw new KernelError("ENXIO");
|
|
12676
12785
|
if (name2 !== void 0) ttyOpenable(this.guarded(), tty);
|
|
12677
|
-
|
|
12786
|
+
const file = tty.file();
|
|
12787
|
+
return this.fds.install(this.options.ttyFilter?.(file) ?? file, 3);
|
|
12678
12788
|
}
|
|
12679
12789
|
openSealed() {
|
|
12680
12790
|
const broker = this.options.sealed;
|
|
@@ -12714,15 +12824,8 @@ var WasmProcess = class {
|
|
|
12714
12824
|
async sealedCaller() {
|
|
12715
12825
|
const shown = await this.options.identity?.();
|
|
12716
12826
|
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
|
-
};
|
|
12827
|
+
const ids = { pid: shown?.pid ?? this.pid, ppid: shown?.ppid ?? 0 };
|
|
12828
|
+
return broker.stamp(ids, this.cred, broker.tagOf(this.pid));
|
|
12726
12829
|
}
|
|
12727
12830
|
guarded() {
|
|
12728
12831
|
const { guard: guard2 } = this.options;
|
|
@@ -13230,13 +13333,13 @@ var WasmProcess = class {
|
|
|
13230
13333
|
while (this.dlLock.depth > 0 && this.dlLock.owner !== owner) {
|
|
13231
13334
|
if (this.dying) throw new KernelError("EINTR");
|
|
13232
13335
|
const interrupt = this.interrupt.signal;
|
|
13233
|
-
const gone = await new Promise((
|
|
13336
|
+
const gone = await new Promise((resolve2) => {
|
|
13234
13337
|
const waiter = {
|
|
13235
13338
|
owner,
|
|
13236
13339
|
wake: (ended) => {
|
|
13237
13340
|
this.dlLock.waiters.delete(waiter);
|
|
13238
13341
|
interrupt.removeEventListener("abort", recheck);
|
|
13239
|
-
|
|
13342
|
+
resolve2(ended);
|
|
13240
13343
|
}
|
|
13241
13344
|
};
|
|
13242
13345
|
const recheck = () => waiter.wake(false);
|
|
@@ -13492,6 +13595,7 @@ function processOptions(opts, header4, hooks, created3) {
|
|
|
13492
13595
|
...inherited(opts),
|
|
13493
13596
|
...opts.owners ? { owners: true } : {},
|
|
13494
13597
|
...opts.sealed ? { sealed: opts.sealed } : {},
|
|
13598
|
+
...opts.ttyFilter ? { ttyFilter: opts.ttyFilter } : {},
|
|
13495
13599
|
...opts.clipboard ? { clipboard: opts.clipboard, ...clipboardName(opts) } : {},
|
|
13496
13600
|
...opts.readonlyAt ? { readonlyAt: opts.readonlyAt } : {},
|
|
13497
13601
|
...opts.dac ? { guard: { dac: opts.dac, fs: opts.fs, created: created3 } } : {},
|
|
@@ -13986,6 +14090,523 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
13986
14090
|
};
|
|
13987
14091
|
}
|
|
13988
14092
|
|
|
14093
|
+
// node_modules/@ai-ecoverse/slicc-scrub/dist/index.js
|
|
14094
|
+
var FRAGMENT = 16;
|
|
14095
|
+
var MIN_VALUE = 8;
|
|
14096
|
+
var MIN_BASE64 = 8;
|
|
14097
|
+
var encoder4 = new TextEncoder();
|
|
14098
|
+
var STD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
14099
|
+
function utf82(text) {
|
|
14100
|
+
return encoder4.encode(text);
|
|
14101
|
+
}
|
|
14102
|
+
function base642(bytes, padded = true) {
|
|
14103
|
+
let out = "";
|
|
14104
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
14105
|
+
const a = bytes[i];
|
|
14106
|
+
const b = i + 1 < bytes.length ? bytes[i + 1] : 0;
|
|
14107
|
+
const c = i + 2 < bytes.length ? bytes[i + 2] : 0;
|
|
14108
|
+
const triple = a << 16 | b << 8 | c;
|
|
14109
|
+
const left = bytes.length - i;
|
|
14110
|
+
out += STD[triple >> 18 & 63] + STD[triple >> 12 & 63];
|
|
14111
|
+
out += left > 1 ? STD[triple >> 6 & 63] : padded ? "=" : "";
|
|
14112
|
+
out += left > 2 ? STD[triple & 63] : padded ? "=" : "";
|
|
14113
|
+
}
|
|
14114
|
+
return out;
|
|
14115
|
+
}
|
|
14116
|
+
function urlSafe(text) {
|
|
14117
|
+
return text.replace(/\+/g, "-").replace(/\//g, "_");
|
|
14118
|
+
}
|
|
14119
|
+
function hex2(bytes) {
|
|
14120
|
+
let out = "";
|
|
14121
|
+
for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
|
|
14122
|
+
return out;
|
|
14123
|
+
}
|
|
14124
|
+
function embedded(bytes, offset) {
|
|
14125
|
+
const shifted = new Uint8Array(offset + bytes.length);
|
|
14126
|
+
shifted.set(bytes, offset);
|
|
14127
|
+
const encoded = base642(shifted);
|
|
14128
|
+
const first = Math.ceil(8 * offset / 6);
|
|
14129
|
+
const last = Math.floor(8 * (offset + bytes.length) / 6);
|
|
14130
|
+
return encoded.slice(first, last);
|
|
14131
|
+
}
|
|
14132
|
+
function unicode(value, upper) {
|
|
14133
|
+
let out = "";
|
|
14134
|
+
for (let i = 0; i < value.length; i++) {
|
|
14135
|
+
const unit = value.charCodeAt(i);
|
|
14136
|
+
if (unit === 34) out += '\\"';
|
|
14137
|
+
else if (unit === 92) out += "\\\\";
|
|
14138
|
+
else if (unit < 32 || unit > 126) {
|
|
14139
|
+
const code = unit.toString(16).padStart(4, "0");
|
|
14140
|
+
out += `\\u${upper ? code.toUpperCase() : code}`;
|
|
14141
|
+
} else out += value[i];
|
|
14142
|
+
}
|
|
14143
|
+
return out;
|
|
14144
|
+
}
|
|
14145
|
+
function percent(value) {
|
|
14146
|
+
let component;
|
|
14147
|
+
try {
|
|
14148
|
+
component = encodeURIComponent(value);
|
|
14149
|
+
} catch {
|
|
14150
|
+
return [];
|
|
14151
|
+
}
|
|
14152
|
+
const lower = component.replace(/%[0-9A-F]{2}/g, (escape) => escape.toLowerCase());
|
|
14153
|
+
const plus = component.replace(/%20/g, "+");
|
|
14154
|
+
let form = "";
|
|
14155
|
+
for (const byte of utf82(value)) {
|
|
14156
|
+
const char = String.fromCharCode(byte);
|
|
14157
|
+
if (/[A-Za-z0-9*\-._]/.test(char)) form += char;
|
|
14158
|
+
else if (byte === 32) form += "+";
|
|
14159
|
+
else form += `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
14160
|
+
}
|
|
14161
|
+
return [component, lower, plus, form];
|
|
14162
|
+
}
|
|
14163
|
+
function html(value, apostrophe) {
|
|
14164
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, apostrophe);
|
|
14165
|
+
}
|
|
14166
|
+
function encodings(bytes) {
|
|
14167
|
+
const standard = [base642(bytes), base642(bytes, false)];
|
|
14168
|
+
for (const offset of [0, 1, 2]) {
|
|
14169
|
+
const run2 = embedded(bytes, offset);
|
|
14170
|
+
if (run2.length >= MIN_BASE64) standard.push(run2);
|
|
14171
|
+
}
|
|
14172
|
+
return [...standard, ...standard.map(urlSafe)];
|
|
14173
|
+
}
|
|
14174
|
+
function shapes(value) {
|
|
14175
|
+
const raw = utf82(value);
|
|
14176
|
+
const seen = /* @__PURE__ */ new Set([value]);
|
|
14177
|
+
const out = [];
|
|
14178
|
+
if (raw.length < FRAGMENT) out.push({ bytes: raw, form: "raw" });
|
|
14179
|
+
for (let offset = 0; raw.length >= FRAGMENT && offset + FRAGMENT <= raw.length; offset++) {
|
|
14180
|
+
out.push({ bytes: raw.subarray(offset, offset + FRAGMENT), form: "fragment", offset });
|
|
14181
|
+
}
|
|
14182
|
+
const add = (text, form) => {
|
|
14183
|
+
if (seen.has(text)) return;
|
|
14184
|
+
seen.add(text);
|
|
14185
|
+
out.push({ bytes: utf82(text), form });
|
|
14186
|
+
};
|
|
14187
|
+
const json5 = JSON.stringify(value).slice(1, -1);
|
|
14188
|
+
for (const text of [
|
|
14189
|
+
json5,
|
|
14190
|
+
json5.replace(/\//g, "\\/"),
|
|
14191
|
+
unicode(value, false),
|
|
14192
|
+
unicode(value, true)
|
|
14193
|
+
]) {
|
|
14194
|
+
add(text, "json");
|
|
14195
|
+
}
|
|
14196
|
+
for (const text of percent(value)) add(text, "percent");
|
|
14197
|
+
for (const text of [html(value, "'"), html(value, "'")]) add(text, "html");
|
|
14198
|
+
for (const text of encodings(raw)) add(text, "base64");
|
|
14199
|
+
add(hex2(raw), "hex");
|
|
14200
|
+
add(hex2(raw).toUpperCase(), "hex");
|
|
14201
|
+
return out;
|
|
14202
|
+
}
|
|
14203
|
+
function wrappable(form) {
|
|
14204
|
+
return form === "base64" || form === "hex";
|
|
14205
|
+
}
|
|
14206
|
+
var Automaton = class {
|
|
14207
|
+
edges = /* @__PURE__ */ new Map();
|
|
14208
|
+
fail = [0];
|
|
14209
|
+
depth = [0];
|
|
14210
|
+
children = [0];
|
|
14211
|
+
out = [[]];
|
|
14212
|
+
dict = [-1];
|
|
14213
|
+
lengths = [];
|
|
14214
|
+
add(bytes) {
|
|
14215
|
+
let node = 0;
|
|
14216
|
+
for (const byte of bytes) {
|
|
14217
|
+
const key = node * 256 + byte;
|
|
14218
|
+
let next2 = this.edges.get(key);
|
|
14219
|
+
if (next2 === void 0) {
|
|
14220
|
+
next2 = this.depth.length;
|
|
14221
|
+
this.edges.set(key, next2);
|
|
14222
|
+
this.fail.push(0);
|
|
14223
|
+
this.depth.push(this.depth[node] + 1);
|
|
14224
|
+
this.children.push(0);
|
|
14225
|
+
this.children[node] += 1;
|
|
14226
|
+
this.out.push([]);
|
|
14227
|
+
this.dict.push(-1);
|
|
14228
|
+
}
|
|
14229
|
+
node = next2;
|
|
14230
|
+
}
|
|
14231
|
+
const id2 = this.lengths.length;
|
|
14232
|
+
this.lengths.push(bytes.length);
|
|
14233
|
+
this.out[node].push(id2);
|
|
14234
|
+
return id2;
|
|
14235
|
+
}
|
|
14236
|
+
build() {
|
|
14237
|
+
const queue = [];
|
|
14238
|
+
const byNode = /* @__PURE__ */ new Map();
|
|
14239
|
+
for (const [key, child] of this.edges) {
|
|
14240
|
+
const parent = Math.floor(key / 256);
|
|
14241
|
+
const list = byNode.get(parent) ?? [];
|
|
14242
|
+
list.push([key % 256, child]);
|
|
14243
|
+
byNode.set(parent, list);
|
|
14244
|
+
}
|
|
14245
|
+
for (const [, child] of byNode.get(0) ?? []) queue.push(child);
|
|
14246
|
+
for (let head = 0; head < queue.length; head++) {
|
|
14247
|
+
const node = queue[head];
|
|
14248
|
+
const fallback = this.fail[node];
|
|
14249
|
+
this.dict[node] = this.out[fallback].length > 0 ? fallback : this.dict[fallback];
|
|
14250
|
+
for (const [byte, child] of byNode.get(node) ?? []) {
|
|
14251
|
+
let state = fallback;
|
|
14252
|
+
let target = this.edges.get(state * 256 + byte);
|
|
14253
|
+
while (target === void 0 && state > 0) {
|
|
14254
|
+
state = this.fail[state];
|
|
14255
|
+
target = this.edges.get(state * 256 + byte);
|
|
14256
|
+
}
|
|
14257
|
+
this.fail[child] = target ?? 0;
|
|
14258
|
+
queue.push(child);
|
|
14259
|
+
}
|
|
14260
|
+
}
|
|
14261
|
+
}
|
|
14262
|
+
step(state, byte) {
|
|
14263
|
+
let current = state;
|
|
14264
|
+
for (; ; ) {
|
|
14265
|
+
const next2 = this.edges.get(current * 256 + byte);
|
|
14266
|
+
if (next2 !== void 0) return next2;
|
|
14267
|
+
if (current === 0) return 0;
|
|
14268
|
+
current = this.fail[current];
|
|
14269
|
+
}
|
|
14270
|
+
}
|
|
14271
|
+
matches(state, visit) {
|
|
14272
|
+
for (let node = state; node > 0; node = this.dict[node]) {
|
|
14273
|
+
for (const id2 of this.out[node]) visit(id2);
|
|
14274
|
+
}
|
|
14275
|
+
}
|
|
14276
|
+
partials(state, length2, visit) {
|
|
14277
|
+
for (let node = state; node > 0; node = this.fail[node]) {
|
|
14278
|
+
if (this.children[node] > 0) visit(length2 - this.depth[node]);
|
|
14279
|
+
}
|
|
14280
|
+
}
|
|
14281
|
+
};
|
|
14282
|
+
var RANK = {
|
|
14283
|
+
raw: 0,
|
|
14284
|
+
fragment: 1,
|
|
14285
|
+
json: 2,
|
|
14286
|
+
percent: 3,
|
|
14287
|
+
html: 4,
|
|
14288
|
+
base64: 5,
|
|
14289
|
+
hex: 6,
|
|
14290
|
+
wrapped: 7
|
|
14291
|
+
};
|
|
14292
|
+
var CR2 = 13;
|
|
14293
|
+
var LF2 = 10;
|
|
14294
|
+
var EMPTY2 = new Uint8Array(0);
|
|
14295
|
+
function register(automaton, sources, ids, bytes, source) {
|
|
14296
|
+
const key = Array.from(bytes).join(",");
|
|
14297
|
+
let id2 = ids.get(key);
|
|
14298
|
+
if (id2 === void 0) {
|
|
14299
|
+
id2 = automaton.add(bytes);
|
|
14300
|
+
ids.set(key, id2);
|
|
14301
|
+
sources[id2] = [];
|
|
14302
|
+
}
|
|
14303
|
+
sources[id2].push(source);
|
|
14304
|
+
}
|
|
14305
|
+
function prepare(secrets) {
|
|
14306
|
+
const main = new Automaton();
|
|
14307
|
+
const wrap = new Automaton();
|
|
14308
|
+
const sources = [];
|
|
14309
|
+
const wrapSources = [];
|
|
14310
|
+
const ids = /* @__PURE__ */ new Map();
|
|
14311
|
+
const wrapIds = /* @__PURE__ */ new Map();
|
|
14312
|
+
const values = secrets.map((secret) => utf82(secret.value));
|
|
14313
|
+
secrets.forEach((secret, index) => {
|
|
14314
|
+
if (typeof secret.value !== "string" || values[index].length < MIN_VALUE) {
|
|
14315
|
+
throw new RangeError(`the value of ${secret.name} is shorter than ${MIN_VALUE} bytes`);
|
|
14316
|
+
}
|
|
14317
|
+
for (const shape of shapes(secret.value)) {
|
|
14318
|
+
const source = { secret: index, form: shape.form, offset: shape.offset };
|
|
14319
|
+
register(main, sources, ids, shape.bytes, source);
|
|
14320
|
+
if (wrappable(shape.form)) register(wrap, wrapSources, wrapIds, shape.bytes, source);
|
|
14321
|
+
}
|
|
14322
|
+
});
|
|
14323
|
+
main.build();
|
|
14324
|
+
wrap.build();
|
|
14325
|
+
const replacements = secrets.map((secret) => [
|
|
14326
|
+
utf82(secret.placeholder),
|
|
14327
|
+
utf82(`[redacted:${secret.name}]`)
|
|
14328
|
+
]);
|
|
14329
|
+
return { secrets, values, main, wrap, sources, wrapSources, replacements };
|
|
14330
|
+
}
|
|
14331
|
+
function better(a, b) {
|
|
14332
|
+
if (!b) return true;
|
|
14333
|
+
if (a.end !== b.end) return a.end > b.end;
|
|
14334
|
+
if (a.rank !== b.rank) return a.rank < b.rank;
|
|
14335
|
+
return a.secret < b.secret;
|
|
14336
|
+
}
|
|
14337
|
+
function resolve(c, input, start2, end, source) {
|
|
14338
|
+
if (source.form !== "fragment") {
|
|
14339
|
+
return {
|
|
14340
|
+
start: start2,
|
|
14341
|
+
end,
|
|
14342
|
+
secret: source.secret,
|
|
14343
|
+
form: source.form,
|
|
14344
|
+
rank: RANK[source.form],
|
|
14345
|
+
growing: false
|
|
14346
|
+
};
|
|
14347
|
+
}
|
|
14348
|
+
const value = c.values[source.secret];
|
|
14349
|
+
let stop = end;
|
|
14350
|
+
let at = source.offset + FRAGMENT;
|
|
14351
|
+
while (stop < input.length && at < value.length && input[stop] === value[at]) {
|
|
14352
|
+
stop++;
|
|
14353
|
+
at++;
|
|
14354
|
+
}
|
|
14355
|
+
const form = source.offset === 0 && at === value.length ? "raw" : "fragment";
|
|
14356
|
+
const growing = stop === input.length && at < value.length;
|
|
14357
|
+
return { start: start2, end: stop, secret: source.secret, form, rank: RANK[form], growing };
|
|
14358
|
+
}
|
|
14359
|
+
function keep(best, candidate) {
|
|
14360
|
+
if (better(candidate, best.get(candidate.start))) best.set(candidate.start, candidate);
|
|
14361
|
+
}
|
|
14362
|
+
function scanMain(c, input, best, partials) {
|
|
14363
|
+
let state = 0;
|
|
14364
|
+
for (let i = 0; i < input.length; i++) {
|
|
14365
|
+
state = c.main.step(state, input[i]);
|
|
14366
|
+
c.main.matches(state, (id2) => {
|
|
14367
|
+
const start2 = i + 1 - c.main.lengths[id2];
|
|
14368
|
+
for (const source of c.sources[id2]) {
|
|
14369
|
+
const candidate = resolve(c, input, start2, i + 1, source);
|
|
14370
|
+
if (candidate.growing) partials.push(candidate.start);
|
|
14371
|
+
keep(best, candidate);
|
|
14372
|
+
}
|
|
14373
|
+
});
|
|
14374
|
+
}
|
|
14375
|
+
c.main.partials(state, input.length, (start2) => partials.push(start2));
|
|
14376
|
+
}
|
|
14377
|
+
function scanWrapped(c, input, best, partials) {
|
|
14378
|
+
const map = [];
|
|
14379
|
+
for (let i = 0; i < input.length; i++) if (input[i] !== CR2 && input[i] !== LF2) map.push(i);
|
|
14380
|
+
if (map.length === input.length) return;
|
|
14381
|
+
let state = 0;
|
|
14382
|
+
for (let v = 0; v < map.length; v++) {
|
|
14383
|
+
state = c.wrap.step(state, input[map[v]]);
|
|
14384
|
+
c.wrap.matches(state, (id2) => {
|
|
14385
|
+
const first = v + 1 - c.wrap.lengths[id2];
|
|
14386
|
+
const start2 = map[first];
|
|
14387
|
+
const end = map[v] + 1;
|
|
14388
|
+
const wrapped = end - start2 !== c.wrap.lengths[id2];
|
|
14389
|
+
for (const source of c.wrapSources[id2]) {
|
|
14390
|
+
const form = wrapped ? "wrapped" : source.form;
|
|
14391
|
+
keep(best, { start: start2, end, secret: source.secret, form, rank: RANK[form], growing: false });
|
|
14392
|
+
}
|
|
14393
|
+
});
|
|
14394
|
+
}
|
|
14395
|
+
c.wrap.partials(state, map.length, (start2) => partials.push(map[start2]));
|
|
14396
|
+
}
|
|
14397
|
+
function count(c, hits, candidate) {
|
|
14398
|
+
const name2 = c.secrets[candidate.secret].name;
|
|
14399
|
+
const key = `${name2}\0${candidate.form}`;
|
|
14400
|
+
const hit = hits.get(key) ?? { name: name2, form: candidate.form, count: 0 };
|
|
14401
|
+
hit.count += 1;
|
|
14402
|
+
hits.set(key, hit);
|
|
14403
|
+
}
|
|
14404
|
+
function concat5(parts2) {
|
|
14405
|
+
let length2 = 0;
|
|
14406
|
+
for (const part of parts2) length2 += part.length;
|
|
14407
|
+
const out = new Uint8Array(length2);
|
|
14408
|
+
let at = 0;
|
|
14409
|
+
for (const part of parts2) {
|
|
14410
|
+
out.set(part, at);
|
|
14411
|
+
at += part.length;
|
|
14412
|
+
}
|
|
14413
|
+
return out;
|
|
14414
|
+
}
|
|
14415
|
+
function pass(c, input, final) {
|
|
14416
|
+
const best = /* @__PURE__ */ new Map();
|
|
14417
|
+
const partials = [];
|
|
14418
|
+
scanMain(c, input, best, partials);
|
|
14419
|
+
scanWrapped(c, input, best, partials);
|
|
14420
|
+
const holds = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
|
|
14421
|
+
const starts = [...best.keys()].sort((a, b) => a - b);
|
|
14422
|
+
const parts2 = [];
|
|
14423
|
+
const hits = /* @__PURE__ */ new Map();
|
|
14424
|
+
let pos = 0;
|
|
14425
|
+
let cut = input.length;
|
|
14426
|
+
let s = 0;
|
|
14427
|
+
let h = 0;
|
|
14428
|
+
for (; ; ) {
|
|
14429
|
+
while (s < starts.length && starts[s] < pos) s++;
|
|
14430
|
+
while (h < holds.length && holds[h] < pos) h++;
|
|
14431
|
+
const hold = h < holds.length ? holds[h] : Infinity;
|
|
14432
|
+
const next2 = s < starts.length ? starts[s] : Infinity;
|
|
14433
|
+
if (hold <= next2) {
|
|
14434
|
+
cut = Math.min(hold, input.length);
|
|
14435
|
+
break;
|
|
14436
|
+
}
|
|
14437
|
+
const candidate = best.get(next2);
|
|
14438
|
+
parts2.push(
|
|
14439
|
+
input.subarray(pos, next2),
|
|
14440
|
+
c.replacements[candidate.secret][candidate.form === "raw" ? 0 : 1]
|
|
14441
|
+
);
|
|
14442
|
+
count(c, hits, candidate);
|
|
14443
|
+
pos = candidate.end;
|
|
14444
|
+
}
|
|
14445
|
+
parts2.push(input.subarray(pos, cut));
|
|
14446
|
+
return { output: concat5(parts2), cut, hits };
|
|
14447
|
+
}
|
|
14448
|
+
function merge(into, from) {
|
|
14449
|
+
for (const [key, hit] of from) {
|
|
14450
|
+
const known = into.get(key);
|
|
14451
|
+
if (known) known.count += hit.count;
|
|
14452
|
+
else into.set(key, { ...hit });
|
|
14453
|
+
}
|
|
14454
|
+
}
|
|
14455
|
+
function compile(secrets, options = {}) {
|
|
14456
|
+
const c = prepare(secrets.map((secret) => ({ ...secret })));
|
|
14457
|
+
const decoder4 = new TextDecoder();
|
|
14458
|
+
const idleMs = options.idleMs ?? 250;
|
|
14459
|
+
const scrubBytes = (input) => {
|
|
14460
|
+
if (c.secrets.length === 0) return { bytes: input.slice(), hits: [] };
|
|
14461
|
+
const result = pass(c, input, true);
|
|
14462
|
+
return { bytes: result.output, hits: [...result.hits.values()] };
|
|
14463
|
+
};
|
|
14464
|
+
return {
|
|
14465
|
+
version: options.version ?? 0,
|
|
14466
|
+
idleMs,
|
|
14467
|
+
size: c.main.lengths.length,
|
|
14468
|
+
bytes: scrubBytes,
|
|
14469
|
+
text(input) {
|
|
14470
|
+
const { bytes, hits } = scrubBytes(utf82(input));
|
|
14471
|
+
return { text: decoder4.decode(bytes), hits };
|
|
14472
|
+
},
|
|
14473
|
+
stream() {
|
|
14474
|
+
let pending = EMPTY2;
|
|
14475
|
+
const hits = /* @__PURE__ */ new Map();
|
|
14476
|
+
const run2 = (final) => {
|
|
14477
|
+
if (c.secrets.length === 0 || pending.length === 0) {
|
|
14478
|
+
const out = pending;
|
|
14479
|
+
pending = EMPTY2;
|
|
14480
|
+
return out;
|
|
14481
|
+
}
|
|
14482
|
+
const result = pass(c, pending, final);
|
|
14483
|
+
merge(hits, result.hits);
|
|
14484
|
+
pending = pending.slice(result.cut);
|
|
14485
|
+
return result.output;
|
|
14486
|
+
};
|
|
14487
|
+
return {
|
|
14488
|
+
push(chunk2) {
|
|
14489
|
+
pending = concat5([pending, chunk2]);
|
|
14490
|
+
return run2(false);
|
|
14491
|
+
},
|
|
14492
|
+
idle() {
|
|
14493
|
+
return pending.length < FRAGMENT ? run2(true) : EMPTY2;
|
|
14494
|
+
},
|
|
14495
|
+
end() {
|
|
14496
|
+
return run2(true);
|
|
14497
|
+
},
|
|
14498
|
+
get hits() {
|
|
14499
|
+
return [...hits.values()];
|
|
14500
|
+
}
|
|
14501
|
+
};
|
|
14502
|
+
}
|
|
14503
|
+
};
|
|
14504
|
+
}
|
|
14505
|
+
|
|
14506
|
+
// src/kernel/scrub-file.ts
|
|
14507
|
+
var SCRUB_IDLE_MS = 50;
|
|
14508
|
+
var encoder5 = new TextEncoder();
|
|
14509
|
+
function scrubberOf(secrets) {
|
|
14510
|
+
const usable = secrets.filter((s) => encoder5.encode(s.value).length >= MIN_VALUE);
|
|
14511
|
+
return usable.length > 0 ? compile(usable, { idleMs: SCRUB_IDLE_MS }) : void 0;
|
|
14512
|
+
}
|
|
14513
|
+
async function writeAll2(file, bytes, signal) {
|
|
14514
|
+
const write = file.write;
|
|
14515
|
+
for (let at = 0; at < bytes.length; ) {
|
|
14516
|
+
at += await write.call(file, bytes.subarray(at), at === 0 ? signal : void 0);
|
|
14517
|
+
}
|
|
14518
|
+
}
|
|
14519
|
+
function bound(file, key) {
|
|
14520
|
+
const method = file[key];
|
|
14521
|
+
return typeof method === "function" ? { [key]: method.bind(file) } : {};
|
|
14522
|
+
}
|
|
14523
|
+
function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
14524
|
+
const file = inner.file;
|
|
14525
|
+
const stream2 = scrubber.stream();
|
|
14526
|
+
let queue = Promise.resolve();
|
|
14527
|
+
let timer;
|
|
14528
|
+
let failed3;
|
|
14529
|
+
const raise = () => {
|
|
14530
|
+
if (failed3 === void 0) return;
|
|
14531
|
+
const err = failed3;
|
|
14532
|
+
failed3 = void 0;
|
|
14533
|
+
throw err;
|
|
14534
|
+
};
|
|
14535
|
+
const enqueue = (bytes, signal) => {
|
|
14536
|
+
const next2 = queue.then(() => bytes.length > 0 ? writeAll2(file, bytes, signal) : void 0);
|
|
14537
|
+
queue = next2.catch(() => void 0);
|
|
14538
|
+
return next2;
|
|
14539
|
+
};
|
|
14540
|
+
const release = () => {
|
|
14541
|
+
timer = void 0;
|
|
14542
|
+
enqueue(stream2.idle()).catch((err) => {
|
|
14543
|
+
failed3 = err;
|
|
14544
|
+
});
|
|
14545
|
+
};
|
|
14546
|
+
return new OpenFile({
|
|
14547
|
+
...bound(file, "read"),
|
|
14548
|
+
...bound(file, "peek"),
|
|
14549
|
+
...bound(file, "poll"),
|
|
14550
|
+
...bound(file, "changed"),
|
|
14551
|
+
...bound(file, "stat"),
|
|
14552
|
+
...file.tty ? { tty: file.tty } : {},
|
|
14553
|
+
...file.clipboard ? { clipboard: file.clipboard } : {},
|
|
14554
|
+
...file.write ? {
|
|
14555
|
+
write: async (bytes, signal) => {
|
|
14556
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
14557
|
+
raise();
|
|
14558
|
+
await enqueue(stream2.push(bytes), signal);
|
|
14559
|
+
timer = setTimeout(release, idleMs);
|
|
14560
|
+
return bytes.length;
|
|
14561
|
+
}
|
|
14562
|
+
} : {},
|
|
14563
|
+
flush: async () => {
|
|
14564
|
+
await queue;
|
|
14565
|
+
raise();
|
|
14566
|
+
await file.flush?.();
|
|
14567
|
+
},
|
|
14568
|
+
close: async () => {
|
|
14569
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
14570
|
+
let failure;
|
|
14571
|
+
try {
|
|
14572
|
+
await enqueue(stream2.end());
|
|
14573
|
+
raise();
|
|
14574
|
+
} catch (err) {
|
|
14575
|
+
failure = { err };
|
|
14576
|
+
}
|
|
14577
|
+
await inner.release();
|
|
14578
|
+
if (failure) throw failure.err;
|
|
14579
|
+
}
|
|
14580
|
+
});
|
|
14581
|
+
}
|
|
14582
|
+
function scrubbedAll(file, scrubbers) {
|
|
14583
|
+
return scrubbers.reduce((inner, scrubber) => scrubbed(inner, scrubber), file);
|
|
14584
|
+
}
|
|
14585
|
+
function stdioFiles(fds) {
|
|
14586
|
+
const files = /* @__PURE__ */ new Set();
|
|
14587
|
+
for (const fd of [1, 2]) {
|
|
14588
|
+
try {
|
|
14589
|
+
files.add(fds.get(fd));
|
|
14590
|
+
} catch {
|
|
14591
|
+
}
|
|
14592
|
+
}
|
|
14593
|
+
return files;
|
|
14594
|
+
}
|
|
14595
|
+
function scrubStdio(fds, scrubber) {
|
|
14596
|
+
const wrapped = /* @__PURE__ */ new Map();
|
|
14597
|
+
const stdio = stdioFiles(fds);
|
|
14598
|
+
for (const fd of fds.numbers()) {
|
|
14599
|
+
const original = fds.get(fd);
|
|
14600
|
+
if (!stdio.has(original) && !original.file.tty) continue;
|
|
14601
|
+
const known = wrapped.get(original);
|
|
14602
|
+
const flags2 = fds.statusFlags(fd);
|
|
14603
|
+
const wrapper = known ? known.retain() : scrubbed(original.retain(), scrubber);
|
|
14604
|
+
wrapped.set(original, wrapper);
|
|
14605
|
+
fds.installAt(fd, wrapper);
|
|
14606
|
+
if (flags2 !== void 0) fds.setStatusFlags(fd, flags2);
|
|
14607
|
+
}
|
|
14608
|
+
}
|
|
14609
|
+
|
|
13989
14610
|
// src/kernel/sealed.ts
|
|
13990
14611
|
var SEALED_MAX_BYTES = 64 * 1024;
|
|
13991
14612
|
var SEALED_TIMEOUT_MS = 1e4;
|
|
@@ -13999,7 +14620,7 @@ var SEALED_OPS = /* @__PURE__ */ new Set([
|
|
|
13999
14620
|
"cancel",
|
|
14000
14621
|
"materialize"
|
|
14001
14622
|
]);
|
|
14002
|
-
var
|
|
14623
|
+
var encoder6 = new TextEncoder();
|
|
14003
14624
|
var decoder3 = new TextDecoder("utf-8", { fatal: true });
|
|
14004
14625
|
function parseSealed(bytes) {
|
|
14005
14626
|
try {
|
|
@@ -14015,11 +14636,16 @@ function parseSealed(bytes) {
|
|
|
14015
14636
|
const req = parsed2;
|
|
14016
14637
|
if (req.v !== 1 || typeof req.op !== "string" || !SEALED_OPS.has(req.op))
|
|
14017
14638
|
throw new KernelError("EINVAL");
|
|
14639
|
+
if (req.op === "materialize" && !materializable(req)) throw new KernelError("EINVAL");
|
|
14018
14640
|
return req;
|
|
14019
14641
|
} finally {
|
|
14020
14642
|
bytes.fill(0);
|
|
14021
14643
|
}
|
|
14022
14644
|
}
|
|
14645
|
+
function materializable(req) {
|
|
14646
|
+
if (req.shellGrants !== true && !isStrings(req.names)) return false;
|
|
14647
|
+
return isStrings(req.argv) && typeof req.path === "string" && typeof req.cwd === "string";
|
|
14648
|
+
}
|
|
14023
14649
|
function errorReply(code, message3) {
|
|
14024
14650
|
return { v: 1, error: { code, message: message3 } };
|
|
14025
14651
|
}
|
|
@@ -14063,12 +14689,14 @@ var SealedChannel = class {
|
|
|
14063
14689
|
const timer = setTimeout(() => control.abort("timeout"), this.broker.timeoutMs);
|
|
14064
14690
|
const req = { ...fields, v: 1, op: fields.op, caller };
|
|
14065
14691
|
const flight = { control, done: Promise.resolve() };
|
|
14066
|
-
flight.done = this.answer(req, control.signal).then((reply) => {
|
|
14692
|
+
flight.done = this.answer(req, control.signal).then(async (reply) => {
|
|
14067
14693
|
clearTimeout(timer);
|
|
14068
14694
|
gone.removeEventListener("abort", withdraw);
|
|
14695
|
+
if (reply && req.op === "materialize")
|
|
14696
|
+
await this.broker.tickets.record(req, reply, caller.pid);
|
|
14069
14697
|
if (this.inflight !== flight) return;
|
|
14070
14698
|
this.inflight = void 0;
|
|
14071
|
-
if (reply) this.reply =
|
|
14699
|
+
if (reply) this.reply = encoder6.encode(serialized(reply));
|
|
14072
14700
|
});
|
|
14073
14701
|
this.inflight = flight;
|
|
14074
14702
|
return length2;
|
|
@@ -14076,8 +14704,8 @@ var SealedChannel = class {
|
|
|
14076
14704
|
async answer(req, signal) {
|
|
14077
14705
|
const hook = this.broker.hook;
|
|
14078
14706
|
if (!hook) return errorReply("ENOTCONN", "no vault is connected");
|
|
14079
|
-
const stopped = new Promise((
|
|
14080
|
-
signal.addEventListener("abort", () =>
|
|
14707
|
+
const stopped = new Promise((resolve2) => {
|
|
14708
|
+
signal.addEventListener("abort", () => resolve2(void 0), { once: true });
|
|
14081
14709
|
});
|
|
14082
14710
|
if (signal.aborted) return void 0;
|
|
14083
14711
|
const asked = Promise.resolve().then(() => hook(req, { signal })).then(
|
|
@@ -14132,17 +14760,60 @@ var SealedChannel = class {
|
|
|
14132
14760
|
this.reply = void 0;
|
|
14133
14761
|
}
|
|
14134
14762
|
};
|
|
14763
|
+
function swapOf(reply) {
|
|
14764
|
+
if (!isRecord(reply) || reply.error !== void 0) return void 0;
|
|
14765
|
+
const values = stringRecord(reply.values);
|
|
14766
|
+
const placeholders = stringRecord(reply.placeholders);
|
|
14767
|
+
return values && placeholders ? { values, placeholders } : void 0;
|
|
14768
|
+
}
|
|
14135
14769
|
var SealedBroker = class {
|
|
14136
14770
|
hook;
|
|
14137
14771
|
users;
|
|
14138
14772
|
timeoutMs;
|
|
14139
14773
|
tagOf;
|
|
14774
|
+
tickets = new TicketBook();
|
|
14775
|
+
userOf = async () => void 0;
|
|
14140
14776
|
constructor(hook, users, timeoutMs = SEALED_TIMEOUT_MS, tagOf = () => void 0) {
|
|
14141
14777
|
this.hook = hook;
|
|
14142
14778
|
this.users = users;
|
|
14143
14779
|
this.timeoutMs = timeoutMs;
|
|
14144
14780
|
this.tagOf = tagOf;
|
|
14145
14781
|
}
|
|
14782
|
+
async stamp(ids, cred, tag) {
|
|
14783
|
+
const user = await this.userOf(cred.euid).catch(() => void 0);
|
|
14784
|
+
return {
|
|
14785
|
+
pid: ids.pid,
|
|
14786
|
+
ppid: ids.ppid,
|
|
14787
|
+
uid: cred.euid,
|
|
14788
|
+
gid: cred.egid,
|
|
14789
|
+
...user !== void 0 ? { user } : {},
|
|
14790
|
+
groups: [...cred.groups],
|
|
14791
|
+
users: this.users,
|
|
14792
|
+
...tag !== void 0 ? { tag } : {}
|
|
14793
|
+
};
|
|
14794
|
+
}
|
|
14795
|
+
async consume(fields) {
|
|
14796
|
+
const { hook } = this;
|
|
14797
|
+
if (!hook) return void 0;
|
|
14798
|
+
const control = new AbortController();
|
|
14799
|
+
const timer = setTimeout(() => control.abort("timeout"), this.timeoutMs);
|
|
14800
|
+
const stopped = new Promise((resolve2) => {
|
|
14801
|
+
control.signal.addEventListener("abort", () => resolve2(void 0), { once: true });
|
|
14802
|
+
});
|
|
14803
|
+
const req = {
|
|
14804
|
+
...fields,
|
|
14805
|
+
v: 1,
|
|
14806
|
+
op: "materializeConsume",
|
|
14807
|
+
caller: fields.stamp
|
|
14808
|
+
};
|
|
14809
|
+
try {
|
|
14810
|
+
const asked = Promise.resolve().then(() => hook(req, { signal: control.signal })).then(swapOf, () => void 0);
|
|
14811
|
+
return await Promise.race([asked, stopped]);
|
|
14812
|
+
} finally {
|
|
14813
|
+
clearTimeout(timer);
|
|
14814
|
+
control.abort("done");
|
|
14815
|
+
}
|
|
14816
|
+
}
|
|
14146
14817
|
open() {
|
|
14147
14818
|
const channel = new SealedChannel(this);
|
|
14148
14819
|
return new OpenFile({
|
|
@@ -14641,11 +15312,11 @@ function codeOf3(err) {
|
|
|
14641
15312
|
}
|
|
14642
15313
|
function wait(ms, signal) {
|
|
14643
15314
|
if (signal.aborted) return Promise.resolve();
|
|
14644
|
-
return new Promise((
|
|
15315
|
+
return new Promise((resolve2) => {
|
|
14645
15316
|
const done4 = () => {
|
|
14646
15317
|
clearTimeout(timer);
|
|
14647
15318
|
signal.removeEventListener("abort", done4);
|
|
14648
|
-
|
|
15319
|
+
resolve2();
|
|
14649
15320
|
};
|
|
14650
15321
|
const timer = setTimeout(done4, ms);
|
|
14651
15322
|
signal.addEventListener("abort", done4, { once: true });
|
|
@@ -14972,11 +15643,11 @@ async function resize(h, path, size) {
|
|
|
14972
15643
|
}
|
|
14973
15644
|
}
|
|
14974
15645
|
function sleep(ms, signal) {
|
|
14975
|
-
return new Promise((
|
|
15646
|
+
return new Promise((resolve2) => {
|
|
14976
15647
|
const done4 = () => {
|
|
14977
15648
|
clearTimeout(timer);
|
|
14978
15649
|
signal.removeEventListener("abort", done4);
|
|
14979
|
-
|
|
15650
|
+
resolve2();
|
|
14980
15651
|
};
|
|
14981
15652
|
const timer = setTimeout(done4, ms);
|
|
14982
15653
|
signal.addEventListener("abort", done4);
|
|
@@ -15059,7 +15730,7 @@ var PORT_DEAD_MS = 1e4;
|
|
|
15059
15730
|
var PORT_LINGER_MS = 1e3;
|
|
15060
15731
|
function timed(transport, ms) {
|
|
15061
15732
|
const inflight = /* @__PURE__ */ new Set();
|
|
15062
|
-
const guard2 = (name2, run2, late, expire) => new Promise((
|
|
15733
|
+
const guard2 = (name2, run2, late, expire) => new Promise((resolve2, reject) => {
|
|
15063
15734
|
let expired = false;
|
|
15064
15735
|
const running = run2();
|
|
15065
15736
|
inflight.add(running);
|
|
@@ -15076,7 +15747,7 @@ function timed(transport, ms) {
|
|
|
15076
15747
|
(value) => {
|
|
15077
15748
|
clearTimeout(timer);
|
|
15078
15749
|
if (expired) late?.(value);
|
|
15079
|
-
|
|
15750
|
+
resolve2(value);
|
|
15080
15751
|
},
|
|
15081
15752
|
(err) => {
|
|
15082
15753
|
clearTimeout(timer);
|
|
@@ -15211,7 +15882,7 @@ var PortTransport = class {
|
|
|
15211
15882
|
ask(message3, bytes = 0, transfer = []) {
|
|
15212
15883
|
const id2 = ++this.next;
|
|
15213
15884
|
if (this.dead) return Promise.reject(fsError2("ENOTCONN", this.dead));
|
|
15214
|
-
return new Promise((
|
|
15885
|
+
return new Promise((resolve2, reject) => {
|
|
15215
15886
|
const timer = setTimeout(
|
|
15216
15887
|
() => {
|
|
15217
15888
|
this.waiting.delete(id2);
|
|
@@ -15225,7 +15896,7 @@ var PortTransport = class {
|
|
|
15225
15896
|
clearTimeout(timer);
|
|
15226
15897
|
this.waiting.delete(id2);
|
|
15227
15898
|
if (reply.error) reject(fsError2(reply.error.code ?? "EIO", reply.error.message ?? ""));
|
|
15228
|
-
else
|
|
15899
|
+
else resolve2(reply);
|
|
15229
15900
|
});
|
|
15230
15901
|
try {
|
|
15231
15902
|
this.port.postMessage({ id: id2, ...message3 }, transfer);
|
|
@@ -15254,7 +15925,7 @@ var PortTransport = class {
|
|
|
15254
15925
|
this.fail("the folder's watch ended");
|
|
15255
15926
|
return Promise.resolve();
|
|
15256
15927
|
}
|
|
15257
|
-
return new Promise((
|
|
15928
|
+
return new Promise((resolve2, reject) => {
|
|
15258
15929
|
const finish = () => {
|
|
15259
15930
|
this.waiting.delete(id2);
|
|
15260
15931
|
signal.removeEventListener("abort", stop);
|
|
@@ -15265,7 +15936,7 @@ var PortTransport = class {
|
|
|
15265
15936
|
this.port.postMessage({ id: id2, op: "unwatch" });
|
|
15266
15937
|
} catch {
|
|
15267
15938
|
}
|
|
15268
|
-
|
|
15939
|
+
resolve2();
|
|
15269
15940
|
};
|
|
15270
15941
|
this.watchBeat();
|
|
15271
15942
|
this.waiting.set(id2, (reply) => {
|
|
@@ -15273,7 +15944,7 @@ var PortTransport = class {
|
|
|
15273
15944
|
if (reply.event) return onEvent(reply.event);
|
|
15274
15945
|
finish();
|
|
15275
15946
|
if (reply.error) reject(fsError2(reply.error.code ?? "ENOTCONN", reply.error.message ?? ""));
|
|
15276
|
-
else
|
|
15947
|
+
else resolve2();
|
|
15277
15948
|
});
|
|
15278
15949
|
signal.addEventListener("abort", stop, { once: true });
|
|
15279
15950
|
try {
|
|
@@ -15489,10 +16160,10 @@ var ChunkedBytes = class {
|
|
|
15489
16160
|
}
|
|
15490
16161
|
truncate(size) {
|
|
15491
16162
|
if (size < this.size) {
|
|
15492
|
-
const
|
|
15493
|
-
this.chunks.length = Math.min(this.chunks.length,
|
|
15494
|
-
const tail = this.chunks[
|
|
15495
|
-
const from = size - (
|
|
16163
|
+
const keep2 = Math.ceil(size / CHUNK3);
|
|
16164
|
+
this.chunks.length = Math.min(this.chunks.length, keep2);
|
|
16165
|
+
const tail = this.chunks[keep2 - 1];
|
|
16166
|
+
const from = size - (keep2 - 1) * CHUNK3;
|
|
15496
16167
|
if (tail && from < tail.length) tail.fill(0, from);
|
|
15497
16168
|
}
|
|
15498
16169
|
this.size = size;
|
|
@@ -15737,8 +16408,8 @@ function importedMemory(bytes) {
|
|
|
15737
16408
|
at = end;
|
|
15738
16409
|
continue;
|
|
15739
16410
|
}
|
|
15740
|
-
const
|
|
15741
|
-
for (let i = 0; i <
|
|
16411
|
+
const count2 = u32();
|
|
16412
|
+
for (let i = 0; i < count2; i++) {
|
|
15742
16413
|
const module = name2();
|
|
15743
16414
|
const field3 = name2();
|
|
15744
16415
|
const kind = bytes[at++];
|
|
@@ -16167,7 +16838,7 @@ ${lines2}
|
|
|
16167
16838
|
const withdraw = () => control.abort("withdrawn");
|
|
16168
16839
|
requester.addEventListener("abort", withdraw, { once: true });
|
|
16169
16840
|
const aborted2 = new Promise(
|
|
16170
|
-
(
|
|
16841
|
+
(resolve2) => control.signal.addEventListener("abort", () => resolve2("aborted"), { once: true })
|
|
16171
16842
|
);
|
|
16172
16843
|
try {
|
|
16173
16844
|
const answered = Promise.resolve().then(() => approve(req, { signal: control.signal })).catch(() => "deny");
|
|
@@ -16293,7 +16964,7 @@ var LAYOUT = [
|
|
|
16293
16964
|
];
|
|
16294
16965
|
var LOAD_SAMPLE_MS = 5e3;
|
|
16295
16966
|
var LOAD_WINDOWS_MS = [6e4, 3e5, 9e5];
|
|
16296
|
-
var
|
|
16967
|
+
var encoder7 = new TextEncoder();
|
|
16297
16968
|
var USERS_MODES = ["off", "report", "enforce"];
|
|
16298
16969
|
function usersMode(mode = "off") {
|
|
16299
16970
|
if (USERS_MODES.includes(mode)) return mode;
|
|
@@ -16324,6 +16995,30 @@ function shebang(head) {
|
|
|
16324
16995
|
if (head[0] !== 35 || head[1] !== 33) return void 0;
|
|
16325
16996
|
return new TextDecoder().decode(head.subarray(0, SHEBANG_MAX)).slice(2).split("\n")[0].trim().split(/[ \t]+/);
|
|
16326
16997
|
}
|
|
16998
|
+
async function rootOnly(fs, path) {
|
|
16999
|
+
const names = chain(path);
|
|
17000
|
+
for (const [i, at] of names.entries()) {
|
|
17001
|
+
const st = await fs.lstat(at).catch(() => void 0);
|
|
17002
|
+
const kind = i === names.length - 1 ? st?.isFile : st?.isDirectory;
|
|
17003
|
+
if (!kind || st?.uid !== 0 || (st.mode & 18) !== 0) return false;
|
|
17004
|
+
}
|
|
17005
|
+
return true;
|
|
17006
|
+
}
|
|
17007
|
+
function plainEnv(words2) {
|
|
17008
|
+
const next2 = words2[1];
|
|
17009
|
+
if (baseName(words2[0] ?? "") !== "env" || next2 === void 0) return false;
|
|
17010
|
+
return next2 === "-S" || !next2.startsWith("-") && !next2.includes("=");
|
|
17011
|
+
}
|
|
17012
|
+
function shebangCommand(words2) {
|
|
17013
|
+
if (!plainEnv(words2)) {
|
|
17014
|
+
const arg2 = words2.slice(1).join(" ");
|
|
17015
|
+
return { interp: words2[0], args: arg2 ? [arg2] : [] };
|
|
17016
|
+
}
|
|
17017
|
+
const split2 = words2[1] === "-S";
|
|
17018
|
+
const [interp, ...rest2] = words2.slice(split2 ? 2 : 1);
|
|
17019
|
+
const arg = rest2.join(" ");
|
|
17020
|
+
return { interp, args: split2 ? rest2 : arg ? [arg] : [] };
|
|
17021
|
+
}
|
|
16327
17022
|
function interpreter(head) {
|
|
16328
17023
|
const words2 = shebang(head);
|
|
16329
17024
|
if (!words2) return "node";
|
|
@@ -16377,7 +17072,7 @@ function childHandle(handle) {
|
|
|
16377
17072
|
onState: (listener) => handle.onState(listener)
|
|
16378
17073
|
};
|
|
16379
17074
|
}
|
|
16380
|
-
function
|
|
17075
|
+
function concat6(chunks2) {
|
|
16381
17076
|
const out = new Uint8Array(chunks2.reduce((n, chunk2) => n + chunk2.length, 0));
|
|
16382
17077
|
let offset = 0;
|
|
16383
17078
|
for (const chunk2 of chunks2) {
|
|
@@ -16463,6 +17158,7 @@ var Launcher = class {
|
|
|
16463
17158
|
usersMode;
|
|
16464
17159
|
dac;
|
|
16465
17160
|
sealed;
|
|
17161
|
+
scrubs = /* @__PURE__ */ new Map();
|
|
16466
17162
|
clipboard;
|
|
16467
17163
|
rootFs;
|
|
16468
17164
|
fileWatches;
|
|
@@ -16486,6 +17182,8 @@ var Launcher = class {
|
|
|
16486
17182
|
void 0,
|
|
16487
17183
|
(pid) => this.tagOf(pid)
|
|
16488
17184
|
);
|
|
17185
|
+
this.sealed.tickets.normalise = (path) => physicalPathAsync(this.base, path);
|
|
17186
|
+
this.sealed.userOf = async (uid) => (await this.users.lookup(uid))?.name;
|
|
16489
17187
|
if (this.owners) options.fs.trackOwners?.();
|
|
16490
17188
|
this.mounts = new MountTable({
|
|
16491
17189
|
open: (type, spec) => this.driver(type, spec),
|
|
@@ -16734,13 +17432,12 @@ var Launcher = class {
|
|
|
16734
17432
|
const binfmt = isWasm(head) ? void 0 : binfmtOf(await this.interpreters(scope), script);
|
|
16735
17433
|
const words2 = shebang(head) ?? (binfmt ? [binfmt] : void 0);
|
|
16736
17434
|
if (!words2) return void 0;
|
|
16737
|
-
|
|
16738
|
-
const [
|
|
16739
|
-
|
|
16740
|
-
const
|
|
16741
|
-
const found = interp ? await this.resolve(interp, interp, cwd, scope) : void 0;
|
|
17435
|
+
const { interp, args } = shebangCommand(words2);
|
|
17436
|
+
const passed = [...args, command ? script : file, ...argv.slice(1)];
|
|
17437
|
+
if (!interp) return void 0;
|
|
17438
|
+
const found = await this.resolve(interp, interp, cwd, scope);
|
|
16742
17439
|
if (!found) {
|
|
16743
|
-
if (
|
|
17440
|
+
if (depth >= MAX_INTERPRETERS || !await this.scriptCommand(interp, cwd, scope)) {
|
|
16744
17441
|
return void 0;
|
|
16745
17442
|
}
|
|
16746
17443
|
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
@@ -16780,6 +17477,99 @@ var Launcher = class {
|
|
|
16780
17477
|
await need(g, "exec", this.fs.resolvePath(req.cwd, file), want);
|
|
16781
17478
|
}
|
|
16782
17479
|
}
|
|
17480
|
+
async checkedPlan(req, { ppid, cred, scope }, fds) {
|
|
17481
|
+
const planned = await this.plan(req.file, req.argv, req.cwd, scope, req.argv0);
|
|
17482
|
+
try {
|
|
17483
|
+
await this.mayExec(cred, { ...req, pid: ppid }, planned);
|
|
17484
|
+
} catch (err) {
|
|
17485
|
+
await fds.closeAll();
|
|
17486
|
+
throw err.code === "EACCES" ? new SpawnError("EACCES") : err;
|
|
17487
|
+
}
|
|
17488
|
+
if (planned) return planned;
|
|
17489
|
+
await fds.closeAll();
|
|
17490
|
+
throw new SpawnError(await this.unrunnable(req.file, req.cwd, scope));
|
|
17491
|
+
}
|
|
17492
|
+
async ticketFile(req, fds) {
|
|
17493
|
+
if (req.file.startsWith("/")) return physicalPathAsync(this.base, req.file);
|
|
17494
|
+
await fds.closeAll();
|
|
17495
|
+
throw new SpawnError("EACCES");
|
|
17496
|
+
}
|
|
17497
|
+
takeTicket(req) {
|
|
17498
|
+
if (!(TICKET_ENV in req.env)) return void 0;
|
|
17499
|
+
return this.sealed.tickets.take(req.env[TICKET_ENV] ?? "") ?? null;
|
|
17500
|
+
}
|
|
17501
|
+
async redeemed(req, who, planned, fds) {
|
|
17502
|
+
if (who.booked === void 0) return { env: req.env };
|
|
17503
|
+
try {
|
|
17504
|
+
const redeemed = await this.redeem(req, who, planned);
|
|
17505
|
+
if (redeemed.scrub) scrubStdio(fds, redeemed.scrub);
|
|
17506
|
+
return redeemed;
|
|
17507
|
+
} catch {
|
|
17508
|
+
await fds.closeAll();
|
|
17509
|
+
throw new SpawnError("EACCES");
|
|
17510
|
+
}
|
|
17511
|
+
}
|
|
17512
|
+
async redeem(req, { ppid, cred, scope, booked }, planned) {
|
|
17513
|
+
const { [TICKET_ENV]: ticket = "", ...env } = req.env;
|
|
17514
|
+
const caller = this.jobs.shown(ppid);
|
|
17515
|
+
const named = typeof req.argv0 === "string" && !planned.script && !planned.target.fixed;
|
|
17516
|
+
const argv = named ? [req.argv0, ...req.argv.slice(1)] : req.argv;
|
|
17517
|
+
const exact = booked?.pid === caller && req.file === booked.path && await physicalPathAsync(this.base, req.cwd) === booked.cwd && await argvDigest(argv) === booked.argv;
|
|
17518
|
+
if (!exact) throw new SpawnError("EACCES");
|
|
17519
|
+
const { requested: path, requestedCwd: cwd, path: resolved2 } = booked;
|
|
17520
|
+
const pid = this.nextPid++;
|
|
17521
|
+
const ids = { pid: req.exec ? caller : pid, ppid: caller };
|
|
17522
|
+
const stamp = await this.sealed.stamp(ids, cred, this.tagOf(ppid));
|
|
17523
|
+
const interpreters = await this.interpreterChain(planned, booked.cwd, scope);
|
|
17524
|
+
const trusted = this.usersMode === "enforce" && await this.trustedFiles(planned, req.file, booked.cwd, scope);
|
|
17525
|
+
const swap = await this.sealed.consume({
|
|
17526
|
+
ticket,
|
|
17527
|
+
stamp,
|
|
17528
|
+
path,
|
|
17529
|
+
resolved: resolved2,
|
|
17530
|
+
argv,
|
|
17531
|
+
cwd,
|
|
17532
|
+
interpreters,
|
|
17533
|
+
trusted
|
|
17534
|
+
});
|
|
17535
|
+
if (!swap) throw new SpawnError("EACCES");
|
|
17536
|
+
const secrets = [];
|
|
17537
|
+
for (const [name2, placeholder] of Object.entries(swap.placeholders)) {
|
|
17538
|
+
const value = swap.values[name2];
|
|
17539
|
+
if (value === void 0 || env[name2] !== placeholder) continue;
|
|
17540
|
+
env[name2] = value;
|
|
17541
|
+
secrets.push({ name: name2, value, placeholder });
|
|
17542
|
+
}
|
|
17543
|
+
const scrub = scrubberOf(secrets);
|
|
17544
|
+
return { env, pid, cwd: booked.cwd, ...scrub ? { scrub } : {} };
|
|
17545
|
+
}
|
|
17546
|
+
async interpreterChain(planned, cwd, scope) {
|
|
17547
|
+
const out = [];
|
|
17548
|
+
for (const entry of planned.via ?? []) {
|
|
17549
|
+
if (entry.includes("/")) {
|
|
17550
|
+
out.push(await physicalPathAsync(this.base, this.fs.resolvePath(cwd, entry)));
|
|
17551
|
+
continue;
|
|
17552
|
+
}
|
|
17553
|
+
const script = (await this.scriptCommand(entry, cwd, scope))?.script;
|
|
17554
|
+
out.push(
|
|
17555
|
+
await physicalPathAsync(this.base, script ?? await this.commandFile(entry, cwd, scope))
|
|
17556
|
+
);
|
|
17557
|
+
}
|
|
17558
|
+
return out;
|
|
17559
|
+
}
|
|
17560
|
+
async commandFile(name2, cwd, scope) {
|
|
17561
|
+
const scoped = await this.resolve(name2, name2, cwd, scope);
|
|
17562
|
+
const system = scope === "" ? scoped : await this.resolve(name2, name2, cwd, "");
|
|
17563
|
+
if (!scoped || system?.glue === scoped.glue) return `/usr/bin/${name2}`;
|
|
17564
|
+
return scoped.glue;
|
|
17565
|
+
}
|
|
17566
|
+
async trustedFiles(planned, file, cwd, scope) {
|
|
17567
|
+
const files = await this.backingOf(planned, file, cwd, scope);
|
|
17568
|
+
for (const at of files) {
|
|
17569
|
+
if (!await rootOnly(this.base, await physicalPathAsync(this.base, at))) return false;
|
|
17570
|
+
}
|
|
17571
|
+
return true;
|
|
17572
|
+
}
|
|
16783
17573
|
async grantedCwd(caller, cwd) {
|
|
16784
17574
|
const real = await physicalPathAsync(this.base, cwd).catch(() => void 0);
|
|
16785
17575
|
return real === cwd && await this.sudoer.reachable(caller, cwd);
|
|
@@ -16798,13 +17588,15 @@ var Launcher = class {
|
|
|
16798
17588
|
}
|
|
16799
17589
|
async backing(file, cwd) {
|
|
16800
17590
|
const planned = await this.plan(file, [file], cwd, "");
|
|
16801
|
-
|
|
17591
|
+
return planned && this.backingOf(planned, file, cwd, "");
|
|
17592
|
+
}
|
|
17593
|
+
async backingOf(planned, file, cwd, scope) {
|
|
16802
17594
|
const { glue, wasm, imports } = planned.target;
|
|
16803
17595
|
const files = [glue, wasm, ...imports ? [imports] : []];
|
|
16804
17596
|
const scripts = [];
|
|
16805
17597
|
for (const name2 of [file, ...planned.via ?? []]) {
|
|
16806
17598
|
if (name2.includes("/") && !COMMAND2.test(name2)) scripts.push(this.fs.resolvePath(cwd, name2));
|
|
16807
|
-
const script = (await this.scriptCommand(name2, cwd,
|
|
17599
|
+
const script = (await this.scriptCommand(name2, cwd, scope))?.script;
|
|
16808
17600
|
if (script) scripts.push(script);
|
|
16809
17601
|
}
|
|
16810
17602
|
files.push(...scripts, ...await this.binfmtManifests(scripts));
|
|
@@ -16933,6 +17725,7 @@ var Launcher = class {
|
|
|
16933
17725
|
const seen = { ...req.env, HOSTNAME: this.hostname, cwd };
|
|
16934
17726
|
const env = { ...expandDefaults(target.env, seen), ...req.env };
|
|
16935
17727
|
for (const key of target.unset ?? []) delete env[key];
|
|
17728
|
+
delete env[TICKET_ENV];
|
|
16936
17729
|
env.HOSTNAME = this.hostname;
|
|
16937
17730
|
let program;
|
|
16938
17731
|
try {
|
|
@@ -16948,16 +17741,23 @@ var Launcher = class {
|
|
|
16948
17741
|
groupSession(pgid) {
|
|
16949
17742
|
return this.jobs.sessionOf(pgid);
|
|
16950
17743
|
}
|
|
17744
|
+
treeScrubs(pid, req) {
|
|
17745
|
+
const inherited2 = req.ppid !== void 0 ? this.scrubs.get(req.ppid) : void 0;
|
|
17746
|
+
const scrubs = req.scrub ? [...inherited2 ?? [], req.scrub] : inherited2;
|
|
17747
|
+
if (scrubs) this.scrubs.set(pid, scrubs);
|
|
17748
|
+
return scrubs;
|
|
17749
|
+
}
|
|
16951
17750
|
start(req) {
|
|
16952
17751
|
this.sampling();
|
|
16953
17752
|
if (req.pgid !== void 0 && this.jobs.sessionOf(req.pgid) === void 0) {
|
|
16954
17753
|
throw new SpawnError("ESRCH");
|
|
16955
17754
|
}
|
|
16956
|
-
const pid = this.nextPid++;
|
|
17755
|
+
const pid = req.pid ?? this.nextPid++;
|
|
17756
|
+
const scrubs = this.treeScrubs(pid, req);
|
|
16957
17757
|
const stack = this.stackFor(req.tag);
|
|
16958
17758
|
const terminal = req.fds.stdioTerminal();
|
|
16959
17759
|
const decided = req.decided ?? Promise.resolve(true);
|
|
16960
|
-
const
|
|
17760
|
+
const count2 = (byParent) => {
|
|
16961
17761
|
this.identities.asked++;
|
|
16962
17762
|
if (!byParent) this.identities.timedOut++;
|
|
16963
17763
|
};
|
|
@@ -16965,7 +17765,7 @@ var Launcher = class {
|
|
|
16965
17765
|
const handle = spawnWasmProcess({
|
|
16966
17766
|
pid,
|
|
16967
17767
|
identity: async () => {
|
|
16968
|
-
await (asked ??= decided.then(
|
|
17768
|
+
await (asked ??= decided.then(count2));
|
|
16969
17769
|
return this.identityOf(pid);
|
|
16970
17770
|
},
|
|
16971
17771
|
onSyscall: (call) => {
|
|
@@ -16979,6 +17779,7 @@ var Launcher = class {
|
|
|
16979
17779
|
...this.owners && req.program.abi === "wasi" ? { fresh: (path, umask) => this.freshModules.add(path, umask, pid) } : {},
|
|
16980
17780
|
...this.owners ? { owners: true } : {},
|
|
16981
17781
|
sealed: this.sealed,
|
|
17782
|
+
...scrubs ? { ttyFilter: (file) => scrubbedAll(file, scrubs) } : {},
|
|
16982
17783
|
clipboard: this.clipboard,
|
|
16983
17784
|
...this.dac ? { dac: this.dac } : {},
|
|
16984
17785
|
program: req.program,
|
|
@@ -17045,6 +17846,7 @@ var Launcher = class {
|
|
|
17045
17846
|
if (spent) addTimes(this.imageTimes, this.jobs.shown(pid), spent);
|
|
17046
17847
|
this.stopped.delete(pid);
|
|
17047
17848
|
this.processes.delete(pid);
|
|
17849
|
+
this.scrubs.delete(pid);
|
|
17048
17850
|
if (this.processes.size === 0) {
|
|
17049
17851
|
clearInterval(this.sampler);
|
|
17050
17852
|
this.sampler = void 0;
|
|
@@ -17216,6 +18018,7 @@ var Launcher = class {
|
|
|
17216
18018
|
}
|
|
17217
18019
|
spawner(ppid, report) {
|
|
17218
18020
|
return async (req, fds, grant) => {
|
|
18021
|
+
const booked = this.takeTicket(req);
|
|
17219
18022
|
if (grant && !await this.grantedCwd(grant.caller, req.cwd)) {
|
|
17220
18023
|
await fds.closeAll();
|
|
17221
18024
|
throw new SpawnError("EACCES");
|
|
@@ -17227,23 +18030,20 @@ var Launcher = class {
|
|
|
17227
18030
|
}
|
|
17228
18031
|
const cred = grant ? grant.cred : this.credOf(ppid);
|
|
17229
18032
|
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
|
-
}
|
|
18033
|
+
const file = booked === void 0 ? req.file : await this.ticketFile(req, fds);
|
|
18034
|
+
const planned = await this.checkedPlan({ ...req, file }, { ppid, cred, scope }, fds);
|
|
18035
|
+
const redeemed = await this.redeemed(
|
|
18036
|
+
{ ...req, file },
|
|
18037
|
+
{ ppid, cred, scope, booked },
|
|
18038
|
+
planned,
|
|
18039
|
+
fds
|
|
18040
|
+
);
|
|
17241
18041
|
const exec = req.exec ? { exec: true } : {};
|
|
17242
18042
|
const deciding = req.exec ? void 0 : this.undecided(ppid);
|
|
17243
18043
|
const handle = await this.launch(planned, {
|
|
17244
18044
|
...deciding ? { decided: deciding.promise } : {},
|
|
17245
|
-
env: req.env,
|
|
17246
18045
|
cwd: req.cwd,
|
|
18046
|
+
...redeemed,
|
|
17247
18047
|
fds,
|
|
17248
18048
|
report,
|
|
17249
18049
|
ppid,
|
|
@@ -17296,11 +18096,11 @@ var Launcher = class {
|
|
|
17296
18096
|
if (!waiting) return;
|
|
17297
18097
|
this.deciding.delete(ppid);
|
|
17298
18098
|
setTimeout(() => {
|
|
17299
|
-
for (const
|
|
18099
|
+
for (const resolve2 of waiting) resolve2(true);
|
|
17300
18100
|
}, 0);
|
|
17301
18101
|
}
|
|
17302
18102
|
forker(ppid, parent) {
|
|
17303
|
-
const { exec: _exec, pgid: _pgid, group: _group, ...image } = parent;
|
|
18103
|
+
const { exec: _exec, pgid: _pgid, group: _group, pid: _pid, scrub: _scrub, ...image } = parent;
|
|
17304
18104
|
return async (state, fds) => childHandle(
|
|
17305
18105
|
this.start({
|
|
17306
18106
|
...image,
|
|
@@ -17334,7 +18134,7 @@ var Launcher = class {
|
|
|
17334
18134
|
}
|
|
17335
18135
|
}
|
|
17336
18136
|
umaskOf(pid) {
|
|
17337
|
-
return this.processes.get(pid)?.umask?.() ??
|
|
18137
|
+
return this.processes.get(pid)?.umask?.() ?? DEFAULT_UMASK2;
|
|
17338
18138
|
}
|
|
17339
18139
|
imageOf(pid) {
|
|
17340
18140
|
const members = this.jobs.list();
|
|
@@ -17677,7 +18477,14 @@ var Launcher = class {
|
|
|
17677
18477
|
);
|
|
17678
18478
|
}
|
|
17679
18479
|
environment(cwd, extra, account) {
|
|
17680
|
-
|
|
18480
|
+
const env = {
|
|
18481
|
+
...this.env,
|
|
18482
|
+
...userEnv(account, this.pnpmHome),
|
|
18483
|
+
PWD: cwd,
|
|
18484
|
+
...extra
|
|
18485
|
+
};
|
|
18486
|
+
delete env[TICKET_ENV];
|
|
18487
|
+
return env;
|
|
17681
18488
|
}
|
|
17682
18489
|
async account(user) {
|
|
17683
18490
|
if (typeof user === "object") return user;
|
|
@@ -17773,7 +18580,7 @@ var Launcher = class {
|
|
|
17773
18580
|
},
|
|
17774
18581
|
account
|
|
17775
18582
|
);
|
|
17776
|
-
const report = (message3) => options.onData(
|
|
18583
|
+
const report = (message3) => options.onData(encoder7.encode(`${message3}\r
|
|
17777
18584
|
`));
|
|
17778
18585
|
const handle = await this.launch(planned, {
|
|
17779
18586
|
env,
|
|
@@ -17804,18 +18611,18 @@ var Launcher = class {
|
|
|
17804
18611
|
const env = this.environment(cwd, options.env, account);
|
|
17805
18612
|
const out = [];
|
|
17806
18613
|
const err = [];
|
|
17807
|
-
const
|
|
18614
|
+
const keep2 = options.collect !== false;
|
|
17808
18615
|
const collect = (chunks2, tee) => (bytes) => {
|
|
17809
|
-
if (
|
|
18616
|
+
if (keep2) chunks2.push(bytes);
|
|
17810
18617
|
tee?.(bytes);
|
|
17811
18618
|
};
|
|
17812
18619
|
const stdout = collect(out, options.onStdout);
|
|
17813
18620
|
const stderr = collect(err, options.onStderr);
|
|
17814
|
-
const report = (message3) => stderr(
|
|
18621
|
+
const report = (message3) => stderr(encoder7.encode(`${message3}
|
|
17815
18622
|
`));
|
|
17816
18623
|
if (!planned) {
|
|
17817
18624
|
report(`${file}: command not found`);
|
|
17818
|
-
return { status: NOT_FOUND, stdout:
|
|
18625
|
+
return { status: NOT_FOUND, stdout: concat6(out), stderr: concat6(err) };
|
|
17819
18626
|
}
|
|
17820
18627
|
const fds = new FdTable();
|
|
17821
18628
|
fds.installAt(0, options.stdin ? bytesSource(options.stdin) : deviceFile("null"));
|
|
@@ -17833,10 +18640,115 @@ var Launcher = class {
|
|
|
17833
18640
|
options.onStarted?.(handle.pid);
|
|
17834
18641
|
const status = await handle.exited;
|
|
17835
18642
|
const signal = handle.termsig();
|
|
17836
|
-
return { status, ...signal ? { signal } : {}, stdout:
|
|
18643
|
+
return { status, ...signal ? { signal } : {}, stdout: concat6(out), stderr: concat6(err) };
|
|
17837
18644
|
}
|
|
17838
18645
|
};
|
|
17839
18646
|
|
|
18647
|
+
// src/node/loopback.ts
|
|
18648
|
+
import { lookup } from "node:dns/promises";
|
|
18649
|
+
import { isIP } from "node:net";
|
|
18650
|
+
var DEVTOOLS_PORTS = [9222, 9223, 9224, 9225, 9226, 9227, 9228, 9229];
|
|
18651
|
+
var METADATA_V6 = [64768, 3778, 0, 0, 0, 0, 0, 596].join(":");
|
|
18652
|
+
var resolveHost = async (host) => (await lookup(host, { all: true, verbatim: true })).map((a) => a.address);
|
|
18653
|
+
function ipv4Place(address) {
|
|
18654
|
+
const [a, b] = address.split(".").map(Number);
|
|
18655
|
+
if (a === 127 || a === 0) return "loopback";
|
|
18656
|
+
if (a === 169 && b === 254) return "link-local";
|
|
18657
|
+
return void 0;
|
|
18658
|
+
}
|
|
18659
|
+
function placeOf(address) {
|
|
18660
|
+
const plain = address.replace(/^\[(.*)\]$/, "$1").toLowerCase();
|
|
18661
|
+
const kind = isIP(plain);
|
|
18662
|
+
if (kind === 4) return ipv4Place(plain);
|
|
18663
|
+
if (kind !== 6) return void 0;
|
|
18664
|
+
const words2 = hextets2(plain);
|
|
18665
|
+
const embedded2 = words2.slice(0, 5).every((w) => w === 0) && (words2[5] === 65535 || words2[5] === 0);
|
|
18666
|
+
if (embedded2 && (words2[5] === 65535 || words2[6] !== 0)) return ipv4Place(ipv4Of(words2));
|
|
18667
|
+
if (words2.slice(0, 7).every((w) => w === 0) && (words2[7] ?? 0) <= 1) return "loopback";
|
|
18668
|
+
if (((words2[0] ?? 0) & 65472) === 65152) return "link-local";
|
|
18669
|
+
if (words2.join(":") === METADATA_V6) return "link-local";
|
|
18670
|
+
return void 0;
|
|
18671
|
+
}
|
|
18672
|
+
function ipv4Of(words2) {
|
|
18673
|
+
const [high = 0, low = 0] = words2.slice(6);
|
|
18674
|
+
return [high >> 8, high & 255, low >> 8, low & 255].join(".");
|
|
18675
|
+
}
|
|
18676
|
+
function hextets2(address) {
|
|
18677
|
+
const dotted = /(\d+\.\d+\.\d+\.\d+)$/.exec(address)?.[1];
|
|
18678
|
+
let text = address;
|
|
18679
|
+
if (dotted) {
|
|
18680
|
+
const [a, b, c, d] = dotted.split(".").map(Number);
|
|
18681
|
+
text = `${address.slice(0, -dotted.length)}${(a << 8 | b).toString(16)}:${(c << 8 | d).toString(16)}`;
|
|
18682
|
+
}
|
|
18683
|
+
const [head = "", tail] = text.split("::");
|
|
18684
|
+
const part = (side) => side ? side.split(":").map((w) => Number.parseInt(w, 16)) : [];
|
|
18685
|
+
const left = part(head);
|
|
18686
|
+
const right = tail === void 0 ? [] : part(tail);
|
|
18687
|
+
const gap = Array(8 - left.length - right.length).fill(0);
|
|
18688
|
+
return [...left, ...gap, ...right];
|
|
18689
|
+
}
|
|
18690
|
+
function loopbackName2(host) {
|
|
18691
|
+
const name2 = host.toLowerCase().replace(/\.$/, "");
|
|
18692
|
+
return name2 === "localhost" || name2.endsWith(".localhost");
|
|
18693
|
+
}
|
|
18694
|
+
function portOf(url) {
|
|
18695
|
+
if (url.port) return Number(url.port);
|
|
18696
|
+
return url.protocol === "https:" || url.protocol === "wss:" ? 443 : 80;
|
|
18697
|
+
}
|
|
18698
|
+
function allows(policy, port) {
|
|
18699
|
+
if (Array.isArray(policy)) return policy.includes(port);
|
|
18700
|
+
return policy === true && !DEVTOOLS_PORTS.includes(port);
|
|
18701
|
+
}
|
|
18702
|
+
function refusal(url, address, place) {
|
|
18703
|
+
const where = `${address}:${portOf(url)}`;
|
|
18704
|
+
const why = place === "link-local" ? `nodeTransport refuses link-local ${where}` : `nodeTransport refuses the host's loopback ${where} (see nodeTransport({ hostLoopback }))`;
|
|
18705
|
+
return Object.assign(new Error(why), { status: 403, code: "EACCES" });
|
|
18706
|
+
}
|
|
18707
|
+
async function addressesOf(host, resolve2) {
|
|
18708
|
+
const plain = host.replace(/^\[(.*)\]$/, "$1");
|
|
18709
|
+
if (isIP(plain)) return [plain];
|
|
18710
|
+
if (loopbackName2(plain)) return ["127.0.0.1"];
|
|
18711
|
+
return resolve2(plain).catch(() => []);
|
|
18712
|
+
}
|
|
18713
|
+
async function checkDestination(target, policy, resolve2 = resolveHost) {
|
|
18714
|
+
const url = new URL(target);
|
|
18715
|
+
for (const address of await addressesOf(url.hostname, resolve2)) {
|
|
18716
|
+
const place = placeOf(address);
|
|
18717
|
+
if (!place) continue;
|
|
18718
|
+
if (place === "loopback" && allows(policy, portOf(url))) continue;
|
|
18719
|
+
throw refusal(url, address, place);
|
|
18720
|
+
}
|
|
18721
|
+
}
|
|
18722
|
+
function guarded2(check, signal) {
|
|
18723
|
+
if (!signal) return check;
|
|
18724
|
+
signal.throwIfAborted();
|
|
18725
|
+
let stop = () => {
|
|
18726
|
+
};
|
|
18727
|
+
const aborted2 = new Promise((_, reject) => {
|
|
18728
|
+
stop = () => reject(signal.reason);
|
|
18729
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
18730
|
+
});
|
|
18731
|
+
return Promise.race([check, aborted2]).finally(() => signal.removeEventListener("abort", stop));
|
|
18732
|
+
}
|
|
18733
|
+
function guardedLoopback(transport, policy, resolve2) {
|
|
18734
|
+
const open = transport.websocket?.bind(transport);
|
|
18735
|
+
return {
|
|
18736
|
+
get traits() {
|
|
18737
|
+
return transport.traits;
|
|
18738
|
+
},
|
|
18739
|
+
fetch: async (request, owner) => {
|
|
18740
|
+
await guarded2(checkDestination(request.url, policy, resolve2), request.signal);
|
|
18741
|
+
return transport.fetch(request, owner);
|
|
18742
|
+
},
|
|
18743
|
+
...open ? {
|
|
18744
|
+
websocket: async (request) => {
|
|
18745
|
+
await guarded2(checkDestination(request.url, policy, resolve2), request.signal);
|
|
18746
|
+
return open(request);
|
|
18747
|
+
}
|
|
18748
|
+
} : {}
|
|
18749
|
+
};
|
|
18750
|
+
}
|
|
18751
|
+
|
|
17840
18752
|
// src/node/memory-root.ts
|
|
17841
18753
|
var fail2 = (name2) => {
|
|
17842
18754
|
throw new DOMException(name2, name2);
|
|
@@ -17902,10 +18814,10 @@ var Chunks = class {
|
|
|
17902
18814
|
this.grow(size);
|
|
17903
18815
|
return;
|
|
17904
18816
|
}
|
|
17905
|
-
const
|
|
17906
|
-
this.blobs.length =
|
|
17907
|
-
if (
|
|
17908
|
-
this.blobs[
|
|
18817
|
+
const keep2 = Math.ceil(size / CHUNK4);
|
|
18818
|
+
this.blobs.length = keep2;
|
|
18819
|
+
if (keep2 > 0)
|
|
18820
|
+
this.blobs[keep2 - 1] = this.blobs[keep2 - 1].slice(0, size - (keep2 - 1) * CHUNK4);
|
|
17909
18821
|
this.size = size;
|
|
17910
18822
|
}
|
|
17911
18823
|
};
|
|
@@ -18043,8 +18955,8 @@ function isMemoryRoot(handle) {
|
|
|
18043
18955
|
}
|
|
18044
18956
|
|
|
18045
18957
|
// src/node/ws-diagnose.ts
|
|
18046
|
-
import { lookup } from "node:dns/promises";
|
|
18047
|
-
import { isIP, connect as tcp } from "node:net";
|
|
18958
|
+
import { lookup as lookup2 } from "node:dns/promises";
|
|
18959
|
+
import { isIP as isIP2, connect as tcp } from "node:net";
|
|
18048
18960
|
import { connect as tls } from "node:tls";
|
|
18049
18961
|
var PROBE_MS = 3e3;
|
|
18050
18962
|
var PASSED = /* @__PURE__ */ new Set(["ECONNREFUSED", "EHOSTUNREACH", "ENETUNREACH", "ETIMEDOUT", "ECONNRESET"]);
|
|
@@ -18054,12 +18966,12 @@ function codeOf5(e) {
|
|
|
18054
18966
|
return typeof code === "string" ? code : void 0;
|
|
18055
18967
|
}
|
|
18056
18968
|
function probe(secure, host, port, ms) {
|
|
18057
|
-
return new Promise((
|
|
18058
|
-
const socket = secure ? tls({ host, port, ...
|
|
18969
|
+
return new Promise((resolve2) => {
|
|
18970
|
+
const socket = secure ? tls({ host, port, ...isIP2(host) ? {} : { servername: host } }) : tcp({ host, port });
|
|
18059
18971
|
const done4 = (code) => {
|
|
18060
18972
|
clearTimeout(timer);
|
|
18061
18973
|
socket.destroy();
|
|
18062
|
-
|
|
18974
|
+
resolve2(code);
|
|
18063
18975
|
};
|
|
18064
18976
|
const timer = setTimeout(() => done4("ETIMEDOUT"), ms);
|
|
18065
18977
|
socket.once(secure ? "secureConnect" : "connect", () => done4("EPROTO"));
|
|
@@ -18075,7 +18987,7 @@ async function diagnose(url, ms = PROBE_MS) {
|
|
|
18075
18987
|
const secure = at.protocol === "wss:";
|
|
18076
18988
|
const port = Number(at.port) || (secure ? 443 : 80);
|
|
18077
18989
|
try {
|
|
18078
|
-
await
|
|
18990
|
+
await lookup2(host);
|
|
18079
18991
|
} catch (e) {
|
|
18080
18992
|
return NO_NAME.has(codeOf5(e) ?? "") ? "EAI_NONAME" : void 0;
|
|
18081
18993
|
}
|
|
@@ -18151,8 +19063,8 @@ var RemoteTransport = class {
|
|
|
18151
19063
|
}
|
|
18152
19064
|
ask(call) {
|
|
18153
19065
|
if (this.failure) return Promise.reject(this.failure);
|
|
18154
|
-
return new Promise((
|
|
18155
|
-
this.waiting.set(call.nid, { resolve, reject });
|
|
19066
|
+
return new Promise((resolve2, reject) => {
|
|
19067
|
+
this.waiting.set(call.nid, { resolve: resolve2, reject });
|
|
18156
19068
|
this.port.postMessage(call);
|
|
18157
19069
|
});
|
|
18158
19070
|
}
|
|
@@ -18332,7 +19244,7 @@ function dialStream(port, onClose) {
|
|
|
18332
19244
|
write(chunk2) {
|
|
18333
19245
|
if (closed) throw errorWithCode("EPIPE: the connection is closed");
|
|
18334
19246
|
const copy = fresh(chunk2);
|
|
18335
|
-
const acked = new Promise((
|
|
19247
|
+
const acked = new Promise((resolve2, reject) => acks.push({ resolve: resolve2, reject }));
|
|
18336
19248
|
port.postMessage(copy, [copy.buffer]);
|
|
18337
19249
|
return acked;
|
|
18338
19250
|
},
|
|
@@ -18352,7 +19264,7 @@ function dialStream(port, onClose) {
|
|
|
18352
19264
|
|
|
18353
19265
|
// src/client/loopback-fetch.ts
|
|
18354
19266
|
var OWN_HEADERS = /* @__PURE__ */ new Set(["host", "connection", "content-length", "transfer-encoding"]);
|
|
18355
|
-
var
|
|
19267
|
+
var encoder8 = new TextEncoder();
|
|
18356
19268
|
var latin12 = new TextDecoder("latin1");
|
|
18357
19269
|
var ByteSource = class {
|
|
18358
19270
|
buffered = new Uint8Array(0);
|
|
@@ -18370,7 +19282,7 @@ var ByteSource = class {
|
|
|
18370
19282
|
return true;
|
|
18371
19283
|
}
|
|
18372
19284
|
async until(marker) {
|
|
18373
|
-
const needle =
|
|
19285
|
+
const needle = encoder8.encode(marker);
|
|
18374
19286
|
for (; ; ) {
|
|
18375
19287
|
const at = indexOf(this.buffered, needle);
|
|
18376
19288
|
if (at >= 0) return this.take(at + needle.length);
|
|
@@ -18381,13 +19293,13 @@ var ByteSource = class {
|
|
|
18381
19293
|
if (this.buffered.length === 0 && !await this.more()) return void 0;
|
|
18382
19294
|
return this.take(Math.min(max, this.buffered.length));
|
|
18383
19295
|
}
|
|
18384
|
-
async exactly(
|
|
18385
|
-
while (this.buffered.length <
|
|
18386
|
-
return this.take(
|
|
19296
|
+
async exactly(count2) {
|
|
19297
|
+
while (this.buffered.length < count2) if (!await this.more()) return void 0;
|
|
19298
|
+
return this.take(count2);
|
|
18387
19299
|
}
|
|
18388
|
-
take(
|
|
18389
|
-
const out = this.buffered.slice(0,
|
|
18390
|
-
this.buffered = this.buffered.slice(
|
|
19300
|
+
take(count2) {
|
|
19301
|
+
const out = this.buffered.slice(0, count2);
|
|
19302
|
+
this.buffered = this.buffered.slice(count2);
|
|
18391
19303
|
return out;
|
|
18392
19304
|
}
|
|
18393
19305
|
};
|
|
@@ -18478,7 +19390,7 @@ async function requestBytes(request) {
|
|
|
18478
19390
|
});
|
|
18479
19391
|
if (body) lines2.push(`Content-Length: ${body.length}`);
|
|
18480
19392
|
lines2.push("Connection: close", "", "");
|
|
18481
|
-
const head =
|
|
19393
|
+
const head = encoder8.encode(lines2.join("\r\n"));
|
|
18482
19394
|
const out = new Uint8Array(head.length + (body?.length ?? 0));
|
|
18483
19395
|
out.set(head);
|
|
18484
19396
|
if (body) out.set(body, head.length);
|
|
@@ -18532,8 +19444,8 @@ var KernelCallError = class extends Error {
|
|
|
18532
19444
|
this.code = code;
|
|
18533
19445
|
}
|
|
18534
19446
|
};
|
|
18535
|
-
var
|
|
18536
|
-
var bytesOf2 = (data) => typeof data === "string" ?
|
|
19447
|
+
var encoder9 = new TextEncoder();
|
|
19448
|
+
var bytesOf2 = (data) => typeof data === "string" ? encoder9.encode(data) : data;
|
|
18537
19449
|
var UNAVAILABLE = {
|
|
18538
19450
|
manualRedirects: false,
|
|
18539
19451
|
encodedBodies: false,
|
|
@@ -18553,7 +19465,7 @@ async function holdLock(locks) {
|
|
|
18553
19465
|
await granted2.promise;
|
|
18554
19466
|
return { name: name2, release: () => held.resolve() };
|
|
18555
19467
|
}
|
|
18556
|
-
function
|
|
19468
|
+
function concat7(chunks2) {
|
|
18557
19469
|
const out = new Uint8Array(chunks2.reduce((n, c) => n + c.length, 0));
|
|
18558
19470
|
let at = 0;
|
|
18559
19471
|
for (const chunk2 of chunks2) {
|
|
@@ -18604,8 +19516,8 @@ var Channel = class {
|
|
|
18604
19516
|
const id2 = ++this.nextId;
|
|
18605
19517
|
const { failure } = this;
|
|
18606
19518
|
if (failure) return { id: id2, done: Promise.reject(failure) };
|
|
18607
|
-
const done4 = new Promise((
|
|
18608
|
-
this.pending.set(id2, { resolve, reject, ...handlers });
|
|
19519
|
+
const done4 = new Promise((resolve2, reject) => {
|
|
19520
|
+
this.pending.set(id2, { resolve: resolve2, reject, ...handlers });
|
|
18609
19521
|
this.port.postMessage({ ...call, id: id2 });
|
|
18610
19522
|
});
|
|
18611
19523
|
return { id: id2, done: done4 };
|
|
@@ -18743,7 +19655,7 @@ async function runOn(channel, argv, opts) {
|
|
|
18743
19655
|
onStderr: tee(2, onStderr)
|
|
18744
19656
|
});
|
|
18745
19657
|
const { status, signal } = await child.ended;
|
|
18746
|
-
const text = (fd) => new TextDecoder().decode(
|
|
19658
|
+
const text = (fd) => new TextDecoder().decode(concat7(chunks2[fd]));
|
|
18747
19659
|
return {
|
|
18748
19660
|
pid: child.pid,
|
|
18749
19661
|
status,
|
|
@@ -18924,9 +19836,10 @@ function hostfsFetchOf(options) {
|
|
|
18924
19836
|
}
|
|
18925
19837
|
};
|
|
18926
19838
|
}
|
|
18927
|
-
function nodeTransport() {
|
|
19839
|
+
function nodeTransport(options = {}) {
|
|
18928
19840
|
const transport = fetchTransport({ webSocket: true, webSocketHeaders: true, redirect: "manual" });
|
|
18929
|
-
|
|
19841
|
+
const open = { ...transport, traits: { ...transport.traits, crossOrigin: "any" } };
|
|
19842
|
+
return diagnosing(guardedLoopback(open, options.hostLoopback ?? false));
|
|
18930
19843
|
}
|
|
18931
19844
|
var TERMINATED = "the kernel is terminated";
|
|
18932
19845
|
var EXIT_GRACE_MS = 50;
|
|
@@ -19022,10 +19935,10 @@ async function createNodeKernel(options = {}) {
|
|
|
19022
19935
|
...options.approve ? { approve: options.approve } : {}
|
|
19023
19936
|
});
|
|
19024
19937
|
await launcher.prepare();
|
|
19025
|
-
const guard2 = (work) => new Promise((
|
|
19938
|
+
const guard2 = (work) => new Promise((resolve2, reject) => {
|
|
19026
19939
|
if (terminated) return reject(new Error(TERMINATED));
|
|
19027
19940
|
pending.add(reject);
|
|
19028
|
-
work().then(
|
|
19941
|
+
work().then(resolve2, reject).finally(() => pending.delete(reject));
|
|
19029
19942
|
});
|
|
19030
19943
|
const decoder4 = new TextDecoder();
|
|
19031
19944
|
return {
|