@ai-ecoverse/slicc-kernel 1.81.0 → 1.83.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -1
- package/dist/index.js +44 -3
- package/dist/index.js.map +3 -3
- package/dist/kernel-worker.js +1203 -221
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +1174 -225
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js.map +2 -2
- package/package.json +3 -2
package/dist/kernel-worker.js
CHANGED
|
@@ -131,8 +131,8 @@ function descendants(path) {
|
|
|
131
131
|
return IDBKeyRange.bound(`${path}/`, `${path}0`, false, true);
|
|
132
132
|
}
|
|
133
133
|
function settle(transaction, value) {
|
|
134
|
-
return new Promise((
|
|
135
|
-
transaction.oncomplete = () =>
|
|
134
|
+
return new Promise((resolve2, reject) => {
|
|
135
|
+
transaction.oncomplete = () => resolve2(value());
|
|
136
136
|
transaction.onabort = () => reject(transaction.error ?? new Error("metadata transaction aborted"));
|
|
137
137
|
});
|
|
138
138
|
}
|
|
@@ -249,14 +249,14 @@ var IndexedDbMeta = class {
|
|
|
249
249
|
}
|
|
250
250
|
};
|
|
251
251
|
function openMeta(name2, factory) {
|
|
252
|
-
return new Promise((
|
|
252
|
+
return new Promise((resolve2, reject) => {
|
|
253
253
|
const request2 = factory.open(name2, META_VERSION);
|
|
254
254
|
request2.onupgradeneeded = (event) => {
|
|
255
255
|
if (event.oldVersion < 1) {
|
|
256
256
|
request2.result.createObjectStore(META_STORE, { keyPath: "path" }).createIndex("dir", "dir");
|
|
257
257
|
}
|
|
258
258
|
};
|
|
259
|
-
request2.onsuccess = () =>
|
|
259
|
+
request2.onsuccess = () => resolve2(new IndexedDbMeta(request2.result));
|
|
260
260
|
request2.onerror = () => reject(request2.error);
|
|
261
261
|
});
|
|
262
262
|
}
|
|
@@ -360,10 +360,106 @@ async function chownAs(fs, cred, path, change) {
|
|
|
360
360
|
});
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
+
// src/fs/integrity.ts
|
|
364
|
+
var KERNEL_CALLER = { pid: 0, uid: 0 };
|
|
365
|
+
function integrityOptions(options) {
|
|
366
|
+
if (options && typeof options.lookup !== "function") {
|
|
367
|
+
throw new TypeError("protect.integrity.lookup must be a function");
|
|
368
|
+
}
|
|
369
|
+
integrityUnknown(options);
|
|
370
|
+
}
|
|
371
|
+
function integrityUnknown(options) {
|
|
372
|
+
const unknown = options?.unknown ?? "allow";
|
|
373
|
+
if (unknown !== "allow" && unknown !== "deny") {
|
|
374
|
+
throw new TypeError("protect.integrity.unknown must be 'allow' or 'deny'");
|
|
375
|
+
}
|
|
376
|
+
return unknown;
|
|
377
|
+
}
|
|
378
|
+
function hex(digest) {
|
|
379
|
+
return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
380
|
+
}
|
|
381
|
+
async function sha256(bytes) {
|
|
382
|
+
return hex(await crypto.subtle.digest("SHA-256", bytes));
|
|
383
|
+
}
|
|
384
|
+
var Integrity = class {
|
|
385
|
+
prefixes;
|
|
386
|
+
root;
|
|
387
|
+
lookup;
|
|
388
|
+
unknown;
|
|
389
|
+
report;
|
|
390
|
+
unverified = /* @__PURE__ */ new Set();
|
|
391
|
+
constructor(prefixes2, root, options, report) {
|
|
392
|
+
this.prefixes = prefixes2;
|
|
393
|
+
this.root = root;
|
|
394
|
+
this.lookup = options.lookup;
|
|
395
|
+
this.unknown = integrityUnknown(options);
|
|
396
|
+
this.report = report;
|
|
397
|
+
}
|
|
398
|
+
async real(path) {
|
|
399
|
+
const at = normalizePath(path);
|
|
400
|
+
const real = await this.root.realpath?.(at, true).catch(() => void 0) ?? at;
|
|
401
|
+
return isProtected(this.prefixes, real) ? real : void 0;
|
|
402
|
+
}
|
|
403
|
+
async key(path) {
|
|
404
|
+
const real = await this.real(path);
|
|
405
|
+
if (real === void 0 || !this.root.version) return void 0;
|
|
406
|
+
return `${real}\0${await this.root.version(real)}`;
|
|
407
|
+
}
|
|
408
|
+
async read(path, caller, plain) {
|
|
409
|
+
return (await this.readKeyed(path, caller, plain)).bytes;
|
|
410
|
+
}
|
|
411
|
+
async readKeyed(path, caller, plain) {
|
|
412
|
+
const real = await this.real(path);
|
|
413
|
+
if (real === void 0) return { bytes: await plain() };
|
|
414
|
+
const read = this.root.readVersioned ? await this.root.readVersioned(real) : { bytes: await this.root.readFileBuffer(real), version: void 0 };
|
|
415
|
+
const { bytes } = read;
|
|
416
|
+
const keyed = read.version === void 0 ? { bytes } : { bytes, key: `${real}\0${read.version}` };
|
|
417
|
+
const actual = await sha256(bytes);
|
|
418
|
+
const denial = { pid: caller.pid, uid: caller.uid, path: real, actual };
|
|
419
|
+
const tagged = caller.tag !== void 0 ? { tag: caller.tag } : {};
|
|
420
|
+
let expected;
|
|
421
|
+
try {
|
|
422
|
+
expected = await this.expected(real);
|
|
423
|
+
} catch {
|
|
424
|
+
this.say({ ...denial, ...tagged, op: "exec-integrity", errno: "EACCES" });
|
|
425
|
+
throw fsError("EACCES", `integrity lookup failed: ${real}`);
|
|
426
|
+
}
|
|
427
|
+
if (expected === void 0) {
|
|
428
|
+
if (this.unknown === "allow") {
|
|
429
|
+
if (!this.unverified.has(real)) {
|
|
430
|
+
this.unverified.add(real);
|
|
431
|
+
this.say({ ...denial, ...tagged, op: "exec-unverified", errno: "ENODATA" });
|
|
432
|
+
}
|
|
433
|
+
return keyed;
|
|
434
|
+
}
|
|
435
|
+
} else if (expected === actual) {
|
|
436
|
+
return keyed;
|
|
437
|
+
}
|
|
438
|
+
const known = expected !== void 0 ? { expected } : {};
|
|
439
|
+
this.say({ ...denial, ...tagged, ...known, op: "exec-integrity", errno: "EACCES" });
|
|
440
|
+
throw fsError("EACCES", `integrity check failed: ${real}`);
|
|
441
|
+
}
|
|
442
|
+
async expected(path) {
|
|
443
|
+
const answer = await this.lookup(path);
|
|
444
|
+
return typeof answer === "string" ? answer.toLowerCase() : void 0;
|
|
445
|
+
}
|
|
446
|
+
say(event) {
|
|
447
|
+
try {
|
|
448
|
+
this.report(event);
|
|
449
|
+
} catch {
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
|
|
363
454
|
// src/fs/protect.ts
|
|
364
455
|
function protectInit(protection) {
|
|
365
456
|
const writers = [...writerTags(protection)];
|
|
366
|
-
|
|
457
|
+
const { integrity } = protection;
|
|
458
|
+
return {
|
|
459
|
+
paths: [...protection.paths],
|
|
460
|
+
...writers.length > 0 ? { writers } : {},
|
|
461
|
+
...integrity ? { integrity: { unknown: integrityUnknown(integrity) } } : {}
|
|
462
|
+
};
|
|
367
463
|
}
|
|
368
464
|
function writerTags(protection) {
|
|
369
465
|
const writers = protection?.writers ?? [];
|
|
@@ -644,11 +740,11 @@ var RemoteWatch = class {
|
|
|
644
740
|
const seq2 = ++this.seq;
|
|
645
741
|
this.channel.postMessage({ tab: this.tab, paths: this.mine, seq: seq2 });
|
|
646
742
|
if (this.peers.size === 0) return Promise.resolve();
|
|
647
|
-
return new Promise((
|
|
743
|
+
return new Promise((resolve2) => {
|
|
648
744
|
const done4 = () => {
|
|
649
745
|
clearTimeout(timer);
|
|
650
746
|
this.waiting.delete(seq2);
|
|
651
|
-
|
|
747
|
+
resolve2();
|
|
652
748
|
};
|
|
653
749
|
const timer = setTimeout(() => {
|
|
654
750
|
done4();
|
|
@@ -744,7 +840,7 @@ async function openSync(handle) {
|
|
|
744
840
|
const delay = SYNC_BACKOFF_MS[attempt];
|
|
745
841
|
if (!LOCKED.has(err?.name)) throw err;
|
|
746
842
|
if (delay === void 0) return void 0;
|
|
747
|
-
await new Promise((
|
|
843
|
+
await new Promise((resolve2) => setTimeout(resolve2, delay));
|
|
748
844
|
}
|
|
749
845
|
}
|
|
750
846
|
}
|
|
@@ -1201,7 +1297,7 @@ var OpfsFs = class {
|
|
|
1201
1297
|
const again = name2 === "NotReadableError" || locks && LOCKED.has(name2);
|
|
1202
1298
|
if (!again || attempt >= READ_ATTEMPTS)
|
|
1203
1299
|
throw translate(err, path, locks ? "write" : "read");
|
|
1204
|
-
await new Promise((
|
|
1300
|
+
await new Promise((resolve2) => setTimeout(resolve2, attempt * 10));
|
|
1205
1301
|
}
|
|
1206
1302
|
}
|
|
1207
1303
|
}
|
|
@@ -1220,6 +1316,29 @@ var OpfsFs = class {
|
|
|
1220
1316
|
false
|
|
1221
1317
|
);
|
|
1222
1318
|
}
|
|
1319
|
+
async readVersioned(path) {
|
|
1320
|
+
const handle = await this.existing(path);
|
|
1321
|
+
return this.retrying(
|
|
1322
|
+
path,
|
|
1323
|
+
async () => {
|
|
1324
|
+
const file = await handle.getFile();
|
|
1325
|
+
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
1326
|
+
return { bytes, version: `${file.lastModified}:${file.size}` };
|
|
1327
|
+
},
|
|
1328
|
+
false
|
|
1329
|
+
);
|
|
1330
|
+
}
|
|
1331
|
+
async version(path) {
|
|
1332
|
+
const handle = await this.existing(path);
|
|
1333
|
+
return this.retrying(
|
|
1334
|
+
path,
|
|
1335
|
+
async () => {
|
|
1336
|
+
const file = await handle.getFile();
|
|
1337
|
+
return `${file.lastModified}:${file.size}`;
|
|
1338
|
+
},
|
|
1339
|
+
false
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1223
1342
|
async pread(path, offset, length2) {
|
|
1224
1343
|
const handle = await this.existing(path);
|
|
1225
1344
|
return this.retrying(
|
|
@@ -1235,8 +1354,8 @@ var OpfsFs = class {
|
|
|
1235
1354
|
}
|
|
1236
1355
|
async truncate(path, size) {
|
|
1237
1356
|
const handle = await this.existing(path, true);
|
|
1238
|
-
const
|
|
1239
|
-
const target =
|
|
1357
|
+
const resolve2 = this.ranged || this.remote?.watched();
|
|
1358
|
+
const target = resolve2 ? (await this.locate(path, true)).path : path;
|
|
1240
1359
|
await this.retrying(path, () => positioned(handle, (io) => io.truncate(size)), true);
|
|
1241
1360
|
this.written(target);
|
|
1242
1361
|
}
|
|
@@ -1660,8 +1779,8 @@ function memoryMedia() {
|
|
|
1660
1779
|
};
|
|
1661
1780
|
}
|
|
1662
1781
|
function settle2(request2, value) {
|
|
1663
|
-
return new Promise((
|
|
1664
|
-
request2.onsuccess = () =>
|
|
1782
|
+
return new Promise((resolve2, reject) => {
|
|
1783
|
+
request2.onsuccess = () => resolve2(value());
|
|
1665
1784
|
request2.onerror = () => reject(request2.error);
|
|
1666
1785
|
});
|
|
1667
1786
|
}
|
|
@@ -1699,7 +1818,7 @@ function pinScript(url) {
|
|
|
1699
1818
|
|
|
1700
1819
|
// src/cdp/port.ts
|
|
1701
1820
|
function portCdpHook(ask, gone) {
|
|
1702
|
-
return (request2) => new Promise((
|
|
1821
|
+
return (request2) => new Promise((resolve2, reject) => {
|
|
1703
1822
|
const { port1, port2 } = new MessageChannel();
|
|
1704
1823
|
let closed = false;
|
|
1705
1824
|
const conn = {
|
|
@@ -1717,7 +1836,7 @@ function portCdpHook(ask, gone) {
|
|
|
1717
1836
|
};
|
|
1718
1837
|
port1.addEventListener("message", ({ data }) => {
|
|
1719
1838
|
if ("m" in data) conn.onmessage?.(data.m);
|
|
1720
|
-
else if ("open" in data)
|
|
1839
|
+
else if ("open" in data) resolve2(conn);
|
|
1721
1840
|
else if ("error" in data) {
|
|
1722
1841
|
closed = true;
|
|
1723
1842
|
port1.close();
|
|
@@ -2251,9 +2370,9 @@ var KernelPipe = class {
|
|
|
2251
2370
|
let filled = 0;
|
|
2252
2371
|
for (const chunk2 of this.chunks) {
|
|
2253
2372
|
if (filled === out.length) break;
|
|
2254
|
-
const
|
|
2255
|
-
out.set(chunk2.subarray(0,
|
|
2256
|
-
filled +=
|
|
2373
|
+
const count2 = Math.min(chunk2.length, out.length - filled);
|
|
2374
|
+
out.set(chunk2.subarray(0, count2), filled);
|
|
2375
|
+
filled += count2;
|
|
2257
2376
|
}
|
|
2258
2377
|
return out;
|
|
2259
2378
|
}
|
|
@@ -2284,25 +2403,25 @@ var KernelPipe = class {
|
|
|
2284
2403
|
let filled = 0;
|
|
2285
2404
|
while (filled < n) {
|
|
2286
2405
|
const head = this.chunks[0];
|
|
2287
|
-
const
|
|
2288
|
-
out.set(head.subarray(0,
|
|
2289
|
-
filled +=
|
|
2290
|
-
if (
|
|
2291
|
-
else this.chunks[0] = head.subarray(
|
|
2406
|
+
const count2 = Math.min(head.length, n - filled);
|
|
2407
|
+
out.set(head.subarray(0, count2), filled);
|
|
2408
|
+
filled += count2;
|
|
2409
|
+
if (count2 === head.length) this.chunks.shift();
|
|
2410
|
+
else this.chunks[0] = head.subarray(count2);
|
|
2292
2411
|
}
|
|
2293
2412
|
this.size -= n;
|
|
2294
2413
|
return out;
|
|
2295
2414
|
}
|
|
2296
2415
|
changed(signal) {
|
|
2297
2416
|
if (signal?.aborted) return Promise.reject(new PipeError("EINTR"));
|
|
2298
|
-
return new Promise((
|
|
2417
|
+
return new Promise((resolve2, reject) => {
|
|
2299
2418
|
const onAbort = () => {
|
|
2300
2419
|
this.waiters = this.waiters.filter((w) => w !== waiter);
|
|
2301
2420
|
reject(new PipeError("EINTR"));
|
|
2302
2421
|
};
|
|
2303
2422
|
const waiter = () => {
|
|
2304
2423
|
signal?.removeEventListener("abort", onAbort);
|
|
2305
|
-
|
|
2424
|
+
resolve2();
|
|
2306
2425
|
};
|
|
2307
2426
|
this.waiters.push(waiter);
|
|
2308
2427
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -2311,7 +2430,7 @@ var KernelPipe = class {
|
|
|
2311
2430
|
wake() {
|
|
2312
2431
|
const waiters = this.waiters;
|
|
2313
2432
|
this.waiters = [];
|
|
2314
|
-
for (const
|
|
2433
|
+
for (const resolve2 of waiters) resolve2();
|
|
2315
2434
|
}
|
|
2316
2435
|
};
|
|
2317
2436
|
|
|
@@ -2772,14 +2891,14 @@ var Changes = class {
|
|
|
2772
2891
|
waiters = [];
|
|
2773
2892
|
wait(signal) {
|
|
2774
2893
|
if (signal?.aborted) return Promise.reject(new KernelError("EINTR"));
|
|
2775
|
-
return new Promise((
|
|
2894
|
+
return new Promise((resolve2, reject) => {
|
|
2776
2895
|
const onAbort = () => {
|
|
2777
2896
|
this.waiters = this.waiters.filter((w) => w !== waiter);
|
|
2778
2897
|
reject(new KernelError("EINTR"));
|
|
2779
2898
|
};
|
|
2780
2899
|
const waiter = () => {
|
|
2781
2900
|
signal?.removeEventListener("abort", onAbort);
|
|
2782
|
-
|
|
2901
|
+
resolve2();
|
|
2783
2902
|
};
|
|
2784
2903
|
this.waiters.push(waiter);
|
|
2785
2904
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -2788,7 +2907,7 @@ var Changes = class {
|
|
|
2788
2907
|
wake() {
|
|
2789
2908
|
const waiters = this.waiters;
|
|
2790
2909
|
this.waiters = [];
|
|
2791
|
-
for (const
|
|
2910
|
+
for (const resolve2 of waiters) resolve2();
|
|
2792
2911
|
}
|
|
2793
2912
|
};
|
|
2794
2913
|
function link(a, b) {
|
|
@@ -2956,7 +3075,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
2956
3075
|
});
|
|
2957
3076
|
const { host, port } = addr;
|
|
2958
3077
|
const dialled = new Promise(
|
|
2959
|
-
(
|
|
3078
|
+
(resolve2) => resolve2(route.uplink.dial({ network: "tcp", host, port, signal: abort.signal }))
|
|
2960
3079
|
);
|
|
2961
3080
|
dialled.then(
|
|
2962
3081
|
(conn) => abort.signal.aborted && conn.close(),
|
|
@@ -3306,8 +3425,8 @@ var MessageQueue = class {
|
|
|
3306
3425
|
this.overflow = overflow;
|
|
3307
3426
|
this.limit = limit;
|
|
3308
3427
|
this.taken = taken;
|
|
3309
|
-
this.closed = new Promise((
|
|
3310
|
-
this.settle =
|
|
3428
|
+
this.closed = new Promise((resolve2) => {
|
|
3429
|
+
this.settle = resolve2;
|
|
3311
3430
|
});
|
|
3312
3431
|
}
|
|
3313
3432
|
push(message3) {
|
|
@@ -3346,8 +3465,8 @@ var MessageQueue = class {
|
|
|
3346
3465
|
continue;
|
|
3347
3466
|
}
|
|
3348
3467
|
if (this.ended) return;
|
|
3349
|
-
await new Promise((
|
|
3350
|
-
this.waiter =
|
|
3468
|
+
await new Promise((resolve2) => {
|
|
3469
|
+
this.waiter = resolve2;
|
|
3351
3470
|
});
|
|
3352
3471
|
}
|
|
3353
3472
|
}
|
|
@@ -3438,8 +3557,8 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
3438
3557
|
const relay = async (nid, socket) => {
|
|
3439
3558
|
let ending;
|
|
3440
3559
|
let late;
|
|
3441
|
-
const unanswered = new Promise((
|
|
3442
|
-
late = () =>
|
|
3560
|
+
const unanswered = new Promise((resolve2) => {
|
|
3561
|
+
late = () => resolve2("late");
|
|
3443
3562
|
});
|
|
3444
3563
|
const flow = {
|
|
3445
3564
|
inflight: 0,
|
|
@@ -3467,8 +3586,8 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
3467
3586
|
}
|
|
3468
3587
|
flow.inflight += payloadSize(data);
|
|
3469
3588
|
while (flow.inflight > INBOUND_LIMIT && !flow.closing) {
|
|
3470
|
-
await new Promise((
|
|
3471
|
-
flow.wake =
|
|
3589
|
+
await new Promise((resolve2) => {
|
|
3590
|
+
flow.wake = resolve2;
|
|
3472
3591
|
});
|
|
3473
3592
|
}
|
|
3474
3593
|
}
|
|
@@ -3487,7 +3606,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
3487
3606
|
if (!socket) return;
|
|
3488
3607
|
socket.send(call.data);
|
|
3489
3608
|
while (socket.buffered > SEND_BUFFER && sockets.has(call.nid)) {
|
|
3490
|
-
await new Promise((
|
|
3609
|
+
await new Promise((resolve2) => setTimeout(resolve2, 10));
|
|
3491
3610
|
}
|
|
3492
3611
|
peer.postMessage({ net: "ws-acked", nid: call.nid, n: payloadSize(call.data) });
|
|
3493
3612
|
};
|
|
@@ -4467,6 +4586,27 @@ function clipboardAsker(port) {
|
|
|
4467
4586
|
return { hook, answer };
|
|
4468
4587
|
}
|
|
4469
4588
|
|
|
4589
|
+
// src/integrity-relay.ts
|
|
4590
|
+
function integrityAsker(port) {
|
|
4591
|
+
const asks = /* @__PURE__ */ new Map();
|
|
4592
|
+
let next2 = 0;
|
|
4593
|
+
const lookup = (path) => {
|
|
4594
|
+
const id2 = ++next2;
|
|
4595
|
+
const waiting = Promise.withResolvers();
|
|
4596
|
+
asks.set(id2, waiting);
|
|
4597
|
+
port.postMessage({ integrityAsk: { id: id2, path } });
|
|
4598
|
+
return waiting.promise;
|
|
4599
|
+
};
|
|
4600
|
+
const answer = ({ id: id2, hash, error }) => {
|
|
4601
|
+
const waiting = asks.get(id2);
|
|
4602
|
+
if (!waiting) return;
|
|
4603
|
+
asks.delete(id2);
|
|
4604
|
+
if (error !== void 0) waiting.reject(new Error(error));
|
|
4605
|
+
else waiting.resolve(hash);
|
|
4606
|
+
};
|
|
4607
|
+
return { lookup, answer };
|
|
4608
|
+
}
|
|
4609
|
+
|
|
4470
4610
|
// src/kernel/net/loopback-names.ts
|
|
4471
4611
|
var HOST_LOOPBACK = "host.slicc.internal";
|
|
4472
4612
|
var HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2];
|
|
@@ -4973,10 +5113,10 @@ var Budget = class {
|
|
|
4973
5113
|
async acquire(n, signal) {
|
|
4974
5114
|
while (this.free < n) {
|
|
4975
5115
|
signal.throwIfAborted();
|
|
4976
|
-
await new Promise((
|
|
5116
|
+
await new Promise((resolve2) => {
|
|
4977
5117
|
const done4 = () => {
|
|
4978
5118
|
signal.removeEventListener("abort", done4);
|
|
4979
|
-
|
|
5119
|
+
resolve2();
|
|
4980
5120
|
};
|
|
4981
5121
|
this.waiters.push(done4);
|
|
4982
5122
|
signal.addEventListener("abort", done4, { once: true });
|
|
@@ -5118,14 +5258,14 @@ async function watchHangup(conn, abort, until) {
|
|
|
5118
5258
|
}
|
|
5119
5259
|
}
|
|
5120
5260
|
function untilAborted(response, signal) {
|
|
5121
|
-
return new Promise((
|
|
5261
|
+
return new Promise((resolve2, reject) => {
|
|
5122
5262
|
const onAbort = () => {
|
|
5123
5263
|
reject(signal.reason ?? new KernelError("EINTR"));
|
|
5124
5264
|
response.then((late) => late.cancel()).catch(() => void 0);
|
|
5125
5265
|
};
|
|
5126
5266
|
if (signal.aborted) return onAbort();
|
|
5127
5267
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5128
|
-
response.then(
|
|
5268
|
+
response.then(resolve2, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
5129
5269
|
});
|
|
5130
5270
|
}
|
|
5131
5271
|
function plainResponse(status, message3) {
|
|
@@ -5158,8 +5298,8 @@ function wireCode(code) {
|
|
|
5158
5298
|
return sendableCode(code) ? code : 1011;
|
|
5159
5299
|
}
|
|
5160
5300
|
function quietly(ms) {
|
|
5161
|
-
return new Promise((
|
|
5162
|
-
AbortSignal.timeout(ms).addEventListener("abort", () =>
|
|
5301
|
+
return new Promise((resolve2) => {
|
|
5302
|
+
AbortSignal.timeout(ms).addEventListener("abort", () => resolve2(), { once: true });
|
|
5163
5303
|
});
|
|
5164
5304
|
}
|
|
5165
5305
|
var RealmProxy = class {
|
|
@@ -5257,7 +5397,7 @@ var RealmProxy = class {
|
|
|
5257
5397
|
return false;
|
|
5258
5398
|
}
|
|
5259
5399
|
const url = ctx.origin ? tunnelRequestUrl(req, ctx.origin) : requestUrl(req);
|
|
5260
|
-
const
|
|
5400
|
+
const keep2 = keepsAlive(req);
|
|
5261
5401
|
const framing = requestFraming(req.headers);
|
|
5262
5402
|
const reserve = framing.kind === "length" ? framing.length : framing.kind === "chunked" ? this.cap() : 0;
|
|
5263
5403
|
if (reserve > this.cap()) throw new HttpError(413, `request body over ${this.cap()} bytes`);
|
|
@@ -5280,7 +5420,7 @@ var RealmProxy = class {
|
|
|
5280
5420
|
} finally {
|
|
5281
5421
|
this.bodies.release(reserve);
|
|
5282
5422
|
}
|
|
5283
|
-
return await this.relay(conn, req.method, req.minor, response,
|
|
5423
|
+
return await this.relay(conn, req.method, req.minor, response, keep2);
|
|
5284
5424
|
} finally {
|
|
5285
5425
|
this.stop.signal.removeEventListener("abort", stopExchange);
|
|
5286
5426
|
abort.abort();
|
|
@@ -5328,8 +5468,8 @@ var RealmProxy = class {
|
|
|
5328
5468
|
bodiless: bodiless2
|
|
5329
5469
|
});
|
|
5330
5470
|
const chunked = !bodiless2 && minor >= 1;
|
|
5331
|
-
const
|
|
5332
|
-
headers.push(["Connection",
|
|
5471
|
+
const keep2 = keepAlive && (bodiless2 || chunked);
|
|
5472
|
+
headers.push(["Connection", keep2 ? "keep-alive" : "close"]);
|
|
5333
5473
|
if (chunked) headers.push(["Transfer-Encoding", "chunked"]);
|
|
5334
5474
|
const signal = this.stop.signal;
|
|
5335
5475
|
await conn.write(
|
|
@@ -5338,7 +5478,7 @@ var RealmProxy = class {
|
|
|
5338
5478
|
);
|
|
5339
5479
|
if (bodiless2) {
|
|
5340
5480
|
await response.cancel();
|
|
5341
|
-
return
|
|
5481
|
+
return keep2;
|
|
5342
5482
|
}
|
|
5343
5483
|
try {
|
|
5344
5484
|
for await (const piece of response.body) {
|
|
@@ -5349,7 +5489,7 @@ var RealmProxy = class {
|
|
|
5349
5489
|
return false;
|
|
5350
5490
|
}
|
|
5351
5491
|
if (chunked) await conn.write(LAST_CHUNK, signal);
|
|
5352
|
-
return
|
|
5492
|
+
return keep2;
|
|
5353
5493
|
}
|
|
5354
5494
|
async connect(conn, incoming, req, idle) {
|
|
5355
5495
|
const target = tunnelTarget(req);
|
|
@@ -5572,10 +5712,10 @@ function header(der, at) {
|
|
|
5572
5712
|
let len = der[at + 1];
|
|
5573
5713
|
let start2 = at + 2;
|
|
5574
5714
|
if (len & 128) {
|
|
5575
|
-
const
|
|
5715
|
+
const count2 = len & 127;
|
|
5576
5716
|
len = 0;
|
|
5577
|
-
for (let i = 0; i <
|
|
5578
|
-
start2 +=
|
|
5717
|
+
for (let i = 0; i < count2; i++) len = len * 256 + der[start2 + i];
|
|
5718
|
+
start2 += count2;
|
|
5579
5719
|
}
|
|
5580
5720
|
if (start2 + len > der.length) throw new Error("truncated DER");
|
|
5581
5721
|
return [tag, start2, start2 + len];
|
|
@@ -5693,18 +5833,18 @@ var LEAF_LIFETIME = 7 * DAY;
|
|
|
5693
5833
|
var ECDSA = { name: "ECDSA", namedCurve: "P-256" };
|
|
5694
5834
|
var SIGN = { name: "ECDSA", hash: "SHA-256" };
|
|
5695
5835
|
function request(req) {
|
|
5696
|
-
return new Promise((
|
|
5697
|
-
req.onsuccess = () =>
|
|
5836
|
+
return new Promise((resolve2, reject) => {
|
|
5837
|
+
req.onsuccess = () => resolve2(req.result);
|
|
5698
5838
|
req.onerror = () => reject(req.error);
|
|
5699
5839
|
});
|
|
5700
5840
|
}
|
|
5701
5841
|
function indexedDbCaStore(dbName = "slicc-realm-ca") {
|
|
5702
5842
|
let db;
|
|
5703
5843
|
const open = () => {
|
|
5704
|
-
db ??= new Promise((
|
|
5844
|
+
db ??= new Promise((resolve2, reject) => {
|
|
5705
5845
|
const req = indexedDB.open(dbName, 1);
|
|
5706
5846
|
req.onupgradeneeded = () => req.result.createObjectStore("ca");
|
|
5707
|
-
req.onsuccess = () =>
|
|
5847
|
+
req.onsuccess = () => resolve2(req.result);
|
|
5708
5848
|
req.onerror = () => reject(req.error);
|
|
5709
5849
|
});
|
|
5710
5850
|
db.catch(() => {
|
|
@@ -5728,8 +5868,8 @@ function indexedDbCaStore(dbName = "slicc-realm-ca") {
|
|
|
5728
5868
|
if (kept === record) store.put(record, owner);
|
|
5729
5869
|
else stored = kept;
|
|
5730
5870
|
};
|
|
5731
|
-
await new Promise((
|
|
5732
|
-
tx.oncomplete = () =>
|
|
5871
|
+
await new Promise((resolve2, reject) => {
|
|
5872
|
+
tx.oncomplete = () => resolve2();
|
|
5733
5873
|
tx.onerror = () => reject(tx.error);
|
|
5734
5874
|
});
|
|
5735
5875
|
return stored;
|
|
@@ -6258,8 +6398,8 @@ var RemoteTransport = class {
|
|
|
6258
6398
|
}
|
|
6259
6399
|
ask(call) {
|
|
6260
6400
|
if (this.failure) return Promise.reject(this.failure);
|
|
6261
|
-
return new Promise((
|
|
6262
|
-
this.waiting.set(call.nid, { resolve, reject });
|
|
6401
|
+
return new Promise((resolve2, reject) => {
|
|
6402
|
+
this.waiting.set(call.nid, { resolve: resolve2, reject });
|
|
6263
6403
|
this.port.postMessage(call);
|
|
6264
6404
|
});
|
|
6265
6405
|
}
|
|
@@ -6664,7 +6804,7 @@ var CdpFacade = class {
|
|
|
6664
6804
|
const conn = await this.host(runtime);
|
|
6665
6805
|
try {
|
|
6666
6806
|
const reply = await new Promise(
|
|
6667
|
-
(
|
|
6807
|
+
(resolve2, reject) => {
|
|
6668
6808
|
const timer = setTimeout(
|
|
6669
6809
|
() => reject(new HttpError(504, "the CDP host did not answer Target.getTargets")),
|
|
6670
6810
|
this.options.listTimeout ?? LIST_TIMEOUT
|
|
@@ -6677,7 +6817,7 @@ var CdpFacade = class {
|
|
|
6677
6817
|
const parsed2 = JSON.parse(message3);
|
|
6678
6818
|
if (parsed2.id !== 1) return;
|
|
6679
6819
|
clearTimeout(timer);
|
|
6680
|
-
|
|
6820
|
+
resolve2(parsed2);
|
|
6681
6821
|
};
|
|
6682
6822
|
conn.send(JSON.stringify({ id: 1, method: "Target.getTargets" }));
|
|
6683
6823
|
}
|
|
@@ -6737,9 +6877,9 @@ var Relay = class {
|
|
|
6737
6877
|
}
|
|
6738
6878
|
async start(head) {
|
|
6739
6879
|
await this.send(head);
|
|
6740
|
-
const hostGone = new Promise((
|
|
6880
|
+
const hostGone = new Promise((resolve2) => {
|
|
6741
6881
|
this.host.onclose = (reason) => {
|
|
6742
|
-
void this.end(reason ? CLOSE.error : CLOSE.normal, reason ?? "").then(() =>
|
|
6882
|
+
void this.end(reason ? CLOSE.error : CLOSE.normal, reason ?? "").then(() => resolve2());
|
|
6743
6883
|
};
|
|
6744
6884
|
});
|
|
6745
6885
|
this.host.onmessage = (message3) => {
|
|
@@ -6753,8 +6893,8 @@ var Relay = class {
|
|
|
6753
6893
|
await Promise.race([pumping, hostGone]);
|
|
6754
6894
|
await this.writes;
|
|
6755
6895
|
let timer;
|
|
6756
|
-
const waited = new Promise((
|
|
6757
|
-
timer = setTimeout(
|
|
6896
|
+
const waited = new Promise((resolve2) => {
|
|
6897
|
+
timer = setTimeout(resolve2, this.closeWaitMs);
|
|
6758
6898
|
});
|
|
6759
6899
|
await Promise.race([pumping, waited]);
|
|
6760
6900
|
clearTimeout(timer);
|
|
@@ -7093,7 +7233,7 @@ function owned(path, st) {
|
|
|
7093
7233
|
function unchanged(a, b, bytes) {
|
|
7094
7234
|
return a.ino === b.ino && a.mtime.getTime() === b.mtime.getTime() && a.size === b.size && bytes.length === b.size;
|
|
7095
7235
|
}
|
|
7096
|
-
async function
|
|
7236
|
+
async function sha2562(bytes) {
|
|
7097
7237
|
const digest = new Uint8Array(
|
|
7098
7238
|
await crypto.subtle.digest("SHA-256", bytes)
|
|
7099
7239
|
);
|
|
@@ -7149,7 +7289,7 @@ async function attest(fs, asked, o) {
|
|
|
7149
7289
|
const bytes = (await fs.readFileBuffer(path)).slice();
|
|
7150
7290
|
const after = await fs.lstat(path);
|
|
7151
7291
|
if (unchanged(before, after, bytes)) {
|
|
7152
|
-
return attested(path, after, bytes, await
|
|
7292
|
+
return attested(path, after, bytes, await sha2562(bytes), o, parents);
|
|
7153
7293
|
}
|
|
7154
7294
|
if (tries >= 1) refuse("EAGAIN", path, "changed while it was read");
|
|
7155
7295
|
}
|
|
@@ -7404,16 +7544,16 @@ var FreshModules = class {
|
|
|
7404
7544
|
if (head) await decide(path, head);
|
|
7405
7545
|
};
|
|
7406
7546
|
}
|
|
7407
|
-
const
|
|
7547
|
+
const bound2 = /* @__PURE__ */ new WeakMap();
|
|
7408
7548
|
return new Proxy(fs, {
|
|
7409
7549
|
get(target, key, receiver) {
|
|
7410
7550
|
if (Object.hasOwn(overrides, key)) return overrides[key];
|
|
7411
7551
|
const value = Reflect.get(target, key, receiver);
|
|
7412
7552
|
if (typeof value !== "function") return value;
|
|
7413
|
-
let method =
|
|
7553
|
+
let method = bound2.get(value);
|
|
7414
7554
|
if (method === void 0) {
|
|
7415
7555
|
method = value.bind(target);
|
|
7416
|
-
|
|
7556
|
+
bound2.set(value, method);
|
|
7417
7557
|
}
|
|
7418
7558
|
return method;
|
|
7419
7559
|
}
|
|
@@ -7481,12 +7621,12 @@ var PathGate = class {
|
|
|
7481
7621
|
tails = /* @__PURE__ */ new Map();
|
|
7482
7622
|
async acquire(path) {
|
|
7483
7623
|
const prev = this.tails.get(path) ?? Promise.resolve();
|
|
7484
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
7624
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
7485
7625
|
const tail = prev.then(() => promise);
|
|
7486
7626
|
this.tails.set(path, tail);
|
|
7487
7627
|
await prev;
|
|
7488
7628
|
return () => {
|
|
7489
|
-
|
|
7629
|
+
resolve2();
|
|
7490
7630
|
if (this.tails.get(path) === tail) this.tails.delete(path);
|
|
7491
7631
|
};
|
|
7492
7632
|
}
|
|
@@ -7964,7 +8104,7 @@ var ChildTable = class {
|
|
|
7964
8104
|
}
|
|
7965
8105
|
async nextChange(candidates, flags2, interrupt) {
|
|
7966
8106
|
let wake;
|
|
7967
|
-
const stateChange = new Promise((
|
|
8107
|
+
const stateChange = new Promise((resolve2) => wake = resolve2);
|
|
7968
8108
|
const watching = flags2.untraced || flags2.continued;
|
|
7969
8109
|
if (watching && wake) this.stateChanged.push(wake);
|
|
7970
8110
|
try {
|
|
@@ -8011,6 +8151,65 @@ var ChildTable = class {
|
|
|
8011
8151
|
}
|
|
8012
8152
|
};
|
|
8013
8153
|
|
|
8154
|
+
// src/kernel/exec-ticket.ts
|
|
8155
|
+
var TICKET_ENV = "SLICC_SEALED_TICKET";
|
|
8156
|
+
var TICKET_TTL_MS = 3e4;
|
|
8157
|
+
var MAX_TICKETS = 256;
|
|
8158
|
+
var TICKET = /^[0-9a-f]{32}$/;
|
|
8159
|
+
async function argvDigest(argv) {
|
|
8160
|
+
const bytes = new TextEncoder().encode(JSON.stringify(argv));
|
|
8161
|
+
const hash = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
|
|
8162
|
+
return [...hash].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
8163
|
+
}
|
|
8164
|
+
function isStrings(value) {
|
|
8165
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
8166
|
+
}
|
|
8167
|
+
function stringRecord(value) {
|
|
8168
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
8169
|
+
const entries = Object.entries(value);
|
|
8170
|
+
return entries.every(([, v]) => typeof v === "string") ? Object.fromEntries(entries) : void 0;
|
|
8171
|
+
}
|
|
8172
|
+
var TicketBook = class {
|
|
8173
|
+
booked = /* @__PURE__ */ new Map();
|
|
8174
|
+
now;
|
|
8175
|
+
normalise = async (path) => path;
|
|
8176
|
+
constructor(now = Date.now) {
|
|
8177
|
+
this.now = now;
|
|
8178
|
+
}
|
|
8179
|
+
get size() {
|
|
8180
|
+
return this.booked.size;
|
|
8181
|
+
}
|
|
8182
|
+
async record(req, reply, pid) {
|
|
8183
|
+
const { ticket, error } = reply;
|
|
8184
|
+
if (error !== void 0 || typeof ticket !== "string" || !TICKET.test(ticket)) return;
|
|
8185
|
+
const { path, argv, cwd } = req;
|
|
8186
|
+
const entry = {
|
|
8187
|
+
pid,
|
|
8188
|
+
path: await this.normalise(path),
|
|
8189
|
+
requested: path,
|
|
8190
|
+
requestedCwd: cwd,
|
|
8191
|
+
argv: await argvDigest(argv),
|
|
8192
|
+
cwd: await this.normalise(cwd),
|
|
8193
|
+
at: this.now()
|
|
8194
|
+
};
|
|
8195
|
+
this.prune();
|
|
8196
|
+
while (this.booked.size >= MAX_TICKETS)
|
|
8197
|
+
this.booked.delete(this.booked.keys().next().value);
|
|
8198
|
+
this.booked.set(ticket, entry);
|
|
8199
|
+
}
|
|
8200
|
+
take(ticket) {
|
|
8201
|
+
const booked = this.booked.get(ticket);
|
|
8202
|
+
this.booked.delete(ticket);
|
|
8203
|
+
return booked && this.now() - booked.at < TICKET_TTL_MS ? booked : void 0;
|
|
8204
|
+
}
|
|
8205
|
+
prune() {
|
|
8206
|
+
const now = this.now();
|
|
8207
|
+
for (const [ticket, booked] of this.booked) {
|
|
8208
|
+
if (now - booked.at >= TICKET_TTL_MS) this.booked.delete(ticket);
|
|
8209
|
+
}
|
|
8210
|
+
}
|
|
8211
|
+
};
|
|
8212
|
+
|
|
8014
8213
|
// src/mount/protocol.ts
|
|
8015
8214
|
var DRIVER_PROTOCOL = [1, 2];
|
|
8016
8215
|
function driverVersionError(theirs) {
|
|
@@ -8081,7 +8280,7 @@ var DriverConnection = class _DriverConnection {
|
|
|
8081
8280
|
call(call, transfer = []) {
|
|
8082
8281
|
if (this.failure) return Promise.reject(this.failure);
|
|
8083
8282
|
const id2 = ++this.nextId;
|
|
8084
|
-
return new Promise((
|
|
8283
|
+
return new Promise((resolve2, reject) => {
|
|
8085
8284
|
const timer = unref(
|
|
8086
8285
|
setTimeout(() => {
|
|
8087
8286
|
this.waiting.delete(id2);
|
|
@@ -8094,7 +8293,7 @@ var DriverConnection = class _DriverConnection {
|
|
|
8094
8293
|
this.onFail?.(error);
|
|
8095
8294
|
}, this.timeoutMs)
|
|
8096
8295
|
);
|
|
8097
|
-
this.waiting.set(id2, { resolve, reject, timer });
|
|
8296
|
+
this.waiting.set(id2, { resolve: resolve2, reject, timer });
|
|
8098
8297
|
this.port.postMessage({ ...call, id: id2 }, transfer);
|
|
8099
8298
|
});
|
|
8100
8299
|
}
|
|
@@ -8237,8 +8436,8 @@ var HeldPaths = class extends Map {
|
|
|
8237
8436
|
this.keptHandles.delete(handle);
|
|
8238
8437
|
if (kept) this.letGo(kept);
|
|
8239
8438
|
}
|
|
8240
|
-
const
|
|
8241
|
-
if (
|
|
8439
|
+
const count2 = (this.opens.get(key) ?? 0) + (on ? 1 : -1);
|
|
8440
|
+
if (count2 > 0) this.opens.set(key, count2);
|
|
8242
8441
|
else {
|
|
8243
8442
|
this.opens.delete(key);
|
|
8244
8443
|
for (const id2 of this.handlesAt(key)) this.handles.delete(id2);
|
|
@@ -8252,8 +8451,8 @@ var HeldPaths = class extends Map {
|
|
|
8252
8451
|
return this.lastHandle;
|
|
8253
8452
|
}
|
|
8254
8453
|
holdWrite(path, on) {
|
|
8255
|
-
const
|
|
8256
|
-
if (
|
|
8454
|
+
const count2 = (this.get(path) ?? 0) + (on ? 1 : -1);
|
|
8455
|
+
if (count2 > 0) this.set(path, count2);
|
|
8257
8456
|
else {
|
|
8258
8457
|
this.delete(path);
|
|
8259
8458
|
this.revoked.delete(path);
|
|
@@ -8275,18 +8474,18 @@ var HeldPaths = class extends Map {
|
|
|
8275
8474
|
for (const path of this.keys()) if (within5(path, prefix)) this.revoked.add(path);
|
|
8276
8475
|
}
|
|
8277
8476
|
renamed(from, to) {
|
|
8278
|
-
for (const [path,
|
|
8477
|
+
for (const [path, count2] of [...this]) {
|
|
8279
8478
|
if (!within5(path, from)) continue;
|
|
8280
8479
|
const moved2 = to + path.slice(from.length);
|
|
8281
8480
|
this.delete(path);
|
|
8282
|
-
this.set(moved2, (this.get(moved2) ?? 0) +
|
|
8481
|
+
this.set(moved2, (this.get(moved2) ?? 0) + count2);
|
|
8283
8482
|
if (this.revoked.delete(path)) this.revoked.add(moved2);
|
|
8284
8483
|
}
|
|
8285
|
-
for (const [path,
|
|
8484
|
+
for (const [path, count2] of [...this.opens]) {
|
|
8286
8485
|
if (!within5(path, from)) continue;
|
|
8287
8486
|
const moved2 = to + path.slice(from.length);
|
|
8288
8487
|
this.opens.delete(path);
|
|
8289
|
-
this.opens.set(moved2, (this.opens.get(moved2) ?? 0) +
|
|
8488
|
+
this.opens.set(moved2, (this.opens.get(moved2) ?? 0) + count2);
|
|
8290
8489
|
}
|
|
8291
8490
|
for (const [id2, key] of this.handles) {
|
|
8292
8491
|
if (within5(key, from)) this.handles.set(id2, to + key.slice(from.length));
|
|
@@ -10580,7 +10779,7 @@ var AsyncOps = class {
|
|
|
10580
10779
|
this.wake();
|
|
10581
10780
|
}
|
|
10582
10781
|
sleep(timeoutMs, signal) {
|
|
10583
|
-
return new Promise((
|
|
10782
|
+
return new Promise((resolve2, reject) => {
|
|
10584
10783
|
let timer;
|
|
10585
10784
|
const cleanup = () => {
|
|
10586
10785
|
clearTimeout(timer);
|
|
@@ -10589,7 +10788,7 @@ var AsyncOps = class {
|
|
|
10589
10788
|
};
|
|
10590
10789
|
const wake = () => {
|
|
10591
10790
|
cleanup();
|
|
10592
|
-
|
|
10791
|
+
resolve2(true);
|
|
10593
10792
|
};
|
|
10594
10793
|
const abort = () => {
|
|
10595
10794
|
cleanup();
|
|
@@ -10600,7 +10799,7 @@ var AsyncOps = class {
|
|
|
10600
10799
|
if (timeoutMs !== void 0) {
|
|
10601
10800
|
timer = setTimeout(() => {
|
|
10602
10801
|
cleanup();
|
|
10603
|
-
|
|
10802
|
+
resolve2(false);
|
|
10604
10803
|
}, timeoutMs);
|
|
10605
10804
|
}
|
|
10606
10805
|
});
|
|
@@ -11022,7 +11221,7 @@ var Resolver = class {
|
|
|
11022
11221
|
};
|
|
11023
11222
|
function waitFor(lookup, signal) {
|
|
11024
11223
|
lookup.waiters++;
|
|
11025
|
-
return new Promise((
|
|
11224
|
+
return new Promise((resolve2, reject) => {
|
|
11026
11225
|
const abort = () => {
|
|
11027
11226
|
if (--lookup.waiters === 0) lookup.abort.abort(new KernelError("EINTR"));
|
|
11028
11227
|
reject(new KernelError("EINTR"));
|
|
@@ -11032,7 +11231,7 @@ function waitFor(lookup, signal) {
|
|
|
11032
11231
|
if (signal?.aborted) return;
|
|
11033
11232
|
lookup.waiters--;
|
|
11034
11233
|
signal?.removeEventListener("abort", abort);
|
|
11035
|
-
|
|
11234
|
+
resolve2(value);
|
|
11036
11235
|
});
|
|
11037
11236
|
});
|
|
11038
11237
|
}
|
|
@@ -11213,8 +11412,8 @@ var KernelTty = class {
|
|
|
11213
11412
|
}
|
|
11214
11413
|
rubOut(n) {
|
|
11215
11414
|
const dropped2 = this.line.splice(this.line.length - n, n);
|
|
11216
|
-
const
|
|
11217
|
-
const cells =
|
|
11415
|
+
const utf83 = (this.termios.c_iflag & IUTF8) !== 0;
|
|
11416
|
+
const cells = utf83 ? dropped2.filter((b) => !isContinuation(b)).length : dropped2.length;
|
|
11218
11417
|
if (cells > 0 && this.termios.c_lflag & ECHO) {
|
|
11219
11418
|
this.output(encoder3.encode("\b \b".repeat(cells)), false);
|
|
11220
11419
|
}
|
|
@@ -11284,14 +11483,14 @@ var KernelTty = class {
|
|
|
11284
11483
|
}
|
|
11285
11484
|
changed(signal) {
|
|
11286
11485
|
if (signal?.aborted) return Promise.reject(new KernelError("EINTR"));
|
|
11287
|
-
return new Promise((
|
|
11486
|
+
return new Promise((resolve2, reject) => {
|
|
11288
11487
|
const onAbort = () => {
|
|
11289
11488
|
this.waiters = this.waiters.filter((w) => w !== waiter);
|
|
11290
11489
|
reject(new KernelError("EINTR"));
|
|
11291
11490
|
};
|
|
11292
11491
|
const waiter = () => {
|
|
11293
11492
|
signal?.removeEventListener("abort", onAbort);
|
|
11294
|
-
|
|
11493
|
+
resolve2();
|
|
11295
11494
|
};
|
|
11296
11495
|
this.waiters.push(waiter);
|
|
11297
11496
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -11300,7 +11499,7 @@ var KernelTty = class {
|
|
|
11300
11499
|
wake() {
|
|
11301
11500
|
const waiters = this.waiters;
|
|
11302
11501
|
this.waiters = [];
|
|
11303
|
-
for (const
|
|
11502
|
+
for (const resolve2 of waiters) resolve2();
|
|
11304
11503
|
}
|
|
11305
11504
|
};
|
|
11306
11505
|
|
|
@@ -11399,14 +11598,14 @@ var PtyPair = class {
|
|
|
11399
11598
|
}
|
|
11400
11599
|
changed(signal) {
|
|
11401
11600
|
if (signal?.aborted) return Promise.reject(new KernelError("EINTR"));
|
|
11402
|
-
return new Promise((
|
|
11601
|
+
return new Promise((resolve2, reject) => {
|
|
11403
11602
|
const onAbort = () => {
|
|
11404
11603
|
this.waiters = this.waiters.filter((w) => w !== waiter);
|
|
11405
11604
|
reject(new KernelError("EINTR"));
|
|
11406
11605
|
};
|
|
11407
11606
|
const waiter = () => {
|
|
11408
11607
|
signal?.removeEventListener("abort", onAbort);
|
|
11409
|
-
|
|
11608
|
+
resolve2();
|
|
11410
11609
|
};
|
|
11411
11610
|
this.waiters.push(waiter);
|
|
11412
11611
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -11415,7 +11614,7 @@ var PtyPair = class {
|
|
|
11415
11614
|
wake() {
|
|
11416
11615
|
const waiters = this.waiters;
|
|
11417
11616
|
this.waiters = [];
|
|
11418
|
-
for (const
|
|
11617
|
+
for (const resolve2 of waiters) resolve2();
|
|
11419
11618
|
}
|
|
11420
11619
|
};
|
|
11421
11620
|
var PtyTable = class {
|
|
@@ -11480,7 +11679,8 @@ function ptySyscall(req, ctx) {
|
|
|
11480
11679
|
if (!ctx.ptys) throw new KernelError("ENOENT");
|
|
11481
11680
|
const pair = ctx.ptys.get(req.n);
|
|
11482
11681
|
ttyOpenable(ctx.guard, pair.slave);
|
|
11483
|
-
const
|
|
11682
|
+
const slave = pair.openSlave();
|
|
11683
|
+
const fd = ctx.fds.install(ctx.ttyFilter?.(slave) ?? slave, 3);
|
|
11484
11684
|
if (!req.noctty) ctx.jobs?.acquireTerminal(ctx.pid, pair.slave);
|
|
11485
11685
|
return json4(fd);
|
|
11486
11686
|
}
|
|
@@ -11553,8 +11753,8 @@ async function runChild(req, deps) {
|
|
|
11553
11753
|
};
|
|
11554
11754
|
const controls = [];
|
|
11555
11755
|
const capture = () => {
|
|
11556
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
11557
|
-
const control = { shut: false, ended:
|
|
11756
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
11757
|
+
const control = { shut: false, ended: resolve2, eof: promise };
|
|
11558
11758
|
controls.push(control);
|
|
11559
11759
|
return { capture: true, max, overflow: () => stop("ENOBUFS"), control };
|
|
11560
11760
|
};
|
|
@@ -11647,7 +11847,7 @@ async function waitReady(fds, read, write, deadline, interrupted2) {
|
|
|
11647
11847
|
return file.changed === void 0 ? [] : [file.changed(round.signal).catch(() => void 0)];
|
|
11648
11848
|
});
|
|
11649
11849
|
let timer;
|
|
11650
|
-
const expiry = deadline === Number.POSITIVE_INFINITY ? [] : [new Promise((
|
|
11850
|
+
const expiry = deadline === Number.POSITIVE_INFINITY ? [] : [new Promise((resolve2) => timer = setTimeout(resolve2, deadline - Date.now()))];
|
|
11651
11851
|
try {
|
|
11652
11852
|
await Promise.race([...changes, ...expiry, interrupted2]);
|
|
11653
11853
|
} finally {
|
|
@@ -11731,10 +11931,10 @@ async function socketSyscall(req, proc) {
|
|
|
11731
11931
|
}
|
|
11732
11932
|
}
|
|
11733
11933
|
function interruptible2(dialing, signal) {
|
|
11734
|
-
return new Promise((
|
|
11934
|
+
return new Promise((resolve2, reject) => {
|
|
11735
11935
|
const abort = () => reject(new KernelError("EINTR"));
|
|
11736
11936
|
signal.addEventListener("abort", abort, { once: true });
|
|
11737
|
-
dialing.then(
|
|
11937
|
+
dialing.then(resolve2, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
11738
11938
|
});
|
|
11739
11939
|
}
|
|
11740
11940
|
function unnamed(domain) {
|
|
@@ -12581,7 +12781,7 @@ var WasmProcess = class {
|
|
|
12581
12781
|
if (this.stopped) return "stop";
|
|
12582
12782
|
this.stopped = sig;
|
|
12583
12783
|
this.stops++;
|
|
12584
|
-
this.resumed = new Promise((
|
|
12784
|
+
this.resumed = new Promise((resolve2) => this.wake = resolve2);
|
|
12585
12785
|
const blocked = this.interrupt;
|
|
12586
12786
|
this.interrupt = new AbortController();
|
|
12587
12787
|
blocked.abort();
|
|
@@ -12646,7 +12846,9 @@ var WasmProcess = class {
|
|
|
12646
12846
|
const { ptys, jobs } = this.options;
|
|
12647
12847
|
const owner = this.options.owners ? this.ttyOwner() : void 0;
|
|
12648
12848
|
const guard2 = this.guarded();
|
|
12649
|
-
|
|
12849
|
+
const { ttyFilter } = this.options;
|
|
12850
|
+
const ctx = { pid: this.pid, fds: this.fds, ptys, jobs, guard: guard2, owner, ttyFilter };
|
|
12851
|
+
return ptySyscall(req, ctx);
|
|
12650
12852
|
}
|
|
12651
12853
|
return await this.procSyscall(req, cancelled);
|
|
12652
12854
|
} catch (e) {
|
|
@@ -12821,7 +13023,8 @@ var WasmProcess = class {
|
|
|
12821
13023
|
const tty = name2 === void 0 ? this.controllingTerminal() : this.options.jobs?.terminalNamed(name2);
|
|
12822
13024
|
if (!tty) throw new KernelError("ENXIO");
|
|
12823
13025
|
if (name2 !== void 0) ttyOpenable(this.guarded(), tty);
|
|
12824
|
-
|
|
13026
|
+
const file = tty.file();
|
|
13027
|
+
return this.fds.install(this.options.ttyFilter?.(file) ?? file, 3);
|
|
12825
13028
|
}
|
|
12826
13029
|
openSealed() {
|
|
12827
13030
|
const broker = this.options.sealed;
|
|
@@ -12861,15 +13064,8 @@ var WasmProcess = class {
|
|
|
12861
13064
|
async sealedCaller() {
|
|
12862
13065
|
const shown = await this.options.identity?.();
|
|
12863
13066
|
const broker = this.options.sealed;
|
|
12864
|
-
const
|
|
12865
|
-
return
|
|
12866
|
-
pid: shown?.pid ?? this.pid,
|
|
12867
|
-
ppid: shown?.ppid ?? 0,
|
|
12868
|
-
uid: this.cred.euid,
|
|
12869
|
-
gid: this.cred.egid,
|
|
12870
|
-
...tag !== void 0 ? { tag } : {},
|
|
12871
|
-
users: broker.users
|
|
12872
|
-
};
|
|
13067
|
+
const ids = { pid: shown?.pid ?? this.pid, ppid: shown?.ppid ?? 0 };
|
|
13068
|
+
return broker.stamp(ids, this.cred, broker.tagOf(this.pid));
|
|
12873
13069
|
}
|
|
12874
13070
|
guarded() {
|
|
12875
13071
|
const { guard: guard2 } = this.options;
|
|
@@ -13377,13 +13573,13 @@ var WasmProcess = class {
|
|
|
13377
13573
|
while (this.dlLock.depth > 0 && this.dlLock.owner !== owner) {
|
|
13378
13574
|
if (this.dying) throw new KernelError("EINTR");
|
|
13379
13575
|
const interrupt = this.interrupt.signal;
|
|
13380
|
-
const gone = await new Promise((
|
|
13576
|
+
const gone = await new Promise((resolve2) => {
|
|
13381
13577
|
const waiter = {
|
|
13382
13578
|
owner,
|
|
13383
13579
|
wake: (ended) => {
|
|
13384
13580
|
this.dlLock.waiters.delete(waiter);
|
|
13385
13581
|
interrupt.removeEventListener("abort", recheck);
|
|
13386
|
-
|
|
13582
|
+
resolve2(ended);
|
|
13387
13583
|
}
|
|
13388
13584
|
};
|
|
13389
13585
|
const recheck = () => waiter.wake(false);
|
|
@@ -13639,6 +13835,7 @@ function processOptions(opts, header3, hooks, created3) {
|
|
|
13639
13835
|
...inherited(opts),
|
|
13640
13836
|
...opts.owners ? { owners: true } : {},
|
|
13641
13837
|
...opts.sealed ? { sealed: opts.sealed } : {},
|
|
13838
|
+
...opts.ttyFilter ? { ttyFilter: opts.ttyFilter } : {},
|
|
13642
13839
|
...opts.clipboard ? { clipboard: opts.clipboard, ...clipboardName(opts) } : {},
|
|
13643
13840
|
...opts.readonlyAt ? { readonlyAt: opts.readonlyAt } : {},
|
|
13644
13841
|
...opts.dac ? { guard: { dac: opts.dac, fs: opts.fs, created: created3 } } : {},
|
|
@@ -14133,6 +14330,523 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
14133
14330
|
};
|
|
14134
14331
|
}
|
|
14135
14332
|
|
|
14333
|
+
// node_modules/@ai-ecoverse/slicc-scrub/dist/index.js
|
|
14334
|
+
var FRAGMENT = 16;
|
|
14335
|
+
var MIN_VALUE = 8;
|
|
14336
|
+
var MIN_BASE64 = 8;
|
|
14337
|
+
var encoder4 = new TextEncoder();
|
|
14338
|
+
var STD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
14339
|
+
function utf82(text) {
|
|
14340
|
+
return encoder4.encode(text);
|
|
14341
|
+
}
|
|
14342
|
+
function base642(bytes, padded = true) {
|
|
14343
|
+
let out = "";
|
|
14344
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
14345
|
+
const a = bytes[i];
|
|
14346
|
+
const b = i + 1 < bytes.length ? bytes[i + 1] : 0;
|
|
14347
|
+
const c = i + 2 < bytes.length ? bytes[i + 2] : 0;
|
|
14348
|
+
const triple = a << 16 | b << 8 | c;
|
|
14349
|
+
const left = bytes.length - i;
|
|
14350
|
+
out += STD[triple >> 18 & 63] + STD[triple >> 12 & 63];
|
|
14351
|
+
out += left > 1 ? STD[triple >> 6 & 63] : padded ? "=" : "";
|
|
14352
|
+
out += left > 2 ? STD[triple & 63] : padded ? "=" : "";
|
|
14353
|
+
}
|
|
14354
|
+
return out;
|
|
14355
|
+
}
|
|
14356
|
+
function urlSafe(text) {
|
|
14357
|
+
return text.replace(/\+/g, "-").replace(/\//g, "_");
|
|
14358
|
+
}
|
|
14359
|
+
function hex2(bytes) {
|
|
14360
|
+
let out = "";
|
|
14361
|
+
for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
|
|
14362
|
+
return out;
|
|
14363
|
+
}
|
|
14364
|
+
function embedded(bytes, offset) {
|
|
14365
|
+
const shifted = new Uint8Array(offset + bytes.length);
|
|
14366
|
+
shifted.set(bytes, offset);
|
|
14367
|
+
const encoded = base642(shifted);
|
|
14368
|
+
const first = Math.ceil(8 * offset / 6);
|
|
14369
|
+
const last = Math.floor(8 * (offset + bytes.length) / 6);
|
|
14370
|
+
return encoded.slice(first, last);
|
|
14371
|
+
}
|
|
14372
|
+
function unicode(value, upper) {
|
|
14373
|
+
let out = "";
|
|
14374
|
+
for (let i = 0; i < value.length; i++) {
|
|
14375
|
+
const unit = value.charCodeAt(i);
|
|
14376
|
+
if (unit === 34) out += '\\"';
|
|
14377
|
+
else if (unit === 92) out += "\\\\";
|
|
14378
|
+
else if (unit < 32 || unit > 126) {
|
|
14379
|
+
const code = unit.toString(16).padStart(4, "0");
|
|
14380
|
+
out += `\\u${upper ? code.toUpperCase() : code}`;
|
|
14381
|
+
} else out += value[i];
|
|
14382
|
+
}
|
|
14383
|
+
return out;
|
|
14384
|
+
}
|
|
14385
|
+
function percent(value) {
|
|
14386
|
+
let component;
|
|
14387
|
+
try {
|
|
14388
|
+
component = encodeURIComponent(value);
|
|
14389
|
+
} catch {
|
|
14390
|
+
return [];
|
|
14391
|
+
}
|
|
14392
|
+
const lower = component.replace(/%[0-9A-F]{2}/g, (escape) => escape.toLowerCase());
|
|
14393
|
+
const plus = component.replace(/%20/g, "+");
|
|
14394
|
+
let form = "";
|
|
14395
|
+
for (const byte of utf82(value)) {
|
|
14396
|
+
const char = String.fromCharCode(byte);
|
|
14397
|
+
if (/[A-Za-z0-9*\-._]/.test(char)) form += char;
|
|
14398
|
+
else if (byte === 32) form += "+";
|
|
14399
|
+
else form += `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
14400
|
+
}
|
|
14401
|
+
return [component, lower, plus, form];
|
|
14402
|
+
}
|
|
14403
|
+
function html(value, apostrophe) {
|
|
14404
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, apostrophe);
|
|
14405
|
+
}
|
|
14406
|
+
function encodings(bytes) {
|
|
14407
|
+
const standard = [base642(bytes), base642(bytes, false)];
|
|
14408
|
+
for (const offset of [0, 1, 2]) {
|
|
14409
|
+
const run2 = embedded(bytes, offset);
|
|
14410
|
+
if (run2.length >= MIN_BASE64) standard.push(run2);
|
|
14411
|
+
}
|
|
14412
|
+
return [...standard, ...standard.map(urlSafe)];
|
|
14413
|
+
}
|
|
14414
|
+
function shapes(value) {
|
|
14415
|
+
const raw = utf82(value);
|
|
14416
|
+
const seen = /* @__PURE__ */ new Set([value]);
|
|
14417
|
+
const out = [];
|
|
14418
|
+
if (raw.length < FRAGMENT) out.push({ bytes: raw, form: "raw" });
|
|
14419
|
+
for (let offset = 0; raw.length >= FRAGMENT && offset + FRAGMENT <= raw.length; offset++) {
|
|
14420
|
+
out.push({ bytes: raw.subarray(offset, offset + FRAGMENT), form: "fragment", offset });
|
|
14421
|
+
}
|
|
14422
|
+
const add = (text, form) => {
|
|
14423
|
+
if (seen.has(text)) return;
|
|
14424
|
+
seen.add(text);
|
|
14425
|
+
out.push({ bytes: utf82(text), form });
|
|
14426
|
+
};
|
|
14427
|
+
const json5 = JSON.stringify(value).slice(1, -1);
|
|
14428
|
+
for (const text of [
|
|
14429
|
+
json5,
|
|
14430
|
+
json5.replace(/\//g, "\\/"),
|
|
14431
|
+
unicode(value, false),
|
|
14432
|
+
unicode(value, true)
|
|
14433
|
+
]) {
|
|
14434
|
+
add(text, "json");
|
|
14435
|
+
}
|
|
14436
|
+
for (const text of percent(value)) add(text, "percent");
|
|
14437
|
+
for (const text of [html(value, "'"), html(value, "'")]) add(text, "html");
|
|
14438
|
+
for (const text of encodings(raw)) add(text, "base64");
|
|
14439
|
+
add(hex2(raw), "hex");
|
|
14440
|
+
add(hex2(raw).toUpperCase(), "hex");
|
|
14441
|
+
return out;
|
|
14442
|
+
}
|
|
14443
|
+
function wrappable(form) {
|
|
14444
|
+
return form === "base64" || form === "hex";
|
|
14445
|
+
}
|
|
14446
|
+
var Automaton = class {
|
|
14447
|
+
edges = /* @__PURE__ */ new Map();
|
|
14448
|
+
fail = [0];
|
|
14449
|
+
depth = [0];
|
|
14450
|
+
children = [0];
|
|
14451
|
+
out = [[]];
|
|
14452
|
+
dict = [-1];
|
|
14453
|
+
lengths = [];
|
|
14454
|
+
add(bytes) {
|
|
14455
|
+
let node = 0;
|
|
14456
|
+
for (const byte of bytes) {
|
|
14457
|
+
const key = node * 256 + byte;
|
|
14458
|
+
let next2 = this.edges.get(key);
|
|
14459
|
+
if (next2 === void 0) {
|
|
14460
|
+
next2 = this.depth.length;
|
|
14461
|
+
this.edges.set(key, next2);
|
|
14462
|
+
this.fail.push(0);
|
|
14463
|
+
this.depth.push(this.depth[node] + 1);
|
|
14464
|
+
this.children.push(0);
|
|
14465
|
+
this.children[node] += 1;
|
|
14466
|
+
this.out.push([]);
|
|
14467
|
+
this.dict.push(-1);
|
|
14468
|
+
}
|
|
14469
|
+
node = next2;
|
|
14470
|
+
}
|
|
14471
|
+
const id2 = this.lengths.length;
|
|
14472
|
+
this.lengths.push(bytes.length);
|
|
14473
|
+
this.out[node].push(id2);
|
|
14474
|
+
return id2;
|
|
14475
|
+
}
|
|
14476
|
+
build() {
|
|
14477
|
+
const queue = [];
|
|
14478
|
+
const byNode = /* @__PURE__ */ new Map();
|
|
14479
|
+
for (const [key, child] of this.edges) {
|
|
14480
|
+
const parent = Math.floor(key / 256);
|
|
14481
|
+
const list = byNode.get(parent) ?? [];
|
|
14482
|
+
list.push([key % 256, child]);
|
|
14483
|
+
byNode.set(parent, list);
|
|
14484
|
+
}
|
|
14485
|
+
for (const [, child] of byNode.get(0) ?? []) queue.push(child);
|
|
14486
|
+
for (let head = 0; head < queue.length; head++) {
|
|
14487
|
+
const node = queue[head];
|
|
14488
|
+
const fallback = this.fail[node];
|
|
14489
|
+
this.dict[node] = this.out[fallback].length > 0 ? fallback : this.dict[fallback];
|
|
14490
|
+
for (const [byte, child] of byNode.get(node) ?? []) {
|
|
14491
|
+
let state = fallback;
|
|
14492
|
+
let target = this.edges.get(state * 256 + byte);
|
|
14493
|
+
while (target === void 0 && state > 0) {
|
|
14494
|
+
state = this.fail[state];
|
|
14495
|
+
target = this.edges.get(state * 256 + byte);
|
|
14496
|
+
}
|
|
14497
|
+
this.fail[child] = target ?? 0;
|
|
14498
|
+
queue.push(child);
|
|
14499
|
+
}
|
|
14500
|
+
}
|
|
14501
|
+
}
|
|
14502
|
+
step(state, byte) {
|
|
14503
|
+
let current = state;
|
|
14504
|
+
for (; ; ) {
|
|
14505
|
+
const next2 = this.edges.get(current * 256 + byte);
|
|
14506
|
+
if (next2 !== void 0) return next2;
|
|
14507
|
+
if (current === 0) return 0;
|
|
14508
|
+
current = this.fail[current];
|
|
14509
|
+
}
|
|
14510
|
+
}
|
|
14511
|
+
matches(state, visit) {
|
|
14512
|
+
for (let node = state; node > 0; node = this.dict[node]) {
|
|
14513
|
+
for (const id2 of this.out[node]) visit(id2);
|
|
14514
|
+
}
|
|
14515
|
+
}
|
|
14516
|
+
partials(state, length2, visit) {
|
|
14517
|
+
for (let node = state; node > 0; node = this.fail[node]) {
|
|
14518
|
+
if (this.children[node] > 0) visit(length2 - this.depth[node]);
|
|
14519
|
+
}
|
|
14520
|
+
}
|
|
14521
|
+
};
|
|
14522
|
+
var RANK = {
|
|
14523
|
+
raw: 0,
|
|
14524
|
+
fragment: 1,
|
|
14525
|
+
json: 2,
|
|
14526
|
+
percent: 3,
|
|
14527
|
+
html: 4,
|
|
14528
|
+
base64: 5,
|
|
14529
|
+
hex: 6,
|
|
14530
|
+
wrapped: 7
|
|
14531
|
+
};
|
|
14532
|
+
var CR2 = 13;
|
|
14533
|
+
var LF2 = 10;
|
|
14534
|
+
var EMPTY2 = new Uint8Array(0);
|
|
14535
|
+
function register(automaton, sources, ids, bytes, source) {
|
|
14536
|
+
const key = Array.from(bytes).join(",");
|
|
14537
|
+
let id2 = ids.get(key);
|
|
14538
|
+
if (id2 === void 0) {
|
|
14539
|
+
id2 = automaton.add(bytes);
|
|
14540
|
+
ids.set(key, id2);
|
|
14541
|
+
sources[id2] = [];
|
|
14542
|
+
}
|
|
14543
|
+
sources[id2].push(source);
|
|
14544
|
+
}
|
|
14545
|
+
function prepare(secrets) {
|
|
14546
|
+
const main = new Automaton();
|
|
14547
|
+
const wrap = new Automaton();
|
|
14548
|
+
const sources = [];
|
|
14549
|
+
const wrapSources = [];
|
|
14550
|
+
const ids = /* @__PURE__ */ new Map();
|
|
14551
|
+
const wrapIds = /* @__PURE__ */ new Map();
|
|
14552
|
+
const values = secrets.map((secret) => utf82(secret.value));
|
|
14553
|
+
secrets.forEach((secret, index) => {
|
|
14554
|
+
if (typeof secret.value !== "string" || values[index].length < MIN_VALUE) {
|
|
14555
|
+
throw new RangeError(`the value of ${secret.name} is shorter than ${MIN_VALUE} bytes`);
|
|
14556
|
+
}
|
|
14557
|
+
for (const shape of shapes(secret.value)) {
|
|
14558
|
+
const source = { secret: index, form: shape.form, offset: shape.offset };
|
|
14559
|
+
register(main, sources, ids, shape.bytes, source);
|
|
14560
|
+
if (wrappable(shape.form)) register(wrap, wrapSources, wrapIds, shape.bytes, source);
|
|
14561
|
+
}
|
|
14562
|
+
});
|
|
14563
|
+
main.build();
|
|
14564
|
+
wrap.build();
|
|
14565
|
+
const replacements = secrets.map((secret) => [
|
|
14566
|
+
utf82(secret.placeholder),
|
|
14567
|
+
utf82(`[redacted:${secret.name}]`)
|
|
14568
|
+
]);
|
|
14569
|
+
return { secrets, values, main, wrap, sources, wrapSources, replacements };
|
|
14570
|
+
}
|
|
14571
|
+
function better(a, b) {
|
|
14572
|
+
if (!b) return true;
|
|
14573
|
+
if (a.end !== b.end) return a.end > b.end;
|
|
14574
|
+
if (a.rank !== b.rank) return a.rank < b.rank;
|
|
14575
|
+
return a.secret < b.secret;
|
|
14576
|
+
}
|
|
14577
|
+
function resolve(c, input, start2, end, source) {
|
|
14578
|
+
if (source.form !== "fragment") {
|
|
14579
|
+
return {
|
|
14580
|
+
start: start2,
|
|
14581
|
+
end,
|
|
14582
|
+
secret: source.secret,
|
|
14583
|
+
form: source.form,
|
|
14584
|
+
rank: RANK[source.form],
|
|
14585
|
+
growing: false
|
|
14586
|
+
};
|
|
14587
|
+
}
|
|
14588
|
+
const value = c.values[source.secret];
|
|
14589
|
+
let stop = end;
|
|
14590
|
+
let at = source.offset + FRAGMENT;
|
|
14591
|
+
while (stop < input.length && at < value.length && input[stop] === value[at]) {
|
|
14592
|
+
stop++;
|
|
14593
|
+
at++;
|
|
14594
|
+
}
|
|
14595
|
+
const form = source.offset === 0 && at === value.length ? "raw" : "fragment";
|
|
14596
|
+
const growing = stop === input.length && at < value.length;
|
|
14597
|
+
return { start: start2, end: stop, secret: source.secret, form, rank: RANK[form], growing };
|
|
14598
|
+
}
|
|
14599
|
+
function keep(best, candidate) {
|
|
14600
|
+
if (better(candidate, best.get(candidate.start))) best.set(candidate.start, candidate);
|
|
14601
|
+
}
|
|
14602
|
+
function scanMain(c, input, best, partials) {
|
|
14603
|
+
let state = 0;
|
|
14604
|
+
for (let i = 0; i < input.length; i++) {
|
|
14605
|
+
state = c.main.step(state, input[i]);
|
|
14606
|
+
c.main.matches(state, (id2) => {
|
|
14607
|
+
const start2 = i + 1 - c.main.lengths[id2];
|
|
14608
|
+
for (const source of c.sources[id2]) {
|
|
14609
|
+
const candidate = resolve(c, input, start2, i + 1, source);
|
|
14610
|
+
if (candidate.growing) partials.push(candidate.start);
|
|
14611
|
+
keep(best, candidate);
|
|
14612
|
+
}
|
|
14613
|
+
});
|
|
14614
|
+
}
|
|
14615
|
+
c.main.partials(state, input.length, (start2) => partials.push(start2));
|
|
14616
|
+
}
|
|
14617
|
+
function scanWrapped(c, input, best, partials) {
|
|
14618
|
+
const map = [];
|
|
14619
|
+
for (let i = 0; i < input.length; i++) if (input[i] !== CR2 && input[i] !== LF2) map.push(i);
|
|
14620
|
+
if (map.length === input.length) return;
|
|
14621
|
+
let state = 0;
|
|
14622
|
+
for (let v = 0; v < map.length; v++) {
|
|
14623
|
+
state = c.wrap.step(state, input[map[v]]);
|
|
14624
|
+
c.wrap.matches(state, (id2) => {
|
|
14625
|
+
const first = v + 1 - c.wrap.lengths[id2];
|
|
14626
|
+
const start2 = map[first];
|
|
14627
|
+
const end = map[v] + 1;
|
|
14628
|
+
const wrapped = end - start2 !== c.wrap.lengths[id2];
|
|
14629
|
+
for (const source of c.wrapSources[id2]) {
|
|
14630
|
+
const form = wrapped ? "wrapped" : source.form;
|
|
14631
|
+
keep(best, { start: start2, end, secret: source.secret, form, rank: RANK[form], growing: false });
|
|
14632
|
+
}
|
|
14633
|
+
});
|
|
14634
|
+
}
|
|
14635
|
+
c.wrap.partials(state, map.length, (start2) => partials.push(map[start2]));
|
|
14636
|
+
}
|
|
14637
|
+
function count(c, hits, candidate) {
|
|
14638
|
+
const name2 = c.secrets[candidate.secret].name;
|
|
14639
|
+
const key = `${name2}\0${candidate.form}`;
|
|
14640
|
+
const hit = hits.get(key) ?? { name: name2, form: candidate.form, count: 0 };
|
|
14641
|
+
hit.count += 1;
|
|
14642
|
+
hits.set(key, hit);
|
|
14643
|
+
}
|
|
14644
|
+
function concat5(parts2) {
|
|
14645
|
+
let length2 = 0;
|
|
14646
|
+
for (const part of parts2) length2 += part.length;
|
|
14647
|
+
const out = new Uint8Array(length2);
|
|
14648
|
+
let at = 0;
|
|
14649
|
+
for (const part of parts2) {
|
|
14650
|
+
out.set(part, at);
|
|
14651
|
+
at += part.length;
|
|
14652
|
+
}
|
|
14653
|
+
return out;
|
|
14654
|
+
}
|
|
14655
|
+
function pass(c, input, final) {
|
|
14656
|
+
const best = /* @__PURE__ */ new Map();
|
|
14657
|
+
const partials = [];
|
|
14658
|
+
scanMain(c, input, best, partials);
|
|
14659
|
+
scanWrapped(c, input, best, partials);
|
|
14660
|
+
const holds = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
|
|
14661
|
+
const starts = [...best.keys()].sort((a, b) => a - b);
|
|
14662
|
+
const parts2 = [];
|
|
14663
|
+
const hits = /* @__PURE__ */ new Map();
|
|
14664
|
+
let pos = 0;
|
|
14665
|
+
let cut = input.length;
|
|
14666
|
+
let s = 0;
|
|
14667
|
+
let h = 0;
|
|
14668
|
+
for (; ; ) {
|
|
14669
|
+
while (s < starts.length && starts[s] < pos) s++;
|
|
14670
|
+
while (h < holds.length && holds[h] < pos) h++;
|
|
14671
|
+
const hold = h < holds.length ? holds[h] : Infinity;
|
|
14672
|
+
const next2 = s < starts.length ? starts[s] : Infinity;
|
|
14673
|
+
if (hold <= next2) {
|
|
14674
|
+
cut = Math.min(hold, input.length);
|
|
14675
|
+
break;
|
|
14676
|
+
}
|
|
14677
|
+
const candidate = best.get(next2);
|
|
14678
|
+
parts2.push(
|
|
14679
|
+
input.subarray(pos, next2),
|
|
14680
|
+
c.replacements[candidate.secret][candidate.form === "raw" ? 0 : 1]
|
|
14681
|
+
);
|
|
14682
|
+
count(c, hits, candidate);
|
|
14683
|
+
pos = candidate.end;
|
|
14684
|
+
}
|
|
14685
|
+
parts2.push(input.subarray(pos, cut));
|
|
14686
|
+
return { output: concat5(parts2), cut, hits };
|
|
14687
|
+
}
|
|
14688
|
+
function merge(into, from) {
|
|
14689
|
+
for (const [key, hit] of from) {
|
|
14690
|
+
const known = into.get(key);
|
|
14691
|
+
if (known) known.count += hit.count;
|
|
14692
|
+
else into.set(key, { ...hit });
|
|
14693
|
+
}
|
|
14694
|
+
}
|
|
14695
|
+
function compile(secrets, options = {}) {
|
|
14696
|
+
const c = prepare(secrets.map((secret) => ({ ...secret })));
|
|
14697
|
+
const decoder4 = new TextDecoder();
|
|
14698
|
+
const idleMs = options.idleMs ?? 250;
|
|
14699
|
+
const scrubBytes = (input) => {
|
|
14700
|
+
if (c.secrets.length === 0) return { bytes: input.slice(), hits: [] };
|
|
14701
|
+
const result = pass(c, input, true);
|
|
14702
|
+
return { bytes: result.output, hits: [...result.hits.values()] };
|
|
14703
|
+
};
|
|
14704
|
+
return {
|
|
14705
|
+
version: options.version ?? 0,
|
|
14706
|
+
idleMs,
|
|
14707
|
+
size: c.main.lengths.length,
|
|
14708
|
+
bytes: scrubBytes,
|
|
14709
|
+
text(input) {
|
|
14710
|
+
const { bytes, hits } = scrubBytes(utf82(input));
|
|
14711
|
+
return { text: decoder4.decode(bytes), hits };
|
|
14712
|
+
},
|
|
14713
|
+
stream() {
|
|
14714
|
+
let pending = EMPTY2;
|
|
14715
|
+
const hits = /* @__PURE__ */ new Map();
|
|
14716
|
+
const run2 = (final) => {
|
|
14717
|
+
if (c.secrets.length === 0 || pending.length === 0) {
|
|
14718
|
+
const out = pending;
|
|
14719
|
+
pending = EMPTY2;
|
|
14720
|
+
return out;
|
|
14721
|
+
}
|
|
14722
|
+
const result = pass(c, pending, final);
|
|
14723
|
+
merge(hits, result.hits);
|
|
14724
|
+
pending = pending.slice(result.cut);
|
|
14725
|
+
return result.output;
|
|
14726
|
+
};
|
|
14727
|
+
return {
|
|
14728
|
+
push(chunk2) {
|
|
14729
|
+
pending = concat5([pending, chunk2]);
|
|
14730
|
+
return run2(false);
|
|
14731
|
+
},
|
|
14732
|
+
idle() {
|
|
14733
|
+
return pending.length < FRAGMENT ? run2(true) : EMPTY2;
|
|
14734
|
+
},
|
|
14735
|
+
end() {
|
|
14736
|
+
return run2(true);
|
|
14737
|
+
},
|
|
14738
|
+
get hits() {
|
|
14739
|
+
return [...hits.values()];
|
|
14740
|
+
}
|
|
14741
|
+
};
|
|
14742
|
+
}
|
|
14743
|
+
};
|
|
14744
|
+
}
|
|
14745
|
+
|
|
14746
|
+
// src/kernel/scrub-file.ts
|
|
14747
|
+
var SCRUB_IDLE_MS = 50;
|
|
14748
|
+
var encoder5 = new TextEncoder();
|
|
14749
|
+
function scrubberOf(secrets) {
|
|
14750
|
+
const usable = secrets.filter((s) => encoder5.encode(s.value).length >= MIN_VALUE);
|
|
14751
|
+
return usable.length > 0 ? compile(usable, { idleMs: SCRUB_IDLE_MS }) : void 0;
|
|
14752
|
+
}
|
|
14753
|
+
async function writeAll2(file, bytes, signal) {
|
|
14754
|
+
const write = file.write;
|
|
14755
|
+
for (let at = 0; at < bytes.length; ) {
|
|
14756
|
+
at += await write.call(file, bytes.subarray(at), at === 0 ? signal : void 0);
|
|
14757
|
+
}
|
|
14758
|
+
}
|
|
14759
|
+
function bound(file, key) {
|
|
14760
|
+
const method = file[key];
|
|
14761
|
+
return typeof method === "function" ? { [key]: method.bind(file) } : {};
|
|
14762
|
+
}
|
|
14763
|
+
function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
14764
|
+
const file = inner.file;
|
|
14765
|
+
const stream = scrubber.stream();
|
|
14766
|
+
let queue = Promise.resolve();
|
|
14767
|
+
let timer;
|
|
14768
|
+
let failed3;
|
|
14769
|
+
const raise = () => {
|
|
14770
|
+
if (failed3 === void 0) return;
|
|
14771
|
+
const err = failed3;
|
|
14772
|
+
failed3 = void 0;
|
|
14773
|
+
throw err;
|
|
14774
|
+
};
|
|
14775
|
+
const enqueue = (bytes, signal) => {
|
|
14776
|
+
const next2 = queue.then(() => bytes.length > 0 ? writeAll2(file, bytes, signal) : void 0);
|
|
14777
|
+
queue = next2.catch(() => void 0);
|
|
14778
|
+
return next2;
|
|
14779
|
+
};
|
|
14780
|
+
const release = () => {
|
|
14781
|
+
timer = void 0;
|
|
14782
|
+
enqueue(stream.idle()).catch((err) => {
|
|
14783
|
+
failed3 = err;
|
|
14784
|
+
});
|
|
14785
|
+
};
|
|
14786
|
+
return new OpenFile({
|
|
14787
|
+
...bound(file, "read"),
|
|
14788
|
+
...bound(file, "peek"),
|
|
14789
|
+
...bound(file, "poll"),
|
|
14790
|
+
...bound(file, "changed"),
|
|
14791
|
+
...bound(file, "stat"),
|
|
14792
|
+
...file.tty ? { tty: file.tty } : {},
|
|
14793
|
+
...file.clipboard ? { clipboard: file.clipboard } : {},
|
|
14794
|
+
...file.write ? {
|
|
14795
|
+
write: async (bytes, signal) => {
|
|
14796
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
14797
|
+
raise();
|
|
14798
|
+
await enqueue(stream.push(bytes), signal);
|
|
14799
|
+
timer = setTimeout(release, idleMs);
|
|
14800
|
+
return bytes.length;
|
|
14801
|
+
}
|
|
14802
|
+
} : {},
|
|
14803
|
+
flush: async () => {
|
|
14804
|
+
await queue;
|
|
14805
|
+
raise();
|
|
14806
|
+
await file.flush?.();
|
|
14807
|
+
},
|
|
14808
|
+
close: async () => {
|
|
14809
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
14810
|
+
let failure2;
|
|
14811
|
+
try {
|
|
14812
|
+
await enqueue(stream.end());
|
|
14813
|
+
raise();
|
|
14814
|
+
} catch (err) {
|
|
14815
|
+
failure2 = { err };
|
|
14816
|
+
}
|
|
14817
|
+
await inner.release();
|
|
14818
|
+
if (failure2) throw failure2.err;
|
|
14819
|
+
}
|
|
14820
|
+
});
|
|
14821
|
+
}
|
|
14822
|
+
function scrubbedAll(file, scrubbers) {
|
|
14823
|
+
return scrubbers.reduce((inner, scrubber) => scrubbed(inner, scrubber), file);
|
|
14824
|
+
}
|
|
14825
|
+
function stdioFiles(fds) {
|
|
14826
|
+
const files = /* @__PURE__ */ new Set();
|
|
14827
|
+
for (const fd of [1, 2]) {
|
|
14828
|
+
try {
|
|
14829
|
+
files.add(fds.get(fd));
|
|
14830
|
+
} catch {
|
|
14831
|
+
}
|
|
14832
|
+
}
|
|
14833
|
+
return files;
|
|
14834
|
+
}
|
|
14835
|
+
function scrubStdio(fds, scrubber) {
|
|
14836
|
+
const wrapped = /* @__PURE__ */ new Map();
|
|
14837
|
+
const stdio = stdioFiles(fds);
|
|
14838
|
+
for (const fd of fds.numbers()) {
|
|
14839
|
+
const original = fds.get(fd);
|
|
14840
|
+
if (!stdio.has(original) && !original.file.tty) continue;
|
|
14841
|
+
const known = wrapped.get(original);
|
|
14842
|
+
const flags2 = fds.statusFlags(fd);
|
|
14843
|
+
const wrapper = known ? known.retain() : scrubbed(original.retain(), scrubber);
|
|
14844
|
+
wrapped.set(original, wrapper);
|
|
14845
|
+
fds.installAt(fd, wrapper);
|
|
14846
|
+
if (flags2 !== void 0) fds.setStatusFlags(fd, flags2);
|
|
14847
|
+
}
|
|
14848
|
+
}
|
|
14849
|
+
|
|
14136
14850
|
// src/kernel/sealed.ts
|
|
14137
14851
|
var SEALED_MAX_BYTES = 64 * 1024;
|
|
14138
14852
|
var SEALED_TIMEOUT_MS = 1e4;
|
|
@@ -14146,7 +14860,7 @@ var SEALED_OPS = /* @__PURE__ */ new Set([
|
|
|
14146
14860
|
"cancel",
|
|
14147
14861
|
"materialize"
|
|
14148
14862
|
]);
|
|
14149
|
-
var
|
|
14863
|
+
var encoder6 = new TextEncoder();
|
|
14150
14864
|
var decoder3 = new TextDecoder("utf-8", { fatal: true });
|
|
14151
14865
|
function parseSealed(bytes) {
|
|
14152
14866
|
try {
|
|
@@ -14162,11 +14876,16 @@ function parseSealed(bytes) {
|
|
|
14162
14876
|
const req = parsed2;
|
|
14163
14877
|
if (req.v !== 1 || typeof req.op !== "string" || !SEALED_OPS.has(req.op))
|
|
14164
14878
|
throw new KernelError("EINVAL");
|
|
14879
|
+
if (req.op === "materialize" && !materializable(req)) throw new KernelError("EINVAL");
|
|
14165
14880
|
return req;
|
|
14166
14881
|
} finally {
|
|
14167
14882
|
bytes.fill(0);
|
|
14168
14883
|
}
|
|
14169
14884
|
}
|
|
14885
|
+
function materializable(req) {
|
|
14886
|
+
if (req.shellGrants !== true && !isStrings(req.names)) return false;
|
|
14887
|
+
return isStrings(req.argv) && typeof req.path === "string" && typeof req.cwd === "string";
|
|
14888
|
+
}
|
|
14170
14889
|
function errorReply(code, message3) {
|
|
14171
14890
|
return { v: 1, error: { code, message: message3 } };
|
|
14172
14891
|
}
|
|
@@ -14210,12 +14929,14 @@ var SealedChannel = class {
|
|
|
14210
14929
|
const timer = setTimeout(() => control.abort("timeout"), this.broker.timeoutMs);
|
|
14211
14930
|
const req = { ...fields, v: 1, op: fields.op, caller };
|
|
14212
14931
|
const flight = { control, done: Promise.resolve() };
|
|
14213
|
-
flight.done = this.answer(req, control.signal).then((reply) => {
|
|
14932
|
+
flight.done = this.answer(req, control.signal).then(async (reply) => {
|
|
14214
14933
|
clearTimeout(timer);
|
|
14215
14934
|
gone.removeEventListener("abort", withdraw);
|
|
14935
|
+
if (reply && req.op === "materialize")
|
|
14936
|
+
await this.broker.tickets.record(req, reply, caller.pid);
|
|
14216
14937
|
if (this.inflight !== flight) return;
|
|
14217
14938
|
this.inflight = void 0;
|
|
14218
|
-
if (reply) this.reply =
|
|
14939
|
+
if (reply) this.reply = encoder6.encode(serialized(reply));
|
|
14219
14940
|
});
|
|
14220
14941
|
this.inflight = flight;
|
|
14221
14942
|
return length2;
|
|
@@ -14223,8 +14944,8 @@ var SealedChannel = class {
|
|
|
14223
14944
|
async answer(req, signal) {
|
|
14224
14945
|
const hook = this.broker.hook;
|
|
14225
14946
|
if (!hook) return errorReply("ENOTCONN", "no vault is connected");
|
|
14226
|
-
const stopped = new Promise((
|
|
14227
|
-
signal.addEventListener("abort", () =>
|
|
14947
|
+
const stopped = new Promise((resolve2) => {
|
|
14948
|
+
signal.addEventListener("abort", () => resolve2(void 0), { once: true });
|
|
14228
14949
|
});
|
|
14229
14950
|
if (signal.aborted) return void 0;
|
|
14230
14951
|
const asked = Promise.resolve().then(() => hook(req, { signal })).then(
|
|
@@ -14279,17 +15000,60 @@ var SealedChannel = class {
|
|
|
14279
15000
|
this.reply = void 0;
|
|
14280
15001
|
}
|
|
14281
15002
|
};
|
|
15003
|
+
function swapOf(reply) {
|
|
15004
|
+
if (!isRecord(reply) || reply.error !== void 0) return void 0;
|
|
15005
|
+
const values = stringRecord(reply.values);
|
|
15006
|
+
const placeholders = stringRecord(reply.placeholders);
|
|
15007
|
+
return values && placeholders ? { values, placeholders } : void 0;
|
|
15008
|
+
}
|
|
14282
15009
|
var SealedBroker = class {
|
|
14283
15010
|
hook;
|
|
14284
15011
|
users;
|
|
14285
15012
|
timeoutMs;
|
|
14286
15013
|
tagOf;
|
|
15014
|
+
tickets = new TicketBook();
|
|
15015
|
+
userOf = async () => void 0;
|
|
14287
15016
|
constructor(hook, users, timeoutMs = SEALED_TIMEOUT_MS, tagOf = () => void 0) {
|
|
14288
15017
|
this.hook = hook;
|
|
14289
15018
|
this.users = users;
|
|
14290
15019
|
this.timeoutMs = timeoutMs;
|
|
14291
15020
|
this.tagOf = tagOf;
|
|
14292
15021
|
}
|
|
15022
|
+
async stamp(ids, cred, tag) {
|
|
15023
|
+
const user = await this.userOf(cred.euid).catch(() => void 0);
|
|
15024
|
+
return {
|
|
15025
|
+
pid: ids.pid,
|
|
15026
|
+
ppid: ids.ppid,
|
|
15027
|
+
uid: cred.euid,
|
|
15028
|
+
gid: cred.egid,
|
|
15029
|
+
...user !== void 0 ? { user } : {},
|
|
15030
|
+
groups: [...cred.groups],
|
|
15031
|
+
users: this.users,
|
|
15032
|
+
...tag !== void 0 ? { tag } : {}
|
|
15033
|
+
};
|
|
15034
|
+
}
|
|
15035
|
+
async consume(fields) {
|
|
15036
|
+
const { hook } = this;
|
|
15037
|
+
if (!hook) return void 0;
|
|
15038
|
+
const control = new AbortController();
|
|
15039
|
+
const timer = setTimeout(() => control.abort("timeout"), this.timeoutMs);
|
|
15040
|
+
const stopped = new Promise((resolve2) => {
|
|
15041
|
+
control.signal.addEventListener("abort", () => resolve2(void 0), { once: true });
|
|
15042
|
+
});
|
|
15043
|
+
const req = {
|
|
15044
|
+
...fields,
|
|
15045
|
+
v: 1,
|
|
15046
|
+
op: "materializeConsume",
|
|
15047
|
+
caller: fields.stamp
|
|
15048
|
+
};
|
|
15049
|
+
try {
|
|
15050
|
+
const asked = Promise.resolve().then(() => hook(req, { signal: control.signal })).then(swapOf, () => void 0);
|
|
15051
|
+
return await Promise.race([asked, stopped]);
|
|
15052
|
+
} finally {
|
|
15053
|
+
clearTimeout(timer);
|
|
15054
|
+
control.abort("done");
|
|
15055
|
+
}
|
|
15056
|
+
}
|
|
14293
15057
|
open() {
|
|
14294
15058
|
const channel = new SealedChannel(this);
|
|
14295
15059
|
return new OpenFile({
|
|
@@ -14788,11 +15552,11 @@ function codeOf3(err) {
|
|
|
14788
15552
|
}
|
|
14789
15553
|
function wait(ms, signal) {
|
|
14790
15554
|
if (signal.aborted) return Promise.resolve();
|
|
14791
|
-
return new Promise((
|
|
15555
|
+
return new Promise((resolve2) => {
|
|
14792
15556
|
const done4 = () => {
|
|
14793
15557
|
clearTimeout(timer);
|
|
14794
15558
|
signal.removeEventListener("abort", done4);
|
|
14795
|
-
|
|
15559
|
+
resolve2();
|
|
14796
15560
|
};
|
|
14797
15561
|
const timer = setTimeout(done4, ms);
|
|
14798
15562
|
signal.addEventListener("abort", done4, { once: true });
|
|
@@ -15119,11 +15883,11 @@ async function resize(h, path, size) {
|
|
|
15119
15883
|
}
|
|
15120
15884
|
}
|
|
15121
15885
|
function sleep(ms, signal) {
|
|
15122
|
-
return new Promise((
|
|
15886
|
+
return new Promise((resolve2) => {
|
|
15123
15887
|
const done4 = () => {
|
|
15124
15888
|
clearTimeout(timer);
|
|
15125
15889
|
signal.removeEventListener("abort", done4);
|
|
15126
|
-
|
|
15890
|
+
resolve2();
|
|
15127
15891
|
};
|
|
15128
15892
|
const timer = setTimeout(done4, ms);
|
|
15129
15893
|
signal.addEventListener("abort", done4);
|
|
@@ -15206,7 +15970,7 @@ var PORT_DEAD_MS = 1e4;
|
|
|
15206
15970
|
var PORT_LINGER_MS = 1e3;
|
|
15207
15971
|
function timed(transport, ms) {
|
|
15208
15972
|
const inflight = /* @__PURE__ */ new Set();
|
|
15209
|
-
const guard2 = (name2, run2, late, expire) => new Promise((
|
|
15973
|
+
const guard2 = (name2, run2, late, expire) => new Promise((resolve2, reject) => {
|
|
15210
15974
|
let expired = false;
|
|
15211
15975
|
const running = run2();
|
|
15212
15976
|
inflight.add(running);
|
|
@@ -15223,7 +15987,7 @@ function timed(transport, ms) {
|
|
|
15223
15987
|
(value) => {
|
|
15224
15988
|
clearTimeout(timer);
|
|
15225
15989
|
if (expired) late?.(value);
|
|
15226
|
-
|
|
15990
|
+
resolve2(value);
|
|
15227
15991
|
},
|
|
15228
15992
|
(err) => {
|
|
15229
15993
|
clearTimeout(timer);
|
|
@@ -15358,7 +16122,7 @@ var PortTransport = class {
|
|
|
15358
16122
|
ask(message3, bytes = 0, transfer = []) {
|
|
15359
16123
|
const id2 = ++this.next;
|
|
15360
16124
|
if (this.dead) return Promise.reject(fsError2("ENOTCONN", this.dead));
|
|
15361
|
-
return new Promise((
|
|
16125
|
+
return new Promise((resolve2, reject) => {
|
|
15362
16126
|
const timer = setTimeout(
|
|
15363
16127
|
() => {
|
|
15364
16128
|
this.waiting.delete(id2);
|
|
@@ -15372,7 +16136,7 @@ var PortTransport = class {
|
|
|
15372
16136
|
clearTimeout(timer);
|
|
15373
16137
|
this.waiting.delete(id2);
|
|
15374
16138
|
if (reply.error) reject(fsError2(reply.error.code ?? "EIO", reply.error.message ?? ""));
|
|
15375
|
-
else
|
|
16139
|
+
else resolve2(reply);
|
|
15376
16140
|
});
|
|
15377
16141
|
try {
|
|
15378
16142
|
this.port.postMessage({ id: id2, ...message3 }, transfer);
|
|
@@ -15401,7 +16165,7 @@ var PortTransport = class {
|
|
|
15401
16165
|
this.fail("the folder's watch ended");
|
|
15402
16166
|
return Promise.resolve();
|
|
15403
16167
|
}
|
|
15404
|
-
return new Promise((
|
|
16168
|
+
return new Promise((resolve2, reject) => {
|
|
15405
16169
|
const finish = () => {
|
|
15406
16170
|
this.waiting.delete(id2);
|
|
15407
16171
|
signal.removeEventListener("abort", stop);
|
|
@@ -15412,7 +16176,7 @@ var PortTransport = class {
|
|
|
15412
16176
|
this.port.postMessage({ id: id2, op: "unwatch" });
|
|
15413
16177
|
} catch {
|
|
15414
16178
|
}
|
|
15415
|
-
|
|
16179
|
+
resolve2();
|
|
15416
16180
|
};
|
|
15417
16181
|
this.watchBeat();
|
|
15418
16182
|
this.waiting.set(id2, (reply) => {
|
|
@@ -15420,7 +16184,7 @@ var PortTransport = class {
|
|
|
15420
16184
|
if (reply.event) return onEvent(reply.event);
|
|
15421
16185
|
finish();
|
|
15422
16186
|
if (reply.error) reject(fsError2(reply.error.code ?? "ENOTCONN", reply.error.message ?? ""));
|
|
15423
|
-
else
|
|
16187
|
+
else resolve2();
|
|
15424
16188
|
});
|
|
15425
16189
|
signal.addEventListener("abort", stop, { once: true });
|
|
15426
16190
|
try {
|
|
@@ -15533,10 +16297,10 @@ var ChunkedBytes = class {
|
|
|
15533
16297
|
}
|
|
15534
16298
|
truncate(size) {
|
|
15535
16299
|
if (size < this.size) {
|
|
15536
|
-
const
|
|
15537
|
-
this.chunks.length = Math.min(this.chunks.length,
|
|
15538
|
-
const tail = this.chunks[
|
|
15539
|
-
const from = size - (
|
|
16300
|
+
const keep2 = Math.ceil(size / CHUNK3);
|
|
16301
|
+
this.chunks.length = Math.min(this.chunks.length, keep2);
|
|
16302
|
+
const tail = this.chunks[keep2 - 1];
|
|
16303
|
+
const from = size - (keep2 - 1) * CHUNK3;
|
|
15540
16304
|
if (tail && from < tail.length) tail.fill(0, from);
|
|
15541
16305
|
}
|
|
15542
16306
|
this.size = size;
|
|
@@ -15781,8 +16545,8 @@ function importedMemory(bytes) {
|
|
|
15781
16545
|
at = end;
|
|
15782
16546
|
continue;
|
|
15783
16547
|
}
|
|
15784
|
-
const
|
|
15785
|
-
for (let i = 0; i <
|
|
16548
|
+
const count2 = u32();
|
|
16549
|
+
for (let i = 0; i < count2; i++) {
|
|
15786
16550
|
const module = name2();
|
|
15787
16551
|
const field3 = name2();
|
|
15788
16552
|
const kind = bytes[at++];
|
|
@@ -16211,7 +16975,7 @@ ${lines2}
|
|
|
16211
16975
|
const withdraw = () => control.abort("withdrawn");
|
|
16212
16976
|
requester.addEventListener("abort", withdraw, { once: true });
|
|
16213
16977
|
const aborted2 = new Promise(
|
|
16214
|
-
(
|
|
16978
|
+
(resolve2) => control.signal.addEventListener("abort", () => resolve2("aborted"), { once: true })
|
|
16215
16979
|
);
|
|
16216
16980
|
try {
|
|
16217
16981
|
const answered2 = Promise.resolve().then(() => approve(req, { signal: control.signal })).catch(() => "deny");
|
|
@@ -16337,7 +17101,7 @@ var LAYOUT = [
|
|
|
16337
17101
|
];
|
|
16338
17102
|
var LOAD_SAMPLE_MS = 5e3;
|
|
16339
17103
|
var LOAD_WINDOWS_MS = [6e4, 3e5, 9e5];
|
|
16340
|
-
var
|
|
17104
|
+
var encoder7 = new TextEncoder();
|
|
16341
17105
|
var USERS_MODES = ["off", "report", "enforce"];
|
|
16342
17106
|
function usersMode(mode = "off") {
|
|
16343
17107
|
if (USERS_MODES.includes(mode)) return mode;
|
|
@@ -16368,6 +17132,30 @@ function shebang(head) {
|
|
|
16368
17132
|
if (head[0] !== 35 || head[1] !== 33) return void 0;
|
|
16369
17133
|
return new TextDecoder().decode(head.subarray(0, SHEBANG_MAX)).slice(2).split("\n")[0].trim().split(/[ \t]+/);
|
|
16370
17134
|
}
|
|
17135
|
+
async function rootOnly(fs, path) {
|
|
17136
|
+
const names = chain(path);
|
|
17137
|
+
for (const [i, at] of names.entries()) {
|
|
17138
|
+
const st = await fs.lstat(at).catch(() => void 0);
|
|
17139
|
+
const kind = i === names.length - 1 ? st?.isFile : st?.isDirectory;
|
|
17140
|
+
if (!kind || st?.uid !== 0 || (st.mode & 18) !== 0) return false;
|
|
17141
|
+
}
|
|
17142
|
+
return true;
|
|
17143
|
+
}
|
|
17144
|
+
function plainEnv(words2) {
|
|
17145
|
+
const next2 = words2[1];
|
|
17146
|
+
if (baseName(words2[0] ?? "") !== "env" || next2 === void 0) return false;
|
|
17147
|
+
return next2 === "-S" || !next2.startsWith("-") && !next2.includes("=");
|
|
17148
|
+
}
|
|
17149
|
+
function shebangCommand(words2) {
|
|
17150
|
+
if (!plainEnv(words2)) {
|
|
17151
|
+
const arg2 = words2.slice(1).join(" ");
|
|
17152
|
+
return { interp: words2[0], args: arg2 ? [arg2] : [] };
|
|
17153
|
+
}
|
|
17154
|
+
const split2 = words2[1] === "-S";
|
|
17155
|
+
const [interp, ...rest2] = words2.slice(split2 ? 2 : 1);
|
|
17156
|
+
const arg = rest2.join(" ");
|
|
17157
|
+
return { interp, args: split2 ? rest2 : arg ? [arg] : [] };
|
|
17158
|
+
}
|
|
16371
17159
|
function interpreter(head) {
|
|
16372
17160
|
const words2 = shebang(head);
|
|
16373
17161
|
if (!words2) return "node";
|
|
@@ -16421,7 +17209,7 @@ function childHandle(handle) {
|
|
|
16421
17209
|
onState: (listener) => handle.onState(listener)
|
|
16422
17210
|
};
|
|
16423
17211
|
}
|
|
16424
|
-
function
|
|
17212
|
+
function concat6(chunks) {
|
|
16425
17213
|
const out = new Uint8Array(chunks.reduce((n, chunk2) => n + chunk2.length, 0));
|
|
16426
17214
|
let offset = 0;
|
|
16427
17215
|
for (const chunk2 of chunks) {
|
|
@@ -16453,6 +17241,13 @@ var Launcher = class {
|
|
|
16453
17241
|
unwatchScopes = () => void 0;
|
|
16454
17242
|
warned = /* @__PURE__ */ new Set();
|
|
16455
17243
|
compiled = /* @__PURE__ */ new Map();
|
|
17244
|
+
texts = /* @__PURE__ */ new Map();
|
|
17245
|
+
integrity;
|
|
17246
|
+
scannedFs;
|
|
17247
|
+
get scanned() {
|
|
17248
|
+
this.scannedFs ??= this.verifiedFs(this.base);
|
|
17249
|
+
return this.scannedFs;
|
|
17250
|
+
}
|
|
16456
17251
|
processes = /* @__PURE__ */ new Map();
|
|
16457
17252
|
zombies = /* @__PURE__ */ new Set();
|
|
16458
17253
|
orphans = /* @__PURE__ */ new Set();
|
|
@@ -16500,6 +17295,7 @@ var Launcher = class {
|
|
|
16500
17295
|
usersMode;
|
|
16501
17296
|
dac;
|
|
16502
17297
|
sealed;
|
|
17298
|
+
scrubs = /* @__PURE__ */ new Map();
|
|
16503
17299
|
clipboard;
|
|
16504
17300
|
rootFs;
|
|
16505
17301
|
fileWatches;
|
|
@@ -16523,6 +17319,8 @@ var Launcher = class {
|
|
|
16523
17319
|
void 0,
|
|
16524
17320
|
(pid) => this.tagOf(pid)
|
|
16525
17321
|
);
|
|
17322
|
+
this.sealed.tickets.normalise = (path) => physicalPathAsync(this.base, path);
|
|
17323
|
+
this.sealed.userOf = async (uid) => (await this.users.lookup(uid))?.name;
|
|
16526
17324
|
if (this.owners) options.fs.trackOwners?.();
|
|
16527
17325
|
this.mounts = new MountTable({
|
|
16528
17326
|
open: (type, spec) => this.driver(type, spec),
|
|
@@ -16556,7 +17354,7 @@ var Launcher = class {
|
|
|
16556
17354
|
if (options.uplink) this.net.useUplink({ uplink: options.uplink, routes: this.routes });
|
|
16557
17355
|
enableNetwork(this.net, {
|
|
16558
17356
|
transport: this.transport,
|
|
16559
|
-
engine: kernelTlsEngine(packageTlsEngine(options.fs, this.modulesDir)),
|
|
17357
|
+
engine: kernelTlsEngine(packageTlsEngine(this.verifiedFs(options.fs), this.modulesDir)),
|
|
16560
17358
|
ca: this.ca
|
|
16561
17359
|
});
|
|
16562
17360
|
enableCdp(this.net, this.cdp);
|
|
@@ -16591,6 +17389,16 @@ var Launcher = class {
|
|
|
16591
17389
|
this.prefixes = protectedPrefixes(options.protect?.paths ?? []);
|
|
16592
17390
|
this.processFs = this.prefixes.length > 0 ? new ProtectedFs(this.prefixes).view(this.fs) : this.fs;
|
|
16593
17391
|
options.fs.protect?.(this.prefixes);
|
|
17392
|
+
const integrity = options.protect?.integrity;
|
|
17393
|
+
integrityOptions(integrity);
|
|
17394
|
+
if (integrity && this.prefixes.length > 0) {
|
|
17395
|
+
this.integrity = new Integrity(
|
|
17396
|
+
this.prefixes,
|
|
17397
|
+
options.fs,
|
|
17398
|
+
integrity,
|
|
17399
|
+
(event) => options.onDenial?.(event)
|
|
17400
|
+
);
|
|
17401
|
+
}
|
|
16594
17402
|
this.users = new UserDb(this.fs, this.owners);
|
|
16595
17403
|
this.sudoer = new Sudo({
|
|
16596
17404
|
fs: this.fs,
|
|
@@ -16636,7 +17444,7 @@ var Launcher = class {
|
|
|
16636
17444
|
commands(scope = "") {
|
|
16637
17445
|
let found = this.catalogs.get(scope);
|
|
16638
17446
|
if (!found) {
|
|
16639
|
-
found = this.roots(scope).then((roots) => scanCommands(this.
|
|
17447
|
+
found = this.roots(scope).then((roots) => scanCommands(this.scanned, roots)).then((commands) => commands.set(SUDO_COMMAND.name, SUDO_COMMAND));
|
|
16640
17448
|
this.catalogs.set(scope, found);
|
|
16641
17449
|
}
|
|
16642
17450
|
return found;
|
|
@@ -16644,7 +17452,7 @@ var Launcher = class {
|
|
|
16644
17452
|
ownCommands(scope) {
|
|
16645
17453
|
let found = this.ownCatalogs.get(scope);
|
|
16646
17454
|
if (!found) {
|
|
16647
|
-
found = pnpmGlobalRoots(this.base, scope).then((roots) => scanCommands(this.
|
|
17455
|
+
found = pnpmGlobalRoots(this.base, scope).then((roots) => scanCommands(this.scanned, roots)).then((commands) => new Set(commands.keys()));
|
|
16648
17456
|
this.ownCatalogs.set(scope, found);
|
|
16649
17457
|
}
|
|
16650
17458
|
return found;
|
|
@@ -16653,7 +17461,7 @@ var Launcher = class {
|
|
|
16653
17461
|
let found = this.binfmts.get(scope);
|
|
16654
17462
|
if (!found) {
|
|
16655
17463
|
found = this.roots(scope).then(
|
|
16656
|
-
(roots) => scanBinfmts(this.
|
|
17464
|
+
(roots) => scanBinfmts(this.scanned, roots, (message3) => {
|
|
16657
17465
|
if (this.warned.has(message3)) return;
|
|
16658
17466
|
this.warned.add(message3);
|
|
16659
17467
|
console.warn(message3);
|
|
@@ -16761,21 +17569,26 @@ var Launcher = class {
|
|
|
16761
17569
|
const binfmt = isWasm(head) ? void 0 : binfmtOf(await this.interpreters(scope), script);
|
|
16762
17570
|
const words2 = shebang(head) ?? (binfmt ? [binfmt] : void 0);
|
|
16763
17571
|
if (!words2) return void 0;
|
|
16764
|
-
|
|
16765
|
-
const [
|
|
16766
|
-
|
|
16767
|
-
const
|
|
16768
|
-
const found = interp ? await this.resolve(interp, interp, cwd, scope) : void 0;
|
|
17572
|
+
const { interp, args } = shebangCommand(words2);
|
|
17573
|
+
const passed = [...args, command ? script : file, ...argv.slice(1)];
|
|
17574
|
+
if (!interp) return void 0;
|
|
17575
|
+
const found = await this.resolve(interp, interp, cwd, scope);
|
|
16769
17576
|
if (!found) {
|
|
16770
|
-
if (
|
|
17577
|
+
if (depth >= MAX_INTERPRETERS || !await this.scriptCommand(interp, cwd, scope)) {
|
|
16771
17578
|
return void 0;
|
|
16772
17579
|
}
|
|
16773
17580
|
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
16774
17581
|
const via = [interp, ...inner?.via ?? []];
|
|
16775
|
-
|
|
17582
|
+
const sources = [script, ...inner?.sources ?? []];
|
|
17583
|
+
return inner && { ...inner, target: withScriptEnv(inner.target, command), via, sources };
|
|
16776
17584
|
}
|
|
16777
17585
|
const target = withScriptEnv(found, command);
|
|
16778
|
-
return {
|
|
17586
|
+
return {
|
|
17587
|
+
target,
|
|
17588
|
+
args: [...target.prefix ?? [], ...passed],
|
|
17589
|
+
via: [interp],
|
|
17590
|
+
sources: [script]
|
|
17591
|
+
};
|
|
16779
17592
|
}
|
|
16780
17593
|
async plan(file, argv, cwd, scope, argv0) {
|
|
16781
17594
|
const found = await this.resolve(file, argv[0] ?? file, cwd, scope);
|
|
@@ -16801,13 +17614,106 @@ var Launcher = class {
|
|
|
16801
17614
|
await need(g, "exec", this.fs.resolvePath(req.cwd, file), want);
|
|
16802
17615
|
}
|
|
16803
17616
|
}
|
|
17617
|
+
async checkedPlan(req, { ppid, cred, scope }, fds) {
|
|
17618
|
+
const planned = await this.plan(req.file, req.argv, req.cwd, scope, req.argv0);
|
|
17619
|
+
try {
|
|
17620
|
+
await this.mayExec(cred, { ...req, pid: ppid }, planned);
|
|
17621
|
+
} catch (err) {
|
|
17622
|
+
await fds.closeAll();
|
|
17623
|
+
throw err.code === "EACCES" ? new SpawnError("EACCES") : err;
|
|
17624
|
+
}
|
|
17625
|
+
if (planned) return planned;
|
|
17626
|
+
await fds.closeAll();
|
|
17627
|
+
throw new SpawnError(await this.unrunnable(req.file, req.cwd, scope));
|
|
17628
|
+
}
|
|
17629
|
+
async ticketFile(req, fds) {
|
|
17630
|
+
if (req.file.startsWith("/")) return physicalPathAsync(this.base, req.file);
|
|
17631
|
+
await fds.closeAll();
|
|
17632
|
+
throw new SpawnError("EACCES");
|
|
17633
|
+
}
|
|
17634
|
+
takeTicket(req) {
|
|
17635
|
+
if (!(TICKET_ENV in req.env)) return void 0;
|
|
17636
|
+
return this.sealed.tickets.take(req.env[TICKET_ENV] ?? "") ?? null;
|
|
17637
|
+
}
|
|
17638
|
+
async redeemed(req, who, planned, fds) {
|
|
17639
|
+
if (who.booked === void 0) return { env: req.env };
|
|
17640
|
+
try {
|
|
17641
|
+
const redeemed = await this.redeem(req, who, planned);
|
|
17642
|
+
if (redeemed.scrub) scrubStdio(fds, redeemed.scrub);
|
|
17643
|
+
return redeemed;
|
|
17644
|
+
} catch {
|
|
17645
|
+
await fds.closeAll();
|
|
17646
|
+
throw new SpawnError("EACCES");
|
|
17647
|
+
}
|
|
17648
|
+
}
|
|
17649
|
+
async redeem(req, { ppid, cred, scope, booked }, planned) {
|
|
17650
|
+
const { [TICKET_ENV]: ticket = "", ...env } = req.env;
|
|
17651
|
+
const caller = this.jobs.shown(ppid);
|
|
17652
|
+
const named = typeof req.argv0 === "string" && !planned.script && !planned.target.fixed;
|
|
17653
|
+
const argv = named ? [req.argv0, ...req.argv.slice(1)] : req.argv;
|
|
17654
|
+
const exact = booked?.pid === caller && req.file === booked.path && await physicalPathAsync(this.base, req.cwd) === booked.cwd && await argvDigest(argv) === booked.argv;
|
|
17655
|
+
if (!exact) throw new SpawnError("EACCES");
|
|
17656
|
+
const { requested: path, requestedCwd: cwd, path: resolved2 } = booked;
|
|
17657
|
+
const pid = this.nextPid++;
|
|
17658
|
+
const ids = { pid: req.exec ? caller : pid, ppid: caller };
|
|
17659
|
+
const stamp = await this.sealed.stamp(ids, cred, this.tagOf(ppid));
|
|
17660
|
+
const interpreters = await this.interpreterChain(planned, booked.cwd, scope);
|
|
17661
|
+
const trusted = this.usersMode === "enforce" && await this.trustedFiles(planned, req.file, booked.cwd, scope);
|
|
17662
|
+
const swap = await this.sealed.consume({
|
|
17663
|
+
ticket,
|
|
17664
|
+
stamp,
|
|
17665
|
+
path,
|
|
17666
|
+
resolved: resolved2,
|
|
17667
|
+
argv,
|
|
17668
|
+
cwd,
|
|
17669
|
+
interpreters,
|
|
17670
|
+
trusted
|
|
17671
|
+
});
|
|
17672
|
+
if (!swap) throw new SpawnError("EACCES");
|
|
17673
|
+
const secrets = [];
|
|
17674
|
+
for (const [name2, placeholder] of Object.entries(swap.placeholders)) {
|
|
17675
|
+
const value = swap.values[name2];
|
|
17676
|
+
if (value === void 0 || env[name2] !== placeholder) continue;
|
|
17677
|
+
env[name2] = value;
|
|
17678
|
+
secrets.push({ name: name2, value, placeholder });
|
|
17679
|
+
}
|
|
17680
|
+
const scrub = scrubberOf(secrets);
|
|
17681
|
+
return { env, pid, cwd: booked.cwd, ...scrub ? { scrub } : {} };
|
|
17682
|
+
}
|
|
17683
|
+
async interpreterChain(planned, cwd, scope) {
|
|
17684
|
+
const out = [];
|
|
17685
|
+
for (const entry of planned.via ?? []) {
|
|
17686
|
+
if (entry.includes("/")) {
|
|
17687
|
+
out.push(await physicalPathAsync(this.base, this.fs.resolvePath(cwd, entry)));
|
|
17688
|
+
continue;
|
|
17689
|
+
}
|
|
17690
|
+
const script = (await this.scriptCommand(entry, cwd, scope))?.script;
|
|
17691
|
+
out.push(
|
|
17692
|
+
await physicalPathAsync(this.base, script ?? await this.commandFile(entry, cwd, scope))
|
|
17693
|
+
);
|
|
17694
|
+
}
|
|
17695
|
+
return out;
|
|
17696
|
+
}
|
|
17697
|
+
async commandFile(name2, cwd, scope) {
|
|
17698
|
+
const scoped = await this.resolve(name2, name2, cwd, scope);
|
|
17699
|
+
const system = scope === "" ? scoped : await this.resolve(name2, name2, cwd, "");
|
|
17700
|
+
if (!scoped || system?.glue === scoped.glue) return `/usr/bin/${name2}`;
|
|
17701
|
+
return scoped.glue;
|
|
17702
|
+
}
|
|
17703
|
+
async trustedFiles(planned, file, cwd, scope) {
|
|
17704
|
+
const files = await this.backingOf(planned, file, cwd, scope);
|
|
17705
|
+
for (const at of files) {
|
|
17706
|
+
if (!await rootOnly(this.base, await physicalPathAsync(this.base, at))) return false;
|
|
17707
|
+
}
|
|
17708
|
+
return true;
|
|
17709
|
+
}
|
|
16804
17710
|
async grantedCwd(caller, cwd) {
|
|
16805
17711
|
const real = await physicalPathAsync(this.base, cwd).catch(() => void 0);
|
|
16806
17712
|
return real === cwd && await this.sudoer.reachable(caller, cwd);
|
|
16807
17713
|
}
|
|
16808
17714
|
async binfmtManifests(scripts) {
|
|
16809
17715
|
const sources = /* @__PURE__ */ new Map();
|
|
16810
|
-
const binfmts = await scanBinfmts(this.
|
|
17716
|
+
const binfmts = await scanBinfmts(this.scanned, await this.roots(), void 0, sources);
|
|
16811
17717
|
const manifests = [];
|
|
16812
17718
|
for (const script of scripts) {
|
|
16813
17719
|
const head = await this.head(script);
|
|
@@ -16819,13 +17725,15 @@ var Launcher = class {
|
|
|
16819
17725
|
}
|
|
16820
17726
|
async backing(file, cwd) {
|
|
16821
17727
|
const planned = await this.plan(file, [file], cwd, "");
|
|
16822
|
-
|
|
17728
|
+
return planned && this.backingOf(planned, file, cwd, "");
|
|
17729
|
+
}
|
|
17730
|
+
async backingOf(planned, file, cwd, scope) {
|
|
16823
17731
|
const { glue, wasm, imports } = planned.target;
|
|
16824
17732
|
const files = [glue, wasm, ...imports ? [imports] : []];
|
|
16825
17733
|
const scripts = [];
|
|
16826
17734
|
for (const name2 of [file, ...planned.via ?? []]) {
|
|
16827
17735
|
if (name2.includes("/") && !COMMAND2.test(name2)) scripts.push(this.fs.resolvePath(cwd, name2));
|
|
16828
|
-
const script = (await this.scriptCommand(name2, cwd,
|
|
17736
|
+
const script = (await this.scriptCommand(name2, cwd, scope))?.script;
|
|
16829
17737
|
if (script) scripts.push(script);
|
|
16830
17738
|
}
|
|
16831
17739
|
files.push(...scripts, ...await this.binfmtManifests(scripts));
|
|
@@ -16842,25 +17750,72 @@ var Launcher = class {
|
|
|
16842
17750
|
if (!head || head[0] === 35 && head[1] === 33) return "ENOENT";
|
|
16843
17751
|
return binfmtOf(await this.interpreters(scope), path) ? "ENOENT" : "ENOEXEC";
|
|
16844
17752
|
}
|
|
16845
|
-
|
|
16846
|
-
|
|
16847
|
-
|
|
16848
|
-
|
|
16849
|
-
|
|
16850
|
-
|
|
16851
|
-
|
|
16852
|
-
|
|
16853
|
-
|
|
16854
|
-
|
|
16855
|
-
|
|
16856
|
-
|
|
16857
|
-
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
16863
|
-
|
|
17753
|
+
verifiedFs(fs) {
|
|
17754
|
+
const read = (path) => this.verified(path, KERNEL_CALLER, fs);
|
|
17755
|
+
return Object.assign(Object.create(fs), {
|
|
17756
|
+
readFileBuffer: read,
|
|
17757
|
+
readFile: (path) => this.integrity ? this.text(path, KERNEL_CALLER) : fs.readFile(path)
|
|
17758
|
+
});
|
|
17759
|
+
}
|
|
17760
|
+
async cacheKey(path) {
|
|
17761
|
+
const verified = await this.integrity?.key(path);
|
|
17762
|
+
if (verified !== void 0) return verified;
|
|
17763
|
+
const st = await this.base.stat(path);
|
|
17764
|
+
return `${path}:${st.size}:${st.mtime.getTime()}`;
|
|
17765
|
+
}
|
|
17766
|
+
verified(path, caller, fs = this.base) {
|
|
17767
|
+
const plain = () => fs.readFileBuffer(path);
|
|
17768
|
+
return this.integrity ? this.integrity.read(path, caller, plain) : plain();
|
|
17769
|
+
}
|
|
17770
|
+
keyed(path, caller) {
|
|
17771
|
+
const plain = async () => this.base.readFileBuffer(path);
|
|
17772
|
+
return this.integrity ? this.integrity.readKeyed(path, caller, plain) : plain().then((bytes) => ({ bytes }));
|
|
17773
|
+
}
|
|
17774
|
+
cached(cache, key, load) {
|
|
17775
|
+
const hit = cache.get(key);
|
|
17776
|
+
if (hit !== void 0) return hit;
|
|
17777
|
+
const loading2 = load();
|
|
17778
|
+
const found = loading2.then(({ value }) => value);
|
|
17779
|
+
cache.set(key, found);
|
|
17780
|
+
loading2.then(
|
|
17781
|
+
(done4) => {
|
|
17782
|
+
if (done4.key === key || done4.key === void 0 && !key.includes("\0")) return;
|
|
17783
|
+
if (cache.get(key) === found) cache.delete(key);
|
|
17784
|
+
if (done4.key !== void 0) cache.set(done4.key, found);
|
|
17785
|
+
},
|
|
17786
|
+
() => cache.delete(key)
|
|
17787
|
+
);
|
|
17788
|
+
return found;
|
|
17789
|
+
}
|
|
17790
|
+
async module(path, caller) {
|
|
17791
|
+
const key = await this.cacheKey(path);
|
|
17792
|
+
return this.cached(this.compiled, key, async () => {
|
|
17793
|
+
const { bytes, key: read } = await this.keyed(path, caller);
|
|
17794
|
+
const memory = importedMemory(bytes);
|
|
17795
|
+
const foreign = foreignImports(bytes);
|
|
17796
|
+
const compiled = await WebAssembly.compile(bytes);
|
|
17797
|
+
return { value: { module: compiled, ...memory ? { memory } : {}, foreign }, key: read };
|
|
17798
|
+
});
|
|
17799
|
+
}
|
|
17800
|
+
async checkedSources(planned, caller) {
|
|
17801
|
+
const { target } = planned;
|
|
17802
|
+
const files = [target.wasm, target.glue, target.imports, ...planned.sources ?? []];
|
|
17803
|
+
const manifests = /* @__PURE__ */ new Set();
|
|
17804
|
+
for (const file of files) {
|
|
17805
|
+
const root = file === void 0 ? void 0 : PACKAGE_ROOT.exec(file)?.[1];
|
|
17806
|
+
if (root !== void 0) manifests.add(`${root}/package.json`);
|
|
17807
|
+
}
|
|
17808
|
+
for (const source of planned.sources ?? []) await this.text(source, caller);
|
|
17809
|
+
for (const manifest of manifests) {
|
|
17810
|
+
if (await this.base.exists(manifest)) await this.text(manifest, caller);
|
|
17811
|
+
}
|
|
17812
|
+
}
|
|
17813
|
+
async text(path, caller) {
|
|
17814
|
+
if (!this.integrity) return this.base.readFile(path);
|
|
17815
|
+
const key = await this.cacheKey(path);
|
|
17816
|
+
return this.cached(this.texts, key, async () => {
|
|
17817
|
+
const { bytes, key: read } = await this.keyed(path, caller);
|
|
17818
|
+
return { value: new TextDecoder().decode(bytes), key: read };
|
|
16864
17819
|
});
|
|
16865
17820
|
}
|
|
16866
17821
|
async names(path, module) {
|
|
@@ -16872,23 +17827,23 @@ var Launcher = class {
|
|
|
16872
17827
|
const optional = `${root}-names${beside.slice(root.length)}`;
|
|
16873
17828
|
return await this.base.exists(optional) ? optional : void 0;
|
|
16874
17829
|
}
|
|
16875
|
-
async program(target, env) {
|
|
17830
|
+
async program(target, env, caller) {
|
|
16876
17831
|
if (target.abi === "js" && target.wasm === SUDO_PATH) {
|
|
16877
17832
|
return { abi: "js", glue: SUDO_SOURCE, path: SUDO_PATH };
|
|
16878
17833
|
}
|
|
16879
17834
|
if (target.abi === "js") {
|
|
16880
|
-
return { abi: "js", glue: await this.
|
|
17835
|
+
return { abi: "js", glue: await this.text(target.wasm, caller), path: target.wasm };
|
|
16881
17836
|
}
|
|
16882
17837
|
if (target.abi !== "wasi") {
|
|
16883
17838
|
const [glue, { module: module2 }] = await Promise.all([
|
|
16884
|
-
this.
|
|
16885
|
-
this.module(target.wasm)
|
|
17839
|
+
this.text(target.glue, caller),
|
|
17840
|
+
this.module(target.wasm, caller)
|
|
16886
17841
|
]);
|
|
16887
17842
|
return { glue, module: module2 };
|
|
16888
17843
|
}
|
|
16889
|
-
const { module, memory, foreign } = await this.module(target.wasm);
|
|
17844
|
+
const { module, memory, foreign } = await this.module(target.wasm, caller);
|
|
16890
17845
|
const names = env.SLICC_WASM_BACKTRACE === "1" ? await this.names(target.wasm, module) : void 0;
|
|
16891
|
-
const imports = target.imports ? await this.
|
|
17846
|
+
const imports = target.imports ? await this.text(target.imports, caller) : void 0;
|
|
16892
17847
|
return {
|
|
16893
17848
|
abi: "wasi",
|
|
16894
17849
|
glue: "",
|
|
@@ -16907,10 +17862,13 @@ var Launcher = class {
|
|
|
16907
17862
|
const seen = { ...req.env, HOSTNAME: this.hostname, cwd };
|
|
16908
17863
|
const env = { ...expandDefaults(target.env, seen), ...req.env };
|
|
16909
17864
|
for (const key of target.unset ?? []) delete env[key];
|
|
17865
|
+
delete env[TICKET_ENV];
|
|
16910
17866
|
env.HOSTNAME = this.hostname;
|
|
16911
17867
|
let program;
|
|
16912
17868
|
try {
|
|
16913
|
-
|
|
17869
|
+
const caller = { pid: req.ppid ?? 0, uid: req.cred.euid, tag: req.tag };
|
|
17870
|
+
if (this.integrity) await this.checkedSources(planned, caller);
|
|
17871
|
+
program = await this.program(target, env, caller);
|
|
16914
17872
|
} catch (err) {
|
|
16915
17873
|
await req.fds.closeAll();
|
|
16916
17874
|
throw err;
|
|
@@ -16920,16 +17878,23 @@ var Launcher = class {
|
|
|
16920
17878
|
groupSession(pgid) {
|
|
16921
17879
|
return this.jobs.sessionOf(pgid);
|
|
16922
17880
|
}
|
|
17881
|
+
treeScrubs(pid, req) {
|
|
17882
|
+
const inherited2 = req.ppid !== void 0 ? this.scrubs.get(req.ppid) : void 0;
|
|
17883
|
+
const scrubs = req.scrub ? [...inherited2 ?? [], req.scrub] : inherited2;
|
|
17884
|
+
if (scrubs) this.scrubs.set(pid, scrubs);
|
|
17885
|
+
return scrubs;
|
|
17886
|
+
}
|
|
16923
17887
|
start(req) {
|
|
16924
17888
|
this.sampling();
|
|
16925
17889
|
if (req.pgid !== void 0 && this.jobs.sessionOf(req.pgid) === void 0) {
|
|
16926
17890
|
throw new SpawnError("ESRCH");
|
|
16927
17891
|
}
|
|
16928
|
-
const pid = this.nextPid++;
|
|
17892
|
+
const pid = req.pid ?? this.nextPid++;
|
|
17893
|
+
const scrubs = this.treeScrubs(pid, req);
|
|
16929
17894
|
const stack = this.stackFor(req.tag);
|
|
16930
17895
|
const terminal = req.fds.stdioTerminal();
|
|
16931
17896
|
const decided = req.decided ?? Promise.resolve(true);
|
|
16932
|
-
const
|
|
17897
|
+
const count2 = (byParent) => {
|
|
16933
17898
|
this.identities.asked++;
|
|
16934
17899
|
if (!byParent) this.identities.timedOut++;
|
|
16935
17900
|
};
|
|
@@ -16937,7 +17902,7 @@ var Launcher = class {
|
|
|
16937
17902
|
const handle = spawnWasmProcess({
|
|
16938
17903
|
pid,
|
|
16939
17904
|
identity: async () => {
|
|
16940
|
-
await (asked ??= decided.then(
|
|
17905
|
+
await (asked ??= decided.then(count2));
|
|
16941
17906
|
return this.identityOf(pid);
|
|
16942
17907
|
},
|
|
16943
17908
|
onSyscall: (call) => {
|
|
@@ -16951,6 +17916,7 @@ var Launcher = class {
|
|
|
16951
17916
|
...this.owners && req.program.abi === "wasi" ? { fresh: (path, umask) => this.freshModules.add(path, umask, pid) } : {},
|
|
16952
17917
|
...this.owners ? { owners: true } : {},
|
|
16953
17918
|
sealed: this.sealed,
|
|
17919
|
+
...scrubs ? { ttyFilter: (file) => scrubbedAll(file, scrubs) } : {},
|
|
16954
17920
|
clipboard: this.clipboard,
|
|
16955
17921
|
...this.dac ? { dac: this.dac } : {},
|
|
16956
17922
|
program: req.program,
|
|
@@ -17017,6 +17983,7 @@ var Launcher = class {
|
|
|
17017
17983
|
if (spent) addTimes(this.imageTimes, this.jobs.shown(pid), spent);
|
|
17018
17984
|
this.stopped.delete(pid);
|
|
17019
17985
|
this.processes.delete(pid);
|
|
17986
|
+
this.scrubs.delete(pid);
|
|
17020
17987
|
if (this.processes.size === 0) {
|
|
17021
17988
|
clearInterval(this.sampler);
|
|
17022
17989
|
this.sampler = void 0;
|
|
@@ -17188,6 +18155,7 @@ var Launcher = class {
|
|
|
17188
18155
|
}
|
|
17189
18156
|
spawner(ppid, report) {
|
|
17190
18157
|
return async (req, fds, grant) => {
|
|
18158
|
+
const booked = this.takeTicket(req);
|
|
17191
18159
|
if (grant && !await this.grantedCwd(grant.caller, req.cwd)) {
|
|
17192
18160
|
await fds.closeAll();
|
|
17193
18161
|
throw new SpawnError("EACCES");
|
|
@@ -17199,23 +18167,20 @@ var Launcher = class {
|
|
|
17199
18167
|
}
|
|
17200
18168
|
const cred = grant ? grant.cred : this.credOf(ppid);
|
|
17201
18169
|
const scope = grant ? "" : await this.scopeOf(cred.euid);
|
|
17202
|
-
const
|
|
17203
|
-
|
|
17204
|
-
|
|
17205
|
-
|
|
17206
|
-
|
|
17207
|
-
|
|
17208
|
-
|
|
17209
|
-
|
|
17210
|
-
await fds.closeAll();
|
|
17211
|
-
throw new SpawnError(await this.unrunnable(req.file, req.cwd, scope));
|
|
17212
|
-
}
|
|
18170
|
+
const file = booked === void 0 ? req.file : await this.ticketFile(req, fds);
|
|
18171
|
+
const planned = await this.checkedPlan({ ...req, file }, { ppid, cred, scope }, fds);
|
|
18172
|
+
const redeemed = await this.redeemed(
|
|
18173
|
+
{ ...req, file },
|
|
18174
|
+
{ ppid, cred, scope, booked },
|
|
18175
|
+
planned,
|
|
18176
|
+
fds
|
|
18177
|
+
);
|
|
17213
18178
|
const exec = req.exec ? { exec: true } : {};
|
|
17214
18179
|
const deciding = req.exec ? void 0 : this.undecided(ppid);
|
|
17215
18180
|
const handle = await this.launch(planned, {
|
|
17216
18181
|
...deciding ? { decided: deciding.promise } : {},
|
|
17217
|
-
env: req.env,
|
|
17218
18182
|
cwd: req.cwd,
|
|
18183
|
+
...redeemed,
|
|
17219
18184
|
fds,
|
|
17220
18185
|
report,
|
|
17221
18186
|
ppid,
|
|
@@ -17268,11 +18233,11 @@ var Launcher = class {
|
|
|
17268
18233
|
if (!waiting) return;
|
|
17269
18234
|
this.deciding.delete(ppid);
|
|
17270
18235
|
setTimeout(() => {
|
|
17271
|
-
for (const
|
|
18236
|
+
for (const resolve2 of waiting) resolve2(true);
|
|
17272
18237
|
}, 0);
|
|
17273
18238
|
}
|
|
17274
18239
|
forker(ppid, parent) {
|
|
17275
|
-
const { exec: _exec, pgid: _pgid, group: _group, ...image } = parent;
|
|
18240
|
+
const { exec: _exec, pgid: _pgid, group: _group, pid: _pid, scrub: _scrub, ...image } = parent;
|
|
17276
18241
|
return async (state, fds) => childHandle(
|
|
17277
18242
|
this.start({
|
|
17278
18243
|
...image,
|
|
@@ -17402,11 +18367,14 @@ var Launcher = class {
|
|
|
17402
18367
|
}
|
|
17403
18368
|
};
|
|
17404
18369
|
}
|
|
17405
|
-
const module = (await scanFilesystems(this.
|
|
18370
|
+
const module = (await scanFilesystems(this.scanned, await this.roots())).get(type);
|
|
17406
18371
|
if (!module) throw fsError("ENODEV", `unknown file system type ${type}`);
|
|
17407
18372
|
if (!this.createDriverWorker)
|
|
17408
18373
|
throw fsError("ENODEV", `this kernel cannot start ${type} drivers`);
|
|
17409
|
-
const
|
|
18374
|
+
const root = PACKAGE_ROOT.exec(module)?.[1];
|
|
18375
|
+
if (this.integrity && root !== void 0)
|
|
18376
|
+
await this.text(`${root}/package.json`, KERNEL_CALLER);
|
|
18377
|
+
const code = new TextDecoder().decode(await this.verified(module, KERNEL_CALLER));
|
|
17410
18378
|
const worker = this.createDriverWorker();
|
|
17411
18379
|
const driver = new MessageChannel();
|
|
17412
18380
|
const client = new MessageChannel();
|
|
@@ -17646,7 +18614,14 @@ var Launcher = class {
|
|
|
17646
18614
|
);
|
|
17647
18615
|
}
|
|
17648
18616
|
environment(cwd, extra, account) {
|
|
17649
|
-
|
|
18617
|
+
const env = {
|
|
18618
|
+
...this.env,
|
|
18619
|
+
...userEnv(account, this.pnpmHome),
|
|
18620
|
+
PWD: cwd,
|
|
18621
|
+
...extra
|
|
18622
|
+
};
|
|
18623
|
+
delete env[TICKET_ENV];
|
|
18624
|
+
return env;
|
|
17650
18625
|
}
|
|
17651
18626
|
async account(user) {
|
|
17652
18627
|
if (typeof user === "object") return user;
|
|
@@ -17742,7 +18717,7 @@ var Launcher = class {
|
|
|
17742
18717
|
},
|
|
17743
18718
|
account
|
|
17744
18719
|
);
|
|
17745
|
-
const report = (message3) => options.onData(
|
|
18720
|
+
const report = (message3) => options.onData(encoder7.encode(`${message3}\r
|
|
17746
18721
|
`));
|
|
17747
18722
|
const handle = await this.launch(planned, {
|
|
17748
18723
|
env,
|
|
@@ -17773,18 +18748,18 @@ var Launcher = class {
|
|
|
17773
18748
|
const env = this.environment(cwd, options.env, account);
|
|
17774
18749
|
const out = [];
|
|
17775
18750
|
const err = [];
|
|
17776
|
-
const
|
|
18751
|
+
const keep2 = options.collect !== false;
|
|
17777
18752
|
const collect = (chunks, tee) => (bytes) => {
|
|
17778
|
-
if (
|
|
18753
|
+
if (keep2) chunks.push(bytes);
|
|
17779
18754
|
tee?.(bytes);
|
|
17780
18755
|
};
|
|
17781
18756
|
const stdout = collect(out, options.onStdout);
|
|
17782
18757
|
const stderr = collect(err, options.onStderr);
|
|
17783
|
-
const report = (message3) => stderr(
|
|
18758
|
+
const report = (message3) => stderr(encoder7.encode(`${message3}
|
|
17784
18759
|
`));
|
|
17785
18760
|
if (!planned) {
|
|
17786
18761
|
report(`${file}: command not found`);
|
|
17787
|
-
return { status: NOT_FOUND, stdout:
|
|
18762
|
+
return { status: NOT_FOUND, stdout: concat6(out), stderr: concat6(err) };
|
|
17788
18763
|
}
|
|
17789
18764
|
const fds = new FdTable();
|
|
17790
18765
|
fds.installAt(0, options.stdin ? bytesSource(options.stdin) : deviceFile("null"));
|
|
@@ -17802,7 +18777,7 @@ var Launcher = class {
|
|
|
17802
18777
|
options.onStarted?.(handle.pid);
|
|
17803
18778
|
const status = await handle.exited;
|
|
17804
18779
|
const signal = handle.termsig();
|
|
17805
|
-
return { status, ...signal ? { signal } : {}, stdout:
|
|
18780
|
+
return { status, ...signal ? { signal } : {}, stdout: concat6(out), stderr: concat6(err) };
|
|
17806
18781
|
}
|
|
17807
18782
|
};
|
|
17808
18783
|
|
|
@@ -17903,14 +18878,14 @@ function dial(l, req) {
|
|
|
17903
18878
|
function sudoApprovals(port) {
|
|
17904
18879
|
const waiting = /* @__PURE__ */ new Map();
|
|
17905
18880
|
return {
|
|
17906
|
-
ask: (req, { signal }) => new Promise((
|
|
17907
|
-
waiting.set(req.id,
|
|
18881
|
+
ask: (req, { signal }) => new Promise((resolve2) => {
|
|
18882
|
+
waiting.set(req.id, resolve2);
|
|
17908
18883
|
signal.addEventListener(
|
|
17909
18884
|
"abort",
|
|
17910
18885
|
() => {
|
|
17911
18886
|
waiting.delete(req.id);
|
|
17912
18887
|
port.postMessage({ sudoAbort: { id: req.id, reason: String(signal.reason) } });
|
|
17913
|
-
|
|
18888
|
+
resolve2("deny");
|
|
17914
18889
|
},
|
|
17915
18890
|
{ once: true }
|
|
17916
18891
|
);
|
|
@@ -17977,22 +18952,26 @@ function usersOp(l, req) {
|
|
|
17977
18952
|
if (req.op === "groups-remove-member") return l.users.removeMember(req.group, req.user);
|
|
17978
18953
|
return l.users.list();
|
|
17979
18954
|
}
|
|
17980
|
-
function hostOptions(req, port, sealed, clipboard) {
|
|
18955
|
+
function hostOptions(req, port, sealed, clipboard, lookup) {
|
|
17981
18956
|
return {
|
|
17982
18957
|
...req.hostname !== void 0 ? { hostname: req.hostname } : {},
|
|
17983
18958
|
...req.users !== void 0 ? { users: req.users } : {},
|
|
17984
18959
|
...req.denials ? { onDenial: (denial) => port.postMessage({ denial }) } : {},
|
|
17985
|
-
...req.protect ? { protect:
|
|
18960
|
+
...req.protect ? { protect: hostProtect(req.protect, lookup) } : {},
|
|
17986
18961
|
...req.sealed ? { sealed } : {},
|
|
17987
18962
|
...req.clipboard ? { clipboard } : {}
|
|
17988
18963
|
};
|
|
17989
18964
|
}
|
|
18965
|
+
function hostProtect(init, lookup) {
|
|
18966
|
+
const { integrity, ...rest2 } = protectInit(init);
|
|
18967
|
+
return { ...rest2, ...integrity ? { integrity: { ...integrity, lookup } } : {} };
|
|
18968
|
+
}
|
|
17990
18969
|
function policyAsker(port) {
|
|
17991
18970
|
const policies = /* @__PURE__ */ new Map();
|
|
17992
18971
|
let nextPolicy = 0;
|
|
17993
|
-
const askPolicy = (req) => new Promise((
|
|
18972
|
+
const askPolicy = (req) => new Promise((resolve2) => {
|
|
17994
18973
|
const id2 = ++nextPolicy;
|
|
17995
|
-
policies.set(id2,
|
|
18974
|
+
policies.set(id2, resolve2);
|
|
17996
18975
|
port.postMessage({ mountPolicy: { id: id2, req } });
|
|
17997
18976
|
});
|
|
17998
18977
|
return {
|
|
@@ -18015,14 +18994,15 @@ function serveKernel(port, deps) {
|
|
|
18015
18994
|
const clients = /* @__PURE__ */ new Set();
|
|
18016
18995
|
const sealed = sealedAsker(port);
|
|
18017
18996
|
const clipboard = clipboardAsker(port);
|
|
18997
|
+
const integrity = integrityAsker(port);
|
|
18018
18998
|
const approvals = sudoApprovals(port);
|
|
18019
18999
|
const locks = deps.locks === null ? void 0 : deps.locks ?? locksOf();
|
|
18020
19000
|
let holding;
|
|
18021
19001
|
function holdLock(locks2) {
|
|
18022
|
-
holding ??= new Promise((
|
|
19002
|
+
holding ??= new Promise((resolve2) => {
|
|
18023
19003
|
const name2 = `slicc-kernel:${crypto.randomUUID()}`;
|
|
18024
19004
|
void locks2.request(name2, () => {
|
|
18025
|
-
|
|
19005
|
+
resolve2(name2);
|
|
18026
19006
|
return new Promise(() => {
|
|
18027
19007
|
});
|
|
18028
19008
|
});
|
|
@@ -18081,7 +19061,7 @@ function serveKernel(port, deps) {
|
|
|
18081
19061
|
...deps.createDriverWorker ? { createDriverWorker: deps.createDriverWorker } : {},
|
|
18082
19062
|
...req.modules ? { modules: req.modules } : {},
|
|
18083
19063
|
...req.env ? { env: req.env } : {},
|
|
18084
|
-
...hostOptions(req, port, sealed.hook, clipboard.hook),
|
|
19064
|
+
...hostOptions(req, port, sealed.hook, clipboard.hook, integrity.lookup),
|
|
18085
19065
|
...req.approve ? { approve: approvals.ask } : {},
|
|
18086
19066
|
...net,
|
|
18087
19067
|
...media ? { media } : {},
|
|
@@ -18151,6 +19131,8 @@ function serveKernel(port, deps) {
|
|
|
18151
19131
|
if (sealedReply) return sealed.answer(sealedReply);
|
|
18152
19132
|
const clipboardReply = event.data.clipboardReply;
|
|
18153
19133
|
if (clipboardReply) return clipboard.answer(clipboardReply);
|
|
19134
|
+
const integrityReply = event.data.integrityReply;
|
|
19135
|
+
if (integrityReply) return integrity.answer(integrityReply);
|
|
18154
19136
|
const grant = event.data.hostfsGrant;
|
|
18155
19137
|
if (grant) return granted2(grant);
|
|
18156
19138
|
if (allowed(event.data)) return;
|