@ai-ecoverse/slicc-kernel 1.170.3 → 1.171.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 +10 -3
- package/dist/driver-worker.js +32 -10
- package/dist/driver-worker.js.map +3 -3
- package/dist/index.js +49 -19
- package/dist/index.js.map +3 -3
- package/dist/kernel-worker.js +394 -284
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-driver-worker.js +36 -14
- package/dist/node-driver-worker.js.map +3 -3
- package/dist/node-process-worker.cjs +3 -3
- package/dist/node-process-worker.cjs.map +2 -2
- package/dist/node-process-worker.js +3 -3
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +491 -324
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +3 -3
- package/dist/process-worker.js.map +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/kernel/net/http-syscalls.d.ts +1 -0
- package/dist/types/kernel/net/placeholder-floor.d.ts +8 -0
- package/dist/types/kernel/net/remote-transport.d.ts +4 -1
- package/dist/types/kernel/net/transport.d.ts +4 -0
- package/dist/types/node/follow.d.ts +4 -0
- package/dist/types/node.d.ts +1 -0
- package/dist/types/realm/sync-fs-wire.d.ts +1 -1
- package/dist/types/transport.d.ts +2 -2
- package/package.json +2 -2
package/dist/node.js
CHANGED
|
@@ -2362,9 +2362,9 @@ var KernelSocket = class _KernelSocket {
|
|
|
2362
2362
|
case SO_TYPE:
|
|
2363
2363
|
return SOCK_STREAM;
|
|
2364
2364
|
case SO_ERROR: {
|
|
2365
|
-
const
|
|
2365
|
+
const failed4 = this.failed;
|
|
2366
2366
|
this.failed = void 0;
|
|
2367
|
-
return
|
|
2367
|
+
return failed4 ? wasiErrno(failed4) : 0;
|
|
2368
2368
|
}
|
|
2369
2369
|
case SO_ACCEPTCONN:
|
|
2370
2370
|
return this.state === "listening" ? 1 : 0;
|
|
@@ -3695,7 +3695,7 @@ function satisfies(version, range2) {
|
|
|
3695
3695
|
}
|
|
3696
3696
|
|
|
3697
3697
|
// src/version.ts
|
|
3698
|
-
var KERNEL_VERSION = true ? "1.
|
|
3698
|
+
var KERNEL_VERSION = true ? "1.171.0" : "0.0.0-dev";
|
|
3699
3699
|
var OS_RELEASE = "6.0.0-slicc";
|
|
3700
3700
|
function procVersion() {
|
|
3701
3701
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -3987,10 +3987,10 @@ async function tierPackages(fs, physical, roots, bins, kernel, global) {
|
|
|
3987
3987
|
const own = commandsOf(pkg, manifest);
|
|
3988
3988
|
const named = new Set(own.map((command) => command.name));
|
|
3989
3989
|
const extra = bins ? await binCommandsOf(physical, pkg, manifest, named) : [];
|
|
3990
|
-
const
|
|
3990
|
+
const refused4 = engineRefusal(manifest, kernel);
|
|
3991
3991
|
const name2 = pkg.slice(root.length + 1);
|
|
3992
3992
|
const dependency = direct?.has(name2) === false;
|
|
3993
|
-
const marks = { ...
|
|
3993
|
+
const marks = { ...refused4 ? { refused: refused4 } : {}, ...dependency ? { dependency } : {} };
|
|
3994
3994
|
out.push({
|
|
3995
3995
|
name: name2,
|
|
3996
3996
|
pkg,
|
|
@@ -4022,7 +4022,7 @@ function winners(tier) {
|
|
|
4022
4022
|
}
|
|
4023
4023
|
return out;
|
|
4024
4024
|
}
|
|
4025
|
-
async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, kernel = KERNEL_VERSION,
|
|
4025
|
+
async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, kernel = KERNEL_VERSION, refused4, global = /* @__PURE__ */ new Set()) {
|
|
4026
4026
|
const found = /* @__PURE__ */ new Map();
|
|
4027
4027
|
const physical = physicalResolver(fs);
|
|
4028
4028
|
const tiers = (typeof modules === "string" ? [modules] : modules).map(
|
|
@@ -4036,7 +4036,7 @@ async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, ke
|
|
|
4036
4036
|
const dependencies = [];
|
|
4037
4037
|
for (const [index, roots] of tiers.entries()) {
|
|
4038
4038
|
const tier = await tierPackages(fs, physical, roots, index >= binsFrom, kernel, global);
|
|
4039
|
-
if (
|
|
4039
|
+
if (refused4) refused4.push(...tier.flatMap((entry) => entry.commands.filter((c) => c.refused)));
|
|
4040
4040
|
await take(tier.filter((entry) => !entry.dependency));
|
|
4041
4041
|
dependencies.push(tier.filter((entry) => entry.dependency));
|
|
4042
4042
|
}
|
|
@@ -5102,12 +5102,12 @@ var UnlinkedKeeper = class {
|
|
|
5102
5102
|
return this.locks;
|
|
5103
5103
|
}
|
|
5104
5104
|
async undoing(op, peers, sends, heard, shared2 = []) {
|
|
5105
|
-
let
|
|
5105
|
+
let failed4;
|
|
5106
5106
|
let out;
|
|
5107
5107
|
try {
|
|
5108
5108
|
out = await op();
|
|
5109
5109
|
} catch (err) {
|
|
5110
|
-
|
|
5110
|
+
failed4 = err ?? new Error("failed");
|
|
5111
5111
|
await this.rollBackAsides(sends, shared2);
|
|
5112
5112
|
}
|
|
5113
5113
|
const hiddenShared = new Set(shared2.map((one) => one.hidden));
|
|
@@ -5128,7 +5128,7 @@ var UnlinkedKeeper = class {
|
|
|
5128
5128
|
const done4 = () => one.release().then(() => this.dropIfLast(one.hidden));
|
|
5129
5129
|
void Promise.all(waits.map(({ told }) => told)).then(done4, done4);
|
|
5130
5130
|
}
|
|
5131
|
-
if (
|
|
5131
|
+
if (failed4 !== void 0) throw failed4;
|
|
5132
5132
|
return out;
|
|
5133
5133
|
}
|
|
5134
5134
|
async rollBackAsides(sends, shared2) {
|
|
@@ -5602,6 +5602,78 @@ var CronService = class {
|
|
|
5602
5602
|
}
|
|
5603
5603
|
};
|
|
5604
5604
|
|
|
5605
|
+
// src/kernel/net/placeholder-floor.ts
|
|
5606
|
+
var PLACEHOLDER = /fnox_proxy_[0-9a-f]{24}/;
|
|
5607
|
+
var ESCAPE = /%([0-9a-f]{2})/gi;
|
|
5608
|
+
var BASIC = /\bbasic\b(.*)/is;
|
|
5609
|
+
var PERCENT_LAYERS = 8;
|
|
5610
|
+
var BASE64_GROUP = 4;
|
|
5611
|
+
var PLACEHOLDER_REFUSED = "refused: this request has a sealed placeholder in its URL, a header or a Basic credential, and nothing fills it, so it was not sent";
|
|
5612
|
+
var PlaceholderRefused = class extends Error {
|
|
5613
|
+
status = 403;
|
|
5614
|
+
code = "EACCES";
|
|
5615
|
+
constructor() {
|
|
5616
|
+
super(PLACEHOLDER_REFUSED);
|
|
5617
|
+
}
|
|
5618
|
+
};
|
|
5619
|
+
function carries(text) {
|
|
5620
|
+
let layer = text;
|
|
5621
|
+
for (let i = 0; i < PERCENT_LAYERS; i++) {
|
|
5622
|
+
if (PLACEHOLDER.test(layer)) return true;
|
|
5623
|
+
const next3 = layer.replace(
|
|
5624
|
+
ESCAPE,
|
|
5625
|
+
(_, hex4) => String.fromCharCode(Number.parseInt(hex4, 16))
|
|
5626
|
+
);
|
|
5627
|
+
if (next3 === layer) return false;
|
|
5628
|
+
layer = next3;
|
|
5629
|
+
}
|
|
5630
|
+
return PLACEHOLDER.test(layer);
|
|
5631
|
+
}
|
|
5632
|
+
function basicCarries(value2) {
|
|
5633
|
+
const credential = BASIC.exec(value2)?.[1];
|
|
5634
|
+
if (credential === void 0) return false;
|
|
5635
|
+
const letters = credential.replace(/[^A-Za-z0-9+/_-]/g, "").replaceAll("-", "+").replaceAll("_", "/");
|
|
5636
|
+
for (let shift = 0; shift < BASE64_GROUP; shift++) {
|
|
5637
|
+
const part = letters.slice(shift);
|
|
5638
|
+
const whole = part.length % BASE64_GROUP === 1 ? part.slice(0, -1) : part;
|
|
5639
|
+
if (carries(atob(whole))) return true;
|
|
5640
|
+
}
|
|
5641
|
+
return false;
|
|
5642
|
+
}
|
|
5643
|
+
function headersCarry(headers) {
|
|
5644
|
+
return headers.some(
|
|
5645
|
+
([name2, value2]) => carries(name2.toLowerCase()) || carries(value2) || basicCarries(value2)
|
|
5646
|
+
);
|
|
5647
|
+
}
|
|
5648
|
+
function urlCarries(url) {
|
|
5649
|
+
return carries(url) || URL.canParse(url) && carries(new URL(url).href);
|
|
5650
|
+
}
|
|
5651
|
+
function refuse(request) {
|
|
5652
|
+
if (urlCarries(request.url) || headersCarry(request.headers)) throw new PlaceholderRefused();
|
|
5653
|
+
}
|
|
5654
|
+
function refuseSocket(request) {
|
|
5655
|
+
refuse(request);
|
|
5656
|
+
if (request.protocols.some(carries)) throw new PlaceholderRefused();
|
|
5657
|
+
}
|
|
5658
|
+
function placeholderFloor(inner) {
|
|
5659
|
+
const open = inner.websocket?.bind(inner);
|
|
5660
|
+
return {
|
|
5661
|
+
get traits() {
|
|
5662
|
+
return inner.traits;
|
|
5663
|
+
},
|
|
5664
|
+
...open ? {
|
|
5665
|
+
websocket: async (request) => {
|
|
5666
|
+
refuseSocket(request);
|
|
5667
|
+
return open(request);
|
|
5668
|
+
}
|
|
5669
|
+
} : {},
|
|
5670
|
+
async fetch(request, owner) {
|
|
5671
|
+
refuse(request);
|
|
5672
|
+
return inner.fetch(request, owner);
|
|
5673
|
+
}
|
|
5674
|
+
};
|
|
5675
|
+
}
|
|
5676
|
+
|
|
5605
5677
|
// src/kernel/net/ws-queue.ts
|
|
5606
5678
|
var INBOUND_LIMIT = 16 * 1024 * 1024;
|
|
5607
5679
|
var MESSAGE_LIMIT = 64 * 1024 * 1024;
|
|
@@ -6118,8 +6190,8 @@ var RealmProxy = class {
|
|
|
6118
6190
|
}
|
|
6119
6191
|
async connect(conn, incoming, req, idle2) {
|
|
6120
6192
|
const target = tunnelTarget(req);
|
|
6121
|
-
const
|
|
6122
|
-
if (
|
|
6193
|
+
const refused4 = target.port === 443 ? await this.tunnelReady(target) : void 0;
|
|
6194
|
+
if (refused4) throw refused4;
|
|
6123
6195
|
await conn.write(latin1Bytes("HTTP/1.1 200 Connection Established\r\n\r\n"), this.stop.signal);
|
|
6124
6196
|
try {
|
|
6125
6197
|
const first = await incoming.peek(this.stop.signal);
|
|
@@ -6176,7 +6248,8 @@ var RealmProxy = class {
|
|
|
6176
6248
|
});
|
|
6177
6249
|
} catch (e) {
|
|
6178
6250
|
waiting.abort();
|
|
6179
|
-
|
|
6251
|
+
const status = e instanceof PlaceholderRefused ? e.status : 502;
|
|
6252
|
+
throw new HttpError(status, e instanceof Error ? e.message : String(e));
|
|
6180
6253
|
}
|
|
6181
6254
|
ctx.idle.ms = Number.POSITIVE_INFINITY;
|
|
6182
6255
|
try {
|
|
@@ -6390,7 +6463,7 @@ async function relay(socket, conn) {
|
|
|
6390
6463
|
// src/fs/attest.ts
|
|
6391
6464
|
var ATTEST_MAX = 1024 * 1024;
|
|
6392
6465
|
var UNOWNED = 1e3;
|
|
6393
|
-
function
|
|
6466
|
+
function refuse2(code, path, why) {
|
|
6394
6467
|
throw Object.assign(new Error(`attest ${path}: ${why}`), { code });
|
|
6395
6468
|
}
|
|
6396
6469
|
function chainOf(path) {
|
|
@@ -6432,11 +6505,11 @@ async function trustedParents(fs, path, o) {
|
|
|
6432
6505
|
const parents = [];
|
|
6433
6506
|
for (const dir of chainOf(path).slice(0, -1)) {
|
|
6434
6507
|
const st = await fs.lstat(dir);
|
|
6435
|
-
if (st.isSymbolicLink)
|
|
6436
|
-
if (!st.isDirectory)
|
|
6508
|
+
if (st.isSymbolicLink) refuse2("EACCES", path, `${dir} is a symlink`);
|
|
6509
|
+
if (!st.isDirectory) refuse2("ENOTDIR", path, `${dir} is not a directory`);
|
|
6437
6510
|
const perm = owned(dir, st);
|
|
6438
6511
|
if (o.users !== "off" && (perm.uid !== 0 || (perm.mode & 18) !== 0)) {
|
|
6439
|
-
|
|
6512
|
+
refuse2("EACCES", path, `${dir} is not root-owned or is writable by group or others`);
|
|
6440
6513
|
}
|
|
6441
6514
|
parents.push(perm);
|
|
6442
6515
|
}
|
|
@@ -6444,27 +6517,27 @@ async function trustedParents(fs, path, o) {
|
|
|
6444
6517
|
}
|
|
6445
6518
|
async function attest(fs, asked, o) {
|
|
6446
6519
|
if (typeof asked !== "string" || !asked.startsWith("/")) {
|
|
6447
|
-
|
|
6520
|
+
refuse2("EINVAL", String(asked), "not an absolute path");
|
|
6448
6521
|
}
|
|
6449
6522
|
const path = normalizePath(asked);
|
|
6450
6523
|
const mount = o.mounts.find((target) => {
|
|
6451
6524
|
const at = normalizePath(target);
|
|
6452
6525
|
return at === "/" || under(path, at);
|
|
6453
6526
|
});
|
|
6454
|
-
if (mount !== void 0)
|
|
6527
|
+
if (mount !== void 0) refuse2("EACCES", path, `under the mount ${mount}`);
|
|
6455
6528
|
const parents = await trustedParents(fs, path, o);
|
|
6456
6529
|
for (let tries = 0; ; tries++) {
|
|
6457
6530
|
const before = await fs.lstat(path);
|
|
6458
|
-
if (before.isSymbolicLink)
|
|
6531
|
+
if (before.isSymbolicLink) refuse2("EACCES", path, "is a symlink");
|
|
6459
6532
|
if (!before.isFile)
|
|
6460
|
-
|
|
6461
|
-
if (before.size > ATTEST_MAX)
|
|
6533
|
+
refuse2(before.isDirectory ? "EISDIR" : "EINVAL", path, "is not a regular file");
|
|
6534
|
+
if (before.size > ATTEST_MAX) refuse2("EFBIG", path, `is over ${ATTEST_MAX} bytes`);
|
|
6462
6535
|
const bytes = (await fs.readFileBuffer(path)).slice();
|
|
6463
6536
|
const after = await fs.lstat(path);
|
|
6464
6537
|
if (unchanged(before, after, bytes)) {
|
|
6465
6538
|
return attested(path, after, bytes, await sha256(bytes), o, parents);
|
|
6466
6539
|
}
|
|
6467
|
-
if (tries >= 1)
|
|
6540
|
+
if (tries >= 1) refuse2("EAGAIN", path, "changed while it was read");
|
|
6468
6541
|
}
|
|
6469
6542
|
}
|
|
6470
6543
|
var WATCH_DEBOUNCE_MS = 50;
|
|
@@ -9293,8 +9366,8 @@ var DriverConnection = class _DriverConnection {
|
|
|
9293
9366
|
} finally {
|
|
9294
9367
|
clearTimeout(timer);
|
|
9295
9368
|
}
|
|
9296
|
-
const
|
|
9297
|
-
if (
|
|
9369
|
+
const refused4 = driverVersionError(hello.protocol);
|
|
9370
|
+
if (refused4) throw errnoError("EPROTO", refused4);
|
|
9298
9371
|
if (hello.error) throw errnoError(hello.errno ?? "EIO", hello.error);
|
|
9299
9372
|
return new _DriverConnection(port, hello.capabilities ?? {}, waiting, timeoutMs, options);
|
|
9300
9373
|
}
|
|
@@ -11318,8 +11391,8 @@ async function guarded(entry, path, req) {
|
|
|
11318
11391
|
return { paths };
|
|
11319
11392
|
} catch (err) {
|
|
11320
11393
|
const refusal3 = err.code === "EACCES";
|
|
11321
|
-
const
|
|
11322
|
-
return { refused:
|
|
11394
|
+
const refused4 = req.op === "exists" && refusal3 ? json2(false) : toErrno(err);
|
|
11395
|
+
return { refused: refused4 };
|
|
11323
11396
|
}
|
|
11324
11397
|
}
|
|
11325
11398
|
async function copyOp(entry, path, req) {
|
|
@@ -11515,13 +11588,13 @@ async function created(entry, req) {
|
|
|
11515
11588
|
return seen === void 0 ? looked : json2({ ...looked.json, seen });
|
|
11516
11589
|
}
|
|
11517
11590
|
var DENIED = /* @__PURE__ */ new Set(["EACCES", "EPERM"]);
|
|
11518
|
-
async function rmPermitted(entry, path, req,
|
|
11591
|
+
async function rmPermitted(entry, path, req, refused4) {
|
|
11519
11592
|
const st = await entry.fs.lstat(path).catch(() => void 0);
|
|
11520
|
-
if (!st?.isDirectory) return
|
|
11593
|
+
if (!st?.isDirectory) return refused4;
|
|
11521
11594
|
const unlisted = await guarded(entry, path, { ...req, op: "readdir" });
|
|
11522
11595
|
if ("refused" in unlisted) return unlisted.refused;
|
|
11523
11596
|
const names2 = await entry.fs.readdir(path).catch(() => void 0);
|
|
11524
|
-
if (!names2) return
|
|
11597
|
+
if (!names2) return refused4;
|
|
11525
11598
|
let first;
|
|
11526
11599
|
for (const name2 of names2) {
|
|
11527
11600
|
const child = await dispatchOne(entry, {
|
|
@@ -11572,14 +11645,14 @@ async function newDevName(entry, path, req) {
|
|
|
11572
11645
|
const named = NAMING.has(req.op);
|
|
11573
11646
|
if (!named && !CREATIONS.has(req.op)) return void 0;
|
|
11574
11647
|
const target = named ? entry.fs.resolvePath(entry.cwd, req.arg2 ?? "") : path;
|
|
11575
|
-
const
|
|
11576
|
-
if (!
|
|
11648
|
+
const refused4 = devCreation(target, entry.cred?.());
|
|
11649
|
+
if (!refused4) return void 0;
|
|
11577
11650
|
const there = await entry.fs.lstat(target).then(
|
|
11578
11651
|
() => true,
|
|
11579
11652
|
() => false
|
|
11580
11653
|
);
|
|
11581
11654
|
if (there) return void 0;
|
|
11582
|
-
return { ok: false, errno:
|
|
11655
|
+
return { ok: false, errno: refused4, message: `${target}: no new names in /dev or /proc` };
|
|
11583
11656
|
}
|
|
11584
11657
|
var MISS_OPS = /* @__PURE__ */ new Set(["stat", "lstat"]);
|
|
11585
11658
|
async function linkFree(fs, path) {
|
|
@@ -11702,7 +11775,7 @@ function encodeSabResult(result) {
|
|
|
11702
11775
|
message: result.message,
|
|
11703
11776
|
...result.direct ? { direct: true } : {},
|
|
11704
11777
|
...result.dev !== void 0 ? { dev: result.dev } : {},
|
|
11705
|
-
...result.detail
|
|
11778
|
+
...result.detail ? { detail: result.detail } : {}
|
|
11706
11779
|
})
|
|
11707
11780
|
)
|
|
11708
11781
|
};
|
|
@@ -13034,11 +13107,11 @@ var EpollFile = class _EpollFile {
|
|
|
13034
13107
|
const round = new AbortController();
|
|
13035
13108
|
const stop = () => round.abort();
|
|
13036
13109
|
signal.addEventListener("abort", stop, { once: true });
|
|
13037
|
-
let
|
|
13110
|
+
let failed4 = false;
|
|
13038
13111
|
try {
|
|
13039
13112
|
await file.changed(round.signal);
|
|
13040
13113
|
} catch {
|
|
13041
|
-
|
|
13114
|
+
failed4 = true;
|
|
13042
13115
|
} finally {
|
|
13043
13116
|
round.abort();
|
|
13044
13117
|
signal.removeEventListener("abort", stop);
|
|
@@ -13046,7 +13119,7 @@ var EpollFile = class _EpollFile {
|
|
|
13046
13119
|
if (signal.aborted) return;
|
|
13047
13120
|
reg.gen++;
|
|
13048
13121
|
this.changes.wake();
|
|
13049
|
-
if (
|
|
13122
|
+
if (failed4) await pause(RETRY_MS, signal);
|
|
13050
13123
|
}
|
|
13051
13124
|
}
|
|
13052
13125
|
};
|
|
@@ -13682,8 +13755,8 @@ var KernelLoopback = class {
|
|
|
13682
13755
|
);
|
|
13683
13756
|
} catch (err) {
|
|
13684
13757
|
socket.close();
|
|
13685
|
-
const
|
|
13686
|
-
throw
|
|
13758
|
+
const refused4 = err instanceof KernelError && err.code === "ECONNREFUSED";
|
|
13759
|
+
throw refused4 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
|
|
13687
13760
|
}
|
|
13688
13761
|
signal.addEventListener("abort", () => socket.close(), { once: true });
|
|
13689
13762
|
return socket;
|
|
@@ -15116,23 +15189,29 @@ var HttpHandles = class {
|
|
|
15116
15189
|
return response.redirected ? { ...head, json: { ...head.json, redirected: true } } : head;
|
|
15117
15190
|
} catch (e) {
|
|
15118
15191
|
entry.upload?.cancel();
|
|
15119
|
-
|
|
15120
|
-
|
|
15121
|
-
const status = e.status;
|
|
15122
|
-
if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
|
|
15123
|
-
const code = codeOf2(e);
|
|
15124
|
-
const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
|
|
15125
|
-
const failed3 = e.detail === "transport";
|
|
15126
|
-
return { ok: false, errno: errno3, message: text, ...failed3 ? { detail: "transport" } : {} };
|
|
15127
|
-
}
|
|
15128
|
-
entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
|
|
15129
|
-
return this.headOf(handle, req.url, {
|
|
15130
|
-
status,
|
|
15131
|
-
statusText: "",
|
|
15132
|
-
headers: [["content-type", "text/plain; charset=utf-8"]]
|
|
15133
|
-
});
|
|
15192
|
+
if (port !== void 0) return { ok: false, errno: codeOf2(e), message: message2(e) };
|
|
15193
|
+
return this.failure(handle, req, e, entry);
|
|
15134
15194
|
}
|
|
15135
15195
|
}
|
|
15196
|
+
failure(handle, req, e, entry) {
|
|
15197
|
+
const text = message2(e);
|
|
15198
|
+
if (e instanceof PlaceholderRefused) {
|
|
15199
|
+
return { ok: false, errno: e.code, message: text, detail: "placeholder" };
|
|
15200
|
+
}
|
|
15201
|
+
const status = e.status;
|
|
15202
|
+
if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
|
|
15203
|
+
const code = codeOf2(e);
|
|
15204
|
+
const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
|
|
15205
|
+
const failed4 = e.detail === "transport";
|
|
15206
|
+
return { ok: false, errno: errno3, message: text, ...failed4 ? { detail: "transport" } : {} };
|
|
15207
|
+
}
|
|
15208
|
+
entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
|
|
15209
|
+
return this.headOf(handle, req.url, {
|
|
15210
|
+
status,
|
|
15211
|
+
statusText: "",
|
|
15212
|
+
headers: [["content-type", "text/plain; charset=utf-8"]]
|
|
15213
|
+
});
|
|
15214
|
+
}
|
|
15136
15215
|
headOf(handle, url, response) {
|
|
15137
15216
|
const { status, statusText, headers } = response;
|
|
15138
15217
|
return { ok: true, kind: "json", json: { handle, status, statusText, url, headers } };
|
|
@@ -17032,23 +17111,23 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
17032
17111
|
let pending = 0;
|
|
17033
17112
|
let busy = false;
|
|
17034
17113
|
let timer;
|
|
17035
|
-
let
|
|
17114
|
+
let failed4;
|
|
17036
17115
|
const waiters = /* @__PURE__ */ new Set();
|
|
17037
17116
|
const quiet3 = () => !busy && pending === 0;
|
|
17038
17117
|
const wake = () => {
|
|
17039
17118
|
for (const waiter of [...waiters]) waiter();
|
|
17040
17119
|
};
|
|
17041
17120
|
const raise = () => {
|
|
17042
|
-
if (
|
|
17043
|
-
const err =
|
|
17044
|
-
|
|
17121
|
+
if (failed4 === void 0) return;
|
|
17122
|
+
const err = failed4;
|
|
17123
|
+
failed4 = void 0;
|
|
17045
17124
|
throw err;
|
|
17046
17125
|
};
|
|
17047
17126
|
const later = (bytes) => {
|
|
17048
17127
|
if (bytes.length === 0) return;
|
|
17049
17128
|
pending += 1;
|
|
17050
17129
|
tail2 = tail2.then(() => writeAll2(file, bytes)).catch((err) => {
|
|
17051
|
-
if (
|
|
17130
|
+
if (failed4 === void 0) failed4 = err;
|
|
17052
17131
|
}).finally(() => {
|
|
17053
17132
|
pending -= 1;
|
|
17054
17133
|
if (quiet3()) wake();
|
|
@@ -18230,7 +18309,7 @@ var HEAD_MAX = 16 * 1024;
|
|
|
18230
18309
|
var ANY_PLACEHOLDER = /fnox_proxy_[0-9a-f]{24}/g;
|
|
18231
18310
|
var REQUEST_LINE2 = /^([!#$%&'*+.^_`|~0-9A-Za-z-]+) ([\x21-\x7e]+) HTTP\/1\.[01]$/;
|
|
18232
18311
|
var HEADER_LINE = /^([!#$%&'*+.^_`|~0-9A-Za-z-]+):[ \t]*(.*?)[ \t]*$/;
|
|
18233
|
-
var
|
|
18312
|
+
var BASIC2 = /^(Basic[ \t]+)([A-Za-z0-9+/]+={0,2})$/i;
|
|
18234
18313
|
var encoder8 = new TextEncoder();
|
|
18235
18314
|
function binary(text) {
|
|
18236
18315
|
let out = "";
|
|
@@ -18246,7 +18325,7 @@ function sniffHttp1(start2) {
|
|
|
18246
18325
|
return "no";
|
|
18247
18326
|
}
|
|
18248
18327
|
function basicOf(value2) {
|
|
18249
|
-
const m =
|
|
18328
|
+
const m = BASIC2.exec(value2);
|
|
18250
18329
|
if (!m) return void 0;
|
|
18251
18330
|
try {
|
|
18252
18331
|
return { scheme: m[1], decoded: atob(m[2]) };
|
|
@@ -25179,6 +25258,234 @@ function enableDnsStub(net, stub) {
|
|
|
25179
25258
|
});
|
|
25180
25259
|
}
|
|
25181
25260
|
|
|
25261
|
+
// src/kernel/net/remote-transport.ts
|
|
25262
|
+
var TransportError = class extends Error {
|
|
25263
|
+
status;
|
|
25264
|
+
code;
|
|
25265
|
+
detail;
|
|
25266
|
+
constructor(message3, status, code, detail) {
|
|
25267
|
+
super(message3);
|
|
25268
|
+
this.status = status;
|
|
25269
|
+
this.code = code;
|
|
25270
|
+
this.detail = detail === "transport" ? detail : void 0;
|
|
25271
|
+
}
|
|
25272
|
+
};
|
|
25273
|
+
function unfollowed2(redirect) {
|
|
25274
|
+
return redirect !== void 0 && redirect !== "follow";
|
|
25275
|
+
}
|
|
25276
|
+
function honors(traits, redirect) {
|
|
25277
|
+
if (traits.redirectPolicy === true) return true;
|
|
25278
|
+
const hops = traits.redirectHops;
|
|
25279
|
+
const raw2 = traits.manualRedirects === true && (hops === void 0 || hops === false);
|
|
25280
|
+
return redirect === "manual" && raw2;
|
|
25281
|
+
}
|
|
25282
|
+
function refused3(message3) {
|
|
25283
|
+
return new TransportError(message3, 502, void 0, "transport");
|
|
25284
|
+
}
|
|
25285
|
+
var RemoteTransport = class {
|
|
25286
|
+
traits;
|
|
25287
|
+
port;
|
|
25288
|
+
waiting = /* @__PURE__ */ new Map();
|
|
25289
|
+
nextId = 0;
|
|
25290
|
+
sockets = /* @__PURE__ */ new Map();
|
|
25291
|
+
uploads = /* @__PURE__ */ new Map();
|
|
25292
|
+
failure;
|
|
25293
|
+
constructor(port, traits) {
|
|
25294
|
+
this.port = port;
|
|
25295
|
+
this.traits = traits;
|
|
25296
|
+
}
|
|
25297
|
+
receive(reply) {
|
|
25298
|
+
if (reply.net === "body-pull") {
|
|
25299
|
+
void this.pull(reply.nid);
|
|
25300
|
+
return;
|
|
25301
|
+
}
|
|
25302
|
+
const socket = this.sockets.get(reply.nid);
|
|
25303
|
+
if (socket && this.toSocket(reply, socket)) return;
|
|
25304
|
+
const waiter = this.waiting.get(reply.nid);
|
|
25305
|
+
if (!waiter) return;
|
|
25306
|
+
this.waiting.delete(reply.nid);
|
|
25307
|
+
if (reply.net === "error") {
|
|
25308
|
+
waiter.reject(new TransportError(reply.message, reply.status, reply.code, reply.detail));
|
|
25309
|
+
} else waiter.resolve(reply);
|
|
25310
|
+
}
|
|
25311
|
+
toSocket(reply, socket) {
|
|
25312
|
+
if (reply.net === "ws-message") socket.queue.push(reply.data);
|
|
25313
|
+
else if (reply.net === "ws-acked") socket.acked(reply.n);
|
|
25314
|
+
else if (reply.net === "ws-closed") {
|
|
25315
|
+
this.sockets.delete(reply.nid);
|
|
25316
|
+
socket.queue.end({ code: reply.code, reason: reply.reason });
|
|
25317
|
+
} else return false;
|
|
25318
|
+
return true;
|
|
25319
|
+
}
|
|
25320
|
+
async pull(nid) {
|
|
25321
|
+
const upload = this.uploads.get(nid);
|
|
25322
|
+
if (!upload) {
|
|
25323
|
+
this.port.postMessage({ net: "body-error", nid, message: "the request body is gone" });
|
|
25324
|
+
return;
|
|
25325
|
+
}
|
|
25326
|
+
try {
|
|
25327
|
+
const next3 = await upload.next();
|
|
25328
|
+
if (next3.done) {
|
|
25329
|
+
this.uploads.delete(nid);
|
|
25330
|
+
this.port.postMessage({ net: "body-end", nid });
|
|
25331
|
+
} else this.port.postMessage({ net: "body-chunk", nid, bytes: next3.value });
|
|
25332
|
+
} catch (e) {
|
|
25333
|
+
this.uploads.delete(nid);
|
|
25334
|
+
this.port.postMessage({
|
|
25335
|
+
net: "body-error",
|
|
25336
|
+
nid,
|
|
25337
|
+
message: e instanceof Error ? e.message : String(e)
|
|
25338
|
+
});
|
|
25339
|
+
}
|
|
25340
|
+
}
|
|
25341
|
+
dropUpload(nid) {
|
|
25342
|
+
const upload = this.uploads.get(nid);
|
|
25343
|
+
this.uploads.delete(nid);
|
|
25344
|
+
void upload?.return?.().catch(() => void 0);
|
|
25345
|
+
}
|
|
25346
|
+
fail(error) {
|
|
25347
|
+
this.failure = error;
|
|
25348
|
+
for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);
|
|
25349
|
+
for (const waiter of this.waiting.values()) waiter.reject(error);
|
|
25350
|
+
this.waiting.clear();
|
|
25351
|
+
for (const socket of this.sockets.values())
|
|
25352
|
+
socket.queue.end({ code: 1011, reason: error.message });
|
|
25353
|
+
this.sockets.clear();
|
|
25354
|
+
}
|
|
25355
|
+
ask(call) {
|
|
25356
|
+
if (this.failure) return Promise.reject(this.failure);
|
|
25357
|
+
return new Promise((resolve2, reject) => {
|
|
25358
|
+
this.waiting.set(call.nid, { resolve: resolve2, reject });
|
|
25359
|
+
this.port.postMessage(call);
|
|
25360
|
+
});
|
|
25361
|
+
}
|
|
25362
|
+
cancel(nid) {
|
|
25363
|
+
const waiter = this.waiting.get(nid);
|
|
25364
|
+
this.waiting.delete(nid);
|
|
25365
|
+
waiter?.reject(new TransportError("the request was cancelled"));
|
|
25366
|
+
this.port.postMessage({ net: "cancel", nid });
|
|
25367
|
+
}
|
|
25368
|
+
async fetch(request) {
|
|
25369
|
+
const nid = ++this.nextId;
|
|
25370
|
+
const { signal, redirect } = request;
|
|
25371
|
+
signal.throwIfAborted();
|
|
25372
|
+
if (unfollowed2(redirect) && !honors(this.traits, redirect)) {
|
|
25373
|
+
throw refused3(`this transport cannot honor redirect: ${redirect}`);
|
|
25374
|
+
}
|
|
25375
|
+
let finished = false;
|
|
25376
|
+
const abort = () => {
|
|
25377
|
+
finished = true;
|
|
25378
|
+
this.dropUpload(nid);
|
|
25379
|
+
this.cancel(nid);
|
|
25380
|
+
};
|
|
25381
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
25382
|
+
const finish = () => {
|
|
25383
|
+
this.dropUpload(nid);
|
|
25384
|
+
if (finished) return;
|
|
25385
|
+
finished = true;
|
|
25386
|
+
signal.removeEventListener("abort", abort);
|
|
25387
|
+
};
|
|
25388
|
+
if (request.bodyStream) this.uploads.set(nid, request.bodyStream[Symbol.asyncIterator]());
|
|
25389
|
+
let head;
|
|
25390
|
+
try {
|
|
25391
|
+
head = await this.ask({
|
|
25392
|
+
net: "fetch",
|
|
25393
|
+
nid,
|
|
25394
|
+
url: request.url,
|
|
25395
|
+
method: request.method,
|
|
25396
|
+
headers: request.headers,
|
|
25397
|
+
...request.bodyStream ? { streamed: true } : request.body ? { body: request.body } : {},
|
|
25398
|
+
...redirect !== void 0 ? { redirect } : {}
|
|
25399
|
+
});
|
|
25400
|
+
} catch (e) {
|
|
25401
|
+
finish();
|
|
25402
|
+
throw e;
|
|
25403
|
+
}
|
|
25404
|
+
const { status, statusText, headers, url, redirected: redirected2, redirects, opaqueRedirect } = head;
|
|
25405
|
+
const read = async () => {
|
|
25406
|
+
if (finished) return void 0;
|
|
25407
|
+
const reply = await this.ask({ net: "read", nid }).catch((e) => {
|
|
25408
|
+
finish();
|
|
25409
|
+
throw e;
|
|
25410
|
+
});
|
|
25411
|
+
if (reply.net === "chunk") return reply.bytes;
|
|
25412
|
+
finish();
|
|
25413
|
+
return void 0;
|
|
25414
|
+
};
|
|
25415
|
+
const cancel = async () => {
|
|
25416
|
+
if (finished) return;
|
|
25417
|
+
finish();
|
|
25418
|
+
this.cancel(nid);
|
|
25419
|
+
};
|
|
25420
|
+
if (unfollowed2(redirect) && (redirected2 || redirects?.length)) {
|
|
25421
|
+
await cancel();
|
|
25422
|
+
throw refused3(`this transport followed a redirect despite redirect: ${redirect}`);
|
|
25423
|
+
}
|
|
25424
|
+
return {
|
|
25425
|
+
...url !== void 0 ? { url } : {},
|
|
25426
|
+
...redirected2 !== void 0 ? { redirected: redirected2 } : {},
|
|
25427
|
+
...redirects ? { redirects } : {},
|
|
25428
|
+
...opaqueRedirect ? { opaqueRedirect } : {},
|
|
25429
|
+
status,
|
|
25430
|
+
statusText,
|
|
25431
|
+
headers,
|
|
25432
|
+
cancel,
|
|
25433
|
+
body: {
|
|
25434
|
+
[Symbol.asyncIterator]: () => ({
|
|
25435
|
+
next: async () => {
|
|
25436
|
+
const bytes = await read();
|
|
25437
|
+
return bytes ? { value: bytes, done: false } : { value: void 0, done: true };
|
|
25438
|
+
},
|
|
25439
|
+
return: async () => {
|
|
25440
|
+
await cancel();
|
|
25441
|
+
return { value: void 0, done: true };
|
|
25442
|
+
}
|
|
25443
|
+
})
|
|
25444
|
+
}
|
|
25445
|
+
};
|
|
25446
|
+
}
|
|
25447
|
+
async websocket(request) {
|
|
25448
|
+
const nid = ++this.nextId;
|
|
25449
|
+
const { signal } = request;
|
|
25450
|
+
signal.throwIfAborted();
|
|
25451
|
+
const abort = () => this.cancel(nid);
|
|
25452
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
25453
|
+
let opened2;
|
|
25454
|
+
try {
|
|
25455
|
+
opened2 = await this.ask({
|
|
25456
|
+
net: "ws-open",
|
|
25457
|
+
nid,
|
|
25458
|
+
url: request.url,
|
|
25459
|
+
protocols: request.protocols,
|
|
25460
|
+
headers: request.headers
|
|
25461
|
+
});
|
|
25462
|
+
} finally {
|
|
25463
|
+
signal.removeEventListener("abort", abort);
|
|
25464
|
+
}
|
|
25465
|
+
const close = (code, reason) => this.port.postMessage({ net: "ws-close", nid, code, reason });
|
|
25466
|
+
const queue = new MessageQueue(
|
|
25467
|
+
() => close(1e3, "a message is too big"),
|
|
25468
|
+
Number.POSITIVE_INFINITY,
|
|
25469
|
+
(n) => this.port.postMessage({ net: "ws-consumed", nid, n })
|
|
25470
|
+
);
|
|
25471
|
+
let unacked = 0;
|
|
25472
|
+
this.sockets.set(nid, { queue, acked: (n) => void (unacked -= n) });
|
|
25473
|
+
return {
|
|
25474
|
+
protocol: opened2.protocol,
|
|
25475
|
+
get buffered() {
|
|
25476
|
+
return unacked;
|
|
25477
|
+
},
|
|
25478
|
+
send: (data) => {
|
|
25479
|
+
unacked += payloadSize(data);
|
|
25480
|
+
this.port.postMessage({ net: "ws-send", nid, data });
|
|
25481
|
+
},
|
|
25482
|
+
messages: queue,
|
|
25483
|
+
close,
|
|
25484
|
+
closed: queue.closed
|
|
25485
|
+
};
|
|
25486
|
+
}
|
|
25487
|
+
};
|
|
25488
|
+
|
|
25182
25489
|
// src/kernel/net/redirect-hops.ts
|
|
25183
25490
|
var HELD_MS = 3e4;
|
|
25184
25491
|
var HELD_MAX2 = 64;
|
|
@@ -25254,7 +25561,10 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
25254
25561
|
return { ...inner.traits, manualRedirects: true };
|
|
25255
25562
|
},
|
|
25256
25563
|
...inner.websocket ? { websocket: inner.websocket.bind(inner) } : {},
|
|
25257
|
-
async fetch(request,
|
|
25564
|
+
async fetch(request, ...rest2) {
|
|
25565
|
+
if (unfollowed2(request.redirect)) return inner.fetch(request, ...rest2);
|
|
25566
|
+
const [caller] = rest2;
|
|
25567
|
+
const owner = caller ?? KERNEL;
|
|
25258
25568
|
const key = keyOf3(owner, request.method, request.url);
|
|
25259
25569
|
const waiting = held.get(key);
|
|
25260
25570
|
if (waiting && waiting.fingerprint === fingerprint(request.headers)) {
|
|
@@ -25263,7 +25573,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
25263
25573
|
return replay(waiting);
|
|
25264
25574
|
}
|
|
25265
25575
|
if (waiting) drop(key);
|
|
25266
|
-
const response = await inner.fetch(request);
|
|
25576
|
+
const response = await inner.fetch(request, ...rest2);
|
|
25267
25577
|
if (!response.redirects?.length) return response;
|
|
25268
25578
|
return replay({
|
|
25269
25579
|
owner,
|
|
@@ -25448,11 +25758,11 @@ var PackageLocks = class {
|
|
|
25448
25758
|
if (!locks) return Promise.resolve(() => {
|
|
25449
25759
|
});
|
|
25450
25760
|
const { promise: held, resolve: release } = Promise.withResolvers();
|
|
25451
|
-
return new Promise((granted2,
|
|
25761
|
+
return new Promise((granted2, failed4) => {
|
|
25452
25762
|
locks.request(replacingLock(this.metadata, root), { mode: "exclusive" }, () => {
|
|
25453
25763
|
granted2(() => release());
|
|
25454
25764
|
return held;
|
|
25455
|
-
}).catch(
|
|
25765
|
+
}).catch(failed4);
|
|
25456
25766
|
});
|
|
25457
25767
|
}
|
|
25458
25768
|
};
|
|
@@ -25702,9 +26012,9 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
|
|
|
25702
26012
|
let open = false;
|
|
25703
26013
|
const reply = (message3, transfer = []) => port.postMessage(message3, transfer);
|
|
25704
26014
|
async function hello(message3) {
|
|
25705
|
-
const
|
|
25706
|
-
if (
|
|
25707
|
-
reply({ hello: { protocol: DRIVER_PROTOCOL, error:
|
|
26015
|
+
const refused4 = driverVersionError(message3.protocol);
|
|
26016
|
+
if (refused4) {
|
|
26017
|
+
reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused4, errno: "EPROTO" } });
|
|
25708
26018
|
return;
|
|
25709
26019
|
}
|
|
25710
26020
|
try {
|
|
@@ -27946,12 +28256,12 @@ var OpfsFs = class {
|
|
|
27946
28256
|
if (!move) return false;
|
|
27947
28257
|
for (let attempt = 0; ; attempt++) {
|
|
27948
28258
|
this.others++;
|
|
27949
|
-
const
|
|
28259
|
+
const failed4 = await move.call(handle, dir, name2).then(
|
|
27950
28260
|
() => void 0,
|
|
27951
28261
|
(err) => ({ err })
|
|
27952
28262
|
);
|
|
27953
|
-
if (!
|
|
27954
|
-
const error =
|
|
28263
|
+
if (!failed4) return true;
|
|
28264
|
+
const error = failed4.err?.name;
|
|
27955
28265
|
if (handle.kind !== "file" || !LOCKED.has(error)) return false;
|
|
27956
28266
|
const delay2 = SYNC_BACKOFF_MS[attempt];
|
|
27957
28267
|
if (delay2 === void 0) throw fsError("EBUSY", name2);
|
|
@@ -28514,22 +28824,22 @@ async function mountFstab(lines2, mount, signal, retries = FSTAB_RETRIES, discar
|
|
|
28514
28824
|
);
|
|
28515
28825
|
}
|
|
28516
28826
|
async function mountLine({ line, spec, invalid }, mount, signal, retries, discard) {
|
|
28517
|
-
let
|
|
28827
|
+
let failed4 = invalid;
|
|
28518
28828
|
for (let attempt = 0; !invalid && attempt <= retries.length && !signal.aborted; attempt++) {
|
|
28519
28829
|
try {
|
|
28520
28830
|
const entry = await mount(spec);
|
|
28521
28831
|
if (!signal.aborted) return { line, target: spec.target, entry };
|
|
28522
28832
|
discard(entry);
|
|
28523
|
-
|
|
28833
|
+
failed4 = Object.assign(new Error("the kernel stopped"), { code: "ECANCELED" });
|
|
28524
28834
|
break;
|
|
28525
28835
|
} catch (err) {
|
|
28526
|
-
|
|
28836
|
+
failed4 = err;
|
|
28527
28837
|
if (FINAL.has(codeOf6(err)) || attempt === retries.length) break;
|
|
28528
28838
|
await wait(retries[attempt], signal);
|
|
28529
28839
|
}
|
|
28530
28840
|
}
|
|
28531
|
-
const code = codeOf6(
|
|
28532
|
-
return { line, target: spec.target, code, error: String(
|
|
28841
|
+
const code = codeOf6(failed4);
|
|
28842
|
+
return { line, target: spec.target, code, error: String(failed4?.message ?? code) };
|
|
28533
28843
|
}
|
|
28534
28844
|
|
|
28535
28845
|
// src/mount/hostfs.ts
|
|
@@ -30990,7 +31300,7 @@ var Launcher = class {
|
|
|
30990
31300
|
...options.env
|
|
30991
31301
|
};
|
|
30992
31302
|
this.ca = kernelCa(options.caStore ?? memoryCaStore());
|
|
30993
|
-
this.transport = replayingHops(options.transport ?? missingTransport());
|
|
31303
|
+
this.transport = placeholderFloor(replayingHops(options.transport ?? missingTransport()));
|
|
30994
31304
|
this.announcedTraits = JSON.stringify(this.transport.traits);
|
|
30995
31305
|
this.uplink = options.uplink;
|
|
30996
31306
|
this.routes = new Routes(options.uplink?.traits.ipv6 === true);
|
|
@@ -31145,16 +31455,16 @@ var Launcher = class {
|
|
|
31145
31455
|
if (!found) {
|
|
31146
31456
|
found = this.swaps.settled().then(() => this.trustedAppended()).then(async (appended2) => {
|
|
31147
31457
|
const tiers = await this.tiers(scope, appended2);
|
|
31148
|
-
const
|
|
31458
|
+
const refused4 = [];
|
|
31149
31459
|
const commands = await scanCommands(
|
|
31150
31460
|
this.scanned,
|
|
31151
31461
|
tiers,
|
|
31152
31462
|
tiers.length - appended2.length,
|
|
31153
31463
|
void 0,
|
|
31154
|
-
|
|
31464
|
+
refused4,
|
|
31155
31465
|
await this.globalRoots(scope)
|
|
31156
31466
|
);
|
|
31157
|
-
this.refusedOf.set(commands,
|
|
31467
|
+
this.refusedOf.set(commands, refused4.map(refusing));
|
|
31158
31468
|
return commands;
|
|
31159
31469
|
}).then(
|
|
31160
31470
|
(commands) => this.refusals(commands).set(SUDO_COMMAND.name, SUDO_COMMAND).set(CRONTAB_COMMAND.name, CRONTAB_COMMAND)
|
|
@@ -31360,14 +31670,14 @@ var Launcher = class {
|
|
|
31360
31670
|
return await this.commandAt(path, scope) ?? await this.refusedAt(path, name2, scope);
|
|
31361
31671
|
}
|
|
31362
31672
|
async refusedAt(path, name2, scope) {
|
|
31363
|
-
const
|
|
31364
|
-
if (
|
|
31673
|
+
const refused4 = this.refusedOf.get(await this.commands(scope)) ?? [];
|
|
31674
|
+
if (refused4.length === 0) return void 0;
|
|
31365
31675
|
const st = await this.base.stat(path).catch(() => void 0);
|
|
31366
31676
|
if (!st?.isFile) return void 0;
|
|
31367
31677
|
const real = await physicalPathAsync(this.base, path).catch(() => path);
|
|
31368
31678
|
const same2 = async (own) => own === path || await physicalPathAsync(this.base, own).catch(() => own) === real;
|
|
31369
31679
|
const owners = [];
|
|
31370
|
-
for (const c of
|
|
31680
|
+
for (const c of refused4) {
|
|
31371
31681
|
const origin = c.origin;
|
|
31372
31682
|
for (const own of [origin.glue, origin.wasm, ...origin.variants ?? []]) {
|
|
31373
31683
|
if (!await same2(own)) continue;
|
|
@@ -31377,11 +31687,11 @@ var Launcher = class {
|
|
|
31377
31687
|
}
|
|
31378
31688
|
const stem = name2.replace(/\.wasm$/, "");
|
|
31379
31689
|
const named = owners.find((c) => c.name === name2) ?? owners.find((c) => c.name === stem);
|
|
31380
|
-
return named ?? owners[0] ?? await this.refusedCopy(real, name2,
|
|
31690
|
+
return named ?? owners[0] ?? await this.refusedCopy(real, name2, refused4);
|
|
31381
31691
|
}
|
|
31382
|
-
async refusedCopy(real, name2,
|
|
31692
|
+
async refusedCopy(real, name2, refused4) {
|
|
31383
31693
|
const dir = real.slice(0, real.lastIndexOf("/"));
|
|
31384
|
-
for (const c of
|
|
31694
|
+
for (const c of refused4) {
|
|
31385
31695
|
const origin = c.origin;
|
|
31386
31696
|
if (origin.abi !== "emscripten" || origin.script || c.name !== name2) continue;
|
|
31387
31697
|
const own = await physicalPathAsync(this.base, origin.glue).catch(() => origin.glue);
|
|
@@ -31589,12 +31899,12 @@ var Launcher = class {
|
|
|
31589
31899
|
return void 0;
|
|
31590
31900
|
}
|
|
31591
31901
|
async planOne(req, { ppid, cred, scope }, catalogOnly = false) {
|
|
31592
|
-
const
|
|
31902
|
+
const refused4 = (err) => {
|
|
31593
31903
|
throw codeOf8(err) === "EACCES" ? new SpawnError("EACCES") : err;
|
|
31594
31904
|
};
|
|
31595
|
-
const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(
|
|
31905
|
+
const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused4);
|
|
31596
31906
|
const planned = await this.plan(file, req.argv, req.cwd, scope, req.argv0, catalogOnly);
|
|
31597
|
-
await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(
|
|
31907
|
+
await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused4);
|
|
31598
31908
|
if (planned) return planned;
|
|
31599
31909
|
throw new SpawnError(catalogOnly ? "ENOENT" : await this.unrunnable(file, req.cwd, scope));
|
|
31600
31910
|
}
|
|
@@ -32882,8 +33192,8 @@ var Launcher = class {
|
|
|
32882
33192
|
for (const name2 of names2 ?? []) {
|
|
32883
33193
|
const path = joinName(real, name2);
|
|
32884
33194
|
if (await this.base.hasOwner(path)) continue;
|
|
32885
|
-
const
|
|
32886
|
-
if (
|
|
33195
|
+
const failed4 = this.inUse(path) ? "busy" : await this.base.rm(path, { recursive: true, force: true }).catch(String);
|
|
33196
|
+
if (failed4 === void 0) removed++;
|
|
32887
33197
|
else left++;
|
|
32888
33198
|
}
|
|
32889
33199
|
if (removed > 0) {
|
|
@@ -33676,10 +33986,11 @@ function fetchTransport(options = {}) {
|
|
|
33676
33986
|
const send2 = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
33677
33987
|
const Socket = options.webSocket === true ? globalThis.WebSocket : options.webSocket || void 0;
|
|
33678
33988
|
const headers = options.webSocketHeaders === true;
|
|
33679
|
-
const
|
|
33989
|
+
const instance = options.redirect ?? "follow";
|
|
33680
33990
|
return {
|
|
33681
33991
|
traits: {
|
|
33682
|
-
manualRedirects:
|
|
33992
|
+
manualRedirects: instance === "manual",
|
|
33993
|
+
redirectPolicy: true,
|
|
33683
33994
|
encodedBodies: false,
|
|
33684
33995
|
maxRequestBody: options.maxRequestBody ?? MAX_REQUEST_BODY,
|
|
33685
33996
|
crossOrigin: "cors",
|
|
@@ -33695,7 +34006,7 @@ function fetchTransport(options = {}) {
|
|
|
33695
34006
|
headers: joinHeaders(request.headers),
|
|
33696
34007
|
...requestBody(request),
|
|
33697
34008
|
signal: request.signal,
|
|
33698
|
-
redirect,
|
|
34009
|
+
redirect: request.redirect ?? instance,
|
|
33699
34010
|
credentials: "omit",
|
|
33700
34011
|
mode: "cors"
|
|
33701
34012
|
});
|
|
@@ -33719,6 +34030,7 @@ function fetchTransport(options = {}) {
|
|
|
33719
34030
|
const body = chunks(response.body, options.bodyIdleMs ?? BODY_IDLE_MS);
|
|
33720
34031
|
return {
|
|
33721
34032
|
...response.redirected ? { url: response.url, redirected: true } : {},
|
|
34033
|
+
...response.type === "opaqueredirect" ? { opaqueRedirect: true } : {},
|
|
33722
34034
|
status: response.status,
|
|
33723
34035
|
statusText: response.statusText,
|
|
33724
34036
|
headers: headers2,
|
|
@@ -33754,6 +34066,19 @@ function uploadsFor(peer) {
|
|
|
33754
34066
|
});
|
|
33755
34067
|
return { of, answer: (call) => pulls.get(call.nid)?.(call) };
|
|
33756
34068
|
}
|
|
34069
|
+
function headOf(nid, response) {
|
|
34070
|
+
return {
|
|
34071
|
+
net: "head",
|
|
34072
|
+
nid,
|
|
34073
|
+
...response.url !== void 0 ? { url: response.url } : {},
|
|
34074
|
+
...response.redirected !== void 0 ? { redirected: response.redirected } : {},
|
|
34075
|
+
...response.redirects ? { redirects: response.redirects } : {},
|
|
34076
|
+
...response.opaqueRedirect ? { opaqueRedirect: true } : {},
|
|
34077
|
+
status: response.status,
|
|
34078
|
+
statusText: response.statusText,
|
|
34079
|
+
headers: response.headers
|
|
34080
|
+
};
|
|
34081
|
+
}
|
|
33757
34082
|
function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS3 } = {}) {
|
|
33758
34083
|
const open = /* @__PURE__ */ new Map();
|
|
33759
34084
|
const fail3 = (nid, e) => {
|
|
@@ -33779,6 +34104,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS3 } = {})
|
|
|
33779
34104
|
method: call.method,
|
|
33780
34105
|
headers: call.headers,
|
|
33781
34106
|
...call.streamed ? { bodyStream: uploads.of(call.nid, abort.signal) } : call.body ? { body: call.body } : {},
|
|
34107
|
+
...call.redirect !== void 0 ? { redirect: call.redirect } : {},
|
|
33782
34108
|
signal: abort.signal
|
|
33783
34109
|
});
|
|
33784
34110
|
if (!open.has(call.nid)) {
|
|
@@ -33786,15 +34112,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS3 } = {})
|
|
|
33786
34112
|
return;
|
|
33787
34113
|
}
|
|
33788
34114
|
open.set(call.nid, { abort, body: response.body[Symbol.asyncIterator](), response });
|
|
33789
|
-
peer.postMessage(
|
|
33790
|
-
net: "head",
|
|
33791
|
-
nid: call.nid,
|
|
33792
|
-
...response.redirected ? { url: response.url, redirected: true } : {},
|
|
33793
|
-
...response.redirects ? { redirects: response.redirects } : {},
|
|
33794
|
-
status: response.status,
|
|
33795
|
-
statusText: response.statusText,
|
|
33796
|
-
headers: response.headers
|
|
33797
|
-
});
|
|
34115
|
+
peer.postMessage(headOf(call.nid, response));
|
|
33798
34116
|
} catch (e) {
|
|
33799
34117
|
fail3(call.nid, e);
|
|
33800
34118
|
}
|
|
@@ -34294,9 +34612,9 @@ function serveClient(port, host) {
|
|
|
34294
34612
|
ended.resolve();
|
|
34295
34613
|
}
|
|
34296
34614
|
async function hello(message3) {
|
|
34297
|
-
const
|
|
34298
|
-
if (
|
|
34299
|
-
send2({ hello: { protocol: PROTOCOL, error:
|
|
34615
|
+
const refused4 = versionError(message3.protocol) ?? await hosts.requests.accept(host, message3);
|
|
34616
|
+
if (refused4) {
|
|
34617
|
+
send2({ hello: { protocol: PROTOCOL, error: refused4 } });
|
|
34300
34618
|
detach();
|
|
34301
34619
|
return;
|
|
34302
34620
|
}
|
|
@@ -34440,6 +34758,60 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
34440
34758
|
import { subscribe } from "node:diagnostics_channel";
|
|
34441
34759
|
import { lookup as lookup2 } from "node:dns/promises";
|
|
34442
34760
|
import { isIP as isIP3 } from "node:net";
|
|
34761
|
+
|
|
34762
|
+
// src/node/follow.ts
|
|
34763
|
+
var MAX_REDIRECTS = 20;
|
|
34764
|
+
var REDIRECTS = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
34765
|
+
var BODY_HEADERS = /* @__PURE__ */ new Set([
|
|
34766
|
+
"content-encoding",
|
|
34767
|
+
"content-language",
|
|
34768
|
+
"content-length",
|
|
34769
|
+
"content-location",
|
|
34770
|
+
"content-type"
|
|
34771
|
+
]);
|
|
34772
|
+
var CREDENTIALS = /* @__PURE__ */ new Set(["authorization", "proxy-authorization", "cookie", "cookie2"]);
|
|
34773
|
+
function failed3(message3) {
|
|
34774
|
+
return Object.assign(new Error(message3), { status: 502, detail: "transport" });
|
|
34775
|
+
}
|
|
34776
|
+
function locationOf(headers) {
|
|
34777
|
+
return headers.find(([name2]) => name2.toLowerCase() === "location")?.[1];
|
|
34778
|
+
}
|
|
34779
|
+
function nextHop(hop, status, location) {
|
|
34780
|
+
if (!URL.canParse(location, hop.url)) throw failed3(`a bad redirect from ${hop.url}`);
|
|
34781
|
+
const next3 = new URL(location, hop.url);
|
|
34782
|
+
if (next3.protocol !== "http:" && next3.protocol !== "https:") {
|
|
34783
|
+
throw failed3(`a redirect from ${hop.url} to ${next3.protocol}`);
|
|
34784
|
+
}
|
|
34785
|
+
next3.hash = "";
|
|
34786
|
+
const toGet = (status === 301 || status === 302) && hop.method === "POST" || status === 303 && hop.method !== "GET" && hop.method !== "HEAD";
|
|
34787
|
+
if (hop.bodyStream && !toGet) throw failed3(`a ${status} redirect would resend a streamed body`);
|
|
34788
|
+
const crossOrigin = next3.origin !== new URL(hop.url).origin;
|
|
34789
|
+
const { body, bodyStream: bodyStream2, ...rest2 } = hop;
|
|
34790
|
+
return {
|
|
34791
|
+
...rest2,
|
|
34792
|
+
...body && !toGet ? { body } : {},
|
|
34793
|
+
url: next3.href,
|
|
34794
|
+
method: toGet ? "GET" : hop.method,
|
|
34795
|
+
headers: hop.headers.filter(
|
|
34796
|
+
([name2]) => !(toGet && BODY_HEADERS.has(name2.toLowerCase())) && !(crossOrigin && CREDENTIALS.has(name2.toLowerCase()))
|
|
34797
|
+
)
|
|
34798
|
+
};
|
|
34799
|
+
}
|
|
34800
|
+
async function followRedirects(send2, request) {
|
|
34801
|
+
let hop = { ...request, redirect: "manual" };
|
|
34802
|
+
for (let hops = 0; ; hops++) {
|
|
34803
|
+
const response = await send2(hop);
|
|
34804
|
+
const location = locationOf(response.headers);
|
|
34805
|
+
if (!REDIRECTS.has(response.status) || location === void 0) {
|
|
34806
|
+
return hops > 0 ? { ...response, url: hop.url, redirected: true } : response;
|
|
34807
|
+
}
|
|
34808
|
+
await response.cancel();
|
|
34809
|
+
if (hops >= MAX_REDIRECTS) throw failed3(`too many redirects from ${request.url}`);
|
|
34810
|
+
hop = nextHop(hop, response.status, location);
|
|
34811
|
+
}
|
|
34812
|
+
}
|
|
34813
|
+
|
|
34814
|
+
// src/node/loopback.ts
|
|
34443
34815
|
var DEVTOOLS_PORTS = [9222, 9223, 9224, 9225, 9226, 9227, 9228, 9229];
|
|
34444
34816
|
var METADATA_V6 = [64768, 3778, 0, 0, 0, 0, 0, 596].join(":");
|
|
34445
34817
|
var resolveHost = async (host) => (await lookup2(host, { all: true, verbatim: true })).map((a) => a.address);
|
|
@@ -34604,19 +34976,20 @@ function ensureSubscribed() {
|
|
|
34604
34976
|
function guardedLoopback(transport, policy, resolve2) {
|
|
34605
34977
|
ensureSubscribed();
|
|
34606
34978
|
const open = transport.websocket?.bind(transport);
|
|
34979
|
+
const send2 = async (request, owner) => {
|
|
34980
|
+
await guarded2(checkDestination(request.url, policy, resolve2), request.signal);
|
|
34981
|
+
const entry = { policy };
|
|
34982
|
+
try {
|
|
34983
|
+
return await loopbackStore.run(entry, () => transport.fetch(request, owner));
|
|
34984
|
+
} catch (err) {
|
|
34985
|
+
throw entry.refused ?? err;
|
|
34986
|
+
}
|
|
34987
|
+
};
|
|
34607
34988
|
return {
|
|
34608
34989
|
get traits() {
|
|
34609
34990
|
return transport.traits;
|
|
34610
34991
|
},
|
|
34611
|
-
fetch:
|
|
34612
|
-
await guarded2(checkDestination(request.url, policy, resolve2), request.signal);
|
|
34613
|
-
const entry = { policy };
|
|
34614
|
-
try {
|
|
34615
|
-
return await loopbackStore.run(entry, () => transport.fetch(request, owner));
|
|
34616
|
-
} catch (err) {
|
|
34617
|
-
throw entry.refused ?? err;
|
|
34618
|
-
}
|
|
34619
|
-
},
|
|
34992
|
+
fetch: (request, owner) => request.redirect === "follow" ? followRedirects((hop) => send2(hop, owner), request) : send2(request, owner),
|
|
34620
34993
|
...open ? {
|
|
34621
34994
|
websocket: async (request) => {
|
|
34622
34995
|
await guarded2(checkDestination(request.url, policy, resolve2), request.signal);
|
|
@@ -35002,212 +35375,6 @@ function diagnosing(transport, check = byDefault) {
|
|
|
35002
35375
|
};
|
|
35003
35376
|
}
|
|
35004
35377
|
|
|
35005
|
-
// src/kernel/net/remote-transport.ts
|
|
35006
|
-
var TransportError = class extends Error {
|
|
35007
|
-
status;
|
|
35008
|
-
code;
|
|
35009
|
-
detail;
|
|
35010
|
-
constructor(message3, status, code, detail) {
|
|
35011
|
-
super(message3);
|
|
35012
|
-
this.status = status;
|
|
35013
|
-
this.code = code;
|
|
35014
|
-
this.detail = detail === "transport" ? detail : void 0;
|
|
35015
|
-
}
|
|
35016
|
-
};
|
|
35017
|
-
var RemoteTransport = class {
|
|
35018
|
-
traits;
|
|
35019
|
-
port;
|
|
35020
|
-
waiting = /* @__PURE__ */ new Map();
|
|
35021
|
-
nextId = 0;
|
|
35022
|
-
sockets = /* @__PURE__ */ new Map();
|
|
35023
|
-
uploads = /* @__PURE__ */ new Map();
|
|
35024
|
-
failure;
|
|
35025
|
-
constructor(port, traits) {
|
|
35026
|
-
this.port = port;
|
|
35027
|
-
this.traits = traits;
|
|
35028
|
-
}
|
|
35029
|
-
receive(reply) {
|
|
35030
|
-
if (reply.net === "body-pull") {
|
|
35031
|
-
void this.pull(reply.nid);
|
|
35032
|
-
return;
|
|
35033
|
-
}
|
|
35034
|
-
const socket = this.sockets.get(reply.nid);
|
|
35035
|
-
if (socket && this.toSocket(reply, socket)) return;
|
|
35036
|
-
const waiter = this.waiting.get(reply.nid);
|
|
35037
|
-
if (!waiter) return;
|
|
35038
|
-
this.waiting.delete(reply.nid);
|
|
35039
|
-
if (reply.net === "error") {
|
|
35040
|
-
waiter.reject(new TransportError(reply.message, reply.status, reply.code, reply.detail));
|
|
35041
|
-
} else waiter.resolve(reply);
|
|
35042
|
-
}
|
|
35043
|
-
toSocket(reply, socket) {
|
|
35044
|
-
if (reply.net === "ws-message") socket.queue.push(reply.data);
|
|
35045
|
-
else if (reply.net === "ws-acked") socket.acked(reply.n);
|
|
35046
|
-
else if (reply.net === "ws-closed") {
|
|
35047
|
-
this.sockets.delete(reply.nid);
|
|
35048
|
-
socket.queue.end({ code: reply.code, reason: reply.reason });
|
|
35049
|
-
} else return false;
|
|
35050
|
-
return true;
|
|
35051
|
-
}
|
|
35052
|
-
async pull(nid) {
|
|
35053
|
-
const upload = this.uploads.get(nid);
|
|
35054
|
-
if (!upload) {
|
|
35055
|
-
this.port.postMessage({ net: "body-error", nid, message: "the request body is gone" });
|
|
35056
|
-
return;
|
|
35057
|
-
}
|
|
35058
|
-
try {
|
|
35059
|
-
const next3 = await upload.next();
|
|
35060
|
-
if (next3.done) {
|
|
35061
|
-
this.uploads.delete(nid);
|
|
35062
|
-
this.port.postMessage({ net: "body-end", nid });
|
|
35063
|
-
} else this.port.postMessage({ net: "body-chunk", nid, bytes: next3.value });
|
|
35064
|
-
} catch (e) {
|
|
35065
|
-
this.uploads.delete(nid);
|
|
35066
|
-
this.port.postMessage({
|
|
35067
|
-
net: "body-error",
|
|
35068
|
-
nid,
|
|
35069
|
-
message: e instanceof Error ? e.message : String(e)
|
|
35070
|
-
});
|
|
35071
|
-
}
|
|
35072
|
-
}
|
|
35073
|
-
dropUpload(nid) {
|
|
35074
|
-
const upload = this.uploads.get(nid);
|
|
35075
|
-
this.uploads.delete(nid);
|
|
35076
|
-
void upload?.return?.().catch(() => void 0);
|
|
35077
|
-
}
|
|
35078
|
-
fail(error) {
|
|
35079
|
-
this.failure = error;
|
|
35080
|
-
for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);
|
|
35081
|
-
for (const waiter of this.waiting.values()) waiter.reject(error);
|
|
35082
|
-
this.waiting.clear();
|
|
35083
|
-
for (const socket of this.sockets.values())
|
|
35084
|
-
socket.queue.end({ code: 1011, reason: error.message });
|
|
35085
|
-
this.sockets.clear();
|
|
35086
|
-
}
|
|
35087
|
-
ask(call) {
|
|
35088
|
-
if (this.failure) return Promise.reject(this.failure);
|
|
35089
|
-
return new Promise((resolve2, reject) => {
|
|
35090
|
-
this.waiting.set(call.nid, { resolve: resolve2, reject });
|
|
35091
|
-
this.port.postMessage(call);
|
|
35092
|
-
});
|
|
35093
|
-
}
|
|
35094
|
-
cancel(nid) {
|
|
35095
|
-
const waiter = this.waiting.get(nid);
|
|
35096
|
-
this.waiting.delete(nid);
|
|
35097
|
-
waiter?.reject(new TransportError("the request was cancelled"));
|
|
35098
|
-
this.port.postMessage({ net: "cancel", nid });
|
|
35099
|
-
}
|
|
35100
|
-
async fetch(request) {
|
|
35101
|
-
const nid = ++this.nextId;
|
|
35102
|
-
const { signal } = request;
|
|
35103
|
-
signal.throwIfAborted();
|
|
35104
|
-
let finished = false;
|
|
35105
|
-
const abort = () => {
|
|
35106
|
-
finished = true;
|
|
35107
|
-
this.dropUpload(nid);
|
|
35108
|
-
this.cancel(nid);
|
|
35109
|
-
};
|
|
35110
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
35111
|
-
const finish = () => {
|
|
35112
|
-
this.dropUpload(nid);
|
|
35113
|
-
if (finished) return;
|
|
35114
|
-
finished = true;
|
|
35115
|
-
signal.removeEventListener("abort", abort);
|
|
35116
|
-
};
|
|
35117
|
-
if (request.bodyStream) this.uploads.set(nid, request.bodyStream[Symbol.asyncIterator]());
|
|
35118
|
-
let head;
|
|
35119
|
-
try {
|
|
35120
|
-
head = await this.ask({
|
|
35121
|
-
net: "fetch",
|
|
35122
|
-
nid,
|
|
35123
|
-
url: request.url,
|
|
35124
|
-
method: request.method,
|
|
35125
|
-
headers: request.headers,
|
|
35126
|
-
...request.bodyStream ? { streamed: true } : request.body ? { body: request.body } : {}
|
|
35127
|
-
});
|
|
35128
|
-
} catch (e) {
|
|
35129
|
-
finish();
|
|
35130
|
-
throw e;
|
|
35131
|
-
}
|
|
35132
|
-
const { status, statusText, headers, url, redirected: redirected2, redirects } = head;
|
|
35133
|
-
const read = async () => {
|
|
35134
|
-
if (finished) return void 0;
|
|
35135
|
-
const reply = await this.ask({ net: "read", nid }).catch((e) => {
|
|
35136
|
-
finish();
|
|
35137
|
-
throw e;
|
|
35138
|
-
});
|
|
35139
|
-
if (reply.net === "chunk") return reply.bytes;
|
|
35140
|
-
finish();
|
|
35141
|
-
return void 0;
|
|
35142
|
-
};
|
|
35143
|
-
const cancel = async () => {
|
|
35144
|
-
if (finished) return;
|
|
35145
|
-
finish();
|
|
35146
|
-
this.cancel(nid);
|
|
35147
|
-
};
|
|
35148
|
-
return {
|
|
35149
|
-
...redirected2 ? { url, redirected: redirected2 } : {},
|
|
35150
|
-
...redirects ? { redirects } : {},
|
|
35151
|
-
status,
|
|
35152
|
-
statusText,
|
|
35153
|
-
headers,
|
|
35154
|
-
cancel,
|
|
35155
|
-
body: {
|
|
35156
|
-
[Symbol.asyncIterator]: () => ({
|
|
35157
|
-
next: async () => {
|
|
35158
|
-
const bytes = await read();
|
|
35159
|
-
return bytes ? { value: bytes, done: false } : { value: void 0, done: true };
|
|
35160
|
-
},
|
|
35161
|
-
return: async () => {
|
|
35162
|
-
await cancel();
|
|
35163
|
-
return { value: void 0, done: true };
|
|
35164
|
-
}
|
|
35165
|
-
})
|
|
35166
|
-
}
|
|
35167
|
-
};
|
|
35168
|
-
}
|
|
35169
|
-
async websocket(request) {
|
|
35170
|
-
const nid = ++this.nextId;
|
|
35171
|
-
const { signal } = request;
|
|
35172
|
-
signal.throwIfAborted();
|
|
35173
|
-
const abort = () => this.cancel(nid);
|
|
35174
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
35175
|
-
let opened2;
|
|
35176
|
-
try {
|
|
35177
|
-
opened2 = await this.ask({
|
|
35178
|
-
net: "ws-open",
|
|
35179
|
-
nid,
|
|
35180
|
-
url: request.url,
|
|
35181
|
-
protocols: request.protocols,
|
|
35182
|
-
headers: request.headers
|
|
35183
|
-
});
|
|
35184
|
-
} finally {
|
|
35185
|
-
signal.removeEventListener("abort", abort);
|
|
35186
|
-
}
|
|
35187
|
-
const close = (code, reason) => this.port.postMessage({ net: "ws-close", nid, code, reason });
|
|
35188
|
-
const queue = new MessageQueue(
|
|
35189
|
-
() => close(1e3, "a message is too big"),
|
|
35190
|
-
Number.POSITIVE_INFINITY,
|
|
35191
|
-
(n) => this.port.postMessage({ net: "ws-consumed", nid, n })
|
|
35192
|
-
);
|
|
35193
|
-
let unacked = 0;
|
|
35194
|
-
this.sockets.set(nid, { queue, acked: (n) => void (unacked -= n) });
|
|
35195
|
-
return {
|
|
35196
|
-
protocol: opened2.protocol,
|
|
35197
|
-
get buffered() {
|
|
35198
|
-
return unacked;
|
|
35199
|
-
},
|
|
35200
|
-
send: (data) => {
|
|
35201
|
-
unacked += payloadSize(data);
|
|
35202
|
-
this.port.postMessage({ net: "ws-send", nid, data });
|
|
35203
|
-
},
|
|
35204
|
-
messages: queue,
|
|
35205
|
-
close,
|
|
35206
|
-
closed: queue.closed
|
|
35207
|
-
};
|
|
35208
|
-
}
|
|
35209
|
-
};
|
|
35210
|
-
|
|
35211
35378
|
// src/serve.ts
|
|
35212
35379
|
function signalNumber(name2) {
|
|
35213
35380
|
const key = name2.slice(3);
|
|
@@ -35841,9 +36008,9 @@ async function greet(channel, lock, timeoutMs, requests) {
|
|
|
35841
36008
|
} finally {
|
|
35842
36009
|
clearTimeout(timer);
|
|
35843
36010
|
}
|
|
35844
|
-
const
|
|
35845
|
-
if (
|
|
35846
|
-
const error = new Error(
|
|
36011
|
+
const refused4 = hello.error ?? versionError(hello.protocol);
|
|
36012
|
+
if (refused4) {
|
|
36013
|
+
const error = new Error(refused4);
|
|
35847
36014
|
channel.end(error);
|
|
35848
36015
|
throw error;
|
|
35849
36016
|
}
|