@ai-ecoverse/slicc-kernel 1.170.4 → 1.172.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -8
- package/dist/driver-worker.js +35 -11
- package/dist/driver-worker.js.map +3 -3
- package/dist/index.js +263 -53
- package/dist/index.js.map +4 -4
- package/dist/kernel-worker.js +779 -438
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-driver-worker.js +39 -15
- package/dist/node-driver-worker.js.map +3 -3
- package/dist/node-process-worker.cjs +1 -1
- package/dist/node-process-worker.js +1 -1
- package/dist/node.js +798 -488
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +1 -1
- package/dist/testing.js +498 -3
- package/dist/testing.js.map +4 -4
- package/dist/types/fs/attest.d.ts +12 -2
- package/dist/types/index.d.ts +13 -5
- package/dist/types/kernel/net/http-syscalls.d.ts +3 -1
- package/dist/types/kernel/net/loopback-transport.d.ts +1 -1
- package/dist/types/kernel/net/placeholder-floor.d.ts +9 -3
- package/dist/types/kernel/net/remote-transport.d.ts +8 -2
- package/dist/types/kernel/net/sealed-fetch.d.ts +27 -0
- package/dist/types/kernel/net/transport.d.ts +6 -1
- package/dist/types/kernel/socket.d.ts +4 -1
- package/dist/types/launcher.d.ts +12 -2
- package/dist/types/node/follow.d.ts +4 -0
- package/dist/types/node.d.ts +13 -4
- package/dist/types/sealed-relay.d.ts +12 -2
- package/dist/types/serve.d.ts +8 -1
- package/dist/types/testing.d.ts +3 -0
- package/dist/types/transport.d.ts +4 -3
- package/package.json +1 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -182,13 +182,13 @@ var IndexedDbMeta = class {
|
|
|
182
182
|
return [transaction, transaction.objectStore(META_STORE)];
|
|
183
183
|
}
|
|
184
184
|
async get(paths) {
|
|
185
|
-
const
|
|
186
|
-
if (
|
|
185
|
+
const missing6 = paths.filter((path) => !this.cache.has(path));
|
|
186
|
+
if (missing6.length > 0) {
|
|
187
187
|
this.settleRemoves();
|
|
188
188
|
const generation = this.generation;
|
|
189
189
|
const [transaction, store] = this.transaction("readonly");
|
|
190
190
|
const found = /* @__PURE__ */ new Map();
|
|
191
|
-
for (const path of
|
|
191
|
+
for (const path of missing6) {
|
|
192
192
|
const request3 = store.get(path);
|
|
193
193
|
request3.onsuccess = () => void found.set(path, request3.result ?? null);
|
|
194
194
|
}
|
|
@@ -1237,10 +1237,10 @@ var RemoteWatch = class {
|
|
|
1237
1237
|
});
|
|
1238
1238
|
}
|
|
1239
1239
|
}
|
|
1240
|
-
heldBy({ tab, holds:
|
|
1240
|
+
heldBy({ tab, holds: holds3, seq: seq2 }) {
|
|
1241
1241
|
const from = tab;
|
|
1242
|
-
const { add, drop } =
|
|
1243
|
-
if (
|
|
1242
|
+
const { add, drop } = holds3;
|
|
1243
|
+
if (holds3?.instance !== void 0) this.instances.set(from, holds3.instance);
|
|
1244
1244
|
const held = this.peerHolds.get(from) ?? /* @__PURE__ */ new Map();
|
|
1245
1245
|
for (const path of drop) held.delete(path);
|
|
1246
1246
|
for (const [path, fid] of add) held.set(path, fid);
|
|
@@ -1524,11 +1524,11 @@ var META_OPS = ["get", "update", "move", "remove", "links", "under", "all"];
|
|
|
1524
1524
|
var FILE_ID_TRIES = 3;
|
|
1525
1525
|
function sidecar(meta) {
|
|
1526
1526
|
const pathOf = ([first]) => [first, "/"].flat().find((p) => typeof p === "string");
|
|
1527
|
-
const
|
|
1527
|
+
const guarded3 = (op) => (...args) => meta[op].apply(meta, args).catch((err) => {
|
|
1528
1528
|
throw translate(err, pathOf(args), "sidecar", false);
|
|
1529
1529
|
});
|
|
1530
1530
|
const names2 = meta.fresh ? [...META_OPS, "fresh"] : META_OPS;
|
|
1531
|
-
const ops = Object.fromEntries(names2.map((op) => [op,
|
|
1531
|
+
const ops = Object.fromEntries(names2.map((op) => [op, guarded3(op)]));
|
|
1532
1532
|
const { updateMany } = meta;
|
|
1533
1533
|
ops.updateMany = updateMany ? (changes) => updateMany.call(meta, changes).catch((err) => {
|
|
1534
1534
|
throw translate(err, changes[0]?.path ?? "/", "sidecar", false);
|
|
@@ -3638,12 +3638,12 @@ var OpfsFs = class {
|
|
|
3638
3638
|
if (!move) return false;
|
|
3639
3639
|
for (let attempt = 0; ; attempt++) {
|
|
3640
3640
|
this.others++;
|
|
3641
|
-
const
|
|
3641
|
+
const failed4 = await move.call(handle, dir, name2).then(
|
|
3642
3642
|
() => void 0,
|
|
3643
3643
|
(err) => ({ err })
|
|
3644
3644
|
);
|
|
3645
|
-
if (!
|
|
3646
|
-
const error =
|
|
3645
|
+
if (!failed4) return true;
|
|
3646
|
+
const error = failed4.err?.name;
|
|
3647
3647
|
if (handle.kind !== "file" || !LOCKED.has(error)) return false;
|
|
3648
3648
|
const delay2 = SYNC_BACKOFF_MS[attempt];
|
|
3649
3649
|
if (delay2 === void 0) throw fsError("EBUSY", name2);
|
|
@@ -6842,9 +6842,9 @@ var KernelSocket = class _KernelSocket {
|
|
|
6842
6842
|
case SO_TYPE:
|
|
6843
6843
|
return SOCK_STREAM;
|
|
6844
6844
|
case SO_ERROR: {
|
|
6845
|
-
const
|
|
6845
|
+
const failed4 = this.failed;
|
|
6846
6846
|
this.failed = void 0;
|
|
6847
|
-
return
|
|
6847
|
+
return failed4 ? wasiErrno(failed4) : 0;
|
|
6848
6848
|
}
|
|
6849
6849
|
case SO_ACCEPTCONN:
|
|
6850
6850
|
return this.state === "listening" ? 1 : 0;
|
|
@@ -6924,6 +6924,7 @@ var LoopbackNet = class {
|
|
|
6924
6924
|
internal = /* @__PURE__ */ new Set();
|
|
6925
6925
|
reserved = /* @__PURE__ */ new Set();
|
|
6926
6926
|
facades = /* @__PURE__ */ new Map();
|
|
6927
|
+
proxyStamped;
|
|
6927
6928
|
nextEphemeral = EPHEMERAL_FIRST;
|
|
6928
6929
|
route;
|
|
6929
6930
|
origins;
|
|
@@ -6998,9 +6999,15 @@ var LoopbackNet = class {
|
|
|
6998
6999
|
this.kernelOnly(port, true);
|
|
6999
7000
|
this.facades.set(port, name2);
|
|
7000
7001
|
}
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7002
|
+
stampProxy(port) {
|
|
7003
|
+
this.proxyStamped = port;
|
|
7004
|
+
}
|
|
7005
|
+
get originsStamped() {
|
|
7006
|
+
return this.proxyStamped !== void 0;
|
|
7007
|
+
}
|
|
7008
|
+
stampsPeers(addr) {
|
|
7009
|
+
if (addr.family !== "inet" || !isLoopback(canonicalHost(addr.host))) return false;
|
|
7010
|
+
return this.facades.has(addr.port) || this.proxyStamped === addr.port;
|
|
7004
7011
|
}
|
|
7005
7012
|
activate(addr, start2) {
|
|
7006
7013
|
this.activators.set(keyOf(addr), start2);
|
|
@@ -7310,7 +7317,34 @@ function uploadsFor(peer) {
|
|
|
7310
7317
|
});
|
|
7311
7318
|
return { of, answer: (call) => pulls.get(call.nid)?.(call) };
|
|
7312
7319
|
}
|
|
7313
|
-
function
|
|
7320
|
+
function headOf(nid, response) {
|
|
7321
|
+
return {
|
|
7322
|
+
net: "head",
|
|
7323
|
+
nid,
|
|
7324
|
+
...response.url !== void 0 ? { url: response.url } : {},
|
|
7325
|
+
...response.redirected !== void 0 ? { redirected: response.redirected } : {},
|
|
7326
|
+
...response.redirects ? { redirects: response.redirects } : {},
|
|
7327
|
+
...response.opaqueRedirect ? { opaqueRedirect: true } : {},
|
|
7328
|
+
status: response.status,
|
|
7329
|
+
statusText: response.statusText,
|
|
7330
|
+
headers: response.headers
|
|
7331
|
+
};
|
|
7332
|
+
}
|
|
7333
|
+
function requestOf(call, signal, uploads) {
|
|
7334
|
+
const { url, method, headers, streamed, body, redirect, nid } = call;
|
|
7335
|
+
return {
|
|
7336
|
+
url,
|
|
7337
|
+
method,
|
|
7338
|
+
headers,
|
|
7339
|
+
...streamed ? { bodyStream: uploads.of(nid, signal) } : body ? { body } : {},
|
|
7340
|
+
...redirect !== void 0 ? { redirect } : {},
|
|
7341
|
+
signal
|
|
7342
|
+
};
|
|
7343
|
+
}
|
|
7344
|
+
function serveTransport(peer, transport, {
|
|
7345
|
+
closeWaitMs = CLOSE_WAIT_MS2,
|
|
7346
|
+
attributed = false
|
|
7347
|
+
} = {}) {
|
|
7314
7348
|
const open2 = /* @__PURE__ */ new Map();
|
|
7315
7349
|
const fail2 = (nid, e) => {
|
|
7316
7350
|
open2.delete(nid);
|
|
@@ -7330,27 +7364,17 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS2 } = {})
|
|
|
7330
7364
|
const entry = { abort };
|
|
7331
7365
|
open2.set(call.nid, entry);
|
|
7332
7366
|
try {
|
|
7333
|
-
const response = await transport.fetch(
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
signal: abort.signal
|
|
7339
|
-
});
|
|
7367
|
+
const response = await transport.fetch(
|
|
7368
|
+
requestOf(call, abort.signal, uploads),
|
|
7369
|
+
attributed ? call.owner : void 0,
|
|
7370
|
+
attributed ? call.stamp : void 0
|
|
7371
|
+
);
|
|
7340
7372
|
if (!open2.has(call.nid)) {
|
|
7341
7373
|
await response.cancel();
|
|
7342
7374
|
return;
|
|
7343
7375
|
}
|
|
7344
7376
|
open2.set(call.nid, { abort, body: response.body[Symbol.asyncIterator](), response });
|
|
7345
|
-
peer.postMessage(
|
|
7346
|
-
net: "head",
|
|
7347
|
-
nid: call.nid,
|
|
7348
|
-
...response.redirected ? { url: response.url, redirected: true } : {},
|
|
7349
|
-
...response.redirects ? { redirects: response.redirects } : {},
|
|
7350
|
-
status: response.status,
|
|
7351
|
-
statusText: response.statusText,
|
|
7352
|
-
headers: response.headers
|
|
7353
|
-
});
|
|
7377
|
+
peer.postMessage(headOf(call.nid, response));
|
|
7354
7378
|
} catch (e) {
|
|
7355
7379
|
fail2(call.nid, e);
|
|
7356
7380
|
}
|
|
@@ -8206,9 +8230,9 @@ function serveClient(port, host) {
|
|
|
8206
8230
|
ended.resolve();
|
|
8207
8231
|
}
|
|
8208
8232
|
async function hello(message3) {
|
|
8209
|
-
const
|
|
8210
|
-
if (
|
|
8211
|
-
send2({ hello: { protocol: PROTOCOL, error:
|
|
8233
|
+
const refused4 = versionError(message3.protocol) ?? await hosts.requests.accept(host, message3);
|
|
8234
|
+
if (refused4) {
|
|
8235
|
+
send2({ hello: { protocol: PROTOCOL, error: refused4 } });
|
|
8212
8236
|
detach();
|
|
8213
8237
|
return;
|
|
8214
8238
|
}
|
|
@@ -8498,7 +8522,7 @@ function satisfies(version, range2) {
|
|
|
8498
8522
|
}
|
|
8499
8523
|
|
|
8500
8524
|
// src/version.ts
|
|
8501
|
-
var KERNEL_VERSION = true ? "1.
|
|
8525
|
+
var KERNEL_VERSION = true ? "1.172.0" : "0.0.0-dev";
|
|
8502
8526
|
var OS_RELEASE = "6.0.0-slicc";
|
|
8503
8527
|
function procVersion() {
|
|
8504
8528
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -8790,10 +8814,10 @@ async function tierPackages(fs, physical, roots, bins, kernel, global) {
|
|
|
8790
8814
|
const own = commandsOf(pkg, manifest);
|
|
8791
8815
|
const named = new Set(own.map((command) => command.name));
|
|
8792
8816
|
const extra = bins ? await binCommandsOf(physical, pkg, manifest, named) : [];
|
|
8793
|
-
const
|
|
8817
|
+
const refused4 = engineRefusal(manifest, kernel);
|
|
8794
8818
|
const name2 = pkg.slice(root.length + 1);
|
|
8795
8819
|
const dependency = direct?.has(name2) === false;
|
|
8796
|
-
const marks = { ...
|
|
8820
|
+
const marks = { ...refused4 ? { refused: refused4 } : {}, ...dependency ? { dependency } : {} };
|
|
8797
8821
|
out.push({
|
|
8798
8822
|
name: name2,
|
|
8799
8823
|
pkg,
|
|
@@ -8825,7 +8849,7 @@ function winners(tier) {
|
|
|
8825
8849
|
}
|
|
8826
8850
|
return out;
|
|
8827
8851
|
}
|
|
8828
|
-
async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, kernel = KERNEL_VERSION,
|
|
8852
|
+
async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, kernel = KERNEL_VERSION, refused4, global = /* @__PURE__ */ new Set()) {
|
|
8829
8853
|
const found = /* @__PURE__ */ new Map();
|
|
8830
8854
|
const physical = physicalResolver(fs);
|
|
8831
8855
|
const tiers = (typeof modules === "string" ? [modules] : modules).map(
|
|
@@ -8839,7 +8863,7 @@ async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, ke
|
|
|
8839
8863
|
const dependencies = [];
|
|
8840
8864
|
for (const [index, roots] of tiers.entries()) {
|
|
8841
8865
|
const tier = await tierPackages(fs, physical, roots, index >= binsFrom, kernel, global);
|
|
8842
|
-
if (
|
|
8866
|
+
if (refused4) refused4.push(...tier.flatMap((entry) => entry.commands.filter((c) => c.refused)));
|
|
8843
8867
|
await take(tier.filter((entry) => !entry.dependency));
|
|
8844
8868
|
dependencies.push(tier.filter((entry) => entry.dependency));
|
|
8845
8869
|
}
|
|
@@ -9155,32 +9179,32 @@ function nextFire(schedule, after, utc = false) {
|
|
|
9155
9179
|
}
|
|
9156
9180
|
return null;
|
|
9157
9181
|
}
|
|
9158
|
-
function missedFires(schedule, from,
|
|
9182
|
+
function missedFires(schedule, from, until2, utc = false, cap = MISSED_CAP) {
|
|
9159
9183
|
let count2 = 0;
|
|
9160
9184
|
let last = null;
|
|
9161
9185
|
let at = from;
|
|
9162
9186
|
while (count2 < cap) {
|
|
9163
9187
|
at = nextFire(schedule, at, utc);
|
|
9164
|
-
if (at === null || at >
|
|
9188
|
+
if (at === null || at > until2) return { count: count2, last, more: false };
|
|
9165
9189
|
last = at;
|
|
9166
9190
|
count2++;
|
|
9167
9191
|
}
|
|
9168
9192
|
const next3 = nextFire(schedule, last, utc);
|
|
9169
|
-
if (next3 === null || next3 >
|
|
9170
|
-
return { count: count2, last: latestFire(schedule, last,
|
|
9193
|
+
if (next3 === null || next3 > until2) return { count: count2, last, more: false };
|
|
9194
|
+
return { count: count2, last: latestFire(schedule, last, until2, utc), more: true };
|
|
9171
9195
|
}
|
|
9172
|
-
function latestFire(schedule, from,
|
|
9196
|
+
function latestFire(schedule, from, until2, utc = false) {
|
|
9173
9197
|
let found = from;
|
|
9174
9198
|
for (let span = 6e4; ; span *= 2) {
|
|
9175
|
-
const start2 = Math.max(from,
|
|
9199
|
+
const start2 = Math.max(from, until2 - span);
|
|
9176
9200
|
const first = nextFire(schedule, start2, utc);
|
|
9177
|
-
if (first !== null && first <=
|
|
9201
|
+
if (first !== null && first <= until2) {
|
|
9178
9202
|
found = first;
|
|
9179
9203
|
break;
|
|
9180
9204
|
}
|
|
9181
9205
|
if (start2 === from) return from;
|
|
9182
9206
|
}
|
|
9183
|
-
for (let at = nextFire(schedule, found, utc); at !== null && at <=
|
|
9207
|
+
for (let at = nextFire(schedule, found, utc); at !== null && at <= until2; ) {
|
|
9184
9208
|
found = at;
|
|
9185
9209
|
at = nextFire(schedule, at, utc);
|
|
9186
9210
|
}
|
|
@@ -9892,12 +9916,12 @@ var UnlinkedKeeper = class {
|
|
|
9892
9916
|
return this.locks;
|
|
9893
9917
|
}
|
|
9894
9918
|
async undoing(op, peers, sends, heard, shared2 = []) {
|
|
9895
|
-
let
|
|
9919
|
+
let failed4;
|
|
9896
9920
|
let out;
|
|
9897
9921
|
try {
|
|
9898
9922
|
out = await op();
|
|
9899
9923
|
} catch (err) {
|
|
9900
|
-
|
|
9924
|
+
failed4 = err ?? new Error("failed");
|
|
9901
9925
|
await this.rollBackAsides(sends, shared2);
|
|
9902
9926
|
}
|
|
9903
9927
|
const hiddenShared = new Set(shared2.map((one) => one.hidden));
|
|
@@ -9918,7 +9942,7 @@ var UnlinkedKeeper = class {
|
|
|
9918
9942
|
const done5 = () => one.release().then(() => this.dropIfLast(one.hidden));
|
|
9919
9943
|
void Promise.all(waits.map(({ told }) => told)).then(done5, done5);
|
|
9920
9944
|
}
|
|
9921
|
-
if (
|
|
9945
|
+
if (failed4 !== void 0) throw failed4;
|
|
9922
9946
|
return out;
|
|
9923
9947
|
}
|
|
9924
9948
|
async rollBackAsides(sends, shared2) {
|
|
@@ -10065,7 +10089,7 @@ var UnlinkedKeeper = class {
|
|
|
10065
10089
|
// src/cron/clock.ts
|
|
10066
10090
|
var systemCronClock = {
|
|
10067
10091
|
now: () => Date.now(),
|
|
10068
|
-
sleep(
|
|
10092
|
+
sleep(until2, signal) {
|
|
10069
10093
|
if (signal.aborted) return Promise.resolve();
|
|
10070
10094
|
return new Promise((resolve2) => {
|
|
10071
10095
|
const done5 = () => {
|
|
@@ -10073,7 +10097,7 @@ var systemCronClock = {
|
|
|
10073
10097
|
signal.removeEventListener("abort", done5);
|
|
10074
10098
|
resolve2();
|
|
10075
10099
|
};
|
|
10076
|
-
const timer = setTimeout(done5, Math.max(0,
|
|
10100
|
+
const timer = setTimeout(done5, Math.max(0, until2 - Date.now()));
|
|
10077
10101
|
timer.unref?.();
|
|
10078
10102
|
signal.addEventListener("abort", done5, { once: true });
|
|
10079
10103
|
});
|
|
@@ -10177,15 +10201,15 @@ var CronService = class {
|
|
|
10177
10201
|
async pass() {
|
|
10178
10202
|
if (this.wake.signal.aborted) this.wake = new AbortController();
|
|
10179
10203
|
const wake = this.wake;
|
|
10180
|
-
let
|
|
10204
|
+
let until2;
|
|
10181
10205
|
try {
|
|
10182
|
-
|
|
10206
|
+
until2 = await this.tick();
|
|
10183
10207
|
} catch (err) {
|
|
10184
10208
|
await this.error(`cron: ${messageOf(err)}`);
|
|
10185
|
-
|
|
10209
|
+
until2 = this.clock.now() + WAKE_MS;
|
|
10186
10210
|
}
|
|
10187
10211
|
if (this.stopping.signal.aborted) return;
|
|
10188
|
-
await this.clock.sleep(
|
|
10212
|
+
await this.clock.sleep(until2, wake.signal);
|
|
10189
10213
|
}
|
|
10190
10214
|
async provision() {
|
|
10191
10215
|
const { fs, owners } = this.host;
|
|
@@ -10402,14 +10426,17 @@ var PLACEHOLDER_REFUSED = "refused: this request has a sealed placeholder in its
|
|
|
10402
10426
|
var PlaceholderRefused = class extends Error {
|
|
10403
10427
|
status = 403;
|
|
10404
10428
|
code = "EACCES";
|
|
10405
|
-
constructor() {
|
|
10406
|
-
super(
|
|
10429
|
+
constructor(reason = PLACEHOLDER_REFUSED) {
|
|
10430
|
+
super(reason);
|
|
10407
10431
|
}
|
|
10408
10432
|
};
|
|
10409
|
-
function
|
|
10433
|
+
function holds2(text, known) {
|
|
10434
|
+
return PLACEHOLDER.test(text) || known.some((placeholder) => text.includes(placeholder));
|
|
10435
|
+
}
|
|
10436
|
+
function carries(text, known) {
|
|
10410
10437
|
let layer = text;
|
|
10411
10438
|
for (let i = 0; i < PERCENT_LAYERS; i++) {
|
|
10412
|
-
if (
|
|
10439
|
+
if (holds2(layer, known)) return true;
|
|
10413
10440
|
const next3 = layer.replace(
|
|
10414
10441
|
ESCAPE,
|
|
10415
10442
|
(_, hex4) => String.fromCharCode(Number.parseInt(hex4, 16))
|
|
@@ -10417,35 +10444,36 @@ function carries(text) {
|
|
|
10417
10444
|
if (next3 === layer) return false;
|
|
10418
10445
|
layer = next3;
|
|
10419
10446
|
}
|
|
10420
|
-
return
|
|
10447
|
+
return holds2(layer, known);
|
|
10421
10448
|
}
|
|
10422
|
-
function basicCarries(value2) {
|
|
10449
|
+
function basicCarries(value2, known) {
|
|
10423
10450
|
const credential = BASIC.exec(value2)?.[1];
|
|
10424
10451
|
if (credential === void 0) return false;
|
|
10425
10452
|
const letters = credential.replace(/[^A-Za-z0-9+/_-]/g, "").replaceAll("-", "+").replaceAll("_", "/");
|
|
10426
10453
|
for (let shift = 0; shift < BASE64_GROUP; shift++) {
|
|
10427
10454
|
const part = letters.slice(shift);
|
|
10428
10455
|
const whole = part.length % BASE64_GROUP === 1 ? part.slice(0, -1) : part;
|
|
10429
|
-
if (carries(atob(whole))) return true;
|
|
10456
|
+
if (carries(atob(whole), known)) return true;
|
|
10430
10457
|
}
|
|
10431
10458
|
return false;
|
|
10432
10459
|
}
|
|
10433
|
-
function headersCarry(headers) {
|
|
10460
|
+
function headersCarry(headers, known) {
|
|
10434
10461
|
return headers.some(
|
|
10435
|
-
([name2, value2]) => carries(name2.toLowerCase()) || carries(value2) || basicCarries(value2)
|
|
10462
|
+
([name2, value2]) => carries(name2, known) || carries(name2.toLowerCase(), known) || carries(value2, known) || basicCarries(value2, known)
|
|
10436
10463
|
);
|
|
10437
10464
|
}
|
|
10438
|
-
function urlCarries(url) {
|
|
10439
|
-
return carries(url) || URL.canParse(url) && carries(new URL(url).href);
|
|
10465
|
+
function urlCarries(url, known) {
|
|
10466
|
+
return carries(url, known) || URL.canParse(url) && carries(new URL(url).href, known);
|
|
10440
10467
|
}
|
|
10441
|
-
function
|
|
10442
|
-
|
|
10468
|
+
function detected(request3, known) {
|
|
10469
|
+
return urlCarries(request3.url, known) || headersCarry(request3.headers, known);
|
|
10443
10470
|
}
|
|
10444
|
-
function refuseSocket(request3) {
|
|
10445
|
-
|
|
10446
|
-
|
|
10471
|
+
function refuseSocket(request3, known) {
|
|
10472
|
+
if (detected(request3, known) || request3.protocols.some((p) => carries(p, known))) {
|
|
10473
|
+
throw new PlaceholderRefused();
|
|
10474
|
+
}
|
|
10447
10475
|
}
|
|
10448
|
-
function placeholderFloor(inner) {
|
|
10476
|
+
function placeholderFloor(inner, { known = () => [], fill: fill2 } = {}) {
|
|
10449
10477
|
const open2 = inner.websocket?.bind(inner);
|
|
10450
10478
|
return {
|
|
10451
10479
|
get traits() {
|
|
@@ -10453,13 +10481,14 @@ function placeholderFloor(inner) {
|
|
|
10453
10481
|
},
|
|
10454
10482
|
...open2 ? {
|
|
10455
10483
|
websocket: async (request3) => {
|
|
10456
|
-
refuseSocket(request3);
|
|
10484
|
+
refuseSocket(request3, known());
|
|
10457
10485
|
return open2(request3);
|
|
10458
10486
|
}
|
|
10459
10487
|
} : {},
|
|
10460
|
-
async fetch(request3, owner) {
|
|
10461
|
-
|
|
10462
|
-
|
|
10488
|
+
async fetch(request3, owner, stamp) {
|
|
10489
|
+
if (!detected(request3, known())) return inner.fetch(request3, owner, stamp);
|
|
10490
|
+
if (!fill2 || !stamp) throw new PlaceholderRefused();
|
|
10491
|
+
return fill2(request3, stamp);
|
|
10463
10492
|
}
|
|
10464
10493
|
};
|
|
10465
10494
|
}
|
|
@@ -10632,14 +10661,14 @@ function tunnelTarget(req) {
|
|
|
10632
10661
|
}
|
|
10633
10662
|
return { host, port };
|
|
10634
10663
|
}
|
|
10635
|
-
async function watchHangup(conn, abort,
|
|
10636
|
-
while (!
|
|
10664
|
+
async function watchHangup(conn, abort, until2) {
|
|
10665
|
+
while (!until2.aborted && !abort.signal.aborted) {
|
|
10637
10666
|
if (conn.poll().hangup) {
|
|
10638
10667
|
abort.abort(new KernelError("EPIPE"));
|
|
10639
10668
|
return;
|
|
10640
10669
|
}
|
|
10641
10670
|
try {
|
|
10642
|
-
await conn.changed(
|
|
10671
|
+
await conn.changed(until2);
|
|
10643
10672
|
} catch {
|
|
10644
10673
|
return;
|
|
10645
10674
|
}
|
|
@@ -10830,7 +10859,7 @@ var RealmProxy = class {
|
|
|
10830
10859
|
const waiting = new AbortController();
|
|
10831
10860
|
void watchHangup(ctx.socket, abort, waiting.signal);
|
|
10832
10861
|
try {
|
|
10833
|
-
response = await this.upstream(req, url, body, abort.signal, ctx.socket
|
|
10862
|
+
response = await this.upstream(req, url, body, abort.signal, ctx.socket);
|
|
10834
10863
|
} finally {
|
|
10835
10864
|
waiting.abort();
|
|
10836
10865
|
}
|
|
@@ -10857,7 +10886,7 @@ var RealmProxy = class {
|
|
|
10857
10886
|
await conn.write(latin1Bytes("HTTP/1.1 100 Continue\r\n\r\n"), this.stop.signal);
|
|
10858
10887
|
}
|
|
10859
10888
|
}
|
|
10860
|
-
async upstream(req, url, body, signal,
|
|
10889
|
+
async upstream(req, url, body, signal, socket) {
|
|
10861
10890
|
const sent = BODILESS_METHODS.has(req.method) ? void 0 : body;
|
|
10862
10891
|
try {
|
|
10863
10892
|
const fetching = this.options.transport.fetch(
|
|
@@ -10868,7 +10897,8 @@ var RealmProxy = class {
|
|
|
10868
10897
|
...sent instanceof Uint8Array ? { body: sent } : sent ? { bodyStream: sent } : {},
|
|
10869
10898
|
signal
|
|
10870
10899
|
},
|
|
10871
|
-
|
|
10900
|
+
socket.peerCred?.pid,
|
|
10901
|
+
socket.peerStamp
|
|
10872
10902
|
);
|
|
10873
10903
|
return await untilAborted(fetching, signal);
|
|
10874
10904
|
} catch (e) {
|
|
@@ -10912,8 +10942,8 @@ var RealmProxy = class {
|
|
|
10912
10942
|
}
|
|
10913
10943
|
async connect(conn, incoming, req, idle2) {
|
|
10914
10944
|
const target = tunnelTarget(req);
|
|
10915
|
-
const
|
|
10916
|
-
if (
|
|
10945
|
+
const refused4 = target.port === 443 ? await this.tunnelReady(target) : void 0;
|
|
10946
|
+
if (refused4) throw refused4;
|
|
10917
10947
|
await conn.write(latin1Bytes("HTTP/1.1 200 Connection Established\r\n\r\n"), this.stop.signal);
|
|
10918
10948
|
try {
|
|
10919
10949
|
const first = await incoming.peek(this.stop.signal);
|
|
@@ -11185,7 +11215,7 @@ async function relay(socket, conn) {
|
|
|
11185
11215
|
// src/fs/attest.ts
|
|
11186
11216
|
var ATTEST_MAX = 1024 * 1024;
|
|
11187
11217
|
var UNOWNED = 1e3;
|
|
11188
|
-
function
|
|
11218
|
+
function refuse(code, path, why) {
|
|
11189
11219
|
throw Object.assign(new Error(`attest ${path}: ${why}`), { code });
|
|
11190
11220
|
}
|
|
11191
11221
|
function chainOf(path) {
|
|
@@ -11227,39 +11257,49 @@ async function trustedParents(fs, path, o) {
|
|
|
11227
11257
|
const parents = [];
|
|
11228
11258
|
for (const dir of chainOf(path).slice(0, -1)) {
|
|
11229
11259
|
const st = await fs.lstat(dir);
|
|
11230
|
-
if (st.isSymbolicLink)
|
|
11231
|
-
if (!st.isDirectory)
|
|
11260
|
+
if (st.isSymbolicLink) refuse("EACCES", path, `${dir} is a symlink`);
|
|
11261
|
+
if (!st.isDirectory) refuse("ENOTDIR", path, `${dir} is not a directory`);
|
|
11232
11262
|
const perm = owned(dir, st);
|
|
11233
11263
|
if (o.users !== "off" && (perm.uid !== 0 || (perm.mode & 18) !== 0)) {
|
|
11234
|
-
|
|
11264
|
+
refuse("EACCES", path, `${dir} is not root-owned or is writable by group or others`);
|
|
11235
11265
|
}
|
|
11236
11266
|
parents.push(perm);
|
|
11237
11267
|
}
|
|
11238
11268
|
return parents;
|
|
11239
11269
|
}
|
|
11270
|
+
function missing3(e) {
|
|
11271
|
+
return e?.code === "ENOENT";
|
|
11272
|
+
}
|
|
11240
11273
|
async function attest(fs, asked, o) {
|
|
11274
|
+
if (o.absent !== void 0 && o.absent !== "allow") {
|
|
11275
|
+
refuse("EINVAL", String(asked), "absent takes only allow");
|
|
11276
|
+
}
|
|
11241
11277
|
if (typeof asked !== "string" || !asked.startsWith("/")) {
|
|
11242
|
-
|
|
11278
|
+
refuse("EINVAL", String(asked), "not an absolute path");
|
|
11243
11279
|
}
|
|
11244
11280
|
const path = normalizePath(asked);
|
|
11245
11281
|
const mount = o.mounts.find((target) => {
|
|
11246
11282
|
const at = normalizePath(target);
|
|
11247
11283
|
return at === "/" || under2(path, at);
|
|
11248
11284
|
});
|
|
11249
|
-
if (mount !== void 0)
|
|
11285
|
+
if (mount !== void 0) refuse("EACCES", path, `under the mount ${mount}`);
|
|
11250
11286
|
const parents = await trustedParents(fs, path, o);
|
|
11251
11287
|
for (let tries = 0; ; tries++) {
|
|
11252
|
-
const before = await fs.lstat(path)
|
|
11253
|
-
|
|
11288
|
+
const before = await fs.lstat(path).catch((e) => {
|
|
11289
|
+
if (o.absent === "allow" && missing3(e)) return void 0;
|
|
11290
|
+
throw e;
|
|
11291
|
+
});
|
|
11292
|
+
if (!before) return { path, absent: true, users: o.users, onRootFs: true, parents };
|
|
11293
|
+
if (before.isSymbolicLink) refuse("EACCES", path, "is a symlink");
|
|
11254
11294
|
if (!before.isFile)
|
|
11255
|
-
|
|
11256
|
-
if (before.size > ATTEST_MAX)
|
|
11295
|
+
refuse(before.isDirectory ? "EISDIR" : "EINVAL", path, "is not a regular file");
|
|
11296
|
+
if (before.size > ATTEST_MAX) refuse("EFBIG", path, `is over ${ATTEST_MAX} bytes`);
|
|
11257
11297
|
const bytes = (await fs.readFileBuffer(path)).slice();
|
|
11258
11298
|
const after = await fs.lstat(path);
|
|
11259
11299
|
if (unchanged(before, after, bytes)) {
|
|
11260
11300
|
return attested(path, after, bytes, await sha2562(bytes), o, parents);
|
|
11261
11301
|
}
|
|
11262
|
-
if (tries >= 1)
|
|
11302
|
+
if (tries >= 1) refuse("EAGAIN", path, "changed while it was read");
|
|
11263
11303
|
}
|
|
11264
11304
|
}
|
|
11265
11305
|
var WATCH_DEBOUNCE_MS = 50;
|
|
@@ -11318,7 +11358,7 @@ var S_IFREG2 = 32768;
|
|
|
11318
11358
|
var COMMAND = /^\/(?:usr\/)?bin\/([^/]+)$/;
|
|
11319
11359
|
var MAX_LINKS6 = 40;
|
|
11320
11360
|
var BIN_ENTRY = /\/bin\/[^/]+$/;
|
|
11321
|
-
function
|
|
11361
|
+
function missing4(err) {
|
|
11322
11362
|
return err?.code === "ENOENT";
|
|
11323
11363
|
}
|
|
11324
11364
|
function synthetic(directory, path) {
|
|
@@ -11422,7 +11462,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
|
|
|
11422
11462
|
}
|
|
11423
11463
|
async function entryTarget(path) {
|
|
11424
11464
|
if (!BIN_ENTRY.test(path) || !(await virtual(path))?.isFile) return void 0;
|
|
11425
|
-
if (!await fs.lstat(path).then(() => false,
|
|
11465
|
+
if (!await fs.lstat(path).then(() => false, missing4)) return void 0;
|
|
11426
11466
|
const target = await targetOf2(path);
|
|
11427
11467
|
return target?.path === path ? void 0 : target;
|
|
11428
11468
|
}
|
|
@@ -11434,11 +11474,11 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
|
|
|
11434
11474
|
return target?.path;
|
|
11435
11475
|
}
|
|
11436
11476
|
const absent2 = (err) => {
|
|
11437
|
-
if (
|
|
11477
|
+
if (missing4(err)) return EMPTY2;
|
|
11438
11478
|
throw err;
|
|
11439
11479
|
};
|
|
11440
11480
|
async function content(path, err) {
|
|
11441
|
-
if (!
|
|
11481
|
+
if (!missing4(err) || !(await linked2(path))?.isFile) throw err;
|
|
11442
11482
|
const target = await redirected2(path);
|
|
11443
11483
|
return target === void 0 ? EMPTY2 : fs.readFileBuffer(target).catch(absent2);
|
|
11444
11484
|
}
|
|
@@ -11447,7 +11487,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
|
|
|
11447
11487
|
try {
|
|
11448
11488
|
return await real(path);
|
|
11449
11489
|
} catch (err) {
|
|
11450
|
-
const found =
|
|
11490
|
+
const found = missing4(err) ? await linked2(path) : void 0;
|
|
11451
11491
|
if (found) return found;
|
|
11452
11492
|
throw err;
|
|
11453
11493
|
}
|
|
@@ -11472,7 +11512,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
|
|
|
11472
11512
|
const extra = await children3(path);
|
|
11473
11513
|
if (!extra) return fs.readdir(path);
|
|
11474
11514
|
const real = await fs.readdir(path).catch((err) => {
|
|
11475
|
-
if (
|
|
11515
|
+
if (missing4(err)) return [];
|
|
11476
11516
|
throw err;
|
|
11477
11517
|
});
|
|
11478
11518
|
return [.../* @__PURE__ */ new Set([...real, ...extra])].sort();
|
|
@@ -11481,7 +11521,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
|
|
|
11481
11521
|
const extra = await children3(path);
|
|
11482
11522
|
if (!extra) return fs.readdirStat(path);
|
|
11483
11523
|
const real = await fs.readdirStat(path).catch((err) => {
|
|
11484
|
-
if (
|
|
11524
|
+
if (missing4(err)) return [];
|
|
11485
11525
|
throw err;
|
|
11486
11526
|
});
|
|
11487
11527
|
const seen = new Set(real.map(([name2]) => name2));
|
|
@@ -11515,7 +11555,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
|
|
|
11515
11555
|
...ranged2 ? {
|
|
11516
11556
|
...ranged2,
|
|
11517
11557
|
pread: (path, offset, length2, version) => ranged2.pread(path, offset, length2, version).catch(async (err) => {
|
|
11518
|
-
const target =
|
|
11558
|
+
const target = missing4(err) ? await redirected2(path) : void 0;
|
|
11519
11559
|
if (target === void 0) throw err;
|
|
11520
11560
|
return ranged2.pread(target, offset, length2).catch(absent2);
|
|
11521
11561
|
})
|
|
@@ -11546,7 +11586,7 @@ var S_IFREG3 = 32768;
|
|
|
11546
11586
|
var MAX_HOPS2 = 40;
|
|
11547
11587
|
var parentOf6 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
11548
11588
|
var baseOf2 = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
11549
|
-
function
|
|
11589
|
+
function missing5(err) {
|
|
11550
11590
|
return err?.code === "ENOENT";
|
|
11551
11591
|
}
|
|
11552
11592
|
function statOf(path, bytes) {
|
|
@@ -11599,11 +11639,11 @@ function withEtcFiles(fs, files) {
|
|
|
11599
11639
|
const text = files.get(path)?.();
|
|
11600
11640
|
return text === void 0 ? void 0 : new TextEncoder().encode(text);
|
|
11601
11641
|
};
|
|
11602
|
-
const absent2 = (path) => fs.lstat(path).then(() => false,
|
|
11642
|
+
const absent2 = (path) => fs.lstat(path).then(() => false, missing5);
|
|
11603
11643
|
const follow2 = linkFollower(fs, files);
|
|
11604
11644
|
const listedAbsent = async (path) => files.has(path) && await absent2(path) ? bytesOf2(path) : void 0;
|
|
11605
11645
|
const fallback = (path, make) => async (err) => {
|
|
11606
|
-
const at =
|
|
11646
|
+
const at = missing5(err) ? await follow2(path) : void 0;
|
|
11607
11647
|
const bytes = at === void 0 ? void 0 : await listedAbsent(at);
|
|
11608
11648
|
if (bytes === void 0 || at === void 0) throw err;
|
|
11609
11649
|
return make(bytes, at);
|
|
@@ -13418,8 +13458,8 @@ var DriverConnection = class _DriverConnection {
|
|
|
13418
13458
|
} finally {
|
|
13419
13459
|
clearTimeout(timer);
|
|
13420
13460
|
}
|
|
13421
|
-
const
|
|
13422
|
-
if (
|
|
13461
|
+
const refused4 = driverVersionError(hello.protocol);
|
|
13462
|
+
if (refused4) throw errnoError("EPROTO", refused4);
|
|
13423
13463
|
if (hello.error) throw errnoError(hello.errno ?? "EIO", hello.error);
|
|
13424
13464
|
return new _DriverConnection(port, hello.capabilities ?? {}, waiting, timeoutMs, options);
|
|
13425
13465
|
}
|
|
@@ -13503,29 +13543,29 @@ var HeldSet = class extends Set {
|
|
|
13503
13543
|
this.idle = idle2;
|
|
13504
13544
|
this.moved = moved2;
|
|
13505
13545
|
}
|
|
13506
|
-
add(
|
|
13507
|
-
|
|
13508
|
-
|
|
13509
|
-
return super.add(
|
|
13546
|
+
add(holds3) {
|
|
13547
|
+
holds3.onIdle = this.idle;
|
|
13548
|
+
holds3.onMoved = this.moved;
|
|
13549
|
+
return super.add(holds3);
|
|
13510
13550
|
}
|
|
13511
13551
|
doubt(paths, over) {
|
|
13512
|
-
for (const
|
|
13513
|
-
for (const path of paths)
|
|
13514
|
-
if (over !== void 0)
|
|
13552
|
+
for (const holds3 of this) {
|
|
13553
|
+
for (const path of paths) holds3.doubt(path, true);
|
|
13554
|
+
if (over !== void 0) holds3.doubt(over);
|
|
13515
13555
|
}
|
|
13516
13556
|
}
|
|
13517
13557
|
async bindIds(id2) {
|
|
13518
|
-
for (const
|
|
13558
|
+
for (const holds3 of [...this]) await holds3.bindIds(id2);
|
|
13519
13559
|
}
|
|
13520
13560
|
heldIds() {
|
|
13521
13561
|
const out = /* @__PURE__ */ new Map();
|
|
13522
|
-
for (const
|
|
13562
|
+
for (const holds3 of this) for (const [path, fid] of holds3.heldIds()) out.set(path, fid);
|
|
13523
13563
|
return [...out];
|
|
13524
13564
|
}
|
|
13525
|
-
delete(
|
|
13526
|
-
const removed = super.delete(
|
|
13527
|
-
for (const path of /* @__PURE__ */ new Set([...
|
|
13528
|
-
|
|
13565
|
+
delete(holds3) {
|
|
13566
|
+
const removed = super.delete(holds3);
|
|
13567
|
+
for (const path of /* @__PURE__ */ new Set([...holds3.keys(), ...holds3.opens.keys()])) this.idle(path);
|
|
13568
|
+
holds3.releaseAll();
|
|
13529
13569
|
return removed;
|
|
13530
13570
|
}
|
|
13531
13571
|
};
|
|
@@ -15443,8 +15483,8 @@ async function guarded(entry, path, req) {
|
|
|
15443
15483
|
return { paths };
|
|
15444
15484
|
} catch (err) {
|
|
15445
15485
|
const refusal2 = err.code === "EACCES";
|
|
15446
|
-
const
|
|
15447
|
-
return { refused:
|
|
15486
|
+
const refused4 = req.op === "exists" && refusal2 ? json2(false) : toErrno(err);
|
|
15487
|
+
return { refused: refused4 };
|
|
15448
15488
|
}
|
|
15449
15489
|
}
|
|
15450
15490
|
async function copyOp(entry, path, req) {
|
|
@@ -15640,13 +15680,13 @@ async function created2(entry, req) {
|
|
|
15640
15680
|
return seen === void 0 ? looked : json2({ ...looked.json, seen });
|
|
15641
15681
|
}
|
|
15642
15682
|
var DENIED = /* @__PURE__ */ new Set(["EACCES", "EPERM"]);
|
|
15643
|
-
async function rmPermitted(entry, path, req,
|
|
15683
|
+
async function rmPermitted(entry, path, req, refused4) {
|
|
15644
15684
|
const st = await entry.fs.lstat(path).catch(() => void 0);
|
|
15645
|
-
if (!st?.isDirectory) return
|
|
15685
|
+
if (!st?.isDirectory) return refused4;
|
|
15646
15686
|
const unlisted = await guarded(entry, path, { ...req, op: "readdir" });
|
|
15647
15687
|
if ("refused" in unlisted) return unlisted.refused;
|
|
15648
15688
|
const names2 = await entry.fs.readdir(path).catch(() => void 0);
|
|
15649
|
-
if (!names2) return
|
|
15689
|
+
if (!names2) return refused4;
|
|
15650
15690
|
let first;
|
|
15651
15691
|
for (const name2 of names2) {
|
|
15652
15692
|
const child = await dispatchOne(entry, {
|
|
@@ -15697,14 +15737,14 @@ async function newDevName(entry, path, req) {
|
|
|
15697
15737
|
const named = NAMING.has(req.op);
|
|
15698
15738
|
if (!named && !CREATIONS.has(req.op)) return void 0;
|
|
15699
15739
|
const target = named ? entry.fs.resolvePath(entry.cwd, req.arg2 ?? "") : path;
|
|
15700
|
-
const
|
|
15701
|
-
if (!
|
|
15740
|
+
const refused4 = devCreation(target, entry.cred?.());
|
|
15741
|
+
if (!refused4) return void 0;
|
|
15702
15742
|
const there = await entry.fs.lstat(target).then(
|
|
15703
15743
|
() => true,
|
|
15704
15744
|
() => false
|
|
15705
15745
|
);
|
|
15706
15746
|
if (there) return void 0;
|
|
15707
|
-
return { ok: false, errno:
|
|
15747
|
+
return { ok: false, errno: refused4, message: `${target}: no new names in /dev or /proc` };
|
|
15708
15748
|
}
|
|
15709
15749
|
var MISS_OPS = /* @__PURE__ */ new Set(["stat", "lstat"]);
|
|
15710
15750
|
async function linkFree(fs, path) {
|
|
@@ -16416,9 +16456,9 @@ var SYS_TREE = {
|
|
|
16416
16456
|
`,
|
|
16417
16457
|
slicc_file_ids: (listing) => `${listing.fileIds ?? 0}
|
|
16418
16458
|
`,
|
|
16419
|
-
slicc_peer_holds: ({ holds:
|
|
16459
|
+
slicc_peer_holds: ({ holds: holds3 }) => `${holds3?.mine ?? 0} ${holds3?.peers ?? 0} ${holds3?.sent ?? 0}
|
|
16420
16460
|
`,
|
|
16421
|
-
slicc_peer_held: ({ holds:
|
|
16461
|
+
slicc_peer_held: ({ holds: holds3 }) => (holds3?.held ?? []).map((path) => `${path}
|
|
16422
16462
|
`).join(""),
|
|
16423
16463
|
slicc_rename_acks: (listing) => {
|
|
16424
16464
|
const samples = [...listing.renameAcks?.ackMs ?? []].sort((a, b) => a - b);
|
|
@@ -17159,11 +17199,11 @@ var EpollFile = class _EpollFile {
|
|
|
17159
17199
|
const round = new AbortController();
|
|
17160
17200
|
const stop = () => round.abort();
|
|
17161
17201
|
signal.addEventListener("abort", stop, { once: true });
|
|
17162
|
-
let
|
|
17202
|
+
let failed4 = false;
|
|
17163
17203
|
try {
|
|
17164
17204
|
await file.changed(round.signal);
|
|
17165
17205
|
} catch {
|
|
17166
|
-
|
|
17206
|
+
failed4 = true;
|
|
17167
17207
|
} finally {
|
|
17168
17208
|
round.abort();
|
|
17169
17209
|
signal.removeEventListener("abort", stop);
|
|
@@ -17171,7 +17211,7 @@ var EpollFile = class _EpollFile {
|
|
|
17171
17211
|
if (signal.aborted) return;
|
|
17172
17212
|
reg.gen++;
|
|
17173
17213
|
this.changes.wake();
|
|
17174
|
-
if (
|
|
17214
|
+
if (failed4) await pause(RETRY_MS, signal);
|
|
17175
17215
|
}
|
|
17176
17216
|
}
|
|
17177
17217
|
};
|
|
@@ -17807,8 +17847,8 @@ var KernelLoopback = class {
|
|
|
17807
17847
|
);
|
|
17808
17848
|
} catch (err) {
|
|
17809
17849
|
socket.close();
|
|
17810
|
-
const
|
|
17811
|
-
throw
|
|
17850
|
+
const refused4 = err instanceof KernelError && err.code === "ECONNREFUSED";
|
|
17851
|
+
throw refused4 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
|
|
17812
17852
|
}
|
|
17813
17853
|
signal.addEventListener("abort", () => socket.close(), { once: true });
|
|
17814
17854
|
return socket;
|
|
@@ -18152,11 +18192,11 @@ function ipv6(host) {
|
|
|
18152
18192
|
const back = halves.length === 2 ? groups(halves[1]) : [];
|
|
18153
18193
|
if (![...head, ...back].every((g) => /^[0-9A-Fa-f]{1,4}$/.test(g))) return void 0;
|
|
18154
18194
|
const words2 = [...head, ...back].map((g) => Number.parseInt(g, 16));
|
|
18155
|
-
const
|
|
18156
|
-
if (halves.length === 2 ?
|
|
18195
|
+
const missing6 = 8 - words2.length - tail2.length;
|
|
18196
|
+
if (halves.length === 2 ? missing6 < 1 : missing6 !== 0) return void 0;
|
|
18157
18197
|
const all = [
|
|
18158
18198
|
...head.map((g) => Number.parseInt(g, 16)),
|
|
18159
|
-
...new Array(halves.length === 2 ?
|
|
18199
|
+
...new Array(halves.length === 2 ? missing6 : 0).fill(0),
|
|
18160
18200
|
...back.map((g) => Number.parseInt(g, 16)),
|
|
18161
18201
|
...tail2
|
|
18162
18202
|
];
|
|
@@ -19201,10 +19241,12 @@ var HttpHandles = class {
|
|
|
19201
19241
|
ws;
|
|
19202
19242
|
owner;
|
|
19203
19243
|
local;
|
|
19204
|
-
|
|
19244
|
+
stamp;
|
|
19245
|
+
constructor(transport, owner, local2, stamp) {
|
|
19205
19246
|
this.transport = transport;
|
|
19206
19247
|
this.owner = owner;
|
|
19207
19248
|
this.local = local2;
|
|
19249
|
+
this.stamp = stamp;
|
|
19208
19250
|
this.ws = new WsHandles(transport, () => ++this.nextHandle, local2);
|
|
19209
19251
|
}
|
|
19210
19252
|
syscall(req) {
|
|
@@ -19280,7 +19322,7 @@ var HttpHandles = class {
|
|
|
19280
19322
|
...entry.upload ? { bodyStream: entry.upload } : req.body ? { body: req.body } : {},
|
|
19281
19323
|
signal: entry.abort.signal
|
|
19282
19324
|
};
|
|
19283
|
-
const response = port === void 0 ? await this.transport.fetch(request3, this.owner) : await this.local.fetch(request3, port);
|
|
19325
|
+
const response = port === void 0 ? await this.transport.fetch(request3, this.owner, await this.stamp?.()) : await this.local.fetch(request3, port);
|
|
19284
19326
|
entry.body = response.body[Symbol.asyncIterator]();
|
|
19285
19327
|
entry.cancel = () => response.cancel();
|
|
19286
19328
|
if (!this.open.has(handle)) await entry.cancel().catch(() => void 0);
|
|
@@ -19302,8 +19344,8 @@ var HttpHandles = class {
|
|
|
19302
19344
|
if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
|
|
19303
19345
|
const code = codeOf2(e);
|
|
19304
19346
|
const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
|
|
19305
|
-
const
|
|
19306
|
-
return { ok: false, errno: errno3, message: text, ...
|
|
19347
|
+
const failed4 = e.detail === "transport";
|
|
19348
|
+
return { ok: false, errno: errno3, message: text, ...failed4 ? { detail: "transport" } : {} };
|
|
19307
19349
|
}
|
|
19308
19350
|
entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
|
|
19309
19351
|
return this.headOf(handle, req.url, {
|
|
@@ -21210,7 +21252,7 @@ function pass(c, input, final) {
|
|
|
21210
21252
|
const partials = [];
|
|
21211
21253
|
scanMain(c, input, best, partials);
|
|
21212
21254
|
scanWrapped(c, input, best, partials);
|
|
21213
|
-
const
|
|
21255
|
+
const holds3 = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
|
|
21214
21256
|
const starts = [...best.keys()].sort((a, b) => a - b);
|
|
21215
21257
|
const parts2 = [];
|
|
21216
21258
|
const hits = /* @__PURE__ */ new Map();
|
|
@@ -21220,8 +21262,8 @@ function pass(c, input, final) {
|
|
|
21220
21262
|
let h = 0;
|
|
21221
21263
|
for (; ; ) {
|
|
21222
21264
|
while (s < starts.length && starts[s] < pos) s++;
|
|
21223
|
-
while (h <
|
|
21224
|
-
const hold = h <
|
|
21265
|
+
while (h < holds3.length && holds3[h] < pos) h++;
|
|
21266
|
+
const hold = h < holds3.length ? holds3[h] : Infinity;
|
|
21225
21267
|
const next3 = s < starts.length ? starts[s] : Infinity;
|
|
21226
21268
|
if (hold <= next3) {
|
|
21227
21269
|
cut = Math.min(hold, input.length);
|
|
@@ -21323,23 +21365,23 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
21323
21365
|
let pending = 0;
|
|
21324
21366
|
let busy = false;
|
|
21325
21367
|
let timer;
|
|
21326
|
-
let
|
|
21368
|
+
let failed4;
|
|
21327
21369
|
const waiters = /* @__PURE__ */ new Set();
|
|
21328
21370
|
const quiet2 = () => !busy && pending === 0;
|
|
21329
21371
|
const wake = () => {
|
|
21330
21372
|
for (const waiter of [...waiters]) waiter();
|
|
21331
21373
|
};
|
|
21332
21374
|
const raise = () => {
|
|
21333
|
-
if (
|
|
21334
|
-
const err =
|
|
21335
|
-
|
|
21375
|
+
if (failed4 === void 0) return;
|
|
21376
|
+
const err = failed4;
|
|
21377
|
+
failed4 = void 0;
|
|
21336
21378
|
throw err;
|
|
21337
21379
|
};
|
|
21338
21380
|
const later = (bytes) => {
|
|
21339
21381
|
if (bytes.length === 0) return;
|
|
21340
21382
|
pending += 1;
|
|
21341
21383
|
tail2 = tail2.then(() => writeAll3(file, bytes)).catch((err) => {
|
|
21342
|
-
if (
|
|
21384
|
+
if (failed4 === void 0) failed4 = err;
|
|
21343
21385
|
}).finally(() => {
|
|
21344
21386
|
pending -= 1;
|
|
21345
21387
|
if (quiet2()) wake();
|
|
@@ -24414,7 +24456,7 @@ async function connect(req, proc) {
|
|
|
24414
24456
|
}
|
|
24415
24457
|
const path = filePath(req.addr);
|
|
24416
24458
|
const name2 = path !== void 0 ? await proc.names?.find(path) : void 0;
|
|
24417
|
-
const stamp = proc.net.
|
|
24459
|
+
const stamp = proc.net.stampsPeers(req.addr) && await proc.stamp?.();
|
|
24418
24460
|
const dialing = target.connect(req.addr, true, proc.cred?.(), stamp || void 0, true, name2);
|
|
24419
24461
|
if (req.nonblock) {
|
|
24420
24462
|
dialing?.catch(() => void 0);
|
|
@@ -24536,7 +24578,7 @@ async function secureConnect(req, proc) {
|
|
|
24536
24578
|
delete req.clientCert;
|
|
24537
24579
|
throw new KernelError("ENOTSUP");
|
|
24538
24580
|
}
|
|
24539
|
-
return { ...tlsOverTransport(req, proc), path: "transport", substitutes: true };
|
|
24581
|
+
return { ...await tlsOverTransport(req, proc), path: "transport", substitutes: true };
|
|
24540
24582
|
}
|
|
24541
24583
|
const socket = proc.net.socket("inet");
|
|
24542
24584
|
const fd = proc.fds.install(new OpenFile(socket), 3);
|
|
@@ -24555,7 +24597,7 @@ async function uplinked(proc, host) {
|
|
|
24555
24597
|
return false;
|
|
24556
24598
|
}
|
|
24557
24599
|
}
|
|
24558
|
-
function tlsOverTransport(req, proc) {
|
|
24600
|
+
async function tlsOverTransport(req, proc) {
|
|
24559
24601
|
if (req.ca) throw new KernelError("ENOTSUP");
|
|
24560
24602
|
if (req.alpn && req.alpn.length > 0 && !req.alpn.includes("http/1.1")) {
|
|
24561
24603
|
throw new KernelError("EPROTONOSUPPORT");
|
|
@@ -24568,7 +24610,9 @@ function tlsOverTransport(req, proc) {
|
|
|
24568
24610
|
if (isLoopbackHost(servername) || isLoopbackHost(req.host)) throw new KernelError("ENOTSUP");
|
|
24569
24611
|
const host = servername.includes(":") && !servername.startsWith("[") ? `[${servername}]` : servername;
|
|
24570
24612
|
const origin = req.port === 443 ? `https://${host}` : `https://${host}:${req.port}`;
|
|
24613
|
+
const stamp = proc.net.originsStamped ? await proc.stamp?.() : void 0;
|
|
24571
24614
|
const [mine, theirs] = KernelSocket.pair(proc.net, "inet", proc.cred?.());
|
|
24615
|
+
theirs.peerStamp = stamp;
|
|
24572
24616
|
mine.peer = { family: "inet", host: req.host, port: req.port };
|
|
24573
24617
|
try {
|
|
24574
24618
|
proc.net.serveOrigin(theirs, origin);
|
|
@@ -27727,13 +27771,13 @@ function inherited(opts) {
|
|
|
27727
27771
|
...opts.cred ? { cred: opts.cred } : {}
|
|
27728
27772
|
};
|
|
27729
27773
|
}
|
|
27730
|
-
function heldBy(process,
|
|
27731
|
-
process.keptPath = (path) =>
|
|
27732
|
-
process.keptHandle = (handle) =>
|
|
27733
|
-
process.holdsHandle = (handle) =>
|
|
27774
|
+
function heldBy(process, holds3, replacements) {
|
|
27775
|
+
process.keptPath = (path) => holds3.keptAt(path)?.hidden;
|
|
27776
|
+
process.keptHandle = (handle) => holds3.keptFor(handle)?.hidden;
|
|
27777
|
+
process.holdsHandle = (handle) => holds3.holdsHandle(handle);
|
|
27734
27778
|
if (replacements) process.replacements = replacements;
|
|
27735
27779
|
}
|
|
27736
|
-
function holdingToken(opts,
|
|
27780
|
+
function holdingToken(opts, holds3, caller) {
|
|
27737
27781
|
return mintSyncFsToken({
|
|
27738
27782
|
...opts.owners ? caller : { umask: caller.umask },
|
|
27739
27783
|
...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
|
|
@@ -27750,16 +27794,16 @@ function holdingToken(opts, holds2, caller) {
|
|
|
27750
27794
|
...opts.fileId ? { fileId: opts.fileId } : {},
|
|
27751
27795
|
...opts.announceHold ? { announceHold: opts.announceHold } : {},
|
|
27752
27796
|
...opts.renameSeq ? { renameSeq: opts.renameSeq } : {},
|
|
27753
|
-
hold: (path, on, open2, real, handle, ino, fid) =>
|
|
27754
|
-
boundIno:
|
|
27755
|
-
trust:
|
|
27756
|
-
keptFor: (handle) =>
|
|
27757
|
-
heldAt: (handle) =>
|
|
27758
|
-
unlinked: (path) =>
|
|
27759
|
-
gate: (path, op) => opts.unlinkGate &&
|
|
27760
|
-
own: (path, op) =>
|
|
27761
|
-
revoked: (path) =>
|
|
27762
|
-
renamed: (from, to) =>
|
|
27797
|
+
hold: (path, on, open2, real, handle, ino, fid) => holds3.hold(path, on, open2, real, handle, ino, fid),
|
|
27798
|
+
boundIno: holds3.boundIno.bind(holds3),
|
|
27799
|
+
trust: holds3.trust.bind(holds3),
|
|
27800
|
+
keptFor: (handle) => holds3.keptFor(handle),
|
|
27801
|
+
heldAt: (handle) => holds3.pathOf(handle),
|
|
27802
|
+
unlinked: (path) => holds3.keptAt(path),
|
|
27803
|
+
gate: (path, op) => opts.unlinkGate && holds3.holding(path) ? opts.unlinkGate.run(holds3.keyOf(path), op) : op(),
|
|
27804
|
+
own: (path, op) => holds3.own(path, op),
|
|
27805
|
+
revoked: (path) => holds3.isRevoked(path),
|
|
27806
|
+
renamed: (from, to) => holds3.renamed(from, to)
|
|
27763
27807
|
});
|
|
27764
27808
|
}
|
|
27765
27809
|
function linksOf(opts) {
|
|
@@ -27916,15 +27960,15 @@ function spawnWasmProcess(opts) {
|
|
|
27916
27960
|
)
|
|
27917
27961
|
);
|
|
27918
27962
|
publishStops(process, header4);
|
|
27919
|
-
const
|
|
27920
|
-
opts.held?.add(
|
|
27921
|
-
const token = holdingToken(opts,
|
|
27963
|
+
const holds3 = new HeldPaths();
|
|
27964
|
+
opts.held?.add(holds3);
|
|
27965
|
+
const token = holdingToken(opts, holds3, {
|
|
27922
27966
|
cred: () => process.cred,
|
|
27923
27967
|
umask: () => process.umask,
|
|
27924
27968
|
created: created4,
|
|
27925
|
-
holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (
|
|
27969
|
+
holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (holds3.keeps(path) || await process.holds(path))
|
|
27926
27970
|
});
|
|
27927
|
-
heldBy(process,
|
|
27971
|
+
heldBy(process, holds3, opts.replacements);
|
|
27928
27972
|
const worker = opts.createWorker();
|
|
27929
27973
|
const dying = new Dying();
|
|
27930
27974
|
const dispatch2 = (req, block) => dying.serve(
|
|
@@ -27956,7 +28000,7 @@ function spawnWasmProcess(opts) {
|
|
|
27956
28000
|
responder.dispose();
|
|
27957
28001
|
lane?.dispose();
|
|
27958
28002
|
revokeSyncFsToken(token);
|
|
27959
|
-
opts.held?.delete(
|
|
28003
|
+
opts.held?.delete(holds3);
|
|
27960
28004
|
worker.terminate();
|
|
27961
28005
|
settleExit(process.exit(), settle3, code);
|
|
27962
28006
|
};
|
|
@@ -29035,6 +29079,236 @@ function enableDnsStub(net, stub) {
|
|
|
29035
29079
|
});
|
|
29036
29080
|
}
|
|
29037
29081
|
|
|
29082
|
+
// src/kernel/net/remote-transport.ts
|
|
29083
|
+
var TransportError = class extends Error {
|
|
29084
|
+
status;
|
|
29085
|
+
code;
|
|
29086
|
+
detail;
|
|
29087
|
+
constructor(message3, status, code, detail) {
|
|
29088
|
+
super(message3);
|
|
29089
|
+
this.status = status;
|
|
29090
|
+
this.code = code;
|
|
29091
|
+
this.detail = detail === "transport" ? detail : void 0;
|
|
29092
|
+
}
|
|
29093
|
+
};
|
|
29094
|
+
function unfollowed2(redirect) {
|
|
29095
|
+
return redirect !== void 0 && redirect !== "follow";
|
|
29096
|
+
}
|
|
29097
|
+
function honors(traits, redirect) {
|
|
29098
|
+
if (traits.redirectPolicy === true) return true;
|
|
29099
|
+
const hops = traits.redirectHops;
|
|
29100
|
+
const raw2 = traits.manualRedirects === true && (hops === void 0 || hops === false);
|
|
29101
|
+
return redirect === "manual" && raw2;
|
|
29102
|
+
}
|
|
29103
|
+
function refused3(message3) {
|
|
29104
|
+
return new TransportError(message3, 502, void 0, "transport");
|
|
29105
|
+
}
|
|
29106
|
+
var RemoteTransport = class {
|
|
29107
|
+
traits;
|
|
29108
|
+
port;
|
|
29109
|
+
waiting = /* @__PURE__ */ new Map();
|
|
29110
|
+
nextId = 0;
|
|
29111
|
+
sockets = /* @__PURE__ */ new Map();
|
|
29112
|
+
uploads = /* @__PURE__ */ new Map();
|
|
29113
|
+
failure;
|
|
29114
|
+
constructor(port, traits) {
|
|
29115
|
+
this.port = port;
|
|
29116
|
+
this.traits = traits;
|
|
29117
|
+
}
|
|
29118
|
+
receive(reply) {
|
|
29119
|
+
if (reply.net === "body-pull") {
|
|
29120
|
+
void this.pull(reply.nid);
|
|
29121
|
+
return;
|
|
29122
|
+
}
|
|
29123
|
+
const socket = this.sockets.get(reply.nid);
|
|
29124
|
+
if (socket && this.toSocket(reply, socket)) return;
|
|
29125
|
+
const waiter = this.waiting.get(reply.nid);
|
|
29126
|
+
if (!waiter) return;
|
|
29127
|
+
this.waiting.delete(reply.nid);
|
|
29128
|
+
if (reply.net === "error") {
|
|
29129
|
+
waiter.reject(new TransportError(reply.message, reply.status, reply.code, reply.detail));
|
|
29130
|
+
} else waiter.resolve(reply);
|
|
29131
|
+
}
|
|
29132
|
+
toSocket(reply, socket) {
|
|
29133
|
+
if (reply.net === "ws-message") socket.queue.push(reply.data);
|
|
29134
|
+
else if (reply.net === "ws-acked") socket.acked(reply.n);
|
|
29135
|
+
else if (reply.net === "ws-closed") {
|
|
29136
|
+
this.sockets.delete(reply.nid);
|
|
29137
|
+
socket.queue.end({ code: reply.code, reason: reply.reason });
|
|
29138
|
+
} else return false;
|
|
29139
|
+
return true;
|
|
29140
|
+
}
|
|
29141
|
+
async pull(nid) {
|
|
29142
|
+
const upload = this.uploads.get(nid);
|
|
29143
|
+
if (!upload) {
|
|
29144
|
+
this.port.postMessage({ net: "body-error", nid, message: "the request body is gone" });
|
|
29145
|
+
return;
|
|
29146
|
+
}
|
|
29147
|
+
try {
|
|
29148
|
+
const next3 = await upload.next();
|
|
29149
|
+
if (next3.done) {
|
|
29150
|
+
this.uploads.delete(nid);
|
|
29151
|
+
this.port.postMessage({ net: "body-end", nid });
|
|
29152
|
+
} else this.port.postMessage({ net: "body-chunk", nid, bytes: next3.value });
|
|
29153
|
+
} catch (e) {
|
|
29154
|
+
this.uploads.delete(nid);
|
|
29155
|
+
this.port.postMessage({
|
|
29156
|
+
net: "body-error",
|
|
29157
|
+
nid,
|
|
29158
|
+
message: e instanceof Error ? e.message : String(e)
|
|
29159
|
+
});
|
|
29160
|
+
}
|
|
29161
|
+
}
|
|
29162
|
+
dropUpload(nid) {
|
|
29163
|
+
const upload = this.uploads.get(nid);
|
|
29164
|
+
this.uploads.delete(nid);
|
|
29165
|
+
void upload?.return?.().catch(() => void 0);
|
|
29166
|
+
}
|
|
29167
|
+
fail(error) {
|
|
29168
|
+
this.failure = error;
|
|
29169
|
+
for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);
|
|
29170
|
+
for (const waiter of this.waiting.values()) waiter.reject(error);
|
|
29171
|
+
this.waiting.clear();
|
|
29172
|
+
for (const socket of this.sockets.values())
|
|
29173
|
+
socket.queue.end({ code: 1011, reason: error.message });
|
|
29174
|
+
this.sockets.clear();
|
|
29175
|
+
}
|
|
29176
|
+
ask(call) {
|
|
29177
|
+
if (this.failure) return Promise.reject(this.failure);
|
|
29178
|
+
return new Promise((resolve2, reject) => {
|
|
29179
|
+
this.waiting.set(call.nid, { resolve: resolve2, reject });
|
|
29180
|
+
this.port.postMessage(call);
|
|
29181
|
+
});
|
|
29182
|
+
}
|
|
29183
|
+
cancel(nid) {
|
|
29184
|
+
const waiter = this.waiting.get(nid);
|
|
29185
|
+
this.waiting.delete(nid);
|
|
29186
|
+
waiter?.reject(new TransportError("the request was cancelled"));
|
|
29187
|
+
this.port.postMessage({ net: "cancel", nid });
|
|
29188
|
+
}
|
|
29189
|
+
async fetch(request3, owner, stamp) {
|
|
29190
|
+
const nid = ++this.nextId;
|
|
29191
|
+
const { signal, redirect } = request3;
|
|
29192
|
+
signal.throwIfAborted();
|
|
29193
|
+
if (unfollowed2(redirect) && !honors(this.traits, redirect)) {
|
|
29194
|
+
throw refused3(`this transport cannot honor redirect: ${redirect}`);
|
|
29195
|
+
}
|
|
29196
|
+
let finished = false;
|
|
29197
|
+
const abort = () => {
|
|
29198
|
+
finished = true;
|
|
29199
|
+
this.dropUpload(nid);
|
|
29200
|
+
this.cancel(nid);
|
|
29201
|
+
};
|
|
29202
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
29203
|
+
const finish = () => {
|
|
29204
|
+
this.dropUpload(nid);
|
|
29205
|
+
if (finished) return;
|
|
29206
|
+
finished = true;
|
|
29207
|
+
signal.removeEventListener("abort", abort);
|
|
29208
|
+
};
|
|
29209
|
+
if (request3.bodyStream) this.uploads.set(nid, request3.bodyStream[Symbol.asyncIterator]());
|
|
29210
|
+
let head;
|
|
29211
|
+
try {
|
|
29212
|
+
head = await this.ask({
|
|
29213
|
+
net: "fetch",
|
|
29214
|
+
nid,
|
|
29215
|
+
url: request3.url,
|
|
29216
|
+
method: request3.method,
|
|
29217
|
+
headers: request3.headers,
|
|
29218
|
+
...request3.bodyStream ? { streamed: true } : request3.body ? { body: request3.body } : {},
|
|
29219
|
+
...redirect !== void 0 ? { redirect } : {},
|
|
29220
|
+
...owner !== void 0 ? { owner } : {},
|
|
29221
|
+
...stamp ? { stamp } : {}
|
|
29222
|
+
});
|
|
29223
|
+
} catch (e) {
|
|
29224
|
+
finish();
|
|
29225
|
+
throw e;
|
|
29226
|
+
}
|
|
29227
|
+
const { status, statusText, headers, url, redirected: redirected2, redirects, opaqueRedirect } = head;
|
|
29228
|
+
const read = async () => {
|
|
29229
|
+
if (finished) return void 0;
|
|
29230
|
+
const reply = await this.ask({ net: "read", nid }).catch((e) => {
|
|
29231
|
+
finish();
|
|
29232
|
+
throw e;
|
|
29233
|
+
});
|
|
29234
|
+
if (reply.net === "chunk") return reply.bytes;
|
|
29235
|
+
finish();
|
|
29236
|
+
return void 0;
|
|
29237
|
+
};
|
|
29238
|
+
const cancel = async () => {
|
|
29239
|
+
if (finished) return;
|
|
29240
|
+
finish();
|
|
29241
|
+
this.cancel(nid);
|
|
29242
|
+
};
|
|
29243
|
+
if (unfollowed2(redirect) && (redirected2 || redirects?.length)) {
|
|
29244
|
+
await cancel();
|
|
29245
|
+
throw refused3(`this transport followed a redirect despite redirect: ${redirect}`);
|
|
29246
|
+
}
|
|
29247
|
+
return {
|
|
29248
|
+
...url !== void 0 ? { url } : {},
|
|
29249
|
+
...redirected2 !== void 0 ? { redirected: redirected2 } : {},
|
|
29250
|
+
...redirects ? { redirects } : {},
|
|
29251
|
+
...opaqueRedirect ? { opaqueRedirect } : {},
|
|
29252
|
+
status,
|
|
29253
|
+
statusText,
|
|
29254
|
+
headers,
|
|
29255
|
+
cancel,
|
|
29256
|
+
body: {
|
|
29257
|
+
[Symbol.asyncIterator]: () => ({
|
|
29258
|
+
next: async () => {
|
|
29259
|
+
const bytes = await read();
|
|
29260
|
+
return bytes ? { value: bytes, done: false } : { value: void 0, done: true };
|
|
29261
|
+
},
|
|
29262
|
+
return: async () => {
|
|
29263
|
+
await cancel();
|
|
29264
|
+
return { value: void 0, done: true };
|
|
29265
|
+
}
|
|
29266
|
+
})
|
|
29267
|
+
}
|
|
29268
|
+
};
|
|
29269
|
+
}
|
|
29270
|
+
async websocket(request3) {
|
|
29271
|
+
const nid = ++this.nextId;
|
|
29272
|
+
const { signal } = request3;
|
|
29273
|
+
signal.throwIfAborted();
|
|
29274
|
+
const abort = () => this.cancel(nid);
|
|
29275
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
29276
|
+
let opened2;
|
|
29277
|
+
try {
|
|
29278
|
+
opened2 = await this.ask({
|
|
29279
|
+
net: "ws-open",
|
|
29280
|
+
nid,
|
|
29281
|
+
url: request3.url,
|
|
29282
|
+
protocols: request3.protocols,
|
|
29283
|
+
headers: request3.headers
|
|
29284
|
+
});
|
|
29285
|
+
} finally {
|
|
29286
|
+
signal.removeEventListener("abort", abort);
|
|
29287
|
+
}
|
|
29288
|
+
const close = (code, reason) => this.port.postMessage({ net: "ws-close", nid, code, reason });
|
|
29289
|
+
const queue = new MessageQueue(
|
|
29290
|
+
() => close(1e3, "a message is too big"),
|
|
29291
|
+
Number.POSITIVE_INFINITY,
|
|
29292
|
+
(n) => this.port.postMessage({ net: "ws-consumed", nid, n })
|
|
29293
|
+
);
|
|
29294
|
+
let unacked = 0;
|
|
29295
|
+
this.sockets.set(nid, { queue, acked: (n) => void (unacked -= n) });
|
|
29296
|
+
return {
|
|
29297
|
+
protocol: opened2.protocol,
|
|
29298
|
+
get buffered() {
|
|
29299
|
+
return unacked;
|
|
29300
|
+
},
|
|
29301
|
+
send: (data) => {
|
|
29302
|
+
unacked += payloadSize(data);
|
|
29303
|
+
this.port.postMessage({ net: "ws-send", nid, data });
|
|
29304
|
+
},
|
|
29305
|
+
messages: queue,
|
|
29306
|
+
close,
|
|
29307
|
+
closed: queue.closed
|
|
29308
|
+
};
|
|
29309
|
+
}
|
|
29310
|
+
};
|
|
29311
|
+
|
|
29038
29312
|
// src/kernel/net/redirect-hops.ts
|
|
29039
29313
|
var HELD_MS = 3e4;
|
|
29040
29314
|
var HELD_MAX2 = 64;
|
|
@@ -29110,7 +29384,9 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
29110
29384
|
return { ...inner.traits, manualRedirects: true };
|
|
29111
29385
|
},
|
|
29112
29386
|
...inner.websocket ? { websocket: inner.websocket.bind(inner) } : {},
|
|
29113
|
-
async fetch(request3,
|
|
29387
|
+
async fetch(request3, ...rest2) {
|
|
29388
|
+
if (unfollowed2(request3.redirect)) return inner.fetch(request3, ...rest2);
|
|
29389
|
+
const [caller] = rest2;
|
|
29114
29390
|
const owner = caller ?? KERNEL;
|
|
29115
29391
|
const key = keyOf3(owner, request3.method, request3.url);
|
|
29116
29392
|
const waiting = held.get(key);
|
|
@@ -29120,7 +29396,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
29120
29396
|
return replay(waiting);
|
|
29121
29397
|
}
|
|
29122
29398
|
if (waiting) drop(key);
|
|
29123
|
-
const response = await inner.fetch(request3,
|
|
29399
|
+
const response = await inner.fetch(request3, ...rest2);
|
|
29124
29400
|
if (!response.redirects?.length) return response;
|
|
29125
29401
|
return replay({
|
|
29126
29402
|
owner,
|
|
@@ -29133,6 +29409,143 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
29133
29409
|
};
|
|
29134
29410
|
}
|
|
29135
29411
|
|
|
29412
|
+
// src/kernel/net/sealed-fetch.ts
|
|
29413
|
+
var UNSAFE_FIELD = /[\r\n\0]/;
|
|
29414
|
+
function headerList(headers) {
|
|
29415
|
+
return Array.isArray(headers) && headers.every(
|
|
29416
|
+
(field4) => Array.isArray(field4) && field4.length === 2 && field4.every((text) => typeof text === "string" && !UNSAFE_FIELD.test(text))
|
|
29417
|
+
);
|
|
29418
|
+
}
|
|
29419
|
+
function sealedReplyValid(reply) {
|
|
29420
|
+
if (typeof reply !== "object" || reply === null) return false;
|
|
29421
|
+
const { redirects, redirected: redirected2, status, statusText, headers, url, body, cancel } = reply;
|
|
29422
|
+
return redirects === void 0 && redirected2 !== true && Number.isInteger(status) && status >= 100 && status <= 599 && typeof statusText === "string" && !UNSAFE_FIELD.test(statusText) && headerList(headers) && (url === void 0 || typeof url === "string") && typeof body?.[Symbol.asyncIterator] === "function" && typeof cancel === "function";
|
|
29423
|
+
}
|
|
29424
|
+
function dropSealedReply(reply) {
|
|
29425
|
+
const { cancel } = reply ?? {};
|
|
29426
|
+
if (typeof cancel !== "function") return;
|
|
29427
|
+
void Promise.resolve().then(() => cancel.call(reply)).catch(() => void 0);
|
|
29428
|
+
}
|
|
29429
|
+
function failed2(reason) {
|
|
29430
|
+
const text = reason instanceof Error ? reason.message : String(reason);
|
|
29431
|
+
return new PlaceholderRefused(
|
|
29432
|
+
`refused: the request with a sealed placeholder was not completed: ${text}`
|
|
29433
|
+
);
|
|
29434
|
+
}
|
|
29435
|
+
var Stall = class {
|
|
29436
|
+
idle = new AbortController();
|
|
29437
|
+
ms;
|
|
29438
|
+
timer;
|
|
29439
|
+
signal;
|
|
29440
|
+
constructor(signals, ms) {
|
|
29441
|
+
this.ms = ms;
|
|
29442
|
+
this.signal = AbortSignal.any([...signals, this.idle.signal]);
|
|
29443
|
+
}
|
|
29444
|
+
arm() {
|
|
29445
|
+
clearTimeout(this.timer);
|
|
29446
|
+
this.timer = setTimeout(() => this.idle.abort("timeout"), this.ms);
|
|
29447
|
+
this.timer.unref?.();
|
|
29448
|
+
}
|
|
29449
|
+
touch() {
|
|
29450
|
+
if (this.timer !== void 0) this.arm();
|
|
29451
|
+
}
|
|
29452
|
+
rest() {
|
|
29453
|
+
clearTimeout(this.timer);
|
|
29454
|
+
this.timer = void 0;
|
|
29455
|
+
}
|
|
29456
|
+
};
|
|
29457
|
+
async function until(work, signal) {
|
|
29458
|
+
const stopped = Promise.withResolvers();
|
|
29459
|
+
const stop = () => stopped.reject(signal.reason);
|
|
29460
|
+
if (signal.aborted) stop();
|
|
29461
|
+
else signal.addEventListener("abort", stop, { once: true });
|
|
29462
|
+
try {
|
|
29463
|
+
return await Promise.race([work, stopped.promise]);
|
|
29464
|
+
} finally {
|
|
29465
|
+
signal.removeEventListener("abort", stop);
|
|
29466
|
+
}
|
|
29467
|
+
}
|
|
29468
|
+
async function* ticking(stream, stall) {
|
|
29469
|
+
for await (const chunk2 of stream) {
|
|
29470
|
+
stall.touch();
|
|
29471
|
+
yield chunk2;
|
|
29472
|
+
}
|
|
29473
|
+
}
|
|
29474
|
+
function sealedRequest(request3, stamp, stall) {
|
|
29475
|
+
const { method, url, headers, body, bodyStream } = request3;
|
|
29476
|
+
return {
|
|
29477
|
+
v: 1,
|
|
29478
|
+
caller: structuredClone(stamp),
|
|
29479
|
+
method,
|
|
29480
|
+
url,
|
|
29481
|
+
headers: headers.map(([name2, value2]) => [name2, value2]),
|
|
29482
|
+
redirect: "manual",
|
|
29483
|
+
...bodyStream ? { bodyStream: ticking(bodyStream, stall) } : body ? { body } : {}
|
|
29484
|
+
};
|
|
29485
|
+
}
|
|
29486
|
+
function guarded2(reply, stall) {
|
|
29487
|
+
let finished = false;
|
|
29488
|
+
const cancel = async () => {
|
|
29489
|
+
stall.signal.removeEventListener("abort", dropped2);
|
|
29490
|
+
stall.rest();
|
|
29491
|
+
if (finished) return;
|
|
29492
|
+
finished = true;
|
|
29493
|
+
await reply.cancel().catch(() => void 0);
|
|
29494
|
+
};
|
|
29495
|
+
const dropped2 = () => void cancel();
|
|
29496
|
+
stall.signal.addEventListener("abort", dropped2, { once: true });
|
|
29497
|
+
const source = reply.body[Symbol.asyncIterator]();
|
|
29498
|
+
const body = (async function* () {
|
|
29499
|
+
try {
|
|
29500
|
+
for (; ; ) {
|
|
29501
|
+
stall.arm();
|
|
29502
|
+
const next3 = await until(source.next(), stall.signal);
|
|
29503
|
+
stall.rest();
|
|
29504
|
+
if (next3.done) {
|
|
29505
|
+
finished = true;
|
|
29506
|
+
return;
|
|
29507
|
+
}
|
|
29508
|
+
if (!(next3.value instanceof Uint8Array)) throw failed2("a body chunk is not bytes");
|
|
29509
|
+
if (next3.value.byteLength > 0) yield next3.value;
|
|
29510
|
+
}
|
|
29511
|
+
} finally {
|
|
29512
|
+
await cancel();
|
|
29513
|
+
}
|
|
29514
|
+
})();
|
|
29515
|
+
return {
|
|
29516
|
+
...reply.url !== void 0 ? { url: reply.url } : {},
|
|
29517
|
+
status: reply.status,
|
|
29518
|
+
statusText: reply.statusText,
|
|
29519
|
+
headers: reply.headers,
|
|
29520
|
+
body,
|
|
29521
|
+
cancel
|
|
29522
|
+
};
|
|
29523
|
+
}
|
|
29524
|
+
function sealedFetcher(hook, stop, idleMs = BODY_IDLE_MS) {
|
|
29525
|
+
return async (request3, stamp) => {
|
|
29526
|
+
const stall = new Stall([request3.signal, stop], idleMs);
|
|
29527
|
+
const { signal } = stall;
|
|
29528
|
+
if (signal.aborted) throw failed2(signal.reason);
|
|
29529
|
+
stall.arm();
|
|
29530
|
+
const asked = Promise.resolve().then(() => {
|
|
29531
|
+
signal.throwIfAborted();
|
|
29532
|
+
return hook(sealedRequest(request3, stamp, stall), { signal });
|
|
29533
|
+
});
|
|
29534
|
+
let reply;
|
|
29535
|
+
try {
|
|
29536
|
+
reply = await until(asked, signal);
|
|
29537
|
+
} catch (e) {
|
|
29538
|
+
void asked.then(dropSealedReply, () => void 0);
|
|
29539
|
+
throw failed2(e);
|
|
29540
|
+
} finally {
|
|
29541
|
+
stall.rest();
|
|
29542
|
+
}
|
|
29543
|
+
if (sealedReplyValid(reply)) return guarded2(reply, stall);
|
|
29544
|
+
dropSealedReply(reply);
|
|
29545
|
+
throw failed2("the reply is not a scrubbed response");
|
|
29546
|
+
};
|
|
29547
|
+
}
|
|
29548
|
+
|
|
29136
29549
|
// src/kernel/package-swaps.ts
|
|
29137
29550
|
var SWAP_GAP_MS = 2e3;
|
|
29138
29551
|
var STAGES = ["_tmp_", "_pacquet-stage_"];
|
|
@@ -29305,11 +29718,11 @@ var PackageLocks = class {
|
|
|
29305
29718
|
if (!locks) return Promise.resolve(() => {
|
|
29306
29719
|
});
|
|
29307
29720
|
const { promise: held, resolve: release } = Promise.withResolvers();
|
|
29308
|
-
return new Promise((granted2,
|
|
29721
|
+
return new Promise((granted2, failed4) => {
|
|
29309
29722
|
locks.request(replacingLock(this.metadata, root), { mode: "exclusive" }, () => {
|
|
29310
29723
|
granted2(() => release());
|
|
29311
29724
|
return held;
|
|
29312
|
-
}).catch(
|
|
29725
|
+
}).catch(failed4);
|
|
29313
29726
|
});
|
|
29314
29727
|
}
|
|
29315
29728
|
};
|
|
@@ -29559,9 +29972,9 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
|
|
|
29559
29972
|
let open2 = false;
|
|
29560
29973
|
const reply = (message3, transfer = []) => port.postMessage(message3, transfer);
|
|
29561
29974
|
async function hello(message3) {
|
|
29562
|
-
const
|
|
29563
|
-
if (
|
|
29564
|
-
reply({ hello: { protocol: DRIVER_PROTOCOL, error:
|
|
29975
|
+
const refused4 = driverVersionError(message3.protocol);
|
|
29976
|
+
if (refused4) {
|
|
29977
|
+
reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused4, errno: "EPROTO" } });
|
|
29565
29978
|
return;
|
|
29566
29979
|
}
|
|
29567
29980
|
try {
|
|
@@ -29911,22 +30324,22 @@ async function mountFstab(lines2, mount, signal, retries = FSTAB_RETRIES, discar
|
|
|
29911
30324
|
);
|
|
29912
30325
|
}
|
|
29913
30326
|
async function mountLine({ line, spec, invalid }, mount, signal, retries, discard) {
|
|
29914
|
-
let
|
|
30327
|
+
let failed4 = invalid;
|
|
29915
30328
|
for (let attempt = 0; !invalid && attempt <= retries.length && !signal.aborted; attempt++) {
|
|
29916
30329
|
try {
|
|
29917
30330
|
const entry = await mount(spec);
|
|
29918
30331
|
if (!signal.aborted) return { line, target: spec.target, entry };
|
|
29919
30332
|
discard(entry);
|
|
29920
|
-
|
|
30333
|
+
failed4 = Object.assign(new Error("the kernel stopped"), { code: "ECANCELED" });
|
|
29921
30334
|
break;
|
|
29922
30335
|
} catch (err) {
|
|
29923
|
-
|
|
30336
|
+
failed4 = err;
|
|
29924
30337
|
if (FINAL.has(codeOf6(err)) || attempt === retries.length) break;
|
|
29925
30338
|
await wait(retries[attempt], signal);
|
|
29926
30339
|
}
|
|
29927
30340
|
}
|
|
29928
|
-
const code = codeOf6(
|
|
29929
|
-
return { line, target: spec.target, code, error: String(
|
|
30341
|
+
const code = codeOf6(failed4);
|
|
30342
|
+
return { line, target: spec.target, code, error: String(failed4?.message ?? code) };
|
|
29930
30343
|
}
|
|
29931
30344
|
|
|
29932
30345
|
// src/mount/hostfs.ts
|
|
@@ -31100,7 +31513,7 @@ var RULE = new RegExp(
|
|
|
31100
31513
|
var TERM = /^[A-Za-z0-9._+-]+$/;
|
|
31101
31514
|
var PLAIN3 = /^[A-Za-z0-9_@%+=:,./-]+$/;
|
|
31102
31515
|
var USAGE = "usage: sudo [-n] [-u user] [--] command [args...]\n sudo -l";
|
|
31103
|
-
function
|
|
31516
|
+
function failed3(errno3, error) {
|
|
31104
31517
|
return { error, errno: errno3 };
|
|
31105
31518
|
}
|
|
31106
31519
|
function unescaped(double) {
|
|
@@ -31279,10 +31692,10 @@ var Sudo = class {
|
|
|
31279
31692
|
}
|
|
31280
31693
|
async untrusted(path, cwd, word) {
|
|
31281
31694
|
const files = this.o.backing ? await this.o.backing(path, cwd) : [];
|
|
31282
|
-
if (!files) return
|
|
31695
|
+
if (!files) return failed3("ENOENT", `sudo: ${word}: command not found`);
|
|
31283
31696
|
for (const file of [path, ...files]) {
|
|
31284
31697
|
if (!await this.trusted(file)) {
|
|
31285
|
-
return
|
|
31698
|
+
return failed3("EPERM", `sudo: ${file} must be root's, and writable by root only`);
|
|
31286
31699
|
}
|
|
31287
31700
|
}
|
|
31288
31701
|
return void 0;
|
|
@@ -31299,7 +31712,7 @@ var Sudo = class {
|
|
|
31299
31712
|
}
|
|
31300
31713
|
async request(caller, call, signal) {
|
|
31301
31714
|
const parsed2 = parseArgs(call.args);
|
|
31302
|
-
if (typeof parsed2 === "string") return
|
|
31715
|
+
if (typeof parsed2 === "string") return failed3("EINVAL", parsed2);
|
|
31303
31716
|
if (this.o.mode !== "enforce") {
|
|
31304
31717
|
const mode = this.o.mode;
|
|
31305
31718
|
if (parsed2.list) return { list: `sudo: users are '${mode}': commands run as the caller
|
|
@@ -31308,9 +31721,9 @@ var Sudo = class {
|
|
|
31308
31721
|
}
|
|
31309
31722
|
const { cred } = caller;
|
|
31310
31723
|
const self = await this.o.users.lookup(cred.ruid);
|
|
31311
|
-
if (!self) return
|
|
31724
|
+
if (!self) return failed3("EPERM", `sudo: uid ${cred.ruid} is not in the passwd database`);
|
|
31312
31725
|
const target = await this.lookup(parsed2.user);
|
|
31313
|
-
if (!target) return
|
|
31726
|
+
if (!target) return failed3("ENOENT", `sudo: unknown user ${parsed2.user}`);
|
|
31314
31727
|
const root = cred.euid === 0;
|
|
31315
31728
|
const rules = root ? [] : await this.policy();
|
|
31316
31729
|
const applies = await this.applies(self, cred);
|
|
@@ -31318,13 +31731,13 @@ var Sudo = class {
|
|
|
31318
31731
|
const [word = "", ...args] = parsed2.command;
|
|
31319
31732
|
const cwd = await this.canonical(call.cwd);
|
|
31320
31733
|
if (cwd === void 0 || !await this.reachable(cred, cwd)) {
|
|
31321
|
-
return
|
|
31734
|
+
return failed3(
|
|
31322
31735
|
"EACCES",
|
|
31323
31736
|
`sudo: cannot run in ${call.cwd}: it isn't a directory you can enter`
|
|
31324
31737
|
);
|
|
31325
31738
|
}
|
|
31326
31739
|
const path = await this.locate(word, cwd);
|
|
31327
|
-
if (!path) return
|
|
31740
|
+
if (!path) return failed3("ENOENT", `sudo: ${word}: command not found`);
|
|
31328
31741
|
const untrusted2 = await this.untrusted(path, cwd, word);
|
|
31329
31742
|
if (untrusted2) return untrusted2;
|
|
31330
31743
|
const argv = [path, ...args];
|
|
@@ -31335,24 +31748,24 @@ var Sudo = class {
|
|
|
31335
31748
|
if (root || matching.some((rule) => rule.nopasswd)) return grant();
|
|
31336
31749
|
const quoted = argv.map(quoteWord).join(" ");
|
|
31337
31750
|
if (matching.length === 0) {
|
|
31338
|
-
return
|
|
31751
|
+
return failed3(
|
|
31339
31752
|
"EPERM",
|
|
31340
31753
|
`sudo: ${self.name} is not allowed to run ${quoted} as ${target.name}`
|
|
31341
31754
|
);
|
|
31342
31755
|
}
|
|
31343
|
-
if (parsed2.nonInteractive) return
|
|
31344
|
-
if (this.pending.has(cred.ruid)) return
|
|
31756
|
+
if (parsed2.nonInteractive) return failed3("EPERM", "sudo: a password is required");
|
|
31757
|
+
if (this.pending.has(cred.ruid)) return failed3("EBUSY", "sudo: another request is pending");
|
|
31345
31758
|
this.pending.add(cred.ruid);
|
|
31346
31759
|
try {
|
|
31347
31760
|
const answer2 = await this.ask(caller, self, target, parsed2.command, path, cwd, signal);
|
|
31348
31761
|
if (typeof answer2 !== "string") return answer2;
|
|
31349
31762
|
if (await this.canonical(call.cwd) !== cwd || !await this.reachable(cred, cwd)) {
|
|
31350
|
-
return
|
|
31763
|
+
return failed3("EACCES", `sudo: ${call.cwd} changed while the request waited`);
|
|
31351
31764
|
}
|
|
31352
31765
|
const changed = await this.untrusted(path, cwd, word);
|
|
31353
31766
|
if (changed) return changed;
|
|
31354
31767
|
if (answer2 === "always" && !await this.remember(self, target, cwd, argv)) {
|
|
31355
|
-
return
|
|
31768
|
+
return failed3("EIO", "sudo: the rule could not be recorded");
|
|
31356
31769
|
}
|
|
31357
31770
|
return grant();
|
|
31358
31771
|
} finally {
|
|
@@ -31369,7 +31782,7 @@ var Sudo = class {
|
|
|
31369
31782
|
};
|
|
31370
31783
|
}
|
|
31371
31784
|
if (rules.length === 0) {
|
|
31372
|
-
return
|
|
31785
|
+
return failed3("EPERM", `User ${self.name} is not allowed to run sudo on ${host}.`);
|
|
31373
31786
|
}
|
|
31374
31787
|
const lines2 = rules.map(described).join("\n");
|
|
31375
31788
|
return { list: `User ${self.name} may run the following commands on ${host}:
|
|
@@ -31378,7 +31791,7 @@ ${lines2}
|
|
|
31378
31791
|
}
|
|
31379
31792
|
async ask(caller, self, target, argv, path, cwd, requester) {
|
|
31380
31793
|
const { approve } = this.o;
|
|
31381
|
-
if (!approve || requester.aborted) return
|
|
31794
|
+
if (!approve || requester.aborted) return failed3("EACCES", "sudo: approval denied");
|
|
31382
31795
|
const createdAt = Date.now();
|
|
31383
31796
|
const timeout = this.o.timeoutMs ?? SUDO_TIMEOUT_MS;
|
|
31384
31797
|
const req = {
|
|
@@ -31408,9 +31821,9 @@ ${lines2}
|
|
|
31408
31821
|
const answered2 = Promise.resolve().then(() => approve(req, { signal: control.signal })).catch(() => "deny");
|
|
31409
31822
|
const answer2 = await Promise.race([answered2, aborted3]);
|
|
31410
31823
|
if (answer2 === "aborted" || control.signal.aborted) {
|
|
31411
|
-
return control.signal.reason === "expired" ?
|
|
31824
|
+
return control.signal.reason === "expired" ? failed3("ETIMEDOUT", "sudo: the request expired") : failed3("EINTR", "sudo: the request was withdrawn");
|
|
31412
31825
|
}
|
|
31413
|
-
return answer2 === "once" || answer2 === "always" ? answer2 :
|
|
31826
|
+
return answer2 === "once" || answer2 === "always" ? answer2 : failed3("EACCES", "sudo: approval denied");
|
|
31414
31827
|
} finally {
|
|
31415
31828
|
clearTimeout(timer);
|
|
31416
31829
|
requester.removeEventListener("abort", withdraw);
|
|
@@ -31701,13 +32114,13 @@ function interpreter(head) {
|
|
|
31701
32114
|
function expandDefaults(defaults2, env) {
|
|
31702
32115
|
const out = {};
|
|
31703
32116
|
for (const [key, value2] of Object.entries(defaults2 ?? {})) {
|
|
31704
|
-
let
|
|
32117
|
+
let missing6 = false;
|
|
31705
32118
|
const expanded = value2.replace(ENV_REFERENCE, (_, name2) => {
|
|
31706
32119
|
const set3 = Object.hasOwn(env, name2) ? env[name2] : void 0;
|
|
31707
|
-
if (set3 === void 0)
|
|
32120
|
+
if (set3 === void 0) missing6 = true;
|
|
31708
32121
|
return set3 ?? "";
|
|
31709
32122
|
});
|
|
31710
|
-
if (!
|
|
32123
|
+
if (!missing6) out[key] = expanded;
|
|
31711
32124
|
}
|
|
31712
32125
|
return out;
|
|
31713
32126
|
}
|
|
@@ -31882,6 +32295,9 @@ var Launcher = class {
|
|
|
31882
32295
|
usersMode;
|
|
31883
32296
|
dac;
|
|
31884
32297
|
sealed;
|
|
32298
|
+
fill;
|
|
32299
|
+
fills = new AbortController();
|
|
32300
|
+
placeholders = [];
|
|
31885
32301
|
scrubs = /* @__PURE__ */ new Map();
|
|
31886
32302
|
clipboard;
|
|
31887
32303
|
embedder;
|
|
@@ -31963,7 +32379,7 @@ var Launcher = class {
|
|
|
31963
32379
|
...options.env
|
|
31964
32380
|
};
|
|
31965
32381
|
this.ca = kernelCa(options.caStore ?? memoryCaStore());
|
|
31966
|
-
this.transport =
|
|
32382
|
+
this.transport = this.floored(options);
|
|
31967
32383
|
this.announcedTraits = JSON.stringify(this.transport.traits);
|
|
31968
32384
|
this.uplink = options.uplink;
|
|
31969
32385
|
this.routes = new Routes(options.uplink?.traits.ipv6 === true);
|
|
@@ -32118,16 +32534,16 @@ var Launcher = class {
|
|
|
32118
32534
|
if (!found) {
|
|
32119
32535
|
found = this.swaps.settled().then(() => this.trustedAppended()).then(async (appended2) => {
|
|
32120
32536
|
const tiers = await this.tiers(scope, appended2);
|
|
32121
|
-
const
|
|
32537
|
+
const refused4 = [];
|
|
32122
32538
|
const commands = await scanCommands(
|
|
32123
32539
|
this.scanned,
|
|
32124
32540
|
tiers,
|
|
32125
32541
|
tiers.length - appended2.length,
|
|
32126
32542
|
void 0,
|
|
32127
|
-
|
|
32543
|
+
refused4,
|
|
32128
32544
|
await this.globalRoots(scope)
|
|
32129
32545
|
);
|
|
32130
|
-
this.refusedOf.set(commands,
|
|
32546
|
+
this.refusedOf.set(commands, refused4.map(refusing));
|
|
32131
32547
|
return commands;
|
|
32132
32548
|
}).then(
|
|
32133
32549
|
(commands) => this.refusals(commands).set(SUDO_COMMAND.name, SUDO_COMMAND).set(CRONTAB_COMMAND.name, CRONTAB_COMMAND)
|
|
@@ -32333,14 +32749,14 @@ var Launcher = class {
|
|
|
32333
32749
|
return await this.commandAt(path, scope) ?? await this.refusedAt(path, name2, scope);
|
|
32334
32750
|
}
|
|
32335
32751
|
async refusedAt(path, name2, scope) {
|
|
32336
|
-
const
|
|
32337
|
-
if (
|
|
32752
|
+
const refused4 = this.refusedOf.get(await this.commands(scope)) ?? [];
|
|
32753
|
+
if (refused4.length === 0) return void 0;
|
|
32338
32754
|
const st = await this.base.stat(path).catch(() => void 0);
|
|
32339
32755
|
if (!st?.isFile) return void 0;
|
|
32340
32756
|
const real = await physicalPathAsync(this.base, path).catch(() => path);
|
|
32341
32757
|
const same3 = async (own) => own === path || await physicalPathAsync(this.base, own).catch(() => own) === real;
|
|
32342
32758
|
const owners = [];
|
|
32343
|
-
for (const c of
|
|
32759
|
+
for (const c of refused4) {
|
|
32344
32760
|
const origin = c.origin;
|
|
32345
32761
|
for (const own of [origin.glue, origin.wasm, ...origin.variants ?? []]) {
|
|
32346
32762
|
if (!await same3(own)) continue;
|
|
@@ -32350,11 +32766,11 @@ var Launcher = class {
|
|
|
32350
32766
|
}
|
|
32351
32767
|
const stem = name2.replace(/\.wasm$/, "");
|
|
32352
32768
|
const named = owners.find((c) => c.name === name2) ?? owners.find((c) => c.name === stem);
|
|
32353
|
-
return named ?? owners[0] ?? await this.refusedCopy(real, name2,
|
|
32769
|
+
return named ?? owners[0] ?? await this.refusedCopy(real, name2, refused4);
|
|
32354
32770
|
}
|
|
32355
|
-
async refusedCopy(real, name2,
|
|
32771
|
+
async refusedCopy(real, name2, refused4) {
|
|
32356
32772
|
const dir = real.slice(0, real.lastIndexOf("/"));
|
|
32357
|
-
for (const c of
|
|
32773
|
+
for (const c of refused4) {
|
|
32358
32774
|
const origin = c.origin;
|
|
32359
32775
|
if (origin.abi !== "emscripten" || origin.script || c.name !== name2) continue;
|
|
32360
32776
|
const own = await physicalPathAsync(this.base, origin.glue).catch(() => origin.glue);
|
|
@@ -32562,12 +32978,12 @@ var Launcher = class {
|
|
|
32562
32978
|
return void 0;
|
|
32563
32979
|
}
|
|
32564
32980
|
async planOne(req, { ppid, cred, scope }, catalogOnly = false) {
|
|
32565
|
-
const
|
|
32981
|
+
const refused4 = (err) => {
|
|
32566
32982
|
throw codeOf8(err) === "EACCES" ? new SpawnError("EACCES") : err;
|
|
32567
32983
|
};
|
|
32568
|
-
const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(
|
|
32984
|
+
const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused4);
|
|
32569
32985
|
const planned = await this.plan(file, req.argv, req.cwd, scope, req.argv0, catalogOnly);
|
|
32570
|
-
await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(
|
|
32986
|
+
await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused4);
|
|
32571
32987
|
if (planned) return planned;
|
|
32572
32988
|
throw new SpawnError(catalogOnly ? "ENOENT" : await this.unrunnable(file, req.cwd, scope));
|
|
32573
32989
|
}
|
|
@@ -33025,6 +33441,19 @@ var Launcher = class {
|
|
|
33025
33441
|
groupSession(pgid) {
|
|
33026
33442
|
return this.jobs.sessionOf(pgid);
|
|
33027
33443
|
}
|
|
33444
|
+
floored(options) {
|
|
33445
|
+
const { sealedFetch } = options;
|
|
33446
|
+
this.fill = sealedFetch && this.usersMode === "enforce" ? sealedFetcher(sealedFetch, this.fills.signal) : void 0;
|
|
33447
|
+
if (this.fill) this.net.stampProxy(REALM_PROXY_PORT);
|
|
33448
|
+
return placeholderFloor(replayingHops(options.transport ?? missingTransport()), {
|
|
33449
|
+
known: () => this.placeholders,
|
|
33450
|
+
...this.fill ? { fill: this.fill } : {}
|
|
33451
|
+
});
|
|
33452
|
+
}
|
|
33453
|
+
httpFor(pid) {
|
|
33454
|
+
const stamp = this.fill ? () => this.liveStamp(pid) : void 0;
|
|
33455
|
+
return new HttpHandles(this.transport, pid, this.loopbackFor(pid), stamp);
|
|
33456
|
+
}
|
|
33028
33457
|
loopbackFor(pid) {
|
|
33029
33458
|
return new KernelLoopback(
|
|
33030
33459
|
this.net,
|
|
@@ -33032,7 +33461,7 @@ var Launcher = class {
|
|
|
33032
33461
|
const cred = this.credOf(pid);
|
|
33033
33462
|
return { pid, uid: cred.euid, gid: cred.egid };
|
|
33034
33463
|
},
|
|
33035
|
-
() => this.
|
|
33464
|
+
() => this.liveStamp(pid)
|
|
33036
33465
|
);
|
|
33037
33466
|
}
|
|
33038
33467
|
sourceCheck(pid, writer) {
|
|
@@ -33197,7 +33626,7 @@ var Launcher = class {
|
|
|
33197
33626
|
jobs: this.jobs,
|
|
33198
33627
|
ptys: this.ptys,
|
|
33199
33628
|
net: this.net,
|
|
33200
|
-
http:
|
|
33629
|
+
http: this.httpFor(pid),
|
|
33201
33630
|
locks: this.locks,
|
|
33202
33631
|
fifos: this.fifos,
|
|
33203
33632
|
sems: this.sems,
|
|
@@ -33512,6 +33941,19 @@ var Launcher = class {
|
|
|
33512
33941
|
connectorStamp(pid) {
|
|
33513
33942
|
return this.sealed.stamp(this.identityOf(pid), this.credOf(pid), this.tagsOf(pid));
|
|
33514
33943
|
}
|
|
33944
|
+
async liveStamp(pid) {
|
|
33945
|
+
if (!this.creds.has(pid) || this.zombies.has(pid)) return void 0;
|
|
33946
|
+
return this.connectorStamp(pid);
|
|
33947
|
+
}
|
|
33948
|
+
setPlaceholders(list) {
|
|
33949
|
+
if (!Array.isArray(list) || !list.every((p) => typeof p === "string" && p !== "")) {
|
|
33950
|
+
throw fsError("EINVAL", "setPlaceholders takes a list of non-empty strings");
|
|
33951
|
+
}
|
|
33952
|
+
this.placeholders = [...list];
|
|
33953
|
+
}
|
|
33954
|
+
endFills() {
|
|
33955
|
+
this.fills.abort("terminated");
|
|
33956
|
+
}
|
|
33515
33957
|
identityOf(pid) {
|
|
33516
33958
|
const parent = this.jobs.shownParent(pid);
|
|
33517
33959
|
const alive = parent !== void 0 && this.running(parent);
|
|
@@ -33634,7 +34076,7 @@ var Launcher = class {
|
|
|
33634
34076
|
const at = normalizePath(path);
|
|
33635
34077
|
this.unlinked.closed(at);
|
|
33636
34078
|
this.writers?.unlinked.closed(at);
|
|
33637
|
-
const holding = [...this.held].some((
|
|
34079
|
+
const holding = [...this.held].some((holds3) => holds3.holding(at)) || [...this.openFiles].some((open3) => open3.holdsAt(at));
|
|
33638
34080
|
if (!holding) void this.rootFs.announceHolds?.([], [at], false);
|
|
33639
34081
|
const open2 = [...this.openFiles].some((nodes) => nodes.writes(at)) || heldUnder(this.held, at);
|
|
33640
34082
|
if (!open2) void this.mounts.commit(at).catch(() => void 0);
|
|
@@ -33797,8 +34239,9 @@ var Launcher = class {
|
|
|
33797
34239
|
for (const root of roots) this.integrity.forget(root);
|
|
33798
34240
|
this.resetCatalogs();
|
|
33799
34241
|
}
|
|
33800
|
-
attest(path) {
|
|
34242
|
+
attest(path, options = {}) {
|
|
33801
34243
|
return attest(this.rootFs, path, {
|
|
34244
|
+
...options,
|
|
33802
34245
|
users: this.usersMode,
|
|
33803
34246
|
mounts: this.mounts.list().map((entry) => entry.target).filter((target) => this.mounts.mounted(target) !== void 0)
|
|
33804
34247
|
});
|
|
@@ -33855,8 +34298,8 @@ var Launcher = class {
|
|
|
33855
34298
|
for (const name2 of names2 ?? []) {
|
|
33856
34299
|
const path = joinName(real, name2);
|
|
33857
34300
|
if (await this.base.hasOwner(path)) continue;
|
|
33858
|
-
const
|
|
33859
|
-
if (
|
|
34301
|
+
const failed4 = this.inUse(path) ? "busy" : await this.base.rm(path, { recursive: true, force: true }).catch(String);
|
|
34302
|
+
if (failed4 === void 0) removed++;
|
|
33860
34303
|
else left++;
|
|
33861
34304
|
}
|
|
33862
34305
|
if (removed > 0) {
|
|
@@ -33951,7 +34394,7 @@ var Launcher = class {
|
|
|
33951
34394
|
this.pnpmStale();
|
|
33952
34395
|
if (!detach) return;
|
|
33953
34396
|
for (const nodes of this.openFiles) nodes.revoke(at);
|
|
33954
|
-
for (const
|
|
34397
|
+
for (const holds3 of this.held) holds3.revoke(at);
|
|
33955
34398
|
}
|
|
33956
34399
|
unmountAll() {
|
|
33957
34400
|
this.cron.stop();
|
|
@@ -34162,9 +34605,9 @@ var Launcher = class {
|
|
|
34162
34605
|
}
|
|
34163
34606
|
boundTo(path, hidden, fids) {
|
|
34164
34607
|
const keeping = [...this.held].map(
|
|
34165
|
-
(
|
|
34166
|
-
|
|
34167
|
-
fids.flatMap((fid) => [...
|
|
34608
|
+
(holds3) => [
|
|
34609
|
+
holds3,
|
|
34610
|
+
fids.flatMap((fid) => [...holds3.boundAt(path, fid), ...holds3.boundAt(hidden, fid)])
|
|
34168
34611
|
]
|
|
34169
34612
|
).filter(([, ids]) => ids.length > 0);
|
|
34170
34613
|
const nodes = [...this.openFiles].filter(
|
|
@@ -34175,7 +34618,7 @@ var Launcher = class {
|
|
|
34175
34618
|
(open2) => fids.some((fid) => open2.keepBound([hidden, path], fid, file))
|
|
34176
34619
|
).length;
|
|
34177
34620
|
for (let i = kept; i < nodes.length; i++) file.release();
|
|
34178
|
-
for (const [
|
|
34621
|
+
for (const [holds3, ids] of keeping) holds3.keepBound(ids, path, file);
|
|
34179
34622
|
void this.rootFs.announceHolds?.([], [path, hidden], false);
|
|
34180
34623
|
};
|
|
34181
34624
|
return { keeping, nodes, keep: keep2 };
|
|
@@ -34335,7 +34778,7 @@ var Launcher = class {
|
|
|
34335
34778
|
}
|
|
34336
34779
|
moved(from, to, source) {
|
|
34337
34780
|
this.renameLog.add(from, to);
|
|
34338
|
-
for (const
|
|
34781
|
+
for (const holds3 of this.held) holds3.renamed(from, to);
|
|
34339
34782
|
if (source) return;
|
|
34340
34783
|
for (const nodes of this.openFiles) nodes.renamed(from, to);
|
|
34341
34784
|
this.watchers.moved(from, to);
|
|
@@ -34547,213 +34990,99 @@ function integrityAsker(port) {
|
|
|
34547
34990
|
return { lookup: lookup2, answer: answer2 };
|
|
34548
34991
|
}
|
|
34549
34992
|
|
|
34550
|
-
// src/
|
|
34551
|
-
|
|
34552
|
-
|
|
34553
|
-
|
|
34554
|
-
|
|
34555
|
-
|
|
34556
|
-
|
|
34557
|
-
|
|
34558
|
-
|
|
34559
|
-
|
|
34560
|
-
}
|
|
34561
|
-
};
|
|
34562
|
-
|
|
34563
|
-
|
|
34564
|
-
|
|
34565
|
-
|
|
34566
|
-
|
|
34567
|
-
|
|
34568
|
-
|
|
34569
|
-
|
|
34570
|
-
|
|
34571
|
-
this.port = port;
|
|
34572
|
-
this.traits = traits;
|
|
34573
|
-
}
|
|
34574
|
-
receive(reply) {
|
|
34575
|
-
if (reply.net === "body-pull") {
|
|
34576
|
-
void this.pull(reply.nid);
|
|
34577
|
-
return;
|
|
34578
|
-
}
|
|
34579
|
-
const socket = this.sockets.get(reply.nid);
|
|
34580
|
-
if (socket && this.toSocket(reply, socket)) return;
|
|
34581
|
-
const waiter = this.waiting.get(reply.nid);
|
|
34582
|
-
if (!waiter) return;
|
|
34583
|
-
this.waiting.delete(reply.nid);
|
|
34584
|
-
if (reply.net === "error") {
|
|
34585
|
-
waiter.reject(new TransportError(reply.message, reply.status, reply.code, reply.detail));
|
|
34586
|
-
} else waiter.resolve(reply);
|
|
34587
|
-
}
|
|
34588
|
-
toSocket(reply, socket) {
|
|
34589
|
-
if (reply.net === "ws-message") socket.queue.push(reply.data);
|
|
34590
|
-
else if (reply.net === "ws-acked") socket.acked(reply.n);
|
|
34591
|
-
else if (reply.net === "ws-closed") {
|
|
34592
|
-
this.sockets.delete(reply.nid);
|
|
34593
|
-
socket.queue.end({ code: reply.code, reason: reply.reason });
|
|
34594
|
-
} else return false;
|
|
34595
|
-
return true;
|
|
34596
|
-
}
|
|
34597
|
-
async pull(nid) {
|
|
34598
|
-
const upload = this.uploads.get(nid);
|
|
34599
|
-
if (!upload) {
|
|
34600
|
-
this.port.postMessage({ net: "body-error", nid, message: "the request body is gone" });
|
|
34601
|
-
return;
|
|
34602
|
-
}
|
|
34603
|
-
try {
|
|
34604
|
-
const next3 = await upload.next();
|
|
34605
|
-
if (next3.done) {
|
|
34606
|
-
this.uploads.delete(nid);
|
|
34607
|
-
this.port.postMessage({ net: "body-end", nid });
|
|
34608
|
-
} else this.port.postMessage({ net: "body-chunk", nid, bytes: next3.value });
|
|
34609
|
-
} catch (e) {
|
|
34610
|
-
this.uploads.delete(nid);
|
|
34611
|
-
this.port.postMessage({
|
|
34612
|
-
net: "body-error",
|
|
34613
|
-
nid,
|
|
34614
|
-
message: e instanceof Error ? e.message : String(e)
|
|
34615
|
-
});
|
|
34616
|
-
}
|
|
34617
|
-
}
|
|
34618
|
-
dropUpload(nid) {
|
|
34619
|
-
const upload = this.uploads.get(nid);
|
|
34620
|
-
this.uploads.delete(nid);
|
|
34993
|
+
// src/sealed-relay.ts
|
|
34994
|
+
function textOf(err) {
|
|
34995
|
+
return err instanceof Error ? err.message : String(err);
|
|
34996
|
+
}
|
|
34997
|
+
function sendBytes(port, bytes) {
|
|
34998
|
+
const copy = fresh(bytes);
|
|
34999
|
+
port.postMessage({ t: "chunk", bytes: copy }, [copy.buffer]);
|
|
35000
|
+
}
|
|
35001
|
+
function askFetch(port, req, signal) {
|
|
35002
|
+
signal.throwIfAborted();
|
|
35003
|
+
const { bodyStream, ...wire } = req;
|
|
35004
|
+
const { port1: near, port2: far } = new MessageChannel();
|
|
35005
|
+
const upload = bodyStream?.[Symbol.asyncIterator]();
|
|
35006
|
+
const head = Promise.withResolvers();
|
|
35007
|
+
let reading;
|
|
35008
|
+
let ended = false;
|
|
35009
|
+
const end = (failure2) => {
|
|
35010
|
+
if (ended) return;
|
|
35011
|
+
ended = true;
|
|
35012
|
+
signal.removeEventListener("abort", abort);
|
|
35013
|
+
near.close();
|
|
34621
35014
|
void upload?.return?.().catch(() => void 0);
|
|
34622
|
-
|
|
34623
|
-
|
|
34624
|
-
|
|
34625
|
-
|
|
34626
|
-
|
|
34627
|
-
|
|
34628
|
-
|
|
34629
|
-
|
|
34630
|
-
|
|
34631
|
-
}
|
|
34632
|
-
ask(call) {
|
|
34633
|
-
if (this.failure) return Promise.reject(this.failure);
|
|
34634
|
-
return new Promise((resolve2, reject) => {
|
|
34635
|
-
this.waiting.set(call.nid, { resolve: resolve2, reject });
|
|
34636
|
-
this.port.postMessage(call);
|
|
34637
|
-
});
|
|
34638
|
-
}
|
|
34639
|
-
cancel(nid) {
|
|
34640
|
-
const waiter = this.waiting.get(nid);
|
|
34641
|
-
this.waiting.delete(nid);
|
|
34642
|
-
waiter?.reject(new TransportError("the request was cancelled"));
|
|
34643
|
-
this.port.postMessage({ net: "cancel", nid });
|
|
34644
|
-
}
|
|
34645
|
-
async fetch(request3) {
|
|
34646
|
-
const nid = ++this.nextId;
|
|
34647
|
-
const { signal } = request3;
|
|
34648
|
-
signal.throwIfAborted();
|
|
34649
|
-
let finished = false;
|
|
34650
|
-
const abort = () => {
|
|
34651
|
-
finished = true;
|
|
34652
|
-
this.dropUpload(nid);
|
|
34653
|
-
this.cancel(nid);
|
|
34654
|
-
};
|
|
34655
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
34656
|
-
const finish = () => {
|
|
34657
|
-
this.dropUpload(nid);
|
|
34658
|
-
if (finished) return;
|
|
34659
|
-
finished = true;
|
|
34660
|
-
signal.removeEventListener("abort", abort);
|
|
34661
|
-
};
|
|
34662
|
-
if (request3.bodyStream) this.uploads.set(nid, request3.bodyStream[Symbol.asyncIterator]());
|
|
34663
|
-
let head;
|
|
35015
|
+
head.reject(failure2);
|
|
35016
|
+
reading?.reject(failure2);
|
|
35017
|
+
reading = void 0;
|
|
35018
|
+
};
|
|
35019
|
+
const abort = () => {
|
|
35020
|
+
near.postMessage({ t: "cancel", reason: String(signal.reason) });
|
|
35021
|
+
end(new Error(String(signal.reason)));
|
|
35022
|
+
};
|
|
35023
|
+
const pull = async () => {
|
|
34664
35024
|
try {
|
|
34665
|
-
|
|
34666
|
-
|
|
34667
|
-
|
|
34668
|
-
|
|
34669
|
-
|
|
34670
|
-
|
|
34671
|
-
...request3.bodyStream ? { streamed: true } : request3.body ? { body: request3.body } : {}
|
|
34672
|
-
});
|
|
34673
|
-
} catch (e) {
|
|
34674
|
-
finish();
|
|
34675
|
-
throw e;
|
|
35025
|
+
const next3 = await upload.next();
|
|
35026
|
+
if (ended) return;
|
|
35027
|
+
if (next3.done) near.postMessage({ t: "end" });
|
|
35028
|
+
else sendBytes(near, next3.value);
|
|
35029
|
+
} catch (err) {
|
|
35030
|
+
if (!ended) near.postMessage({ t: "error", message: textOf(err) });
|
|
34676
35031
|
}
|
|
34677
|
-
|
|
34678
|
-
|
|
34679
|
-
|
|
34680
|
-
|
|
34681
|
-
|
|
34682
|
-
|
|
34683
|
-
|
|
34684
|
-
|
|
34685
|
-
|
|
34686
|
-
|
|
35032
|
+
};
|
|
35033
|
+
const respond2 = (message3) => {
|
|
35034
|
+
const { status, statusText, headers, url } = message3;
|
|
35035
|
+
const body = {
|
|
35036
|
+
[Symbol.asyncIterator]: () => ({
|
|
35037
|
+
next: () => {
|
|
35038
|
+
if (ended) return Promise.resolve({ value: void 0, done: true });
|
|
35039
|
+
reading = Promise.withResolvers();
|
|
35040
|
+
near.postMessage({ t: "read" });
|
|
35041
|
+
return reading.promise;
|
|
35042
|
+
},
|
|
35043
|
+
return: async () => {
|
|
35044
|
+
await cancel();
|
|
35045
|
+
return { value: void 0, done: true };
|
|
35046
|
+
}
|
|
35047
|
+
})
|
|
34687
35048
|
};
|
|
34688
35049
|
const cancel = async () => {
|
|
34689
|
-
if (
|
|
34690
|
-
|
|
34691
|
-
|
|
35050
|
+
if (ended) return;
|
|
35051
|
+
near.postMessage({ t: "cancel", reason: "cancelled" });
|
|
35052
|
+
end(new Error("the request was cancelled"));
|
|
34692
35053
|
};
|
|
34693
|
-
|
|
34694
|
-
...
|
|
34695
|
-
...redirects ? { redirects } : {},
|
|
35054
|
+
head.resolve({
|
|
35055
|
+
...url !== void 0 ? { url } : {},
|
|
34696
35056
|
status,
|
|
34697
35057
|
statusText,
|
|
34698
35058
|
headers,
|
|
34699
|
-
|
|
34700
|
-
|
|
34701
|
-
|
|
34702
|
-
|
|
34703
|
-
|
|
34704
|
-
|
|
34705
|
-
|
|
34706
|
-
|
|
34707
|
-
|
|
34708
|
-
|
|
34709
|
-
|
|
34710
|
-
|
|
34711
|
-
}
|
|
34712
|
-
|
|
34713
|
-
|
|
34714
|
-
|
|
34715
|
-
|
|
34716
|
-
|
|
34717
|
-
|
|
34718
|
-
|
|
34719
|
-
|
|
34720
|
-
|
|
34721
|
-
|
|
34722
|
-
|
|
34723
|
-
|
|
34724
|
-
|
|
34725
|
-
|
|
34726
|
-
protocols: request3.protocols,
|
|
34727
|
-
headers: request3.headers
|
|
34728
|
-
});
|
|
34729
|
-
} finally {
|
|
34730
|
-
signal.removeEventListener("abort", abort);
|
|
34731
|
-
}
|
|
34732
|
-
const close = (code, reason) => this.port.postMessage({ net: "ws-close", nid, code, reason });
|
|
34733
|
-
const queue = new MessageQueue(
|
|
34734
|
-
() => close(1e3, "a message is too big"),
|
|
34735
|
-
Number.POSITIVE_INFINITY,
|
|
34736
|
-
(n) => this.port.postMessage({ net: "ws-consumed", nid, n })
|
|
34737
|
-
);
|
|
34738
|
-
let unacked = 0;
|
|
34739
|
-
this.sockets.set(nid, { queue, acked: (n) => void (unacked -= n) });
|
|
34740
|
-
return {
|
|
34741
|
-
protocol: opened2.protocol,
|
|
34742
|
-
get buffered() {
|
|
34743
|
-
return unacked;
|
|
34744
|
-
},
|
|
34745
|
-
send: (data) => {
|
|
34746
|
-
unacked += payloadSize(data);
|
|
34747
|
-
this.port.postMessage({ net: "ws-send", nid, data });
|
|
34748
|
-
},
|
|
34749
|
-
messages: queue,
|
|
34750
|
-
close,
|
|
34751
|
-
closed: queue.closed
|
|
34752
|
-
};
|
|
34753
|
-
}
|
|
34754
|
-
};
|
|
34755
|
-
|
|
34756
|
-
// src/sealed-relay.ts
|
|
35059
|
+
body,
|
|
35060
|
+
cancel
|
|
35061
|
+
});
|
|
35062
|
+
};
|
|
35063
|
+
near.addEventListener("message", ({ data }) => {
|
|
35064
|
+
if (data.t === "pull") void pull();
|
|
35065
|
+
else if (data.t === "stop") void upload?.return?.().catch(() => void 0);
|
|
35066
|
+
else if (data.t === "head") respond2(data);
|
|
35067
|
+
else if (data.t === "chunk") {
|
|
35068
|
+
reading?.resolve({ value: data.bytes, done: false });
|
|
35069
|
+
reading = void 0;
|
|
35070
|
+
} else if (data.t === "end") {
|
|
35071
|
+
reading?.resolve({ value: void 0, done: true });
|
|
35072
|
+
reading = void 0;
|
|
35073
|
+
end(new Error("the response ended"));
|
|
35074
|
+
} else end(new Error(data.message));
|
|
35075
|
+
});
|
|
35076
|
+
near.addEventListener("close", () => end(new Error("the sealed fetch relay closed")));
|
|
35077
|
+
near.start();
|
|
35078
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
35079
|
+
const ask = {
|
|
35080
|
+
req: { ...wire, ...upload ? { streamed: true } : {} },
|
|
35081
|
+
port: far
|
|
35082
|
+
};
|
|
35083
|
+
port.postMessage({ sealedFetch: ask }, [far]);
|
|
35084
|
+
return head.promise;
|
|
35085
|
+
}
|
|
34757
35086
|
function sealedAsker(port) {
|
|
34758
35087
|
const asks = /* @__PURE__ */ new Map();
|
|
34759
35088
|
let next3 = 0;
|
|
@@ -34777,7 +35106,7 @@ function sealedAsker(port) {
|
|
|
34777
35106
|
if (reply) waiting.resolve(reply);
|
|
34778
35107
|
else waiting.reject(new Error(error ?? "no reply"));
|
|
34779
35108
|
};
|
|
34780
|
-
return { hook, answer: answer2 };
|
|
35109
|
+
return { hook, fetch: (req, { signal }) => askFetch(port, req, signal), answer: answer2 };
|
|
34781
35110
|
}
|
|
34782
35111
|
|
|
34783
35112
|
// src/serve.ts
|
|
@@ -34935,13 +35264,15 @@ function transferOf2(req, result) {
|
|
|
34935
35264
|
if (result instanceof MessagePort) return [result];
|
|
34936
35265
|
const bound3 = result?.port;
|
|
34937
35266
|
if (req.op === "connect" && bound3 instanceof MessagePort) return [bound3];
|
|
34938
|
-
if (req.op === "attest"
|
|
35267
|
+
if (req.op === "attest" && "bytes" in result) {
|
|
35268
|
+
return [result.bytes.buffer];
|
|
35269
|
+
}
|
|
34939
35270
|
return void 0;
|
|
34940
35271
|
}
|
|
34941
35272
|
function attestOps(port) {
|
|
34942
35273
|
const watches = /* @__PURE__ */ new Map();
|
|
34943
35274
|
return async (l, req) => {
|
|
34944
|
-
if (req.op === "attest") return l.attest(req.path);
|
|
35275
|
+
if (req.op === "attest") return l.attest(req.path, req.options);
|
|
34945
35276
|
if (req.op === "chmod") return l.fs.chmod(req.path, modeOption(req.mode)).then(() => true);
|
|
34946
35277
|
if (req.op === "integrity-revoke") return l.revokeIntegrity(req.path).then(() => true);
|
|
34947
35278
|
if (req.op === "unwatch-files") {
|
|
@@ -34996,7 +35327,7 @@ async function connectClient(deps, { user, tag, bind: bind2 }) {
|
|
|
34996
35327
|
});
|
|
34997
35328
|
return unbind ? { port: port2, client } : port2;
|
|
34998
35329
|
}
|
|
34999
|
-
function hostOptions(req, port, sealed, clipboard, lookup2, requests) {
|
|
35330
|
+
function hostOptions(req, port, sealed, sealedFetch, clipboard, lookup2, requests) {
|
|
35000
35331
|
return {
|
|
35001
35332
|
cron: { lock: `slicc-kernel-cron:${req.metadata ?? META_DB}` },
|
|
35002
35333
|
...req.hostname !== void 0 ? { hostname: req.hostname } : {},
|
|
@@ -35005,6 +35336,7 @@ function hostOptions(req, port, sealed, clipboard, lookup2, requests) {
|
|
|
35005
35336
|
...req.denials ? { onDenial: (denial) => port.postMessage({ denial }) } : {},
|
|
35006
35337
|
...req.protect ? { protect: hostProtect(req.protect, lookup2) } : {},
|
|
35007
35338
|
...req.sealed ? { sealed } : {},
|
|
35339
|
+
...req.sealedFetch ? { sealedFetch } : {},
|
|
35008
35340
|
...req.clipboard ? { clipboard } : {},
|
|
35009
35341
|
...req.requests ? { embedder: requests.hookFor(0, req.requests) } : {}
|
|
35010
35342
|
};
|
|
@@ -35095,7 +35427,15 @@ function serveKernel(port, deps) {
|
|
|
35095
35427
|
...req.modules ? { modules: req.modules } : {},
|
|
35096
35428
|
...req.commands ? { commands: req.commands } : {},
|
|
35097
35429
|
...req.env ? { env: req.env } : {},
|
|
35098
|
-
...hostOptions(
|
|
35430
|
+
...hostOptions(
|
|
35431
|
+
req,
|
|
35432
|
+
port,
|
|
35433
|
+
sealed.hook,
|
|
35434
|
+
sealed.fetch,
|
|
35435
|
+
clipboard.hook,
|
|
35436
|
+
integrity.lookup,
|
|
35437
|
+
requests
|
|
35438
|
+
),
|
|
35099
35439
|
...req.approve ? { approve: approvals.ask } : {},
|
|
35100
35440
|
...net,
|
|
35101
35441
|
...media ? { media } : {},
|
|
@@ -35122,6 +35462,7 @@ function serveKernel(port, deps) {
|
|
|
35122
35462
|
async function handle(req) {
|
|
35123
35463
|
if (req.op === "init") return init(req);
|
|
35124
35464
|
if (isAttestRequest(req)) return attestOp(await ready2(), req);
|
|
35465
|
+
if (req.op === "sealed-placeholders") return (await ready2()).setPlaceholders(req.list);
|
|
35125
35466
|
if (req.op === "open-terminal") return terminal(req);
|
|
35126
35467
|
if (req.op === "connect") return connect2(req.user, req.tag, req.requests);
|
|
35127
35468
|
if (isUsersRequest(req)) return usersOp(await ready2(), req);
|