@ai-ecoverse/slicc-kernel 1.103.4 → 1.106.3
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 +57 -16
- package/dist/driver-worker.js +36 -1
- package/dist/driver-worker.js.map +2 -2
- package/dist/index.js +89 -5
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +798 -295
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js.map +2 -2
- package/dist/node-driver-worker.js +36 -1
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.js +489 -234
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +846 -315
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +426 -171
- package/dist/process-worker.js.map +4 -4
- package/dist/types/commands.d.ts +6 -1
- package/dist/types/fs/command-stat.d.ts +3 -0
- package/dist/types/fs/commands.d.ts +7 -1
- package/dist/types/fs/engines.d.ts +5 -0
- package/dist/types/fs/types.d.ts +1 -0
- package/dist/types/kernel/host.d.ts +1 -0
- package/dist/types/kernel/net/http-syscalls.d.ts +10 -0
- package/dist/types/kernel/net/http1.d.ts +1 -0
- package/dist/types/kernel/net/remote-transport.d.ts +18 -0
- package/dist/types/kernel/net/transport.d.ts +2 -0
- package/dist/types/kernel/process.d.ts +8 -0
- package/dist/types/launcher.d.ts +4 -0
- package/dist/types/process/js/js-kernel.d.ts +2 -1
- package/dist/types/process/process-signals.d.ts +3 -0
- package/dist/types/process/wasi/wasi-cred.d.ts +11 -0
- package/dist/types/process/wasi/wasi-files.d.ts +1 -0
- package/dist/types/process/wasi/wasi-host.d.ts +9 -0
- package/dist/types/process/wasi/wasi-sigmask.d.ts +7 -1
- package/dist/types/process/wasi/wasix-epoll.d.ts +3 -0
- package/dist/types/refused-command.d.ts +4 -0
- package/dist/types/transport.d.ts +1 -0
- package/package.json +12 -12
package/dist/kernel-worker.js
CHANGED
|
@@ -58,9 +58,9 @@ var PathMap = class {
|
|
|
58
58
|
}
|
|
59
59
|
link(path) {
|
|
60
60
|
for (let child = path, parent = parentOf(path); parent !== void 0; ) {
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
63
|
-
if (
|
|
61
|
+
const set3 = this.children.get(parent);
|
|
62
|
+
if (set3?.has(child)) return;
|
|
63
|
+
if (set3) set3.add(child);
|
|
64
64
|
else this.children.set(parent, /* @__PURE__ */ new Set([child]));
|
|
65
65
|
child = parent;
|
|
66
66
|
parent = parentOf(parent);
|
|
@@ -69,9 +69,9 @@ var PathMap = class {
|
|
|
69
69
|
prune(path) {
|
|
70
70
|
for (let child = path, parent = parentOf(path); parent !== void 0; ) {
|
|
71
71
|
if (this.values.has(child) || this.children.has(child)) return;
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
if (
|
|
72
|
+
const set3 = this.children.get(parent);
|
|
73
|
+
set3?.delete(child);
|
|
74
|
+
if (set3 && set3.size > 0) return;
|
|
75
75
|
this.children.delete(parent);
|
|
76
76
|
child = parent;
|
|
77
77
|
parent = parentOf(parent);
|
|
@@ -208,15 +208,15 @@ var IndexedDbMeta = class {
|
|
|
208
208
|
this.settleRemoves();
|
|
209
209
|
const [transaction, store] = this.transaction("readwrite");
|
|
210
210
|
const request2 = store.get(path);
|
|
211
|
-
let
|
|
211
|
+
let next3;
|
|
212
212
|
request2.onsuccess = () => {
|
|
213
|
-
|
|
214
|
-
if (
|
|
213
|
+
next3 = change(request2.result);
|
|
214
|
+
if (next3) store.put(next3);
|
|
215
215
|
else store.delete(path);
|
|
216
216
|
};
|
|
217
217
|
await settle(transaction, () => void 0);
|
|
218
218
|
this.changed({ paths: [path] });
|
|
219
|
-
this.cache.set(path,
|
|
219
|
+
this.cache.set(path, next3 ?? null);
|
|
220
220
|
}
|
|
221
221
|
async updateMany(changes) {
|
|
222
222
|
const [transaction, store] = this.transaction("readwrite");
|
|
@@ -530,14 +530,14 @@ var Integrity = class {
|
|
|
530
530
|
if (!this.root.version) return void 0;
|
|
531
531
|
return `${real}\0${await this.root.version(real)}`;
|
|
532
532
|
}
|
|
533
|
-
async read(path, caller,
|
|
534
|
-
return (await this.readKeyed(path, caller,
|
|
533
|
+
async read(path, caller, plain2, asked) {
|
|
534
|
+
return (await this.readKeyed(path, caller, plain2, asked)).bytes;
|
|
535
535
|
}
|
|
536
|
-
async readKeyed(path, caller,
|
|
536
|
+
async readKeyed(path, caller, plain2, asked) {
|
|
537
537
|
const found = await this.real(path, asked);
|
|
538
|
-
if (found === void 0) return { bytes: await
|
|
538
|
+
if (found === void 0) return { bytes: await plain2() };
|
|
539
539
|
const { real, name: name2 } = found;
|
|
540
|
-
const read = name2 !== real ? { bytes: await
|
|
540
|
+
const read = name2 !== real ? { bytes: await plain2(), version: void 0 } : this.root.readVersioned ? await this.root.readVersioned(real) : { bytes: await this.root.readFileBuffer(real), version: void 0 };
|
|
541
541
|
const { bytes } = read;
|
|
542
542
|
const keyed = read.version === void 0 ? { bytes } : { bytes, key: `${real}\0${read.version}` };
|
|
543
543
|
await this.verify(name2, bytes, caller, EXEC_OPS);
|
|
@@ -546,9 +546,9 @@ var Integrity = class {
|
|
|
546
546
|
get readsChecked() {
|
|
547
547
|
return this.sources.length > 0;
|
|
548
548
|
}
|
|
549
|
-
async readSource(path, caller,
|
|
549
|
+
async readSource(path, caller, plain2) {
|
|
550
550
|
const found = await this.source(path);
|
|
551
|
-
return found === void 0 ?
|
|
551
|
+
return found === void 0 ? plain2() : this.checked(found, caller, plain2);
|
|
552
552
|
}
|
|
553
553
|
async openSource(path, caller, real) {
|
|
554
554
|
const found = await this.source(path, real);
|
|
@@ -558,10 +558,10 @@ var Integrity = class {
|
|
|
558
558
|
}
|
|
559
559
|
await this.checked(found, caller, () => this.root.readFileBuffer(found.real));
|
|
560
560
|
}
|
|
561
|
-
async checked(found, caller,
|
|
561
|
+
async checked(found, caller, plain2) {
|
|
562
562
|
const { real, name: name2 } = found;
|
|
563
563
|
if (name2 !== real || !this.root.readVersioned) {
|
|
564
|
-
const bytes2 = await
|
|
564
|
+
const bytes2 = await plain2();
|
|
565
565
|
await this.verify(name2, bytes2, caller, READ_OPS);
|
|
566
566
|
return bytes2;
|
|
567
567
|
}
|
|
@@ -1287,8 +1287,8 @@ var OpfsFs = class {
|
|
|
1287
1287
|
this.refuse(found.path);
|
|
1288
1288
|
const [stored] = found.link ? [found.link] : await this.meta.get([found.path]);
|
|
1289
1289
|
const current = await this.ownerAt(found.path, stored);
|
|
1290
|
-
const
|
|
1291
|
-
const handing = found.handle?.kind === "directory" && !sameOwner(
|
|
1290
|
+
const next3 = { uid: change.uid ?? current.uid, gid: change.gid ?? current.gid };
|
|
1291
|
+
const handing = found.handle?.kind === "directory" && !sameOwner(next3, current);
|
|
1292
1292
|
const heir = change.kind === "adopt" ? void 0 : stored?.heir ?? (handing ? [current.uid, current.gid] : void 0);
|
|
1293
1293
|
const ctimeMs = Date.now();
|
|
1294
1294
|
await this.meta.update(found.path, (entry) => {
|
|
@@ -1296,7 +1296,7 @@ var OpfsFs = class {
|
|
|
1296
1296
|
return {
|
|
1297
1297
|
...rest2,
|
|
1298
1298
|
path: found.path,
|
|
1299
|
-
...
|
|
1299
|
+
...next3,
|
|
1300
1300
|
...heir ? { heir } : {},
|
|
1301
1301
|
...change.mode !== void 0 ? { mode: change.mode & PERM_MASK } : {},
|
|
1302
1302
|
ctimeMs
|
|
@@ -2342,11 +2342,11 @@ async function realDir(fs, dir, budget = { hops: 0 }) {
|
|
|
2342
2342
|
at = parentOf4(at);
|
|
2343
2343
|
continue;
|
|
2344
2344
|
}
|
|
2345
|
-
const
|
|
2346
|
-
const link2 = await linkOf(fs,
|
|
2345
|
+
const next3 = at === "/" ? `/${part}` : `${at}/${part}`;
|
|
2346
|
+
const link2 = await linkOf(fs, next3);
|
|
2347
2347
|
if (link2 === void 0) {
|
|
2348
|
-
if (queue.find((p) => p !== ".") === "..") await mustBeDir(fs,
|
|
2349
|
-
at =
|
|
2348
|
+
if (queue.find((p) => p !== ".") === "..") await mustBeDir(fs, next3);
|
|
2349
|
+
at = next3;
|
|
2350
2350
|
continue;
|
|
2351
2351
|
}
|
|
2352
2352
|
if (budget.hops >= MAX_LINKS3) throw fsError("ELOOP", dir);
|
|
@@ -2449,18 +2449,18 @@ async function walk(fs, cred, path, follow2, links) {
|
|
|
2449
2449
|
at = parentOf4(at);
|
|
2450
2450
|
continue;
|
|
2451
2451
|
}
|
|
2452
|
-
const
|
|
2453
|
-
const perm = await perms.at(
|
|
2452
|
+
const next3 = joinName(at, part);
|
|
2453
|
+
const perm = await perms.at(next3);
|
|
2454
2454
|
const last = queue.length === 0;
|
|
2455
2455
|
if (perm?.link !== void 0 && (!last || follow2)) {
|
|
2456
|
-
if (!trustedLink(perm, links)) return { path, perm: void 0, denied:
|
|
2457
|
-
if (++hops > MAX_LINKS4) return { path:
|
|
2456
|
+
if (!trustedLink(perm, links)) return { path, perm: void 0, denied: next3, link: true };
|
|
2457
|
+
if (++hops > MAX_LINKS4) return { path: next3, perm: void 0 };
|
|
2458
2458
|
queue.unshift(...parts(perm.link));
|
|
2459
2459
|
if (perm.link.startsWith("/")) at = "/";
|
|
2460
2460
|
continue;
|
|
2461
2461
|
}
|
|
2462
|
-
if (last) return { path:
|
|
2463
|
-
at =
|
|
2462
|
+
if (last) return { path: next3, perm };
|
|
2463
|
+
at = next3;
|
|
2464
2464
|
}
|
|
2465
2465
|
return { path: at, perm: await perms.at(at) };
|
|
2466
2466
|
}
|
|
@@ -2565,8 +2565,13 @@ function ttyOpenable(g, tty) {
|
|
|
2565
2565
|
async function need(g, op, path, want, options = {}, shown = path) {
|
|
2566
2566
|
const walked = await access(g.fs, g.cred, path, want, linked(g, options));
|
|
2567
2567
|
if (walked.denied !== void 0) deny(g, op, walked.link ? walked.denied : shown);
|
|
2568
|
+
else if (want & R_OK && g.fs.commandTarget) await readsAs(g, op, walked.path, shown);
|
|
2568
2569
|
return walked;
|
|
2569
2570
|
}
|
|
2571
|
+
async function readsAs(g, op, path, shown) {
|
|
2572
|
+
const target = await g.fs.commandTarget?.(path);
|
|
2573
|
+
if (target !== void 0) await need(g, op, target, R_OK, { directory: false }, shown);
|
|
2574
|
+
}
|
|
2570
2575
|
function entryIn(dir, path) {
|
|
2571
2576
|
return joinName(dir.path, path.slice(path.lastIndexOf("/") + 1));
|
|
2572
2577
|
}
|
|
@@ -2725,14 +2730,14 @@ function changeCred(cur, change) {
|
|
|
2725
2730
|
throw fsError("EINVAL", "not a change");
|
|
2726
2731
|
}
|
|
2727
2732
|
const privileged = cur.euid === 0;
|
|
2728
|
-
const
|
|
2733
|
+
const next3 = copyCred(cur);
|
|
2729
2734
|
for (const keys of [UIDS, GIDS]) {
|
|
2730
2735
|
const own = keys.map((key) => cur[key]);
|
|
2731
2736
|
for (const key of keys) {
|
|
2732
2737
|
const value = id(change[key]);
|
|
2733
2738
|
if (value === void 0) continue;
|
|
2734
2739
|
if (!privileged && !own.includes(value)) throw fsError("EPERM", `${key} ${value}`);
|
|
2735
|
-
|
|
2740
|
+
next3[key] = value;
|
|
2736
2741
|
}
|
|
2737
2742
|
}
|
|
2738
2743
|
if (change.groups !== void 0) {
|
|
@@ -2742,9 +2747,9 @@ function changeCred(cur, change) {
|
|
|
2742
2747
|
const groups = change.groups.map((g) => id(g) ?? Number.NaN);
|
|
2743
2748
|
if (groups.some(Number.isNaN)) throw fsError("EINVAL", "not a group list");
|
|
2744
2749
|
if (!privileged) throw fsError("EPERM", "setgroups");
|
|
2745
|
-
|
|
2750
|
+
next3.groups = groups;
|
|
2746
2751
|
}
|
|
2747
|
-
return
|
|
2752
|
+
return next3;
|
|
2748
2753
|
}
|
|
2749
2754
|
function maySignal(sender, target) {
|
|
2750
2755
|
if (sender.euid === 0) return true;
|
|
@@ -3657,10 +3662,10 @@ var KernelSocket = class _KernelSocket {
|
|
|
3657
3662
|
async accept(signal, nonblock = false) {
|
|
3658
3663
|
for (; ; ) {
|
|
3659
3664
|
if (this.state !== "listening") throw new KernelError("EINVAL");
|
|
3660
|
-
const
|
|
3661
|
-
if (
|
|
3665
|
+
const next3 = this.queue.shift();
|
|
3666
|
+
if (next3) {
|
|
3662
3667
|
this.room.wake();
|
|
3663
|
-
return
|
|
3668
|
+
return next3;
|
|
3664
3669
|
}
|
|
3665
3670
|
if (nonblock) throw new KernelError("EAGAIN");
|
|
3666
3671
|
await this.changes.wait(signal);
|
|
@@ -4179,12 +4184,12 @@ var MessageQueue = class {
|
|
|
4179
4184
|
}
|
|
4180
4185
|
async *[Symbol.asyncIterator]() {
|
|
4181
4186
|
for (; ; ) {
|
|
4182
|
-
const
|
|
4183
|
-
if (
|
|
4184
|
-
const n = payloadSize(
|
|
4187
|
+
const next3 = this.items.shift();
|
|
4188
|
+
if (next3 !== void 0) {
|
|
4189
|
+
const n = payloadSize(next3);
|
|
4185
4190
|
this.size -= n;
|
|
4186
4191
|
this.taken?.(n);
|
|
4187
|
-
yield
|
|
4192
|
+
yield next3;
|
|
4188
4193
|
continue;
|
|
4189
4194
|
}
|
|
4190
4195
|
if (this.ended) return;
|
|
@@ -4200,6 +4205,29 @@ var SEND_BUFFER = 1024 * 1024;
|
|
|
4200
4205
|
var CLOSE_WAIT_MS = 5e3;
|
|
4201
4206
|
var NO_WEBSOCKET = "WebSocket not supported by this transport (fetchTransport needs { webSocket: true })";
|
|
4202
4207
|
var MAX_REQUEST_BODY = 64 * 1024 * 1024;
|
|
4208
|
+
function uploadsFor(peer) {
|
|
4209
|
+
const pulls = /* @__PURE__ */ new Map();
|
|
4210
|
+
const of = (nid, signal) => ({
|
|
4211
|
+
async *[Symbol.asyncIterator]() {
|
|
4212
|
+
for (; ; ) {
|
|
4213
|
+
signal.throwIfAborted();
|
|
4214
|
+
const got = await new Promise((resolve2, reject) => {
|
|
4215
|
+
const stop = () => reject(signal.reason);
|
|
4216
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
4217
|
+
pulls.set(nid, (call) => {
|
|
4218
|
+
signal.removeEventListener("abort", stop);
|
|
4219
|
+
resolve2(call);
|
|
4220
|
+
});
|
|
4221
|
+
peer.postMessage({ net: "body-pull", nid });
|
|
4222
|
+
}).finally(() => pulls.delete(nid));
|
|
4223
|
+
if (got.net === "body-end") return;
|
|
4224
|
+
if (got.net === "body-error") throw new Error(got.message);
|
|
4225
|
+
if (got.net === "body-chunk") yield got.bytes;
|
|
4226
|
+
}
|
|
4227
|
+
}
|
|
4228
|
+
});
|
|
4229
|
+
return { of, answer: (call) => pulls.get(call.nid)?.(call) };
|
|
4230
|
+
}
|
|
4203
4231
|
function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
4204
4232
|
const open = /* @__PURE__ */ new Map();
|
|
4205
4233
|
const fail2 = (nid, e) => {
|
|
@@ -4213,6 +4241,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
4213
4241
|
...typeof code === "string" ? { code } : {}
|
|
4214
4242
|
});
|
|
4215
4243
|
};
|
|
4244
|
+
const uploads = uploadsFor(peer);
|
|
4216
4245
|
const start2 = async (call) => {
|
|
4217
4246
|
const abort = new AbortController();
|
|
4218
4247
|
const entry = { abort };
|
|
@@ -4222,7 +4251,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
4222
4251
|
url: call.url,
|
|
4223
4252
|
method: call.method,
|
|
4224
4253
|
headers: call.headers,
|
|
4225
|
-
...call.body ? { body: call.body } : {},
|
|
4254
|
+
...call.streamed ? { bodyStream: uploads.of(call.nid, abort.signal) } : call.body ? { body: call.body } : {},
|
|
4226
4255
|
signal: abort.signal
|
|
4227
4256
|
});
|
|
4228
4257
|
if (!open.has(call.nid)) {
|
|
@@ -4294,9 +4323,9 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
4294
4323
|
try {
|
|
4295
4324
|
const messages = socket.messages[Symbol.asyncIterator]();
|
|
4296
4325
|
for (; ; ) {
|
|
4297
|
-
const
|
|
4298
|
-
if (
|
|
4299
|
-
const data =
|
|
4326
|
+
const next3 = await Promise.race([messages.next(), unanswered]);
|
|
4327
|
+
if (next3 === "late" || next3.done) break;
|
|
4328
|
+
const data = next3.value;
|
|
4300
4329
|
if (flow.closing) continue;
|
|
4301
4330
|
if (payloadSize(data) > MESSAGE_LIMIT) {
|
|
4302
4331
|
oversize = true;
|
|
@@ -4337,12 +4366,12 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
4337
4366
|
const body = open.get(nid)?.body;
|
|
4338
4367
|
if (!body) return;
|
|
4339
4368
|
try {
|
|
4340
|
-
const
|
|
4341
|
-
if (
|
|
4369
|
+
const next3 = await body.next();
|
|
4370
|
+
if (next3.done) {
|
|
4342
4371
|
open.delete(nid);
|
|
4343
4372
|
peer.postMessage({ net: "end", nid });
|
|
4344
4373
|
} else {
|
|
4345
|
-
const bytes = fresh(
|
|
4374
|
+
const bytes = fresh(next3.value);
|
|
4346
4375
|
peer.postMessage({ net: "chunk", nid, bytes }, [bytes.buffer]);
|
|
4347
4376
|
}
|
|
4348
4377
|
} catch (e) {
|
|
@@ -4360,7 +4389,9 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
4360
4389
|
return {
|
|
4361
4390
|
answer(call) {
|
|
4362
4391
|
if (call.net === "fetch") void start2(call);
|
|
4363
|
-
else if (call.net === "
|
|
4392
|
+
else if (call.net === "body-chunk" || call.net === "body-end" || call.net === "body-error") {
|
|
4393
|
+
uploads.answer(call);
|
|
4394
|
+
} else if (call.net === "read") void read(call.nid);
|
|
4364
4395
|
else if (call.net === "ws-open") void openSocket(call);
|
|
4365
4396
|
else if (call.net === "ws-send") void sendOn(call);
|
|
4366
4397
|
else if (call.net === "ws-close") {
|
|
@@ -4570,9 +4601,9 @@ var UserDb = class {
|
|
|
4570
4601
|
}
|
|
4571
4602
|
}
|
|
4572
4603
|
serial(work) {
|
|
4573
|
-
const
|
|
4574
|
-
this.writing =
|
|
4575
|
-
return
|
|
4604
|
+
const next3 = this.writing.then(work);
|
|
4605
|
+
this.writing = next3.catch(() => void 0);
|
|
4606
|
+
return next3;
|
|
4576
4607
|
}
|
|
4577
4608
|
async ensure() {
|
|
4578
4609
|
await this.fs.mkdir("/etc", { recursive: true });
|
|
@@ -4744,14 +4775,14 @@ async function realpath(fs, path) {
|
|
|
4744
4775
|
let resolved2 = "";
|
|
4745
4776
|
for (let hops = 0; parts2.length > 0; ) {
|
|
4746
4777
|
const [name2, ...rest2] = parts2;
|
|
4747
|
-
const
|
|
4748
|
-
if (!(await fs.lstat(
|
|
4749
|
-
resolved2 =
|
|
4778
|
+
const next3 = `${resolved2}/${name2}`;
|
|
4779
|
+
if (!(await fs.lstat(next3)).isSymbolicLink) {
|
|
4780
|
+
resolved2 = next3;
|
|
4750
4781
|
parts2 = rest2;
|
|
4751
4782
|
continue;
|
|
4752
4783
|
}
|
|
4753
4784
|
if (++hops > MAX_LINKS5) throw fsError("ELOOP", path);
|
|
4754
|
-
const target = await fs.readlink(
|
|
4785
|
+
const target = await fs.readlink(next3);
|
|
4755
4786
|
const base = target.startsWith("/") ? "/" : resolved2 || "/";
|
|
4756
4787
|
parts2 = [...fs.resolvePath(base, target).split("/").filter(Boolean), ...rest2];
|
|
4757
4788
|
resolved2 = "";
|
|
@@ -5344,9 +5375,9 @@ var ClipboardBroker = class {
|
|
|
5344
5375
|
// src/clipboard-relay.ts
|
|
5345
5376
|
function clipboardAsker(port) {
|
|
5346
5377
|
const asks = /* @__PURE__ */ new Map();
|
|
5347
|
-
let
|
|
5378
|
+
let next3 = 0;
|
|
5348
5379
|
const ask = (op, stamp, text) => {
|
|
5349
|
-
const id2 = ++
|
|
5380
|
+
const id2 = ++next3;
|
|
5350
5381
|
const waiting = Promise.withResolvers();
|
|
5351
5382
|
asks.set(id2, waiting);
|
|
5352
5383
|
const timer = setTimeout(() => {
|
|
@@ -5374,9 +5405,9 @@ function clipboardAsker(port) {
|
|
|
5374
5405
|
// src/integrity-relay.ts
|
|
5375
5406
|
function integrityAsker(port) {
|
|
5376
5407
|
const asks = /* @__PURE__ */ new Map();
|
|
5377
|
-
let
|
|
5408
|
+
let next3 = 0;
|
|
5378
5409
|
const lookup2 = (path) => {
|
|
5379
|
-
const id2 = ++
|
|
5410
|
+
const id2 = ++next3;
|
|
5380
5411
|
const waiting = Promise.withResolvers();
|
|
5381
5412
|
asks.set(id2, waiting);
|
|
5382
5413
|
port.postMessage({ integrityAsk: { id: id2, path } });
|
|
@@ -5440,10 +5471,10 @@ var Incoming = class {
|
|
|
5440
5471
|
this.eof = true;
|
|
5441
5472
|
return false;
|
|
5442
5473
|
}
|
|
5443
|
-
const
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
this.buf =
|
|
5474
|
+
const next3 = new Uint8Array(this.buf.length + chunk2.length);
|
|
5475
|
+
next3.set(this.buf);
|
|
5476
|
+
next3.set(chunk2, this.buf.length);
|
|
5477
|
+
this.buf = next3;
|
|
5447
5478
|
return true;
|
|
5448
5479
|
}
|
|
5449
5480
|
take(n) {
|
|
@@ -5583,23 +5614,50 @@ async function readBody(incoming, framing, cap, signal) {
|
|
|
5583
5614
|
const chunks = [];
|
|
5584
5615
|
let total = 0;
|
|
5585
5616
|
for (; ; ) {
|
|
5586
|
-
const
|
|
5587
|
-
const size = /^([0-9A-Fa-f]{1,12})[ \t]*(;.*)?$/.exec(sizeLine);
|
|
5588
|
-
if (!size) throw new HttpError(400, "malformed chunk size");
|
|
5589
|
-
const n = Number.parseInt(size[1], 16);
|
|
5617
|
+
const n = await chunkSize(incoming, signal);
|
|
5590
5618
|
if (n === 0) break;
|
|
5591
5619
|
total += n;
|
|
5592
5620
|
if (total > cap) throw new HttpError(413, `request body over ${cap} bytes`);
|
|
5593
5621
|
chunks.push(await incoming.exactly(n, signal));
|
|
5594
5622
|
if (await incoming.line(2, signal) !== "") throw new HttpError(400, "malformed chunk");
|
|
5595
5623
|
}
|
|
5624
|
+
await skipTrailers(incoming, signal);
|
|
5625
|
+
return concat(chunks, total);
|
|
5626
|
+
}
|
|
5627
|
+
async function chunkSize(incoming, signal) {
|
|
5628
|
+
const sizeLine = await incoming.line(MAX_CHUNK_LINE, signal);
|
|
5629
|
+
const size = /^([0-9A-Fa-f]{1,12})[ \t]*(;.*)?$/.exec(sizeLine);
|
|
5630
|
+
if (!size) throw new HttpError(400, "malformed chunk size");
|
|
5631
|
+
return Number.parseInt(size[1], 16);
|
|
5632
|
+
}
|
|
5633
|
+
async function skipTrailers(incoming, signal) {
|
|
5596
5634
|
let trailers = 0;
|
|
5597
5635
|
for (let line = await incoming.line(MAX_TRAILERS, signal); line !== ""; ) {
|
|
5598
5636
|
trailers += line.length;
|
|
5599
5637
|
if (trailers > MAX_TRAILERS) throw new HttpError(431, "trailers too large");
|
|
5600
5638
|
line = await incoming.line(MAX_TRAILERS, signal);
|
|
5601
5639
|
}
|
|
5602
|
-
|
|
5640
|
+
}
|
|
5641
|
+
var STREAM_PIECE = 64 * 1024;
|
|
5642
|
+
async function* pieces(incoming, n, signal) {
|
|
5643
|
+
for (let left = n; left > 0; ) {
|
|
5644
|
+
const piece = await incoming.some(Math.min(left, STREAM_PIECE), signal);
|
|
5645
|
+
if (piece.length === 0) throw new HttpError(400, "connection closed inside a body");
|
|
5646
|
+
left -= piece.length;
|
|
5647
|
+
yield piece;
|
|
5648
|
+
}
|
|
5649
|
+
}
|
|
5650
|
+
async function* streamBody(incoming, framing, signal) {
|
|
5651
|
+
if (framing.kind === "none") return;
|
|
5652
|
+
if (framing.kind === "length") {
|
|
5653
|
+
yield* pieces(incoming, framing.length, signal);
|
|
5654
|
+
return;
|
|
5655
|
+
}
|
|
5656
|
+
for (let n = await chunkSize(incoming, signal); n !== 0; n = await chunkSize(incoming, signal)) {
|
|
5657
|
+
yield* pieces(incoming, n, signal);
|
|
5658
|
+
if (await incoming.line(2, signal) !== "") throw new HttpError(400, "malformed chunk");
|
|
5659
|
+
}
|
|
5660
|
+
await skipTrailers(incoming, signal);
|
|
5603
5661
|
}
|
|
5604
5662
|
function concat(chunks, total = chunks.reduce((n, c) => n + c.length, 0)) {
|
|
5605
5663
|
const out = new Uint8Array(total);
|
|
@@ -5708,11 +5766,11 @@ function frame(opcode, payload) {
|
|
|
5708
5766
|
return out;
|
|
5709
5767
|
}
|
|
5710
5768
|
function clientFrame(opcode, payload) {
|
|
5711
|
-
const
|
|
5712
|
-
const head =
|
|
5769
|
+
const plain2 = frame(opcode, payload);
|
|
5770
|
+
const head = plain2.length - payload.length;
|
|
5713
5771
|
const mask = crypto.getRandomValues(new Uint8Array(4));
|
|
5714
|
-
const out = new Uint8Array(
|
|
5715
|
-
out.set(
|
|
5772
|
+
const out = new Uint8Array(plain2.length + 4);
|
|
5773
|
+
out.set(plain2.subarray(0, head));
|
|
5716
5774
|
out[1] = out[1] | 128;
|
|
5717
5775
|
out.set(mask, head);
|
|
5718
5776
|
for (let i = 0; i < payload.length; i++) {
|
|
@@ -6045,6 +6103,11 @@ async function watchHangup(conn, abort, until) {
|
|
|
6045
6103
|
}
|
|
6046
6104
|
}
|
|
6047
6105
|
}
|
|
6106
|
+
var BODILESS_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
|
|
6107
|
+
async function* drain(body, done4) {
|
|
6108
|
+
yield* body;
|
|
6109
|
+
done4();
|
|
6110
|
+
}
|
|
6048
6111
|
function untilAborted(response, signal) {
|
|
6049
6112
|
return new Promise((resolve2, reject) => {
|
|
6050
6113
|
const onAbort = () => {
|
|
@@ -6187,7 +6250,8 @@ var RealmProxy = class {
|
|
|
6187
6250
|
const url = ctx.origin ? tunnelRequestUrl(req, ctx.origin) : requestUrl(req);
|
|
6188
6251
|
const keep2 = keepsAlive(req);
|
|
6189
6252
|
const framing = requestFraming(req.headers);
|
|
6190
|
-
const
|
|
6253
|
+
const streaming = this.options.transport.traits.streamingBodies === true && framing.kind !== "none" && !BODILESS_METHODS.has(req.method);
|
|
6254
|
+
const reserve = streaming ? 0 : framing.kind === "length" ? framing.length : framing.kind === "chunked" ? this.cap() : 0;
|
|
6191
6255
|
if (reserve > this.cap()) throw new HttpError(413, `request body over ${this.cap()} bytes`);
|
|
6192
6256
|
await this.expectContinue(conn, req, framing.kind !== "none");
|
|
6193
6257
|
await this.bodies.acquire(reserve, this.stop.signal);
|
|
@@ -6195,9 +6259,12 @@ var RealmProxy = class {
|
|
|
6195
6259
|
const abort = new AbortController();
|
|
6196
6260
|
const stopExchange = () => abort.abort();
|
|
6197
6261
|
this.stop.signal.addEventListener("abort", stopExchange, { once: true });
|
|
6262
|
+
let drained = !streaming;
|
|
6198
6263
|
try {
|
|
6199
6264
|
try {
|
|
6200
|
-
const body =
|
|
6265
|
+
const body = streaming ? drain(streamBody(incoming, framing, abort.signal), () => {
|
|
6266
|
+
drained = true;
|
|
6267
|
+
}) : await readBody(incoming, framing, this.cap());
|
|
6201
6268
|
const waiting = new AbortController();
|
|
6202
6269
|
void watchHangup(ctx.socket, abort, waiting.signal);
|
|
6203
6270
|
try {
|
|
@@ -6208,7 +6275,8 @@ var RealmProxy = class {
|
|
|
6208
6275
|
} finally {
|
|
6209
6276
|
this.bodies.release(reserve);
|
|
6210
6277
|
}
|
|
6211
|
-
|
|
6278
|
+
const kept = await this.relay(conn, req.method, req.minor, response, keep2 && drained);
|
|
6279
|
+
return kept && drained;
|
|
6212
6280
|
} finally {
|
|
6213
6281
|
this.stop.signal.removeEventListener("abort", stopExchange);
|
|
6214
6282
|
abort.abort();
|
|
@@ -6228,13 +6296,14 @@ var RealmProxy = class {
|
|
|
6228
6296
|
}
|
|
6229
6297
|
}
|
|
6230
6298
|
async upstream(req, url, body, signal, owner) {
|
|
6299
|
+
const sent = BODILESS_METHODS.has(req.method) ? void 0 : body;
|
|
6231
6300
|
try {
|
|
6232
6301
|
const fetching = this.options.transport.fetch(
|
|
6233
6302
|
{
|
|
6234
6303
|
url: toHostLoopback(url),
|
|
6235
6304
|
method: req.method.toUpperCase(),
|
|
6236
6305
|
headers: forwardRequestHeaders(req.headers),
|
|
6237
|
-
body:
|
|
6306
|
+
...sent instanceof Uint8Array ? { body: sent } : sent ? { bodyStream: sent } : {},
|
|
6238
6307
|
signal
|
|
6239
6308
|
},
|
|
6240
6309
|
owner
|
|
@@ -7152,12 +7221,17 @@ var RemoteTransport = class {
|
|
|
7152
7221
|
waiting = /* @__PURE__ */ new Map();
|
|
7153
7222
|
nextId = 0;
|
|
7154
7223
|
sockets = /* @__PURE__ */ new Map();
|
|
7224
|
+
uploads = /* @__PURE__ */ new Map();
|
|
7155
7225
|
failure;
|
|
7156
7226
|
constructor(port, traits) {
|
|
7157
7227
|
this.port = port;
|
|
7158
7228
|
this.traits = traits;
|
|
7159
7229
|
}
|
|
7160
7230
|
receive(reply) {
|
|
7231
|
+
if (reply.net === "body-pull") {
|
|
7232
|
+
void this.pull(reply.nid);
|
|
7233
|
+
return;
|
|
7234
|
+
}
|
|
7161
7235
|
const socket = this.sockets.get(reply.nid);
|
|
7162
7236
|
if (socket && this.toSocket(reply, socket)) return;
|
|
7163
7237
|
const waiter = this.waiting.get(reply.nid);
|
|
@@ -7176,8 +7250,35 @@ var RemoteTransport = class {
|
|
|
7176
7250
|
} else return false;
|
|
7177
7251
|
return true;
|
|
7178
7252
|
}
|
|
7253
|
+
async pull(nid) {
|
|
7254
|
+
const upload = this.uploads.get(nid);
|
|
7255
|
+
if (!upload) {
|
|
7256
|
+
this.port.postMessage({ net: "body-error", nid, message: "the request body is gone" });
|
|
7257
|
+
return;
|
|
7258
|
+
}
|
|
7259
|
+
try {
|
|
7260
|
+
const next3 = await upload.next();
|
|
7261
|
+
if (next3.done) {
|
|
7262
|
+
this.uploads.delete(nid);
|
|
7263
|
+
this.port.postMessage({ net: "body-end", nid });
|
|
7264
|
+
} else this.port.postMessage({ net: "body-chunk", nid, bytes: next3.value });
|
|
7265
|
+
} catch (e) {
|
|
7266
|
+
this.uploads.delete(nid);
|
|
7267
|
+
this.port.postMessage({
|
|
7268
|
+
net: "body-error",
|
|
7269
|
+
nid,
|
|
7270
|
+
message: e instanceof Error ? e.message : String(e)
|
|
7271
|
+
});
|
|
7272
|
+
}
|
|
7273
|
+
}
|
|
7274
|
+
dropUpload(nid) {
|
|
7275
|
+
const upload = this.uploads.get(nid);
|
|
7276
|
+
this.uploads.delete(nid);
|
|
7277
|
+
void upload?.return?.().catch(() => void 0);
|
|
7278
|
+
}
|
|
7179
7279
|
fail(error) {
|
|
7180
7280
|
this.failure = error;
|
|
7281
|
+
for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);
|
|
7181
7282
|
for (const waiter of this.waiting.values()) waiter.reject(error);
|
|
7182
7283
|
this.waiting.clear();
|
|
7183
7284
|
for (const socket of this.sockets.values())
|
|
@@ -7204,14 +7305,17 @@ var RemoteTransport = class {
|
|
|
7204
7305
|
let finished = false;
|
|
7205
7306
|
const abort = () => {
|
|
7206
7307
|
finished = true;
|
|
7308
|
+
this.dropUpload(nid);
|
|
7207
7309
|
this.cancel(nid);
|
|
7208
7310
|
};
|
|
7209
7311
|
signal.addEventListener("abort", abort, { once: true });
|
|
7210
7312
|
const finish = () => {
|
|
7313
|
+
this.dropUpload(nid);
|
|
7211
7314
|
if (finished) return;
|
|
7212
7315
|
finished = true;
|
|
7213
7316
|
signal.removeEventListener("abort", abort);
|
|
7214
7317
|
};
|
|
7318
|
+
if (request2.bodyStream) this.uploads.set(nid, request2.bodyStream[Symbol.asyncIterator]());
|
|
7215
7319
|
let head;
|
|
7216
7320
|
try {
|
|
7217
7321
|
head = await this.ask({
|
|
@@ -7220,7 +7324,7 @@ var RemoteTransport = class {
|
|
|
7220
7324
|
url: request2.url,
|
|
7221
7325
|
method: request2.method,
|
|
7222
7326
|
headers: request2.headers,
|
|
7223
|
-
...request2.body ? { body: request2.body } : {}
|
|
7327
|
+
...request2.bodyStream ? { streamed: true } : request2.body ? { body: request2.body } : {}
|
|
7224
7328
|
});
|
|
7225
7329
|
} catch (e) {
|
|
7226
7330
|
finish();
|
|
@@ -7730,6 +7834,164 @@ function closeAll(entry) {
|
|
|
7730
7834
|
}
|
|
7731
7835
|
}
|
|
7732
7836
|
|
|
7837
|
+
// src/fs/engines.ts
|
|
7838
|
+
var NUMBER = /^(0|[1-9]\d*)$/;
|
|
7839
|
+
var PART = /^(?:0|[1-9]\d*|[xX*])$/;
|
|
7840
|
+
var IDENTIFIER = /^(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)$/;
|
|
7841
|
+
function identifiers(pre) {
|
|
7842
|
+
if (pre === void 0) return [];
|
|
7843
|
+
const ids = pre.split(".");
|
|
7844
|
+
return ids.every((id2) => IDENTIFIER.test(id2)) ? ids : void 0;
|
|
7845
|
+
}
|
|
7846
|
+
function parseVersion(text) {
|
|
7847
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(text.trim());
|
|
7848
|
+
const pre = identifiers(m?.[4]);
|
|
7849
|
+
if (!m || !pre || ![m[1], m[2], m[3]].every((n) => NUMBER.test(n))) return void 0;
|
|
7850
|
+
return [Number(m[1]), Number(m[2]), Number(m[3]), pre];
|
|
7851
|
+
}
|
|
7852
|
+
function comparePre(a, b) {
|
|
7853
|
+
if (a.length === 0 || b.length === 0) return b.length - a.length;
|
|
7854
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
7855
|
+
const [x, y] = [a[i], b[i]];
|
|
7856
|
+
if (x === void 0 || y === void 0) return x === void 0 ? -1 : 1;
|
|
7857
|
+
if (x === y) continue;
|
|
7858
|
+
const [nx, ny] = [NUMBER.test(x), NUMBER.test(y)];
|
|
7859
|
+
if (nx && ny) return Number(x) - Number(y);
|
|
7860
|
+
if (nx !== ny) return nx ? -1 : 1;
|
|
7861
|
+
return x < y ? -1 : 1;
|
|
7862
|
+
}
|
|
7863
|
+
return 0;
|
|
7864
|
+
}
|
|
7865
|
+
function compare(a, b) {
|
|
7866
|
+
return a[0] - b[0] || a[1] - b[1] || a[2] - b[2] || comparePre(a[3], b[3]);
|
|
7867
|
+
}
|
|
7868
|
+
function partial(text) {
|
|
7869
|
+
const m = /^v?([^.+-]+)(?:\.([^.+-]+))?(?:\.([^.+-]+))?(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(
|
|
7870
|
+
text
|
|
7871
|
+
);
|
|
7872
|
+
if (!m) return void 0;
|
|
7873
|
+
const raw = [m[1], m[2], m[3]];
|
|
7874
|
+
if (!raw.every((p) => p === void 0 || PART.test(p))) return void 0;
|
|
7875
|
+
const parts2 = [];
|
|
7876
|
+
for (const p of raw) {
|
|
7877
|
+
if (p === void 0 || /^[xX*]$/.test(p) || parts2.includes(void 0)) parts2.push(void 0);
|
|
7878
|
+
else parts2.push(Number(p));
|
|
7879
|
+
}
|
|
7880
|
+
const pre = identifiers(m[4]);
|
|
7881
|
+
return pre && { parts: parts2, pre };
|
|
7882
|
+
}
|
|
7883
|
+
function floor(p) {
|
|
7884
|
+
const [a = 0, b = 0, c = 0] = p.parts;
|
|
7885
|
+
return [a, b, c, p.parts.includes(void 0) ? [] : p.pre];
|
|
7886
|
+
}
|
|
7887
|
+
function next(p) {
|
|
7888
|
+
const [a, b] = p.parts;
|
|
7889
|
+
if (a === void 0) return void 0;
|
|
7890
|
+
if (b === void 0) return [a + 1, 0, 0, ["0"]];
|
|
7891
|
+
return [a, b + 1, 0, ["0"]];
|
|
7892
|
+
}
|
|
7893
|
+
var ANY = [[">=", [0, 0, 0, []]]];
|
|
7894
|
+
var NOTHING = [["<", [0, 0, 0, ["0"]]]];
|
|
7895
|
+
function plain(op, p) {
|
|
7896
|
+
const exact = !p.parts.includes(void 0);
|
|
7897
|
+
const low = floor(p);
|
|
7898
|
+
const high = next(p);
|
|
7899
|
+
if (op === ">=") return [[">=", low]];
|
|
7900
|
+
if (op === "<") return [["<", exact ? low : [low[0], low[1], low[2], ["0"]]]];
|
|
7901
|
+
if (exact) return [[op === "" ? "=" : op, low]];
|
|
7902
|
+
if (op === ">") return high ? [[">=", high]] : NOTHING;
|
|
7903
|
+
if (op === "<=") return high ? [["<", high]] : ANY;
|
|
7904
|
+
return high ? [
|
|
7905
|
+
[">=", low],
|
|
7906
|
+
["<", high]
|
|
7907
|
+
] : ANY;
|
|
7908
|
+
}
|
|
7909
|
+
function caret(p) {
|
|
7910
|
+
const [a = 0, b, c] = p.parts;
|
|
7911
|
+
const low = floor(p);
|
|
7912
|
+
if (b === void 0)
|
|
7913
|
+
return [
|
|
7914
|
+
[">=", low],
|
|
7915
|
+
["<", [a + 1, 0, 0, ["0"]]]
|
|
7916
|
+
];
|
|
7917
|
+
if (a > 0)
|
|
7918
|
+
return [
|
|
7919
|
+
[">=", low],
|
|
7920
|
+
["<", [a + 1, 0, 0, ["0"]]]
|
|
7921
|
+
];
|
|
7922
|
+
if (c === void 0 || b > 0)
|
|
7923
|
+
return [
|
|
7924
|
+
[">=", low],
|
|
7925
|
+
["<", [0, b + 1, 0, ["0"]]]
|
|
7926
|
+
];
|
|
7927
|
+
return [
|
|
7928
|
+
[">=", low],
|
|
7929
|
+
["<", [0, b, c + 1, ["0"]]]
|
|
7930
|
+
];
|
|
7931
|
+
}
|
|
7932
|
+
function tilde(p) {
|
|
7933
|
+
const [a = 0, b] = p.parts;
|
|
7934
|
+
const low = floor(p);
|
|
7935
|
+
return [
|
|
7936
|
+
[">=", low],
|
|
7937
|
+
["<", b === void 0 ? [a + 1, 0, 0, ["0"]] : [a, b + 1, 0, ["0"]]]
|
|
7938
|
+
];
|
|
7939
|
+
}
|
|
7940
|
+
function hyphen(from, to) {
|
|
7941
|
+
const high = to.parts.includes(void 0) ? next(to) : void 0;
|
|
7942
|
+
const upper = to.parts.includes(void 0) ? high ? [["<", high]] : [] : [["<=", floor(to)]];
|
|
7943
|
+
return [[">=", floor(from)], ...upper];
|
|
7944
|
+
}
|
|
7945
|
+
function comparator(token) {
|
|
7946
|
+
const m = /^(<=|>=|<|>|=|\^|~>?)?\s*(.*)$/.exec(token);
|
|
7947
|
+
const op = m?.[1] ?? "";
|
|
7948
|
+
const p = partial(m?.[2] ?? "");
|
|
7949
|
+
if (!p) return void 0;
|
|
7950
|
+
const wild = p.parts[0] === void 0;
|
|
7951
|
+
if (op === "^") return wild ? ANY : caret(p);
|
|
7952
|
+
if (op.startsWith("~")) return wild ? ANY : tilde(p);
|
|
7953
|
+
return plain(op, p);
|
|
7954
|
+
}
|
|
7955
|
+
function set2(text) {
|
|
7956
|
+
const trimmed = text.trim().replace(/(<=|>=|<|>|=|\^|~>?)\s+/g, "$1");
|
|
7957
|
+
if (trimmed === "") return ANY;
|
|
7958
|
+
const range = /^(\S+)\s+-\s+(\S+)$/.exec(trimmed);
|
|
7959
|
+
if (range) {
|
|
7960
|
+
const [from, to] = [partial(range[1]), partial(range[2])];
|
|
7961
|
+
return from && to ? hyphen(from, to) : void 0;
|
|
7962
|
+
}
|
|
7963
|
+
const out = [];
|
|
7964
|
+
for (const token of trimmed.split(/\s+/)) {
|
|
7965
|
+
const found = comparator(token);
|
|
7966
|
+
if (!found) return void 0;
|
|
7967
|
+
out.push(...found);
|
|
7968
|
+
}
|
|
7969
|
+
return out;
|
|
7970
|
+
}
|
|
7971
|
+
function holds(v, [op, w]) {
|
|
7972
|
+
const c = compare(v, w);
|
|
7973
|
+
if (op === "<") return c < 0;
|
|
7974
|
+
if (op === "<=") return c <= 0;
|
|
7975
|
+
if (op === ">") return c > 0;
|
|
7976
|
+
if (op === ">=") return c >= 0;
|
|
7977
|
+
return c === 0;
|
|
7978
|
+
}
|
|
7979
|
+
function satisfies(version, range) {
|
|
7980
|
+
const v = parseVersion(version);
|
|
7981
|
+
if (!v) return void 0;
|
|
7982
|
+
const sets = range.split("||").map(set2);
|
|
7983
|
+
if (sets.some((s) => s === void 0)) return void 0;
|
|
7984
|
+
return sets.some((s) => s.every((c) => holds(v, c)));
|
|
7985
|
+
}
|
|
7986
|
+
|
|
7987
|
+
// src/version.ts
|
|
7988
|
+
var KERNEL_VERSION = true ? "1.106.3" : "0.0.0-dev";
|
|
7989
|
+
var OS_RELEASE = "6.0.0-slicc";
|
|
7990
|
+
function procVersion() {
|
|
7991
|
+
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
7992
|
+
`;
|
|
7993
|
+
}
|
|
7994
|
+
|
|
7733
7995
|
// src/commands.ts
|
|
7734
7996
|
var NAME2 = /^[A-Za-z0-9._+-]+$/;
|
|
7735
7997
|
var COMMAND_NAME = /^[^/\s\p{Cc}]+$/u;
|
|
@@ -7941,13 +8203,25 @@ async function binCommandsOf(physical, pkg, manifest, taken) {
|
|
|
7941
8203
|
}
|
|
7942
8204
|
return out;
|
|
7943
8205
|
}
|
|
8206
|
+
function engineRefusal(manifest, kernel) {
|
|
8207
|
+
const engines = manifest.engines;
|
|
8208
|
+
const range = engines && typeof engines === "object" ? engines["slicc-kernel"] : void 0;
|
|
8209
|
+
const running = parseVersion(kernel);
|
|
8210
|
+
if (typeof range !== "string" || !running || running.slice(0, 3).every((n) => n === 0)) {
|
|
8211
|
+
return void 0;
|
|
8212
|
+
}
|
|
8213
|
+
const fits = satisfies(kernel, range);
|
|
8214
|
+
if (fits) return void 0;
|
|
8215
|
+
const who = `${String(manifest.name ?? "?")}@${String(manifest.version ?? "?")}`;
|
|
8216
|
+
return fits === false ? `${who} needs slicc-kernel ${range}; this kernel is ${kernel}` : `${who} has an engines.slicc-kernel range this kernel can't read: ${JSON.stringify(range)}`;
|
|
8217
|
+
}
|
|
7944
8218
|
var PACKAGE_NAME = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
7945
8219
|
function replacesOf(manifest) {
|
|
7946
8220
|
const replaces = manifest.slicc?.replaces;
|
|
7947
8221
|
if (!Array.isArray(replaces)) return [];
|
|
7948
8222
|
return replaces.every((name2) => typeof name2 === "string" && PACKAGE_NAME.test(name2)) ? replaces : [];
|
|
7949
8223
|
}
|
|
7950
|
-
async function tierPackages(fs, physical, roots, bins) {
|
|
8224
|
+
async function tierPackages(fs, physical, roots, bins, kernel) {
|
|
7951
8225
|
const out = [];
|
|
7952
8226
|
for (const root of roots) {
|
|
7953
8227
|
for (const pkg of await packages(fs, root)) {
|
|
@@ -7960,11 +8234,13 @@ async function tierPackages(fs, physical, roots, bins) {
|
|
|
7960
8234
|
const own = commandsOf(pkg, manifest);
|
|
7961
8235
|
const named = new Set(own.map((command) => command.name));
|
|
7962
8236
|
const extra = bins ? await binCommandsOf(physical, pkg, manifest, named) : [];
|
|
8237
|
+
const refused2 = engineRefusal(manifest, kernel);
|
|
8238
|
+
const commands = [...own, ...extra];
|
|
7963
8239
|
out.push({
|
|
7964
8240
|
name: pkg.slice(root.length + 1),
|
|
7965
8241
|
pkg,
|
|
7966
8242
|
replaces: replacesOf(manifest),
|
|
7967
|
-
commands:
|
|
8243
|
+
commands: refused2 ? commands.map((command) => ({ ...command, refused: refused2 })) : commands
|
|
7968
8244
|
});
|
|
7969
8245
|
}
|
|
7970
8246
|
}
|
|
@@ -7990,14 +8266,14 @@ function winners(tier) {
|
|
|
7990
8266
|
}
|
|
7991
8267
|
return out;
|
|
7992
8268
|
}
|
|
7993
|
-
async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY) {
|
|
8269
|
+
async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, kernel = KERNEL_VERSION) {
|
|
7994
8270
|
const found = /* @__PURE__ */ new Map();
|
|
7995
8271
|
const physical = physicalResolver(fs);
|
|
7996
8272
|
const tiers = (typeof modules === "string" ? [modules] : modules).map(
|
|
7997
8273
|
(tier) => typeof tier === "string" ? [tier] : tier
|
|
7998
8274
|
);
|
|
7999
8275
|
for (const [index, roots] of tiers.entries()) {
|
|
8000
|
-
const tier = await tierPackages(fs, physical, roots, index >= binsFrom);
|
|
8276
|
+
const tier = await tierPackages(fs, physical, roots, index >= binsFrom, kernel);
|
|
8001
8277
|
for (const [name2, { pkg, command }] of winners(tier)) {
|
|
8002
8278
|
if (!found.has(name2)) found.set(name2, await withPackagePaths(fs, pkg, command));
|
|
8003
8279
|
}
|
|
@@ -8374,6 +8650,7 @@ var S_IFDIR2 = 16384;
|
|
|
8374
8650
|
var S_IFREG2 = 32768;
|
|
8375
8651
|
var COMMAND = /^\/(?:usr\/)?bin\/([^/]+)$/;
|
|
8376
8652
|
var MAX_LINKS6 = 40;
|
|
8653
|
+
var BIN_ENTRY = /\/bin\/[^/]+$/;
|
|
8377
8654
|
function missing3(err) {
|
|
8378
8655
|
return err?.code === "ENOENT";
|
|
8379
8656
|
}
|
|
@@ -8401,7 +8678,20 @@ async function followLinks(fs, path) {
|
|
|
8401
8678
|
}
|
|
8402
8679
|
return current;
|
|
8403
8680
|
}
|
|
8404
|
-
|
|
8681
|
+
var NOBODY = { ruid: -1, euid: -1, suid: -1, rgid: -1, egid: -1, sgid: -1, groups: [] };
|
|
8682
|
+
var EMPTY = new Uint8Array(0);
|
|
8683
|
+
function quiet(promise) {
|
|
8684
|
+
return promise.catch(() => void 0);
|
|
8685
|
+
}
|
|
8686
|
+
async function readsAs2(fs, cred, target) {
|
|
8687
|
+
const walked = await quiet(access(fs, cred, target, R_OK, { directory: false }));
|
|
8688
|
+
return walked !== void 0 && walked.denied === void 0 && !walked.missing;
|
|
8689
|
+
}
|
|
8690
|
+
async function shownTarget(fs, target) {
|
|
8691
|
+
const st = await quiet(fs.stat(target));
|
|
8692
|
+
return st?.isFile && await readsAs2(fs, NOBODY, target) ? st : void 0;
|
|
8693
|
+
}
|
|
8694
|
+
function withCommandDirs(fs, names, userDir = async () => void 0, owners = false, targetOf2 = async () => void 0) {
|
|
8405
8695
|
async function nearest(path) {
|
|
8406
8696
|
const st = await fs.stat(path).catch(() => void 0);
|
|
8407
8697
|
if (st || path === "/") return st ?? {};
|
|
@@ -8433,9 +8723,54 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
8433
8723
|
const own = await userDir(dir);
|
|
8434
8724
|
return own?.has(path.slice(slash + 1)) ? owned4(synthetic(false, path), dir) : void 0;
|
|
8435
8725
|
}
|
|
8726
|
+
let generation;
|
|
8727
|
+
const targets = /* @__PURE__ */ new Map();
|
|
8728
|
+
async function targetStat(target) {
|
|
8729
|
+
const now = await names();
|
|
8730
|
+
if (now !== generation) {
|
|
8731
|
+
generation = now;
|
|
8732
|
+
targets.clear();
|
|
8733
|
+
}
|
|
8734
|
+
let found = targets.get(target);
|
|
8735
|
+
if (!found) {
|
|
8736
|
+
found = shownTarget(fs, target);
|
|
8737
|
+
targets.set(target, found);
|
|
8738
|
+
}
|
|
8739
|
+
return found;
|
|
8740
|
+
}
|
|
8741
|
+
async function shown(path) {
|
|
8742
|
+
const st = await virtual(path);
|
|
8743
|
+
if (!st?.isFile) return st;
|
|
8744
|
+
const target = await targetOf2(path);
|
|
8745
|
+
const real = target === void 0 ? void 0 : await targetStat(target.path);
|
|
8746
|
+
return real ? { ...st, size: real.size, mtime: real.mtime, ctime: real.mtime, atime: real.mtime } : st;
|
|
8747
|
+
}
|
|
8436
8748
|
async function linked2(path) {
|
|
8437
|
-
return await
|
|
8749
|
+
return await shown(path) ?? shown(await followLinks(fs, path));
|
|
8750
|
+
}
|
|
8751
|
+
async function entryTarget(path) {
|
|
8752
|
+
if (!BIN_ENTRY.test(path) || !(await virtual(path))?.isFile) return void 0;
|
|
8753
|
+
if (!await fs.lstat(path).then(() => false, missing3)) return void 0;
|
|
8754
|
+
const target = await targetOf2(path);
|
|
8755
|
+
return target?.path === path ? void 0 : target;
|
|
8756
|
+
}
|
|
8757
|
+
async function redirected2(path) {
|
|
8758
|
+
const target = await entryTarget(path) ?? await entryTarget(await followLinks(fs, path));
|
|
8759
|
+
if (owners && target?.owner && !await readsAs2(fs, target.owner, target.path)) {
|
|
8760
|
+
throw fsError("EACCES", path);
|
|
8761
|
+
}
|
|
8762
|
+
return target?.path;
|
|
8763
|
+
}
|
|
8764
|
+
const absent2 = (err) => {
|
|
8765
|
+
if (missing3(err)) return EMPTY;
|
|
8766
|
+
throw err;
|
|
8767
|
+
};
|
|
8768
|
+
async function content(path, err) {
|
|
8769
|
+
if (!missing3(err) || !(await linked2(path))?.isFile) throw err;
|
|
8770
|
+
const target = await redirected2(path);
|
|
8771
|
+
return target === void 0 ? EMPTY : fs.readFileBuffer(target).catch(absent2);
|
|
8438
8772
|
}
|
|
8773
|
+
const ranged2 = rangedOps(fs);
|
|
8439
8774
|
async function stat(path, real) {
|
|
8440
8775
|
try {
|
|
8441
8776
|
return await real(path);
|
|
@@ -8447,16 +8782,13 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
8447
8782
|
}
|
|
8448
8783
|
return {
|
|
8449
8784
|
resolvePath: (base, path) => fs.resolvePath(base, path),
|
|
8450
|
-
readFile: (path) => fs.readFile(path)
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8457
|
-
}
|
|
8458
|
-
},
|
|
8459
|
-
writeFile: (path, content, owner) => fs.writeFile(path, content, owner),
|
|
8785
|
+
readFile: (path) => fs.readFile(path).catch(async (err) => {
|
|
8786
|
+
if (!BIN_ENTRY.test(await followLinks(fs, path))) throw err;
|
|
8787
|
+
return new TextDecoder().decode(await content(path, err));
|
|
8788
|
+
}),
|
|
8789
|
+
readFileBuffer: (path) => fs.readFileBuffer(path).catch((err) => content(path, err)),
|
|
8790
|
+
commandTarget: async (path) => (await entryTarget(path))?.path,
|
|
8791
|
+
writeFile: (path, content2, owner) => fs.writeFile(path, content2, owner),
|
|
8460
8792
|
link: (from, to, follow2) => fs.link(from, to, follow2),
|
|
8461
8793
|
links: (path) => mayLink(fs, path),
|
|
8462
8794
|
async exists(path) {
|
|
@@ -8487,7 +8819,7 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
8487
8819
|
added.map(
|
|
8488
8820
|
async (name2) => [
|
|
8489
8821
|
name2,
|
|
8490
|
-
await
|
|
8822
|
+
await shown(`${base}/${name2}`)
|
|
8491
8823
|
]
|
|
8492
8824
|
)
|
|
8493
8825
|
);
|
|
@@ -8505,7 +8837,14 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
8505
8837
|
chmod: (path, mode) => fs.chmod(path, mode),
|
|
8506
8838
|
utimes: (path, atime, mtime) => fs.utimes(path, atime, mtime),
|
|
8507
8839
|
lutimes: (path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
|
|
8508
|
-
...
|
|
8840
|
+
...ranged2 ? {
|
|
8841
|
+
...ranged2,
|
|
8842
|
+
pread: (path, offset, length2, version) => ranged2.pread(path, offset, length2, version).catch(async (err) => {
|
|
8843
|
+
const target = missing3(err) ? await redirected2(path) : void 0;
|
|
8844
|
+
if (target === void 0) throw err;
|
|
8845
|
+
return ranged2.pread(target, offset, length2).catch(absent2);
|
|
8846
|
+
})
|
|
8847
|
+
} : {}
|
|
8509
8848
|
};
|
|
8510
8849
|
}
|
|
8511
8850
|
|
|
@@ -8650,7 +8989,7 @@ var MAX_HOPS2 = 40;
|
|
|
8650
8989
|
function start(path) {
|
|
8651
8990
|
return { done: [], todo: path.split("/").filter((p) => p !== ""), hops: 0 };
|
|
8652
8991
|
}
|
|
8653
|
-
function
|
|
8992
|
+
function next2(walk2) {
|
|
8654
8993
|
while (walk2.todo.length > 0) {
|
|
8655
8994
|
const part = walk2.todo.shift();
|
|
8656
8995
|
if (part === ".") continue;
|
|
@@ -8664,7 +9003,7 @@ function next(walk2) {
|
|
|
8664
9003
|
}
|
|
8665
9004
|
function lexical(path) {
|
|
8666
9005
|
const walk2 = start(path);
|
|
8667
|
-
for (let part =
|
|
9006
|
+
for (let part = next2(walk2); part !== void 0; part = next2(walk2)) walk2.done.push(part);
|
|
8668
9007
|
return `/${walk2.done.join("/")}`;
|
|
8669
9008
|
}
|
|
8670
9009
|
function rest(walk2, part) {
|
|
@@ -8678,7 +9017,7 @@ function follow(walk2, target) {
|
|
|
8678
9017
|
}
|
|
8679
9018
|
async function physicalPathAsync(fs, path) {
|
|
8680
9019
|
const walk2 = start(path);
|
|
8681
|
-
for (let part =
|
|
9020
|
+
for (let part = next2(walk2); part !== void 0; part = next2(walk2)) {
|
|
8682
9021
|
const at = `/${[...walk2.done, part].join("/")}`;
|
|
8683
9022
|
let target;
|
|
8684
9023
|
try {
|
|
@@ -8751,9 +9090,9 @@ var UnlinkedKeeper = class {
|
|
|
8751
9090
|
void locks?.request(lockName(this.instance), () => new Promise(() => void 0));
|
|
8752
9091
|
}
|
|
8753
9092
|
serial(op) {
|
|
8754
|
-
const
|
|
8755
|
-
this.queue =
|
|
8756
|
-
return
|
|
9093
|
+
const next3 = this.queue.then(op);
|
|
9094
|
+
this.queue = next3.catch(() => void 0);
|
|
9095
|
+
return next3;
|
|
8757
9096
|
}
|
|
8758
9097
|
wrap(fs = this.fs) {
|
|
8759
9098
|
const keeper = this;
|
|
@@ -9198,7 +9537,8 @@ var ChildTable = class {
|
|
|
9198
9537
|
const child = this.children.get(pid);
|
|
9199
9538
|
if (!child) return;
|
|
9200
9539
|
this.watchers.set(pid, listener);
|
|
9201
|
-
if (child.stoppedBy !== void 0
|
|
9540
|
+
if (child.stoppedBy !== void 0 && child.code === void 0)
|
|
9541
|
+
listener("stopped", child.stoppedBy);
|
|
9202
9542
|
}
|
|
9203
9543
|
openSlot(slot2, n, captured) {
|
|
9204
9544
|
if ("fd" in slot2) return this.parentFds.get(slot2.fd).retain();
|
|
@@ -9496,14 +9836,14 @@ var HeldSet = class extends Set {
|
|
|
9496
9836
|
super();
|
|
9497
9837
|
this.idle = idle;
|
|
9498
9838
|
}
|
|
9499
|
-
add(
|
|
9500
|
-
|
|
9501
|
-
return super.add(
|
|
9839
|
+
add(holds2) {
|
|
9840
|
+
holds2.onIdle = this.idle;
|
|
9841
|
+
return super.add(holds2);
|
|
9502
9842
|
}
|
|
9503
|
-
delete(
|
|
9504
|
-
const removed = super.delete(
|
|
9505
|
-
for (const path of /* @__PURE__ */ new Set([...
|
|
9506
|
-
|
|
9843
|
+
delete(holds2) {
|
|
9844
|
+
const removed = super.delete(holds2);
|
|
9845
|
+
for (const path of /* @__PURE__ */ new Set([...holds2.keys(), ...holds2.opens.keys()])) this.idle(path);
|
|
9846
|
+
holds2.releaseAll();
|
|
9507
9847
|
return removed;
|
|
9508
9848
|
}
|
|
9509
9849
|
};
|
|
@@ -10690,9 +11030,9 @@ var MountFs = class _MountFs {
|
|
|
10690
11030
|
this.writable(mount, real);
|
|
10691
11031
|
const { uid, gid, mode } = change;
|
|
10692
11032
|
const fresh2 = change.kind === "new" && { uid, gid, mode };
|
|
10693
|
-
const
|
|
11033
|
+
const set3 = fresh2 ? await this.driverOwner(found, real, fresh2, false) : change;
|
|
10694
11034
|
this.table.forget(mount, real);
|
|
10695
|
-
const attrs = Object.entries({ uid:
|
|
11035
|
+
const attrs = Object.entries({ uid: set3.uid, gid: set3.gid, mode: set3.mode });
|
|
10696
11036
|
await mount.conn.call({
|
|
10697
11037
|
op: "setattr",
|
|
10698
11038
|
path: rel2,
|
|
@@ -10719,11 +11059,11 @@ var MountFs = class _MountFs {
|
|
|
10719
11059
|
const real = await this.follow(path);
|
|
10720
11060
|
const found = this.at(real);
|
|
10721
11061
|
if (!found) {
|
|
10722
|
-
const
|
|
11062
|
+
const set3 = () => this.base.utimes(real, atime, mtime);
|
|
10723
11063
|
return this.based(
|
|
10724
11064
|
[real],
|
|
10725
11065
|
redirects,
|
|
10726
|
-
|
|
11066
|
+
set3,
|
|
10727
11067
|
([to], n) => this.utimes(to, atime, mtime, n)
|
|
10728
11068
|
);
|
|
10729
11069
|
}
|
|
@@ -10732,11 +11072,11 @@ var MountFs = class _MountFs {
|
|
|
10732
11072
|
async lutimes(path, atime, mtime, redirects = 0) {
|
|
10733
11073
|
const found = this.at(path);
|
|
10734
11074
|
if (!found) {
|
|
10735
|
-
const
|
|
11075
|
+
const set3 = () => lutimesOf(this.base, path, atime, mtime);
|
|
10736
11076
|
return this.based(
|
|
10737
11077
|
[path],
|
|
10738
11078
|
redirects,
|
|
10739
|
-
|
|
11079
|
+
set3,
|
|
10740
11080
|
([to], n) => this.lutimes(to, atime, mtime, n)
|
|
10741
11081
|
);
|
|
10742
11082
|
}
|
|
@@ -10758,6 +11098,20 @@ var MountFs = class _MountFs {
|
|
|
10758
11098
|
}
|
|
10759
11099
|
};
|
|
10760
11100
|
|
|
11101
|
+
// src/fs/command-stat.ts
|
|
11102
|
+
async function callerStat(g, path, st) {
|
|
11103
|
+
if (!g?.fs.commandTarget || !st.isFile || st.size > 0) return st;
|
|
11104
|
+
const target = await g.fs.commandTarget(path);
|
|
11105
|
+
if (target === void 0) return st;
|
|
11106
|
+
const options = { directory: false, ...g.links === void 0 ? {} : { links: g.links } };
|
|
11107
|
+
const walked = await access(g.fs, g.cred, target, R_OK, options).catch(() => void 0);
|
|
11108
|
+
if (!walked || walked.denied !== void 0 || walked.missing) return st;
|
|
11109
|
+
const real = await g.fs.stat(target).catch(() => void 0);
|
|
11110
|
+
if (!real?.isFile) return st;
|
|
11111
|
+
const { size, mtime } = real;
|
|
11112
|
+
return { ...st, size, mtime, atime: mtime, ctime: mtime };
|
|
11113
|
+
}
|
|
11114
|
+
|
|
10761
11115
|
// src/realm/sync-fs-token-registry.ts
|
|
10762
11116
|
var registry = /* @__PURE__ */ new Map();
|
|
10763
11117
|
function mintSyncFsToken(entry) {
|
|
@@ -10844,8 +11198,10 @@ function statJson(s) {
|
|
|
10844
11198
|
...s.gid !== void 0 ? { gid: s.gid } : {}
|
|
10845
11199
|
};
|
|
10846
11200
|
}
|
|
10847
|
-
async function readdirStat(fs, dir) {
|
|
10848
|
-
|
|
11201
|
+
async function readdirStat(fs, dir, g) {
|
|
11202
|
+
const listed = await fs.readdirStat(dir);
|
|
11203
|
+
const shown = async (name2, stat) => stat && statJson(await callerStat(g, joinName(dir, name2), stat));
|
|
11204
|
+
return Promise.all(listed.map(async ([name2, stat]) => [name2, await shown(name2, stat)]));
|
|
10849
11205
|
}
|
|
10850
11206
|
async function usageAt(entry, path) {
|
|
10851
11207
|
if (!entry.statfs) return void 0;
|
|
@@ -10914,18 +11270,22 @@ async function chown(entry, path, req) {
|
|
|
10914
11270
|
}
|
|
10915
11271
|
async function runMkdir(entry, path, req) {
|
|
10916
11272
|
const { fs } = entry;
|
|
10917
|
-
const
|
|
11273
|
+
const plain2 = plainDirMode(entry, req.mode);
|
|
10918
11274
|
const parentsMode = !req.exclusive ? plainParentsMode(entry) : void 0;
|
|
10919
11275
|
const fixParents = parentsMode !== void 0 ? await missingParents(fs, path, parentsMode) : void 0;
|
|
10920
|
-
const fresh2 =
|
|
11276
|
+
const fresh2 = plain2 !== void 0 && !await fs.exists(path);
|
|
10921
11277
|
await (req.exclusive ? mkdirExclusive(entry, path, req.mode) : fs.mkdir(path, mkdirOptions(entry, req.mode)));
|
|
10922
11278
|
await fixParents?.();
|
|
10923
|
-
if (fresh2) await fs.chmod(path,
|
|
11279
|
+
if (fresh2) await fs.chmod(path, plain2);
|
|
10924
11280
|
return done;
|
|
10925
11281
|
}
|
|
11282
|
+
async function shownAs(entry, path, st) {
|
|
11283
|
+
const real = st.isFile && st.size === 0 ? entry.fs.realpath?.(path, true) : void 0;
|
|
11284
|
+
return callerStat(guardOf(entry), await real?.catch(() => path) ?? path, st);
|
|
11285
|
+
}
|
|
10926
11286
|
function readSource(entry, path) {
|
|
10927
|
-
const
|
|
10928
|
-
return entry.source ? entry.source.read(path,
|
|
11287
|
+
const plain2 = () => entry.fs.readFileBuffer(path);
|
|
11288
|
+
return entry.source ? entry.source.read(path, plain2) : plain2();
|
|
10929
11289
|
}
|
|
10930
11290
|
async function run(entry, path, req) {
|
|
10931
11291
|
const { fs, cwd } = entry;
|
|
@@ -10938,13 +11298,13 @@ async function run(entry, path, req) {
|
|
|
10938
11298
|
case "exists":
|
|
10939
11299
|
return json2(await fs.exists(path));
|
|
10940
11300
|
case "stat":
|
|
10941
|
-
return json2(statJson(await fs.stat(path)));
|
|
11301
|
+
return json2(statJson(await shownAs(entry, path, await fs.stat(path))));
|
|
10942
11302
|
case "lstat":
|
|
10943
|
-
return json2(statJson(await fs.lstat(path)));
|
|
11303
|
+
return json2(statJson(await shownAs(entry, path, await fs.lstat(path))));
|
|
10944
11304
|
case "readdir":
|
|
10945
11305
|
return json2(await fs.readdir(path));
|
|
10946
11306
|
case "readdir-stat":
|
|
10947
|
-
return json2(await readdirStat(fs, path));
|
|
11307
|
+
return json2(await readdirStat(fs, path, guardOf(entry)));
|
|
10948
11308
|
case "mkdir":
|
|
10949
11309
|
return runMkdir(entry, path, req);
|
|
10950
11310
|
case "rm":
|
|
@@ -11866,18 +12226,18 @@ var KernelDgram = class {
|
|
|
11866
12226
|
const pending = this.takeError();
|
|
11867
12227
|
if (pending) throw new KernelError(pending);
|
|
11868
12228
|
if (this.closed) throw new KernelError("EBADF");
|
|
11869
|
-
const
|
|
11870
|
-
if (
|
|
12229
|
+
const next3 = this.queue[0];
|
|
12230
|
+
if (next3) {
|
|
11871
12231
|
if (!peek) {
|
|
11872
12232
|
this.queue.shift();
|
|
11873
|
-
this.queued -=
|
|
12233
|
+
this.queued -= next3.bytes.length;
|
|
11874
12234
|
this.changes.wake();
|
|
11875
12235
|
}
|
|
11876
12236
|
const size = Math.max(0, max);
|
|
11877
12237
|
return {
|
|
11878
|
-
bytes:
|
|
11879
|
-
from:
|
|
11880
|
-
truncated:
|
|
12238
|
+
bytes: next3.bytes.slice(0, size),
|
|
12239
|
+
from: next3.from,
|
|
12240
|
+
truncated: next3.bytes.length > size
|
|
11881
12241
|
};
|
|
11882
12242
|
}
|
|
11883
12243
|
await this.changes.wait(signal);
|
|
@@ -12196,14 +12556,6 @@ var PATH_OPS = new Set(SYNC_FS_OPS);
|
|
|
12196
12556
|
// src/realm/live-vfs-fs.ts
|
|
12197
12557
|
var EARLY_WHOLE_FILE = 64 * 1024;
|
|
12198
12558
|
|
|
12199
|
-
// src/version.ts
|
|
12200
|
-
var KERNEL_VERSION = true ? "1.103.4" : "0.0.0-dev";
|
|
12201
|
-
var OS_RELEASE = "6.0.0-slicc";
|
|
12202
|
-
function procVersion() {
|
|
12203
|
-
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
12204
|
-
`;
|
|
12205
|
-
}
|
|
12206
|
-
|
|
12207
12559
|
// src/process/process-fds.ts
|
|
12208
12560
|
var field2 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
|
|
12209
12561
|
var pinnedRoot;
|
|
@@ -12595,7 +12947,7 @@ function* procWalk(path, follow2) {
|
|
|
12595
12947
|
const whole = normalize(`/${[...done4, part, ...todo].join("/")}`);
|
|
12596
12948
|
if (inProc(at) && inProc(whole)) return broken ?? whole;
|
|
12597
12949
|
if (!follow2 && todo.length === 0) return void 0;
|
|
12598
|
-
const target = yield { at, check: todo.find((
|
|
12950
|
+
const target = yield { at, check: todo.find((next3) => next3 !== ".") === ".." };
|
|
12599
12951
|
if (typeof target === "string") {
|
|
12600
12952
|
if (++hops > MAX_HOPS3) return void 0;
|
|
12601
12953
|
[done4, todo] = throughLink(target, done4, todo);
|
|
@@ -12731,18 +13083,18 @@ function timerAfter(ms, fire) {
|
|
|
12731
13083
|
return timerAt(performance.now() + ms, fire);
|
|
12732
13084
|
}
|
|
12733
13085
|
function repeating(first, every, fire) {
|
|
12734
|
-
let
|
|
13086
|
+
let next3 = performance.now() + first;
|
|
12735
13087
|
let cancel = () => {
|
|
12736
13088
|
};
|
|
12737
13089
|
const tick = () => {
|
|
12738
13090
|
fire();
|
|
12739
13091
|
if (every <= 0) return;
|
|
12740
|
-
|
|
13092
|
+
next3 += every;
|
|
12741
13093
|
const now = performance.now();
|
|
12742
|
-
if (
|
|
12743
|
-
cancel = timerAt(
|
|
13094
|
+
if (next3 <= now) next3 += (Math.floor((now - next3) / every) + 1) * every;
|
|
13095
|
+
cancel = timerAt(next3, tick);
|
|
12744
13096
|
};
|
|
12745
|
-
cancel = timerAt(
|
|
13097
|
+
cancel = timerAt(next3, tick);
|
|
12746
13098
|
return () => cancel();
|
|
12747
13099
|
}
|
|
12748
13100
|
|
|
@@ -13033,11 +13385,11 @@ var LockTable = class {
|
|
|
13033
13385
|
}
|
|
13034
13386
|
changed(key, signal) {
|
|
13035
13387
|
return new Promise((resolve2, reject) => {
|
|
13036
|
-
const
|
|
13037
|
-
this.wakers.set(key,
|
|
13388
|
+
const set3 = this.wakers.get(key) ?? /* @__PURE__ */ new Set();
|
|
13389
|
+
this.wakers.set(key, set3);
|
|
13038
13390
|
const done4 = () => {
|
|
13039
|
-
|
|
13040
|
-
if (
|
|
13391
|
+
set3.delete(wake);
|
|
13392
|
+
if (set3.size === 0 && this.wakers.get(key) === set3) this.wakers.delete(key);
|
|
13041
13393
|
signal.removeEventListener("abort", abort);
|
|
13042
13394
|
};
|
|
13043
13395
|
const wake = () => {
|
|
@@ -13048,7 +13400,7 @@ var LockTable = class {
|
|
|
13048
13400
|
done4();
|
|
13049
13401
|
reject(new KernelError("EINTR"));
|
|
13050
13402
|
};
|
|
13051
|
-
|
|
13403
|
+
set3.add(wake);
|
|
13052
13404
|
signal.addEventListener("abort", abort, { once: true });
|
|
13053
13405
|
});
|
|
13054
13406
|
}
|
|
@@ -13349,9 +13701,10 @@ var MAX_UNREAD = 16 * 1024 * 1024;
|
|
|
13349
13701
|
function errno(code, message3) {
|
|
13350
13702
|
return Object.assign(new Error(`${code}: ${message3}`), { code });
|
|
13351
13703
|
}
|
|
13352
|
-
function requestHead(method, url, headers, extra) {
|
|
13704
|
+
function requestHead(method, url, headers, extra, first = []) {
|
|
13353
13705
|
if (!TOKEN3.test(method)) throw errno("EINVAL", `method ${method}`);
|
|
13354
|
-
const lines2 = [`${method} ${url.pathname}${url.search} HTTP/1.1`, `
|
|
13706
|
+
const lines2 = [`${method} ${url.pathname}${url.search} HTTP/1.1`, `host: ${url.host}`];
|
|
13707
|
+
for (const [name2, value] of first) lines2.push(`${name2}: ${value}`);
|
|
13355
13708
|
for (const [name2, value] of headers) {
|
|
13356
13709
|
if (OWN_HEADERS.has(name2.toLowerCase())) continue;
|
|
13357
13710
|
if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value)) throw errno("EINVAL", `header ${name2}`);
|
|
@@ -13466,8 +13819,8 @@ var KernelLoopback = class {
|
|
|
13466
13819
|
async fetch(req, port) {
|
|
13467
13820
|
const url = new URL(req.url);
|
|
13468
13821
|
const body = req.body ?? (/^(POST|PUT|PATCH)$/i.test(req.method) ? new Uint8Array(0) : void 0);
|
|
13469
|
-
const length2 = body ? [["
|
|
13470
|
-
const head = requestHead(req.method, url, req.headers,
|
|
13822
|
+
const length2 = body ? [["content-length", String(body.length)]] : [];
|
|
13823
|
+
const head = requestHead(req.method, url, req.headers, length2, [["connection", "close"]]);
|
|
13471
13824
|
const socket = await this.connect(url, port, req.signal);
|
|
13472
13825
|
try {
|
|
13473
13826
|
await writeAll2(socket, body ? concat([head, body]) : head, req.signal);
|
|
@@ -13560,7 +13913,7 @@ var LoopbackWebSocket = class {
|
|
|
13560
13913
|
const queue = [];
|
|
13561
13914
|
let wake;
|
|
13562
13915
|
let ended = false;
|
|
13563
|
-
void this.pump(
|
|
13916
|
+
void this.pump(incoming, (message3) => {
|
|
13564
13917
|
queue.push(message3);
|
|
13565
13918
|
this.unread += message3.length;
|
|
13566
13919
|
wake?.();
|
|
@@ -13577,10 +13930,10 @@ var LoopbackWebSocket = class {
|
|
|
13577
13930
|
this.messages = {
|
|
13578
13931
|
[Symbol.asyncIterator]: async function* () {
|
|
13579
13932
|
for (; ; ) {
|
|
13580
|
-
const
|
|
13581
|
-
if (
|
|
13582
|
-
taken(
|
|
13583
|
-
yield
|
|
13933
|
+
const next3 = queue.shift();
|
|
13934
|
+
if (next3 !== void 0) {
|
|
13935
|
+
taken(next3);
|
|
13936
|
+
yield next3;
|
|
13584
13937
|
continue;
|
|
13585
13938
|
}
|
|
13586
13939
|
if (ended) return;
|
|
@@ -13615,7 +13968,8 @@ var LoopbackWebSocket = class {
|
|
|
13615
13968
|
this.pending -= bytes.length;
|
|
13616
13969
|
})();
|
|
13617
13970
|
}
|
|
13618
|
-
async pump(
|
|
13971
|
+
async pump(incoming, deliver) {
|
|
13972
|
+
const reader = new WsReader(incoming, void 0, true, true);
|
|
13619
13973
|
let close = { code: 1006, reason: "", wasClean: false };
|
|
13620
13974
|
try {
|
|
13621
13975
|
for (; ; ) {
|
|
@@ -13637,11 +13991,18 @@ var LoopbackWebSocket = class {
|
|
|
13637
13991
|
} finally {
|
|
13638
13992
|
const late = setTimeout(() => this.stop.abort(), CLOSE_WAIT_MS3);
|
|
13639
13993
|
await this.writes;
|
|
13994
|
+
if (close.wasClean) await this.serverEnd(incoming);
|
|
13640
13995
|
clearTimeout(late);
|
|
13641
13996
|
this.socket.close();
|
|
13642
13997
|
this.settle(close);
|
|
13643
13998
|
}
|
|
13644
13999
|
}
|
|
14000
|
+
async serverEnd(incoming) {
|
|
14001
|
+
try {
|
|
14002
|
+
while ((await incoming.some(64 * 1024, this.stop.signal)).length > 0) ;
|
|
14003
|
+
} catch {
|
|
14004
|
+
}
|
|
14005
|
+
}
|
|
13645
14006
|
sendClose(code, reason) {
|
|
13646
14007
|
if (this.sentClose) return;
|
|
13647
14008
|
this.sentClose = true;
|
|
@@ -13690,9 +14051,9 @@ var WsHandles = class {
|
|
|
13690
14051
|
open = /* @__PURE__ */ new Map();
|
|
13691
14052
|
next;
|
|
13692
14053
|
local;
|
|
13693
|
-
constructor(transport,
|
|
14054
|
+
constructor(transport, next3, local) {
|
|
13694
14055
|
this.transport = transport;
|
|
13695
|
-
this.next =
|
|
14056
|
+
this.next = next3;
|
|
13696
14057
|
this.local = local;
|
|
13697
14058
|
}
|
|
13698
14059
|
owns(handle) {
|
|
@@ -13754,9 +14115,9 @@ var WsHandles = class {
|
|
|
13754
14115
|
}
|
|
13755
14116
|
async recv(socket, entry) {
|
|
13756
14117
|
try {
|
|
13757
|
-
const
|
|
13758
|
-
if (!
|
|
13759
|
-
return typeof
|
|
14118
|
+
const next3 = await entry.messages.next();
|
|
14119
|
+
if (!next3.done) {
|
|
14120
|
+
return typeof next3.value === "string" ? { ok: true, kind: "json", json: { text: next3.value } } : { ok: true, kind: "bytes", bytes: next3.value };
|
|
13760
14121
|
}
|
|
13761
14122
|
const closed = await socket.closed;
|
|
13762
14123
|
return {
|
|
@@ -13804,11 +14165,49 @@ var HTTP_OPS = [
|
|
|
13804
14165
|
"net-open",
|
|
13805
14166
|
"net-head",
|
|
13806
14167
|
"net-read",
|
|
14168
|
+
"net-write",
|
|
14169
|
+
"net-end",
|
|
13807
14170
|
"net-close",
|
|
13808
14171
|
"net-traits",
|
|
13809
14172
|
...WS_OPS
|
|
13810
14173
|
];
|
|
13811
|
-
var
|
|
14174
|
+
var Upload = class {
|
|
14175
|
+
queue = [];
|
|
14176
|
+
ended = false;
|
|
14177
|
+
wake;
|
|
14178
|
+
write(bytes) {
|
|
14179
|
+
if (this.ended) return Promise.resolve(false);
|
|
14180
|
+
return new Promise((taken) => {
|
|
14181
|
+
this.queue.push({ bytes, taken });
|
|
14182
|
+
this.wake?.();
|
|
14183
|
+
});
|
|
14184
|
+
}
|
|
14185
|
+
end() {
|
|
14186
|
+
this.ended = true;
|
|
14187
|
+
this.wake?.();
|
|
14188
|
+
}
|
|
14189
|
+
cancel() {
|
|
14190
|
+
this.ended = true;
|
|
14191
|
+
for (const { taken } of this.queue.splice(0)) taken(false);
|
|
14192
|
+
this.wake?.();
|
|
14193
|
+
}
|
|
14194
|
+
async *[Symbol.asyncIterator]() {
|
|
14195
|
+
for (; ; ) {
|
|
14196
|
+
const next3 = this.queue.shift();
|
|
14197
|
+
if (next3) {
|
|
14198
|
+
next3.taken(true);
|
|
14199
|
+
yield next3.bytes;
|
|
14200
|
+
continue;
|
|
14201
|
+
}
|
|
14202
|
+
if (this.ended) return;
|
|
14203
|
+
await new Promise((resolve2) => {
|
|
14204
|
+
this.wake = resolve2;
|
|
14205
|
+
});
|
|
14206
|
+
this.wake = void 0;
|
|
14207
|
+
}
|
|
14208
|
+
}
|
|
14209
|
+
};
|
|
14210
|
+
var EMPTY2 = new Uint8Array(0);
|
|
13812
14211
|
function message2(e) {
|
|
13813
14212
|
return e instanceof Error ? e.message : String(e);
|
|
13814
14213
|
}
|
|
@@ -13838,6 +14237,8 @@ var HttpHandles = class {
|
|
|
13838
14237
|
if (req.op === "net-open") return Promise.resolve(this.opened(req));
|
|
13839
14238
|
if (req.op === "net-head") return this.head(req.handle);
|
|
13840
14239
|
if (req.op === "net-read") return this.read(req.handle, req.max);
|
|
14240
|
+
if (req.op === "net-write") return this.write(req.handle, req.bytes);
|
|
14241
|
+
if (req.op === "net-end") return Promise.resolve(this.end(req.handle));
|
|
13841
14242
|
if (req.op === "net-traits") return Promise.resolve(this.traits(req.url));
|
|
13842
14243
|
return this.close(req.handle);
|
|
13843
14244
|
}
|
|
@@ -13856,19 +14257,37 @@ var HttpHandles = class {
|
|
|
13856
14257
|
return result;
|
|
13857
14258
|
}
|
|
13858
14259
|
opened(req) {
|
|
14260
|
+
if (req.stream && (this.local?.port(req.url) !== void 0 || !this.transport.traits.streamingBodies)) {
|
|
14261
|
+
return { ok: false, errno: "ENOTSUP", message: "this transport takes whole request bodies" };
|
|
14262
|
+
}
|
|
13859
14263
|
return { ok: true, kind: "json", json: this.start(req).handle };
|
|
13860
14264
|
}
|
|
14265
|
+
async write(handle, bytes) {
|
|
14266
|
+
const upload = this.open.get(handle)?.upload;
|
|
14267
|
+
if (!upload) return { ok: false, errno: "EBADF", message: `no upload ${handle}` };
|
|
14268
|
+
if (!await upload.write(bytes)) {
|
|
14269
|
+
return { ok: false, errno: "EPIPE", message: "the request no longer takes a body" };
|
|
14270
|
+
}
|
|
14271
|
+
return { ok: true, kind: "void" };
|
|
14272
|
+
}
|
|
14273
|
+
end(handle) {
|
|
14274
|
+
const upload = this.open.get(handle)?.upload;
|
|
14275
|
+
if (!upload) return { ok: false, errno: "EBADF", message: `no upload ${handle}` };
|
|
14276
|
+
upload.end();
|
|
14277
|
+
return { ok: true, kind: "void" };
|
|
14278
|
+
}
|
|
13861
14279
|
start(req) {
|
|
13862
14280
|
const handle = ++this.nextHandle;
|
|
13863
14281
|
const abort = new AbortController();
|
|
13864
14282
|
const entry = {
|
|
13865
14283
|
abort,
|
|
13866
14284
|
head: Promise.resolve({ ok: true, kind: "void" }),
|
|
13867
|
-
body: once(
|
|
13868
|
-
left:
|
|
14285
|
+
body: once(EMPTY2),
|
|
14286
|
+
left: EMPTY2,
|
|
13869
14287
|
done: false,
|
|
13870
14288
|
reading: Promise.resolve(),
|
|
13871
|
-
cancel: async () => void 0
|
|
14289
|
+
cancel: async () => void 0,
|
|
14290
|
+
...req.stream ? { upload: new Upload() } : {}
|
|
13872
14291
|
};
|
|
13873
14292
|
this.open.set(handle, entry);
|
|
13874
14293
|
entry.head = this.respond(handle, req, entry);
|
|
@@ -13882,7 +14301,7 @@ var HttpHandles = class {
|
|
|
13882
14301
|
url: target,
|
|
13883
14302
|
method: req.method,
|
|
13884
14303
|
headers: req.headers,
|
|
13885
|
-
...req.body ? { body: req.body } : {},
|
|
14304
|
+
...entry.upload ? { bodyStream: entry.upload } : req.body ? { body: req.body } : {},
|
|
13886
14305
|
signal: entry.abort.signal
|
|
13887
14306
|
};
|
|
13888
14307
|
const response = port === void 0 ? await this.transport.fetch(request2, this.owner) : await this.local.fetch(request2, port);
|
|
@@ -13893,6 +14312,7 @@ var HttpHandles = class {
|
|
|
13893
14312
|
const head = this.headOf(handle, shown, response);
|
|
13894
14313
|
return response.redirected ? { ...head, json: { ...head.json, redirected: true } } : head;
|
|
13895
14314
|
} catch (e) {
|
|
14315
|
+
entry.upload?.cancel();
|
|
13896
14316
|
const text = message2(e);
|
|
13897
14317
|
if (port !== void 0) return { ok: false, errno: codeOf2(e), message: text };
|
|
13898
14318
|
const status = e.status;
|
|
@@ -13929,9 +14349,9 @@ var HttpHandles = class {
|
|
|
13929
14349
|
async take(entry, max) {
|
|
13930
14350
|
if (entry.left.length === 0 && !entry.done) {
|
|
13931
14351
|
try {
|
|
13932
|
-
const
|
|
13933
|
-
if (
|
|
13934
|
-
else entry.left =
|
|
14352
|
+
const next3 = await entry.body.next();
|
|
14353
|
+
if (next3.done) entry.done = true;
|
|
14354
|
+
else entry.left = next3.value;
|
|
13935
14355
|
} catch (e) {
|
|
13936
14356
|
entry.done = true;
|
|
13937
14357
|
const timedOut = e?.code === "ETIMEDOUT";
|
|
@@ -13950,6 +14370,7 @@ var HttpHandles = class {
|
|
|
13950
14370
|
const entry = this.open.get(handle);
|
|
13951
14371
|
if (!entry) return { ok: false, errno: "EBADF", message: `no request ${handle}` };
|
|
13952
14372
|
this.open.delete(handle);
|
|
14373
|
+
entry.upload?.cancel();
|
|
13953
14374
|
entry.abort.abort();
|
|
13954
14375
|
await entry.cancel().catch(() => void 0);
|
|
13955
14376
|
return { ok: true, kind: "void" };
|
|
@@ -14304,12 +14725,12 @@ var KernelTty = class {
|
|
|
14304
14725
|
const chunks = [];
|
|
14305
14726
|
let n = 0;
|
|
14306
14727
|
while (this.readable.length > 0 && n < max) {
|
|
14307
|
-
const
|
|
14308
|
-
if (
|
|
14309
|
-
const take =
|
|
14728
|
+
const next3 = this.readable[0];
|
|
14729
|
+
if (next3 === null || next3 === void 0) break;
|
|
14730
|
+
const take = next3.subarray(0, max - n);
|
|
14310
14731
|
chunks.push(take);
|
|
14311
14732
|
n += take.length;
|
|
14312
|
-
if (take.length <
|
|
14733
|
+
if (take.length < next3.length) this.readable[0] = next3.subarray(take.length);
|
|
14313
14734
|
else this.readable.shift();
|
|
14314
14735
|
if (this.canonical) break;
|
|
14315
14736
|
}
|
|
@@ -14406,11 +14827,11 @@ var PtyPair = class {
|
|
|
14406
14827
|
const chunks = [];
|
|
14407
14828
|
let n = 0;
|
|
14408
14829
|
while (this.queue.length > 0 && n < max - status) {
|
|
14409
|
-
const
|
|
14410
|
-
const take =
|
|
14830
|
+
const next3 = this.queue[0];
|
|
14831
|
+
const take = next3.subarray(0, max - status - n);
|
|
14411
14832
|
chunks.push(take);
|
|
14412
14833
|
n += take.length;
|
|
14413
|
-
if (take.length <
|
|
14834
|
+
if (take.length < next3.length) this.queue[0] = next3.subarray(take.length);
|
|
14414
14835
|
else this.queue.shift();
|
|
14415
14836
|
}
|
|
14416
14837
|
const out = new Uint8Array(status + n);
|
|
@@ -14730,8 +15151,8 @@ var Semaphore = class {
|
|
|
14730
15151
|
this.mode = mode;
|
|
14731
15152
|
}
|
|
14732
15153
|
post() {
|
|
14733
|
-
const
|
|
14734
|
-
if (
|
|
15154
|
+
const next3 = this.waiters.shift();
|
|
15155
|
+
if (next3) next3.grant();
|
|
14735
15156
|
else if (this.value >= SEM_VALUE_MAX) throw new KernelError("EOVERFLOW");
|
|
14736
15157
|
else this.value++;
|
|
14737
15158
|
}
|
|
@@ -15159,9 +15580,9 @@ var VfsNode = class {
|
|
|
15159
15580
|
if (dirty && contents2 !== void 0) this.markDirty();
|
|
15160
15581
|
}
|
|
15161
15582
|
serial(op) {
|
|
15162
|
-
const
|
|
15163
|
-
this.queue =
|
|
15164
|
-
return
|
|
15583
|
+
const next3 = this.queue.then(op);
|
|
15584
|
+
this.queue = next3.catch(() => void 0);
|
|
15585
|
+
return next3;
|
|
15165
15586
|
}
|
|
15166
15587
|
revoke() {
|
|
15167
15588
|
this.revoked = true;
|
|
@@ -15583,9 +16004,9 @@ var VfsNodes = class {
|
|
|
15583
16004
|
}
|
|
15584
16005
|
for (const [p] of moved2) this.byPath.delete(p);
|
|
15585
16006
|
for (const [p, node] of moved2) {
|
|
15586
|
-
const
|
|
15587
|
-
if (node.path === p) node.renamedTo(
|
|
15588
|
-
this.byPath.set(
|
|
16007
|
+
const next3 = to + p.slice(from.length);
|
|
16008
|
+
if (node.path === p) node.renamedTo(next3);
|
|
16009
|
+
this.byPath.set(next3, node);
|
|
15589
16010
|
}
|
|
15590
16011
|
}
|
|
15591
16012
|
};
|
|
@@ -15960,6 +16381,7 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
15960
16381
|
"tty-pgrp-get",
|
|
15961
16382
|
"tty-pgrp-set",
|
|
15962
16383
|
"sig-mask",
|
|
16384
|
+
"sig-waiting",
|
|
15963
16385
|
"sig-pause",
|
|
15964
16386
|
...SOCKET_OPS,
|
|
15965
16387
|
...EPOLL_OPS,
|
|
@@ -16073,16 +16495,8 @@ var WasmProcess = class {
|
|
|
16073
16495
|
if (sig === SIG.STOP) return this.stop(sig);
|
|
16074
16496
|
const bit = sigbit(sig);
|
|
16075
16497
|
if (this.ignores(bit)) return "ignore";
|
|
16076
|
-
if (((this.options.blockedBits?.() ?? 0) & bit) !== 0) {
|
|
16077
|
-
|
|
16078
|
-
if (tid === void 0) {
|
|
16079
|
-
this.options.onPending?.(sig);
|
|
16080
|
-
return "deliver";
|
|
16081
|
-
}
|
|
16082
|
-
if (this.caught & bit) {
|
|
16083
|
-
this.options.threadKill?.(tid, sig);
|
|
16084
|
-
return "deliver";
|
|
16085
|
-
}
|
|
16498
|
+
if (((this.options.blockedBits?.() ?? 0) & bit) !== 0 && this.routeBlocked(sig, bit)) {
|
|
16499
|
+
return "deliver";
|
|
16086
16500
|
}
|
|
16087
16501
|
if (!(this.caught & bit)) {
|
|
16088
16502
|
const action = defaultAction(sig);
|
|
@@ -16099,6 +16513,17 @@ var WasmProcess = class {
|
|
|
16099
16513
|
blocked2.abort();
|
|
16100
16514
|
return "deliver";
|
|
16101
16515
|
}
|
|
16516
|
+
routeBlocked(sig, bit) {
|
|
16517
|
+
const waiter = this.waiterFor(bit);
|
|
16518
|
+
const tid = waiter ?? this.options.unblockedThread?.(sig);
|
|
16519
|
+
if (tid === void 0 || tid === 1) {
|
|
16520
|
+
this.options.onPending?.(sig);
|
|
16521
|
+
return true;
|
|
16522
|
+
}
|
|
16523
|
+
if (waiter === void 0 && !(this.caught & bit)) return false;
|
|
16524
|
+
this.options.threadKill?.(tid, sig);
|
|
16525
|
+
return true;
|
|
16526
|
+
}
|
|
16102
16527
|
async spawn(req) {
|
|
16103
16528
|
const { file, argv, argv0, env, cwd, chdir, stdio, inherit: inherit2, exec, pgid, session, deathSignal } = req;
|
|
16104
16529
|
if (deathSignal !== void 0 && (exec || !isSignal(deathSignal))) {
|
|
@@ -16179,6 +16604,16 @@ var WasmProcess = class {
|
|
|
16179
16604
|
}
|
|
16180
16605
|
blocks = /* @__PURE__ */ new WeakMap();
|
|
16181
16606
|
sizesRead = /* @__PURE__ */ new WeakMap();
|
|
16607
|
+
sigwaiters = /* @__PURE__ */ new Map();
|
|
16608
|
+
setSigwaiter(tid, set3) {
|
|
16609
|
+
if (set3 === 0) this.sigwaiters.delete(tid);
|
|
16610
|
+
else this.sigwaiters.set(tid, set3);
|
|
16611
|
+
}
|
|
16612
|
+
waiterFor(bit) {
|
|
16613
|
+
if (((this.sigwaiters.get(1) ?? 0) & bit) !== 0) return 1;
|
|
16614
|
+
for (const [tid, set3] of this.sigwaiters) if (set3 & bit) return tid;
|
|
16615
|
+
return void 0;
|
|
16616
|
+
}
|
|
16182
16617
|
async syscall(req, cancelled, block) {
|
|
16183
16618
|
this.options.onSyscall?.(req);
|
|
16184
16619
|
const started = performance.now();
|
|
@@ -16435,18 +16870,18 @@ var WasmProcess = class {
|
|
|
16435
16870
|
}
|
|
16436
16871
|
if (this.writesAt(req) && this.options.readonlyAt?.(path)) throw new KernelError("EROFS");
|
|
16437
16872
|
const open = { ...req, path };
|
|
16438
|
-
const
|
|
16873
|
+
const plain2 = this.plainMode(req.mode);
|
|
16439
16874
|
if (req.exclusive) {
|
|
16440
16875
|
await nodes.createExclusive(path, this.newOwner(req.mode));
|
|
16441
|
-
if (
|
|
16876
|
+
if (plain2 !== void 0) await fs.chmod?.(path, plain2);
|
|
16442
16877
|
this.fds.installAt(fd, this.openVfsFile(open, void 0, fs));
|
|
16443
16878
|
} else if (req.create) {
|
|
16444
16879
|
await nodes.onEntry(path, async () => {
|
|
16445
|
-
const marks = this.options.owners ||
|
|
16880
|
+
const marks = this.options.owners || plain2 !== void 0;
|
|
16446
16881
|
const fresh2 = marks && !await present2(fs, path, true);
|
|
16447
16882
|
this.fds.installAt(fd, this.openVfsFile(open, await nodes.identify(path), fs));
|
|
16448
16883
|
await this.fds.get(fd).file.stat?.();
|
|
16449
|
-
if (fresh2 &&
|
|
16884
|
+
if (fresh2 && plain2 !== void 0) await fs.chmod?.(path, plain2);
|
|
16450
16885
|
else if (fresh2) {
|
|
16451
16886
|
await fs.chown?.(path, { ...this.newOwner(req.mode), kind: "new" });
|
|
16452
16887
|
}
|
|
@@ -17087,6 +17522,9 @@ var WasmProcess = class {
|
|
|
17087
17522
|
case "dl-unlock":
|
|
17088
17523
|
this.unlockDl(req.owner);
|
|
17089
17524
|
return { ok: true, kind: "void" };
|
|
17525
|
+
case "sig-waiting":
|
|
17526
|
+
this.setSigwaiter(req.tid, req.set);
|
|
17527
|
+
return { ok: true, kind: "void" };
|
|
17090
17528
|
case "sig-mask":
|
|
17091
17529
|
this.caught = req.caught;
|
|
17092
17530
|
this.ignored = req.ignored;
|
|
@@ -17154,8 +17592,8 @@ var WasmProcess = class {
|
|
|
17154
17592
|
};
|
|
17155
17593
|
withDl(state) {
|
|
17156
17594
|
if (this.dlLog.length === 0) return state;
|
|
17157
|
-
const { next:
|
|
17158
|
-
const dl = { log: [...this.dlLog], next:
|
|
17595
|
+
const { next: next3, handle, free, live } = this.closures;
|
|
17596
|
+
const dl = { log: [...this.dlLog], next: next3, handle, free: [...free], live: [...live] };
|
|
17159
17597
|
return { ...state, dl };
|
|
17160
17598
|
}
|
|
17161
17599
|
seedDl(dl) {
|
|
@@ -17166,8 +17604,8 @@ var WasmProcess = class {
|
|
|
17166
17604
|
this.closures.free.push(...dl.free);
|
|
17167
17605
|
for (const index of dl.live) this.closures.live.add(index);
|
|
17168
17606
|
}
|
|
17169
|
-
allocateClosure(
|
|
17170
|
-
const index = this.closures.free.pop() ?? Math.max(
|
|
17607
|
+
allocateClosure(floor2) {
|
|
17608
|
+
const index = this.closures.free.pop() ?? Math.max(floor2, this.closures.next);
|
|
17171
17609
|
this.closures.next = Math.max(this.closures.next, index + 1);
|
|
17172
17610
|
this.closures.live.add(index);
|
|
17173
17611
|
this.dlLog.push({ kind: "closure", index });
|
|
@@ -17219,8 +17657,8 @@ var WasmProcess = class {
|
|
|
17219
17657
|
wakeDl() {
|
|
17220
17658
|
for (const waiter of [...this.dlLock.waiters]) waiter.wake(false);
|
|
17221
17659
|
}
|
|
17222
|
-
reserveSlots(
|
|
17223
|
-
const base = Math.max(
|
|
17660
|
+
reserveSlots(floor2, size) {
|
|
17661
|
+
const base = Math.max(floor2, this.closures.next);
|
|
17224
17662
|
this.closures.next = base + size;
|
|
17225
17663
|
return base;
|
|
17226
17664
|
}
|
|
@@ -17277,6 +17715,7 @@ var WASM_MAX_THREADS = 256;
|
|
|
17277
17715
|
// src/kernel/host.ts
|
|
17278
17716
|
var CRASHED = 70;
|
|
17279
17717
|
var KILL_GRACE_MS = 2e3;
|
|
17718
|
+
var KILL_HARD_MS = 5e3;
|
|
17280
17719
|
var descIds = /* @__PURE__ */ new WeakMap();
|
|
17281
17720
|
var nextDescId = 1;
|
|
17282
17721
|
function descId(file) {
|
|
@@ -17303,16 +17742,21 @@ function inheritedFds(fds) {
|
|
|
17303
17742
|
var Dying = class {
|
|
17304
17743
|
ending;
|
|
17305
17744
|
timer;
|
|
17745
|
+
hard;
|
|
17306
17746
|
busy = 0;
|
|
17307
17747
|
finish;
|
|
17308
17748
|
start(code, sig, header3, process, finish) {
|
|
17309
17749
|
if (this.ending) return;
|
|
17310
17750
|
this.ending = { code, sig };
|
|
17311
17751
|
this.finish = finish;
|
|
17752
|
+
this.hard = setTimeout(finish, KILL_HARD_MS);
|
|
17312
17753
|
this.arm();
|
|
17313
17754
|
Atomics.store(header3, SAB_I_KILLED, code);
|
|
17314
17755
|
process.die();
|
|
17315
17756
|
}
|
|
17757
|
+
serve(req, work) {
|
|
17758
|
+
return this.ending && isWasmSyscall(req) ? work() : this.serving(work);
|
|
17759
|
+
}
|
|
17316
17760
|
async serving(work) {
|
|
17317
17761
|
this.busy++;
|
|
17318
17762
|
clearTimeout(this.timer);
|
|
@@ -17329,6 +17773,7 @@ var Dying = class {
|
|
|
17329
17773
|
}
|
|
17330
17774
|
clear() {
|
|
17331
17775
|
clearTimeout(this.timer);
|
|
17776
|
+
clearTimeout(this.hard);
|
|
17332
17777
|
}
|
|
17333
17778
|
status(reported2) {
|
|
17334
17779
|
if (this.ending) return [this.ending.code, this.ending.sig];
|
|
@@ -17340,8 +17785,8 @@ function killThread(thread, caught, sig) {
|
|
|
17340
17785
|
const held = (Atomics.load(thread.header, SAB_I_BLOCKED) & sigbit(sig)) !== 0;
|
|
17341
17786
|
if (!held && (caught & sigbit(sig)) === 0) return false;
|
|
17342
17787
|
Atomics.or(thread.header, SAB_I_SIGNALS, sigbit(sig));
|
|
17343
|
-
if (held) return true;
|
|
17344
17788
|
Atomics.notify(thread.header, SAB_I_SIGNALS);
|
|
17789
|
+
if (held) return true;
|
|
17345
17790
|
const blocked2 = thread.interrupt;
|
|
17346
17791
|
thread.interrupt = new AbortController();
|
|
17347
17792
|
blocked2.abort();
|
|
@@ -17437,7 +17882,7 @@ function inherited(opts) {
|
|
|
17437
17882
|
...opts.cred ? { cred: opts.cred } : {}
|
|
17438
17883
|
};
|
|
17439
17884
|
}
|
|
17440
|
-
function holdingToken(opts,
|
|
17885
|
+
function holdingToken(opts, holds2, caller) {
|
|
17441
17886
|
return mintSyncFsToken({
|
|
17442
17887
|
...opts.owners ? caller : { umask: caller.umask },
|
|
17443
17888
|
...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
|
|
@@ -17448,13 +17893,13 @@ function holdingToken(opts, holds, caller) {
|
|
|
17448
17893
|
noLinks: opts.noLinks,
|
|
17449
17894
|
cwd: opts.cwd,
|
|
17450
17895
|
...opts.statfs ? { statfs: opts.statfs } : {},
|
|
17451
|
-
hold: (path, on, open, real, handle) =>
|
|
17452
|
-
keptFor: (handle) =>
|
|
17453
|
-
unlinked: (path) =>
|
|
17454
|
-
gate: (path, op) => opts.unlinkGate &&
|
|
17455
|
-
own: (path, op) =>
|
|
17456
|
-
revoked: (path) =>
|
|
17457
|
-
renamed: (from, to) =>
|
|
17896
|
+
hold: (path, on, open, real, handle) => holds2.hold(path, on, open, real, handle),
|
|
17897
|
+
keptFor: (handle) => holds2.keptFor(handle),
|
|
17898
|
+
unlinked: (path) => holds2.keptAt(path),
|
|
17899
|
+
gate: (path, op) => opts.unlinkGate && holds2.holding(path) ? opts.unlinkGate.run(holds2.keyOf(path), op) : op(),
|
|
17900
|
+
own: (path, op) => holds2.own(path, op),
|
|
17901
|
+
revoked: (path) => holds2.isRevoked(path),
|
|
17902
|
+
renamed: (from, to) => holds2.renamed(from, to)
|
|
17458
17903
|
});
|
|
17459
17904
|
}
|
|
17460
17905
|
function linksOf(opts) {
|
|
@@ -17528,6 +17973,9 @@ function threadInit(opts, program, sab, cred, thread, main) {
|
|
|
17528
17973
|
signals: main
|
|
17529
17974
|
};
|
|
17530
17975
|
}
|
|
17976
|
+
function settleExit(exit, settle3, code) {
|
|
17977
|
+
void exit.catch(() => void 0).then(() => settle3(code & 255));
|
|
17978
|
+
}
|
|
17531
17979
|
function spawnWasmProcess(opts) {
|
|
17532
17980
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
17533
17981
|
const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
@@ -17554,19 +18002,20 @@ function spawnWasmProcess(opts) {
|
|
|
17554
18002
|
)
|
|
17555
18003
|
);
|
|
17556
18004
|
publishStops(process, header3);
|
|
17557
|
-
const
|
|
17558
|
-
opts.held?.add(
|
|
17559
|
-
const token = holdingToken(opts,
|
|
18005
|
+
const holds2 = new HeldPaths();
|
|
18006
|
+
opts.held?.add(holds2);
|
|
18007
|
+
const token = holdingToken(opts, holds2, {
|
|
17560
18008
|
cred: () => process.cred,
|
|
17561
18009
|
umask: () => process.umask,
|
|
17562
18010
|
created: created3,
|
|
17563
|
-
holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (
|
|
18011
|
+
holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (holds2.keeps(path) || await process.holds(path))
|
|
17564
18012
|
});
|
|
17565
|
-
process.keptPath = (path) =>
|
|
17566
|
-
process.keptHandle = (handle2) =>
|
|
18013
|
+
process.keptPath = (path) => holds2.keptAt(path)?.hidden;
|
|
18014
|
+
process.keptHandle = (handle2) => holds2.keptFor(handle2)?.hidden;
|
|
17567
18015
|
const worker = opts.createWorker();
|
|
17568
18016
|
const dying = new Dying();
|
|
17569
|
-
const dispatch2 = (req, block) => dying.
|
|
18017
|
+
const dispatch2 = (req, block) => dying.serve(
|
|
18018
|
+
req,
|
|
17570
18019
|
() => isWasmSyscall(req) ? process.syscall(req, void 0, block) : dispatchSyncFs(req)
|
|
17571
18020
|
);
|
|
17572
18021
|
const clocks = new ProcessClocks(sab, opts.program.abi !== "js", process);
|
|
@@ -17589,12 +18038,9 @@ function spawnWasmProcess(opts) {
|
|
|
17589
18038
|
responder.dispose();
|
|
17590
18039
|
lane?.dispose();
|
|
17591
18040
|
revokeSyncFsToken(token);
|
|
17592
|
-
opts.held?.delete(
|
|
18041
|
+
opts.held?.delete(holds2);
|
|
17593
18042
|
worker.terminate();
|
|
17594
|
-
|
|
17595
|
-
() => settle3(code),
|
|
17596
|
-
() => settle3(code)
|
|
17597
|
-
);
|
|
18043
|
+
settleExit(process.exit(), settle3, code);
|
|
17598
18044
|
};
|
|
17599
18045
|
const exitNow = (code) => {
|
|
17600
18046
|
queueMicrotask(() => finish(...dying.status(code)));
|
|
@@ -17638,7 +18084,7 @@ function spawnWasmProcess(opts) {
|
|
|
17638
18084
|
const tsignals = threadSignalsOf(tsab);
|
|
17639
18085
|
if (thread.blocked) storeBlocked(tsignals.header, thread.blocked);
|
|
17640
18086
|
threadSignals.set(thread.tid, tsignals);
|
|
17641
|
-
const tdispatch = (req, block) => dying.
|
|
18087
|
+
const tdispatch = (req, block) => dying.serve(req, () => threadCall(process, req, threadCancel(tsignals), block));
|
|
17642
18088
|
const tresponder = attachSyncSabResponder(tw, tsab, token, {
|
|
17643
18089
|
dispatch: clocks.timed(clocks.thread(thread.tid, tsab), tdispatch)
|
|
17644
18090
|
});
|
|
@@ -18108,10 +18554,10 @@ var Automaton = class {
|
|
|
18108
18554
|
let node = 0;
|
|
18109
18555
|
for (const byte of bytes) {
|
|
18110
18556
|
const key = node * 256 + byte;
|
|
18111
|
-
let
|
|
18112
|
-
if (
|
|
18113
|
-
|
|
18114
|
-
this.edges.set(key,
|
|
18557
|
+
let next3 = this.edges.get(key);
|
|
18558
|
+
if (next3 === void 0) {
|
|
18559
|
+
next3 = this.depth.length;
|
|
18560
|
+
this.edges.set(key, next3);
|
|
18115
18561
|
this.fail.push(0);
|
|
18116
18562
|
this.depth.push(this.depth[node] + 1);
|
|
18117
18563
|
this.children.push(0);
|
|
@@ -18119,7 +18565,7 @@ var Automaton = class {
|
|
|
18119
18565
|
this.out.push([]);
|
|
18120
18566
|
this.dict.push(-1);
|
|
18121
18567
|
}
|
|
18122
|
-
node =
|
|
18568
|
+
node = next3;
|
|
18123
18569
|
}
|
|
18124
18570
|
const id2 = this.lengths.length;
|
|
18125
18571
|
this.lengths.push(bytes.length);
|
|
@@ -18155,8 +18601,8 @@ var Automaton = class {
|
|
|
18155
18601
|
step(state, byte) {
|
|
18156
18602
|
let current = state;
|
|
18157
18603
|
for (; ; ) {
|
|
18158
|
-
const
|
|
18159
|
-
if (
|
|
18604
|
+
const next3 = this.edges.get(current * 256 + byte);
|
|
18605
|
+
if (next3 !== void 0) return next3;
|
|
18160
18606
|
if (current === 0) return 0;
|
|
18161
18607
|
current = this.fail[current];
|
|
18162
18608
|
}
|
|
@@ -18184,7 +18630,7 @@ var RANK = {
|
|
|
18184
18630
|
};
|
|
18185
18631
|
var CR2 = 13;
|
|
18186
18632
|
var LF2 = 10;
|
|
18187
|
-
var
|
|
18633
|
+
var EMPTY3 = new Uint8Array(0);
|
|
18188
18634
|
function register(automaton, sources, ids, bytes, source) {
|
|
18189
18635
|
const key = Array.from(bytes).join(",");
|
|
18190
18636
|
let id2 = ids.get(key);
|
|
@@ -18310,7 +18756,7 @@ function pass(c, input, final) {
|
|
|
18310
18756
|
const partials = [];
|
|
18311
18757
|
scanMain(c, input, best, partials);
|
|
18312
18758
|
scanWrapped(c, input, best, partials);
|
|
18313
|
-
const
|
|
18759
|
+
const holds2 = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
|
|
18314
18760
|
const starts = [...best.keys()].sort((a, b) => a - b);
|
|
18315
18761
|
const parts2 = [];
|
|
18316
18762
|
const hits = /* @__PURE__ */ new Map();
|
|
@@ -18320,16 +18766,16 @@ function pass(c, input, final) {
|
|
|
18320
18766
|
let h = 0;
|
|
18321
18767
|
for (; ; ) {
|
|
18322
18768
|
while (s < starts.length && starts[s] < pos) s++;
|
|
18323
|
-
while (h <
|
|
18324
|
-
const hold = h <
|
|
18325
|
-
const
|
|
18326
|
-
if (hold <=
|
|
18769
|
+
while (h < holds2.length && holds2[h] < pos) h++;
|
|
18770
|
+
const hold = h < holds2.length ? holds2[h] : Infinity;
|
|
18771
|
+
const next3 = s < starts.length ? starts[s] : Infinity;
|
|
18772
|
+
if (hold <= next3) {
|
|
18327
18773
|
cut = Math.min(hold, input.length);
|
|
18328
18774
|
break;
|
|
18329
18775
|
}
|
|
18330
|
-
const candidate = best.get(
|
|
18776
|
+
const candidate = best.get(next3);
|
|
18331
18777
|
parts2.push(
|
|
18332
|
-
input.subarray(pos,
|
|
18778
|
+
input.subarray(pos, next3),
|
|
18333
18779
|
c.replacements[candidate.secret][candidate.form === "raw" ? 0 : 1]
|
|
18334
18780
|
);
|
|
18335
18781
|
count(c, hits, candidate);
|
|
@@ -18364,12 +18810,12 @@ function compile(secrets, options = {}) {
|
|
|
18364
18810
|
return { text: decoder4.decode(bytes), hits };
|
|
18365
18811
|
},
|
|
18366
18812
|
stream() {
|
|
18367
|
-
let pending =
|
|
18813
|
+
let pending = EMPTY3;
|
|
18368
18814
|
const hits = /* @__PURE__ */ new Map();
|
|
18369
18815
|
const run2 = (final) => {
|
|
18370
18816
|
if (c.secrets.length === 0 || pending.length === 0) {
|
|
18371
18817
|
const out = pending;
|
|
18372
|
-
pending =
|
|
18818
|
+
pending = EMPTY3;
|
|
18373
18819
|
return out;
|
|
18374
18820
|
}
|
|
18375
18821
|
const result = pass(c, pending, final);
|
|
@@ -18383,7 +18829,7 @@ function compile(secrets, options = {}) {
|
|
|
18383
18829
|
return run2(false);
|
|
18384
18830
|
},
|
|
18385
18831
|
idle() {
|
|
18386
|
-
return pending.length < FRAGMENT ? run2(true) :
|
|
18832
|
+
return pending.length < FRAGMENT ? run2(true) : EMPTY3;
|
|
18387
18833
|
},
|
|
18388
18834
|
end() {
|
|
18389
18835
|
return run2(true);
|
|
@@ -18425,7 +18871,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18425
18871
|
let timer;
|
|
18426
18872
|
let failed3;
|
|
18427
18873
|
const waiters = /* @__PURE__ */ new Set();
|
|
18428
|
-
const
|
|
18874
|
+
const quiet2 = () => !busy && pending === 0;
|
|
18429
18875
|
const wake = () => {
|
|
18430
18876
|
for (const waiter of [...waiters]) waiter();
|
|
18431
18877
|
};
|
|
@@ -18442,7 +18888,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18442
18888
|
if (failed3 === void 0) failed3 = err;
|
|
18443
18889
|
}).finally(() => {
|
|
18444
18890
|
pending -= 1;
|
|
18445
|
-
if (
|
|
18891
|
+
if (quiet2()) wake();
|
|
18446
18892
|
});
|
|
18447
18893
|
};
|
|
18448
18894
|
const settling = (signal) => new Promise((resolve2, reject) => {
|
|
@@ -18460,7 +18906,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18460
18906
|
signal?.addEventListener("abort", stop, { once: true });
|
|
18461
18907
|
});
|
|
18462
18908
|
const settled = async () => {
|
|
18463
|
-
while (!
|
|
18909
|
+
while (!quiet2()) await settling();
|
|
18464
18910
|
};
|
|
18465
18911
|
const changed = async (signal) => {
|
|
18466
18912
|
const round = new AbortController();
|
|
@@ -18476,7 +18922,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18476
18922
|
};
|
|
18477
18923
|
const turn = async (signal) => {
|
|
18478
18924
|
for (let waited = false; ; waited = true) {
|
|
18479
|
-
if (
|
|
18925
|
+
if (quiet2() && (pollFile(file).writable || !file.changed)) {
|
|
18480
18926
|
busy = true;
|
|
18481
18927
|
return;
|
|
18482
18928
|
}
|
|
@@ -18505,7 +18951,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18505
18951
|
...bound(file, "stat"),
|
|
18506
18952
|
poll: () => {
|
|
18507
18953
|
const state = pollFile(file);
|
|
18508
|
-
return
|
|
18954
|
+
return quiet2() ? state : { ...state, writable: false };
|
|
18509
18955
|
},
|
|
18510
18956
|
changed,
|
|
18511
18957
|
...file.tty ? { tty: file.tty } : {},
|
|
@@ -18521,7 +18967,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
18521
18967
|
await send(stream.push(taken), signal);
|
|
18522
18968
|
} finally {
|
|
18523
18969
|
busy = false;
|
|
18524
|
-
if (
|
|
18970
|
+
if (quiet2()) wake();
|
|
18525
18971
|
}
|
|
18526
18972
|
timer = setTimeout(release, idleMs);
|
|
18527
18973
|
return taken.length;
|
|
@@ -18622,15 +19068,15 @@ function isRecord(value) {
|
|
|
18622
19068
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18623
19069
|
}
|
|
18624
19070
|
function serialized(reply) {
|
|
18625
|
-
let
|
|
19071
|
+
let plain2;
|
|
18626
19072
|
try {
|
|
18627
19073
|
const text = JSON.stringify(reply);
|
|
18628
|
-
|
|
19074
|
+
plain2 = text === void 0 ? void 0 : JSON.parse(text);
|
|
18629
19075
|
} catch (err) {
|
|
18630
19076
|
return JSON.stringify(errorReply("EIO", lineOf2(err)));
|
|
18631
19077
|
}
|
|
18632
|
-
if (!isRecord(
|
|
18633
|
-
const { v: _, ...rest2 } =
|
|
19078
|
+
if (!isRecord(plain2)) return JSON.stringify(errorReply("EIO", "the vault gave no reply"));
|
|
19079
|
+
const { v: _, ...rest2 } = plain2;
|
|
18634
19080
|
return JSON.stringify({ v: 1, ...rest2 });
|
|
18635
19081
|
}
|
|
18636
19082
|
function lineOf2(err) {
|
|
@@ -19649,22 +20095,22 @@ function keepWatching(loop, signal) {
|
|
|
19649
20095
|
const stop = () => session2.abort();
|
|
19650
20096
|
signal.addEventListener("abort", stop);
|
|
19651
20097
|
let timer;
|
|
19652
|
-
const
|
|
20098
|
+
const quiet2 = () => {
|
|
19653
20099
|
clearTimeout(timer);
|
|
19654
20100
|
timer = setTimeout(stop, silenceMs);
|
|
19655
20101
|
};
|
|
19656
20102
|
let opened2 = false;
|
|
19657
20103
|
try {
|
|
19658
20104
|
const client = await loop.connect();
|
|
19659
|
-
|
|
20105
|
+
quiet2();
|
|
19660
20106
|
await client.watch(
|
|
19661
20107
|
session2.signal,
|
|
19662
20108
|
(event) => {
|
|
19663
|
-
|
|
20109
|
+
quiet2();
|
|
19664
20110
|
if (!event.ping) loop.event(event);
|
|
19665
20111
|
},
|
|
19666
20112
|
() => {
|
|
19667
|
-
|
|
20113
|
+
quiet2();
|
|
19668
20114
|
opened2 = true;
|
|
19669
20115
|
up = true;
|
|
19670
20116
|
loop.up(client);
|
|
@@ -20106,9 +20552,9 @@ function tmpfs() {
|
|
|
20106
20552
|
let node = root;
|
|
20107
20553
|
for (const name2 of parts2(path)) {
|
|
20108
20554
|
if (node.kind !== "directory") throw fsError2("ENOTDIR", path);
|
|
20109
|
-
const
|
|
20110
|
-
if (!
|
|
20111
|
-
node =
|
|
20555
|
+
const next3 = node.children.get(name2);
|
|
20556
|
+
if (!next3) throw fsError2("ENOENT", path);
|
|
20557
|
+
node = next3;
|
|
20112
20558
|
}
|
|
20113
20559
|
return node;
|
|
20114
20560
|
}
|
|
@@ -20414,6 +20860,28 @@ function foreignImports(bytes) {
|
|
|
20414
20860
|
return {};
|
|
20415
20861
|
}
|
|
20416
20862
|
|
|
20863
|
+
// src/refused-command.ts
|
|
20864
|
+
var REFUSED_PATH = "/usr/lib/slicc/refused";
|
|
20865
|
+
var REFUSED_SOURCE = [
|
|
20866
|
+
"export default async function refused(ctx) {",
|
|
20867
|
+
" await ctx.write(2, ctx.argv[1] + '\\n').catch(() => undefined);",
|
|
20868
|
+
" return 126;",
|
|
20869
|
+
"}"
|
|
20870
|
+
].join("\n");
|
|
20871
|
+
function refusing(command) {
|
|
20872
|
+
if (!command.refused) return command;
|
|
20873
|
+
return {
|
|
20874
|
+
name: command.name,
|
|
20875
|
+
abi: "js",
|
|
20876
|
+
glue: REFUSED_PATH,
|
|
20877
|
+
wasm: REFUSED_PATH,
|
|
20878
|
+
argv0: command.name,
|
|
20879
|
+
args: [`${command.name}: ${command.refused}`],
|
|
20880
|
+
refused: command.refused,
|
|
20881
|
+
shows: command.script ?? command.wasm
|
|
20882
|
+
};
|
|
20883
|
+
}
|
|
20884
|
+
|
|
20417
20885
|
// src/sudo.ts
|
|
20418
20886
|
var SUDOERS = "/etc/sudoers";
|
|
20419
20887
|
var SUDOERS_D = "/etc/sudoers.d";
|
|
@@ -20441,13 +20909,13 @@ function splitWords(text) {
|
|
|
20441
20909
|
while (piece.lastIndex < text.length) {
|
|
20442
20910
|
const m = piece.exec(text);
|
|
20443
20911
|
if (!m) return void 0;
|
|
20444
|
-
const [, single, double, escaped,
|
|
20912
|
+
const [, single, double, escaped, plain2, space] = m;
|
|
20445
20913
|
if (space !== void 0) {
|
|
20446
20914
|
if (word !== void 0) words2.push(word);
|
|
20447
20915
|
word = void 0;
|
|
20448
20916
|
continue;
|
|
20449
20917
|
}
|
|
20450
|
-
word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ??
|
|
20918
|
+
word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ?? plain2));
|
|
20451
20919
|
}
|
|
20452
20920
|
if (word !== void 0) words2.push(word);
|
|
20453
20921
|
return words2;
|
|
@@ -20479,7 +20947,7 @@ function parseRule(line) {
|
|
|
20479
20947
|
if (!cmnd?.[0]?.startsWith("/")) return void 0;
|
|
20480
20948
|
return { ...rule, cmnd };
|
|
20481
20949
|
}
|
|
20482
|
-
function flags(parsed2, arg,
|
|
20950
|
+
function flags(parsed2, arg, next3) {
|
|
20483
20951
|
for (let j = 1; j < arg.length; j++) {
|
|
20484
20952
|
const flag = arg[j];
|
|
20485
20953
|
if (flag === "n") parsed2.nonInteractive = true;
|
|
@@ -20487,7 +20955,7 @@ function flags(parsed2, arg, next2) {
|
|
|
20487
20955
|
else if (flag !== "u") return `sudo: invalid option -- '${flag}'
|
|
20488
20956
|
${USAGE}`;
|
|
20489
20957
|
else {
|
|
20490
|
-
const user = arg.slice(j + 1) ||
|
|
20958
|
+
const user = arg.slice(j + 1) || next3;
|
|
20491
20959
|
if (!user) return `sudo: option requires an argument -- 'u'
|
|
20492
20960
|
${USAGE}`;
|
|
20493
20961
|
parsed2.user = user;
|
|
@@ -20937,9 +21405,9 @@ function appendedRoots(given) {
|
|
|
20937
21405
|
return [...roots];
|
|
20938
21406
|
}
|
|
20939
21407
|
function plainEnv(words2) {
|
|
20940
|
-
const
|
|
20941
|
-
if (baseName2(words2[0] ?? "") !== "env" ||
|
|
20942
|
-
return
|
|
21408
|
+
const next3 = words2[1];
|
|
21409
|
+
if (baseName2(words2[0] ?? "") !== "env" || next3 === void 0) return false;
|
|
21410
|
+
return next3 === "-S" || !next3.startsWith("-") && !next3.includes("=");
|
|
20943
21411
|
}
|
|
20944
21412
|
function shebangCommand(words2) {
|
|
20945
21413
|
if (!plainEnv(words2)) {
|
|
@@ -20963,9 +21431,9 @@ function expandDefaults(defaults, env) {
|
|
|
20963
21431
|
for (const [key, value] of Object.entries(defaults ?? {})) {
|
|
20964
21432
|
let missing4 = false;
|
|
20965
21433
|
const expanded = value.replace(ENV_REFERENCE, (_, name2) => {
|
|
20966
|
-
const
|
|
20967
|
-
if (
|
|
20968
|
-
return
|
|
21434
|
+
const set3 = Object.hasOwn(env, name2) ? env[name2] : void 0;
|
|
21435
|
+
if (set3 === void 0) missing4 = true;
|
|
21436
|
+
return set3 ?? "";
|
|
20969
21437
|
});
|
|
20970
21438
|
if (!missing4) out[key] = expanded;
|
|
20971
21439
|
}
|
|
@@ -21190,7 +21658,7 @@ var Launcher = class {
|
|
|
21190
21658
|
const holders = [this.held, this.openFiles];
|
|
21191
21659
|
this.unlinked = new UnlinkedKeeper(
|
|
21192
21660
|
fs,
|
|
21193
|
-
{ [Symbol.iterator]: () => holders.flatMap((
|
|
21661
|
+
{ [Symbol.iterator]: () => holders.flatMap((set3) => [...set3]).values() },
|
|
21194
21662
|
(path) => this.mountRoot(path),
|
|
21195
21663
|
{
|
|
21196
21664
|
locks: webLocks(),
|
|
@@ -21275,11 +21743,21 @@ var Launcher = class {
|
|
|
21275
21743
|
found = this.trustedAppended().then(async (appended2) => {
|
|
21276
21744
|
const tiers = await this.tiers(scope, appended2);
|
|
21277
21745
|
return scanCommands(this.scanned, tiers, tiers.length - appended2.length);
|
|
21278
|
-
}).then((commands) => commands.set(SUDO_COMMAND.name, SUDO_COMMAND));
|
|
21746
|
+
}).then((commands) => this.refusals(commands).set(SUDO_COMMAND.name, SUDO_COMMAND));
|
|
21279
21747
|
this.catalogs.set(scope, found);
|
|
21280
21748
|
}
|
|
21281
21749
|
return found;
|
|
21282
21750
|
}
|
|
21751
|
+
refusals(commands) {
|
|
21752
|
+
for (const [name2, command] of commands) {
|
|
21753
|
+
if (!command.refused) continue;
|
|
21754
|
+
commands.set(name2, refusing(command));
|
|
21755
|
+
if (this.warned.has(command.refused)) continue;
|
|
21756
|
+
this.warned.add(command.refused);
|
|
21757
|
+
console.warn(`slicc-kernel: refusing the commands of ${command.refused}`);
|
|
21758
|
+
}
|
|
21759
|
+
return commands;
|
|
21760
|
+
}
|
|
21283
21761
|
ownCommands(scope) {
|
|
21284
21762
|
let found = this.ownCatalogs.get(scope);
|
|
21285
21763
|
if (!found) {
|
|
@@ -21354,7 +21832,8 @@ var Launcher = class {
|
|
|
21354
21832
|
);
|
|
21355
21833
|
return {
|
|
21356
21834
|
byUid: new Map(users.map((account, i) => [account.uid, homes[i]])),
|
|
21357
|
-
byBin: new Map(homes.map((home) => [`${home}/bin`, home]))
|
|
21835
|
+
byBin: new Map(homes.map((home) => [`${home}/bin`, home])),
|
|
21836
|
+
owners: new Map(homes.map((home, i) => [home, credOf(users[i])]))
|
|
21358
21837
|
};
|
|
21359
21838
|
},
|
|
21360
21839
|
() => ({ byUid: /* @__PURE__ */ new Map(), byBin: /* @__PURE__ */ new Map() })
|
|
@@ -21696,12 +22175,12 @@ var Launcher = class {
|
|
|
21696
22175
|
return `${path}:${st.size}:${st.mtime.getTime()}`;
|
|
21697
22176
|
}
|
|
21698
22177
|
verified(path, caller, fs = this.base) {
|
|
21699
|
-
const
|
|
21700
|
-
return this.integrity ? this.integrity.read(path, caller,
|
|
22178
|
+
const plain2 = () => fs.readFileBuffer(path);
|
|
22179
|
+
return this.integrity ? this.integrity.read(path, caller, plain2) : plain2();
|
|
21701
22180
|
}
|
|
21702
22181
|
keyed(path, caller, asked) {
|
|
21703
|
-
const
|
|
21704
|
-
return this.integrity ? this.integrity.readKeyed(path, caller,
|
|
22182
|
+
const plain2 = async () => this.base.readFileBuffer(path);
|
|
22183
|
+
return this.integrity ? this.integrity.readKeyed(path, caller, plain2, asked) : plain2().then((bytes) => ({ bytes }));
|
|
21705
22184
|
}
|
|
21706
22185
|
cached(cache, key, load) {
|
|
21707
22186
|
const hit = cache.get(key);
|
|
@@ -21772,6 +22251,9 @@ var Launcher = class {
|
|
|
21772
22251
|
if (target.abi === "js" && target.wasm === SUDO_PATH) {
|
|
21773
22252
|
return { abi: "js", glue: SUDO_SOURCE, path: SUDO_PATH };
|
|
21774
22253
|
}
|
|
22254
|
+
if (target.abi === "js" && target.wasm === REFUSED_PATH) {
|
|
22255
|
+
return { abi: "js", glue: REFUSED_SOURCE, path: REFUSED_PATH };
|
|
22256
|
+
}
|
|
21775
22257
|
const { asked } = target;
|
|
21776
22258
|
if (target.abi === "js") {
|
|
21777
22259
|
return { abi: "js", glue: await this.text(target.wasm, caller, asked), path: target.wasm };
|
|
@@ -21841,7 +22323,7 @@ var Launcher = class {
|
|
|
21841
22323
|
});
|
|
21842
22324
|
return {
|
|
21843
22325
|
source: {
|
|
21844
|
-
read: (path,
|
|
22326
|
+
read: (path, plain2) => integrity.readSource(path, caller(), plain2),
|
|
21845
22327
|
open: (path, real) => integrity.openSource(path, caller(), real)
|
|
21846
22328
|
}
|
|
21847
22329
|
};
|
|
@@ -22280,9 +22762,9 @@ var Launcher = class {
|
|
|
22280
22762
|
const members = this.jobs.list();
|
|
22281
22763
|
let image = pid;
|
|
22282
22764
|
for (; ; ) {
|
|
22283
|
-
const
|
|
22284
|
-
if (!
|
|
22285
|
-
image =
|
|
22765
|
+
const next3 = members.find((m) => m.execParent === image);
|
|
22766
|
+
if (!next3) return image;
|
|
22767
|
+
image = next3.pid;
|
|
22286
22768
|
}
|
|
22287
22769
|
}
|
|
22288
22770
|
credOf(pid) {
|
|
@@ -22569,7 +23051,7 @@ var Launcher = class {
|
|
|
22569
23051
|
this.pnpmStale();
|
|
22570
23052
|
if (!detach) return;
|
|
22571
23053
|
for (const nodes of this.openFiles) nodes.revoke(at);
|
|
22572
|
-
for (const
|
|
23054
|
+
for (const holds2 of this.held) holds2.revoke(at);
|
|
22573
23055
|
}
|
|
22574
23056
|
unmountAll() {
|
|
22575
23057
|
this.booting.abort();
|
|
@@ -22715,7 +23197,7 @@ var Launcher = class {
|
|
|
22715
23197
|
this.openFiles.add(nodes);
|
|
22716
23198
|
const unlinked = new UnlinkedKeeper(
|
|
22717
23199
|
fs,
|
|
22718
|
-
{ [Symbol.iterator]: () => [this.held, this.openFiles].flatMap((
|
|
23200
|
+
{ [Symbol.iterator]: () => [this.held, this.openFiles].flatMap((set3) => [...set3]).values() },
|
|
22719
23201
|
(path) => this.mountRoot(path),
|
|
22720
23202
|
{
|
|
22721
23203
|
locks: webLocks(),
|
|
@@ -22743,11 +23225,32 @@ var Launcher = class {
|
|
|
22743
23225
|
commandFs(root) {
|
|
22744
23226
|
return withCommandDirs(
|
|
22745
23227
|
root,
|
|
22746
|
-
async () =>
|
|
23228
|
+
async () => this.commandNames(await this.commands()),
|
|
22747
23229
|
(dir) => this.userCommandDir(dir),
|
|
22748
|
-
this.owners
|
|
23230
|
+
this.owners,
|
|
23231
|
+
(path) => this.entryTarget(path)
|
|
22749
23232
|
);
|
|
22750
23233
|
}
|
|
23234
|
+
named = /* @__PURE__ */ new WeakMap();
|
|
23235
|
+
commandNames(commands) {
|
|
23236
|
+
let names = this.named.get(commands);
|
|
23237
|
+
if (!names) {
|
|
23238
|
+
names = new Set(commands.keys());
|
|
23239
|
+
this.named.set(commands, names);
|
|
23240
|
+
}
|
|
23241
|
+
return names;
|
|
23242
|
+
}
|
|
23243
|
+
async entryTarget(path) {
|
|
23244
|
+
const system = COMMAND2.exec(path)?.[1];
|
|
23245
|
+
const slash = path.lastIndexOf("/");
|
|
23246
|
+
const scopes = await this.userScopes();
|
|
23247
|
+
const scope = system === void 0 ? scopes.byBin.get(path.slice(0, slash)) : "";
|
|
23248
|
+
const name2 = system ?? path.slice(slash + 1);
|
|
23249
|
+
const command = scope === void 0 ? void 0 : (await this.commands(scope)).get(name2);
|
|
23250
|
+
const owner = scope ? scopes.owners?.get(scope) : void 0;
|
|
23251
|
+
const target = command && (command.shows ?? command.script ?? command.wasm);
|
|
23252
|
+
return target === void 0 ? void 0 : { path: target, ...owner ? { owner } : {} };
|
|
23253
|
+
}
|
|
22751
23254
|
processChain(fs, nodes, unlinked) {
|
|
22752
23255
|
nodes.changed = (path) => this.changes.publish(path);
|
|
22753
23256
|
nodes.dirtied = (delta) => this.changes.dirtied(delta);
|
|
@@ -22862,9 +23365,9 @@ var Launcher = class {
|
|
|
22862
23365
|
// src/sealed-relay.ts
|
|
22863
23366
|
function sealedAsker(port) {
|
|
22864
23367
|
const asks = /* @__PURE__ */ new Map();
|
|
22865
|
-
let
|
|
23368
|
+
let next3 = 0;
|
|
22866
23369
|
const hook = (req, { signal }) => {
|
|
22867
|
-
const id2 = ++
|
|
23370
|
+
const id2 = ++next3;
|
|
22868
23371
|
const waiting = Promise.withResolvers();
|
|
22869
23372
|
asks.set(id2, waiting);
|
|
22870
23373
|
const abort = () => {
|