@ai-ecoverse/slicc-kernel 1.49.1 → 1.50.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 +1 -0
- package/dist/driver-worker.js +2 -1
- package/dist/driver-worker.js.map +2 -2
- package/dist/index.js +6 -3
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +165 -65
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-driver-worker.js +2 -1
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node.js +172 -71
- package/dist/node.js.map +4 -4
- package/package.json +1 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -1574,6 +1574,8 @@ var KernelSocket = class _KernelSocket {
|
|
|
1574
1574
|
reset = false;
|
|
1575
1575
|
local;
|
|
1576
1576
|
peer;
|
|
1577
|
+
peerCred;
|
|
1578
|
+
listenerCred;
|
|
1577
1579
|
link;
|
|
1578
1580
|
readShut = false;
|
|
1579
1581
|
writeShut = false;
|
|
@@ -1649,7 +1651,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
1649
1651
|
this.local = this.net.bind(this, addr);
|
|
1650
1652
|
this.boundAt = this.local;
|
|
1651
1653
|
}
|
|
1652
|
-
listen(backlog) {
|
|
1654
|
+
listen(backlog, cred) {
|
|
1653
1655
|
if (this.state === "connected") throw new KernelError("EISCONN");
|
|
1654
1656
|
if (this.state !== "open" && this.state !== "listening") throw new KernelError("EINVAL");
|
|
1655
1657
|
if (!this.local) {
|
|
@@ -1658,6 +1660,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
1658
1660
|
}
|
|
1659
1661
|
this.backlog = Math.min(Math.max(backlog, 1), SOMAXCONN);
|
|
1660
1662
|
this.state = "listening";
|
|
1663
|
+
this.listenerCred ??= cred;
|
|
1661
1664
|
}
|
|
1662
1665
|
async accept(signal, nonblock = false) {
|
|
1663
1666
|
for (; ; ) {
|
|
@@ -1674,7 +1677,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
1674
1677
|
this.changes.wake();
|
|
1675
1678
|
return true;
|
|
1676
1679
|
}
|
|
1677
|
-
connect(addr, viaUplink = true) {
|
|
1680
|
+
connect(addr, viaUplink = true, cred) {
|
|
1678
1681
|
if (this.state === "connected") throw new KernelError("EISCONN");
|
|
1679
1682
|
if (this.state === "connecting") throw new KernelError("EALREADY");
|
|
1680
1683
|
if (this.state !== "open") throw new KernelError("EINVAL");
|
|
@@ -1692,7 +1695,9 @@ var KernelSocket = class _KernelSocket {
|
|
|
1692
1695
|
const server = new _KernelSocket(this.net, this.domain);
|
|
1693
1696
|
server.local = addr.family === "inet" ? { ...addr, host: canonicalHost(addr.host) } : addr;
|
|
1694
1697
|
server.peer = this.local;
|
|
1698
|
+
server.peerCred = cred;
|
|
1695
1699
|
this.peer = server.local;
|
|
1700
|
+
this.peerCred = target.listenerCred;
|
|
1696
1701
|
link(this, server);
|
|
1697
1702
|
if (!target.offer(server)) {
|
|
1698
1703
|
this.unlink();
|
|
@@ -1811,9 +1816,10 @@ var KernelSocket = class _KernelSocket {
|
|
|
1811
1816
|
this.boundAt = void 0;
|
|
1812
1817
|
this.changes.wake();
|
|
1813
1818
|
}
|
|
1814
|
-
static pair(net, domain) {
|
|
1819
|
+
static pair(net, domain, cred) {
|
|
1815
1820
|
const a = new _KernelSocket(net, domain);
|
|
1816
1821
|
const b = new _KernelSocket(net, domain);
|
|
1822
|
+
a.peerCred = b.peerCred = cred;
|
|
1817
1823
|
const name2 = domain === "inet" ? { family: "inet", host: "127.0.0.1", port: 0 } : { family: "unix", path: "" };
|
|
1818
1824
|
a.local = b.local = a.peer = b.peer = name2;
|
|
1819
1825
|
link(a, b);
|
|
@@ -2142,6 +2148,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
2142
2148
|
net: "head",
|
|
2143
2149
|
nid: call.nid,
|
|
2144
2150
|
...response.redirected ? { url: response.url, redirected: true } : {},
|
|
2151
|
+
...response.redirects ? { redirects: response.redirects } : {},
|
|
2145
2152
|
status: response.status,
|
|
2146
2153
|
statusText: response.statusText,
|
|
2147
2154
|
headers: response.headers
|
|
@@ -3698,7 +3705,7 @@ var RealmProxy = class {
|
|
|
3698
3705
|
const waiting = new AbortController();
|
|
3699
3706
|
void watchHangup(ctx.socket, abort, waiting.signal);
|
|
3700
3707
|
try {
|
|
3701
|
-
response = await this.upstream(req, url, body, abort.signal);
|
|
3708
|
+
response = await this.upstream(req, url, body, abort.signal, ctx.socket.peerCred?.pid);
|
|
3702
3709
|
} finally {
|
|
3703
3710
|
waiting.abort();
|
|
3704
3711
|
}
|
|
@@ -3724,15 +3731,18 @@ var RealmProxy = class {
|
|
|
3724
3731
|
await conn.write(latin1Bytes("HTTP/1.1 100 Continue\r\n\r\n"), this.stop.signal);
|
|
3725
3732
|
}
|
|
3726
3733
|
}
|
|
3727
|
-
async upstream(req, url, body, signal) {
|
|
3734
|
+
async upstream(req, url, body, signal, owner) {
|
|
3728
3735
|
try {
|
|
3729
|
-
const fetching = this.options.transport.fetch(
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
+
const fetching = this.options.transport.fetch(
|
|
3737
|
+
{
|
|
3738
|
+
url: toHostLoopback(url),
|
|
3739
|
+
method: req.method.toUpperCase(),
|
|
3740
|
+
headers: forwardRequestHeaders(req.headers),
|
|
3741
|
+
body: req.method === "GET" || req.method === "HEAD" ? void 0 : body,
|
|
3742
|
+
signal
|
|
3743
|
+
},
|
|
3744
|
+
owner
|
|
3745
|
+
);
|
|
3736
3746
|
return await untilAborted(fetching, signal);
|
|
3737
3747
|
} catch (e) {
|
|
3738
3748
|
if (signal.aborted) throw e;
|
|
@@ -3744,13 +3754,13 @@ var RealmProxy = class {
|
|
|
3744
3754
|
}
|
|
3745
3755
|
async relay(conn, method, minor, response, keepAlive) {
|
|
3746
3756
|
const status = response.status;
|
|
3747
|
-
const
|
|
3757
|
+
const bodiless2 = method === "HEAD" || status === 204 || status === 304 || status < 200;
|
|
3748
3758
|
const headers = forwardResponseHeaders(response.headers, {
|
|
3749
3759
|
encodedBodies: this.options.transport.traits.encodedBodies,
|
|
3750
|
-
bodiless
|
|
3760
|
+
bodiless: bodiless2
|
|
3751
3761
|
});
|
|
3752
|
-
const chunked = !
|
|
3753
|
-
const keep = keepAlive && (
|
|
3762
|
+
const chunked = !bodiless2 && minor >= 1;
|
|
3763
|
+
const keep = keepAlive && (bodiless2 || chunked);
|
|
3754
3764
|
headers.push(["Connection", keep ? "keep-alive" : "close"]);
|
|
3755
3765
|
if (chunked) headers.push(["Transfer-Encoding", "chunked"]);
|
|
3756
3766
|
const signal = this.stop.signal;
|
|
@@ -3758,7 +3768,7 @@ var RealmProxy = class {
|
|
|
3758
3768
|
responseHead(status, response.statusText || REASON[status] || "", headers),
|
|
3759
3769
|
signal
|
|
3760
3770
|
);
|
|
3761
|
-
if (
|
|
3771
|
+
if (bodiless2) {
|
|
3762
3772
|
await response.cancel();
|
|
3763
3773
|
return keep;
|
|
3764
3774
|
}
|
|
@@ -4720,7 +4730,7 @@ var RemoteTransport = class {
|
|
|
4720
4730
|
finish();
|
|
4721
4731
|
throw e;
|
|
4722
4732
|
}
|
|
4723
|
-
const { status, statusText, headers, url, redirected } = head;
|
|
4733
|
+
const { status, statusText, headers, url, redirected, redirects } = head;
|
|
4724
4734
|
const read = async () => {
|
|
4725
4735
|
if (finished) return void 0;
|
|
4726
4736
|
const reply = await this.ask({ net: "read", nid }).catch((e) => {
|
|
@@ -4738,6 +4748,7 @@ var RemoteTransport = class {
|
|
|
4738
4748
|
};
|
|
4739
4749
|
return {
|
|
4740
4750
|
...redirected ? { url, redirected } : {},
|
|
4751
|
+
...redirects ? { redirects } : {},
|
|
4741
4752
|
status,
|
|
4742
4753
|
statusText,
|
|
4743
4754
|
headers,
|
|
@@ -7302,9 +7313,9 @@ var SAB_I_KILLED = 13;
|
|
|
7302
7313
|
var SAB_I_ASYNC = 14;
|
|
7303
7314
|
var SAB_I_STOP = 15;
|
|
7304
7315
|
var U32 = 2 ** 32;
|
|
7305
|
-
function storeU53(
|
|
7306
|
-
Atomics.store(
|
|
7307
|
-
Atomics.store(
|
|
7316
|
+
function storeU53(header3, lo, hi, value) {
|
|
7317
|
+
Atomics.store(header3, hi, Math.floor(value / U32));
|
|
7318
|
+
Atomics.store(header3, lo, value % U32 | 0);
|
|
7308
7319
|
}
|
|
7309
7320
|
var SAB_STATE_READY = 2;
|
|
7310
7321
|
var SAB_STATUS_BYTES = 1;
|
|
@@ -7347,7 +7358,7 @@ function sabViews(sab) {
|
|
|
7347
7358
|
var PENDING_TTL_MS = SYNC_FS_REQUEST_TIMEOUT_MS + 5e3;
|
|
7348
7359
|
function attachSyncSabResponder(port, sab, token, opts) {
|
|
7349
7360
|
const views = sabViews(sab);
|
|
7350
|
-
const { header:
|
|
7361
|
+
const { header: header3, window } = views;
|
|
7351
7362
|
const pending = /* @__PURE__ */ new Map();
|
|
7352
7363
|
let disposed = false;
|
|
7353
7364
|
const { dispatch: dispatch2 } = opts;
|
|
@@ -7358,20 +7369,20 @@ function attachSyncSabResponder(port, sab, token, opts) {
|
|
|
7358
7369
|
pending.delete(id2);
|
|
7359
7370
|
}
|
|
7360
7371
|
function publish(id2, entry, offset) {
|
|
7361
|
-
if (Atomics.load(
|
|
7372
|
+
if (Atomics.load(header3, SAB_I_REQ) !== id2) {
|
|
7362
7373
|
drop(id2);
|
|
7363
7374
|
return;
|
|
7364
7375
|
}
|
|
7365
7376
|
const chunk2 = Math.min(window.byteLength, entry.payload.byteLength - offset);
|
|
7366
7377
|
if (chunk2 > 0) window.set(entry.payload.subarray(offset, offset + chunk2));
|
|
7367
|
-
Atomics.store(
|
|
7368
|
-
storeU53(
|
|
7369
|
-
Atomics.store(
|
|
7370
|
-
storeU53(
|
|
7371
|
-
Atomics.store(
|
|
7372
|
-
Atomics.store(
|
|
7373
|
-
Atomics.add(
|
|
7374
|
-
Atomics.notify(
|
|
7378
|
+
Atomics.store(header3, SAB_I_STATUS, entry.status);
|
|
7379
|
+
storeU53(header3, SAB_I_TOTAL, SAB_I_TOTAL_HI, entry.payload.byteLength);
|
|
7380
|
+
Atomics.store(header3, SAB_I_CHUNK, chunk2);
|
|
7381
|
+
storeU53(header3, SAB_I_OFFSET, SAB_I_OFFSET_HI, offset);
|
|
7382
|
+
Atomics.store(header3, SAB_I_SEQ, id2);
|
|
7383
|
+
Atomics.store(header3, SAB_I_STATE, SAB_STATE_READY);
|
|
7384
|
+
Atomics.add(header3, SAB_I_PUB, 1);
|
|
7385
|
+
Atomics.notify(header3, SAB_I_PUB);
|
|
7375
7386
|
if (offset + chunk2 >= entry.payload.byteLength) drop(id2);
|
|
7376
7387
|
}
|
|
7377
7388
|
function settle3(id2, result) {
|
|
@@ -7746,8 +7757,10 @@ var HttpHandles = class {
|
|
|
7746
7757
|
open = /* @__PURE__ */ new Map();
|
|
7747
7758
|
nextHandle = 0;
|
|
7748
7759
|
ws;
|
|
7749
|
-
|
|
7760
|
+
owner;
|
|
7761
|
+
constructor(transport, owner) {
|
|
7750
7762
|
this.transport = transport;
|
|
7763
|
+
this.owner = owner;
|
|
7751
7764
|
this.ws = new WsHandles(transport, () => ++this.nextHandle);
|
|
7752
7765
|
}
|
|
7753
7766
|
syscall(req) {
|
|
@@ -7791,13 +7804,16 @@ var HttpHandles = class {
|
|
|
7791
7804
|
}
|
|
7792
7805
|
async respond(handle, req, entry) {
|
|
7793
7806
|
try {
|
|
7794
|
-
const response = await this.transport.fetch(
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
|
|
7800
|
-
|
|
7807
|
+
const response = await this.transport.fetch(
|
|
7808
|
+
{
|
|
7809
|
+
url: req.url,
|
|
7810
|
+
method: req.method,
|
|
7811
|
+
headers: req.headers,
|
|
7812
|
+
...req.body ? { body: req.body } : {},
|
|
7813
|
+
signal: entry.abort.signal
|
|
7814
|
+
},
|
|
7815
|
+
this.owner
|
|
7816
|
+
);
|
|
7801
7817
|
entry.body = response.body[Symbol.asyncIterator]();
|
|
7802
7818
|
entry.cancel = () => response.cancel();
|
|
7803
7819
|
if (!this.open.has(handle)) await entry.cancel().catch(() => void 0);
|
|
@@ -8523,7 +8539,7 @@ async function socketSyscall(req, proc) {
|
|
|
8523
8539
|
case "sock-open":
|
|
8524
8540
|
return ok(fds.install(new OpenFile(net.socket(req.domain)), 3));
|
|
8525
8541
|
case "sock-pair": {
|
|
8526
|
-
const [a, b] = KernelSocket.pair(net, req.domain);
|
|
8542
|
+
const [a, b] = KernelSocket.pair(net, req.domain, proc.cred?.());
|
|
8527
8543
|
const first = fds.install(new OpenFile(a), 3);
|
|
8528
8544
|
try {
|
|
8529
8545
|
return ok([first, fds.install(new OpenFile(b), 3)]);
|
|
@@ -8536,12 +8552,12 @@ async function socketSyscall(req, proc) {
|
|
|
8536
8552
|
socketAt(fds, req.fd).bind(req.addr);
|
|
8537
8553
|
return ok();
|
|
8538
8554
|
case "sock-listen":
|
|
8539
|
-
socketAt(fds, req.fd).listen(req.backlog);
|
|
8555
|
+
socketAt(fds, req.fd).listen(req.backlog, proc.cred?.());
|
|
8540
8556
|
return ok();
|
|
8541
8557
|
case "sock-accept":
|
|
8542
8558
|
return ok(await accept(proc, req.fd, req.nonblock));
|
|
8543
8559
|
case "sock-connect": {
|
|
8544
|
-
const dialing = socketAt(fds, req.fd).connect(req.addr);
|
|
8560
|
+
const dialing = socketAt(fds, req.fd).connect(req.addr, true, proc.cred?.());
|
|
8545
8561
|
if (req.nonblock) {
|
|
8546
8562
|
dialing?.catch(() => void 0);
|
|
8547
8563
|
throw new KernelError("EINPROGRESS");
|
|
@@ -9957,7 +9973,8 @@ var WasmProcess = class {
|
|
|
9957
9973
|
fds: this.fds,
|
|
9958
9974
|
net: this.net,
|
|
9959
9975
|
blocking: () => this.blockingSignal(cancelled),
|
|
9960
|
-
resolve: (name2, family, blocking) => resolver.resolve(name2, family, blocking)
|
|
9976
|
+
resolve: (name2, family, blocking) => resolver.resolve(name2, family, blocking),
|
|
9977
|
+
cred: () => ({ pid: this.pid, uid: this.cred.euid, gid: this.cred.egid })
|
|
9961
9978
|
});
|
|
9962
9979
|
}
|
|
9963
9980
|
tty(fd) {
|
|
@@ -10173,12 +10190,12 @@ var Dying = class {
|
|
|
10173
10190
|
timer;
|
|
10174
10191
|
busy = 0;
|
|
10175
10192
|
finish;
|
|
10176
|
-
start(code, sig,
|
|
10193
|
+
start(code, sig, header3, process, finish) {
|
|
10177
10194
|
if (this.ending) return;
|
|
10178
10195
|
this.ending = { code, sig };
|
|
10179
10196
|
this.finish = finish;
|
|
10180
10197
|
this.arm();
|
|
10181
|
-
Atomics.store(
|
|
10198
|
+
Atomics.store(header3, SAB_I_KILLED, code);
|
|
10182
10199
|
process.die();
|
|
10183
10200
|
}
|
|
10184
10201
|
async serving(work) {
|
|
@@ -10215,22 +10232,22 @@ function killThread(thread, caught, sig) {
|
|
|
10215
10232
|
function threadCancel(thread) {
|
|
10216
10233
|
return Atomics.load(thread.header, SAB_I_SIGNALS) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
|
|
10217
10234
|
}
|
|
10218
|
-
function notifiers(
|
|
10235
|
+
function notifiers(header3) {
|
|
10219
10236
|
return {
|
|
10220
10237
|
onPending(sig) {
|
|
10221
|
-
Atomics.or(
|
|
10222
|
-
Atomics.notify(
|
|
10238
|
+
Atomics.or(header3, SAB_I_SIGNALS, sigbit(sig));
|
|
10239
|
+
Atomics.notify(header3, SAB_I_SIGNALS);
|
|
10223
10240
|
},
|
|
10224
10241
|
onAsync() {
|
|
10225
|
-
Atomics.add(
|
|
10226
|
-
Atomics.notify(
|
|
10242
|
+
Atomics.add(header3, SAB_I_ASYNC, 1);
|
|
10243
|
+
Atomics.notify(header3, SAB_I_ASYNC);
|
|
10227
10244
|
}
|
|
10228
10245
|
};
|
|
10229
10246
|
}
|
|
10230
|
-
function publishStops(process,
|
|
10247
|
+
function publishStops(process, header3) {
|
|
10231
10248
|
process.onState((state) => {
|
|
10232
|
-
Atomics.store(
|
|
10233
|
-
Atomics.notify(
|
|
10249
|
+
Atomics.store(header3, SAB_I_STOP, state === "stopped" ? 1 : 0);
|
|
10250
|
+
Atomics.notify(header3, SAB_I_STOP);
|
|
10234
10251
|
});
|
|
10235
10252
|
}
|
|
10236
10253
|
function transferOf(opts, lane) {
|
|
@@ -10298,7 +10315,7 @@ function holdingToken(opts, holds) {
|
|
|
10298
10315
|
renamed: (from, to) => holds.renamed(from, to)
|
|
10299
10316
|
});
|
|
10300
10317
|
}
|
|
10301
|
-
function processOptions(opts,
|
|
10318
|
+
function processOptions(opts, header3, hooks) {
|
|
10302
10319
|
return {
|
|
10303
10320
|
...inherited(opts),
|
|
10304
10321
|
...opts.identity ? { identity: opts.identity } : {},
|
|
@@ -10322,27 +10339,27 @@ function processOptions(opts, header2, hooks) {
|
|
|
10322
10339
|
locks: opts.locks,
|
|
10323
10340
|
onReap: opts.onReap,
|
|
10324
10341
|
resolver: opts.resolver,
|
|
10325
|
-
...notifiers(
|
|
10326
|
-
onTimer: (which) => void Atomics.or(
|
|
10327
|
-
hasPending: () => Atomics.load(
|
|
10342
|
+
...notifiers(header3),
|
|
10343
|
+
onTimer: (which) => void Atomics.or(header3, SAB_I_TIMERS, 1 << which),
|
|
10344
|
+
hasPending: () => Atomics.load(header3, SAB_I_SIGNALS) !== 0 || Atomics.load(header3, SAB_I_TIMERS) !== 0,
|
|
10328
10345
|
raise: hooks.raise,
|
|
10329
10346
|
threadKill: hooks.threadKill,
|
|
10330
|
-
...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(
|
|
10347
|
+
...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header3, SAB_I_SIGNALS) } : {}
|
|
10331
10348
|
};
|
|
10332
10349
|
}
|
|
10333
10350
|
function spawnWasmProcess(opts) {
|
|
10334
10351
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
10335
|
-
const
|
|
10352
|
+
const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
10336
10353
|
const threadSignals = /* @__PURE__ */ new Map();
|
|
10337
10354
|
const process = new WasmProcess(
|
|
10338
10355
|
opts.pid,
|
|
10339
10356
|
opts.fds,
|
|
10340
|
-
processOptions(opts,
|
|
10357
|
+
processOptions(opts, header3, {
|
|
10341
10358
|
raise: (sig) => signal(sig),
|
|
10342
10359
|
threadKill: (tid, sig) => killThread(threadSignals.get(tid), process.signalMasks().caught, sig)
|
|
10343
10360
|
})
|
|
10344
10361
|
);
|
|
10345
|
-
publishStops(process,
|
|
10362
|
+
publishStops(process, header3);
|
|
10346
10363
|
const holds = new HeldPaths();
|
|
10347
10364
|
opts.held?.add(holds);
|
|
10348
10365
|
const token = holdingToken(opts, holds);
|
|
@@ -10454,7 +10471,7 @@ function spawnWasmProcess(opts) {
|
|
|
10454
10471
|
if (process.signal(sig) !== "terminate") return;
|
|
10455
10472
|
const code = sig === SIG.KILL ? 137 : 128 + sig;
|
|
10456
10473
|
if (opts.program.abi !== "wasi" || done4) finish(code, sig);
|
|
10457
|
-
else dying.start(code, sig,
|
|
10474
|
+
else dying.start(code, sig, header3, process, () => finish(code, sig));
|
|
10458
10475
|
};
|
|
10459
10476
|
const kill = (code = 137) => finish(code, code > 128 && code < 160 ? code - 128 : void 0);
|
|
10460
10477
|
return {
|
|
@@ -10464,7 +10481,7 @@ function spawnWasmProcess(opts) {
|
|
|
10464
10481
|
signal,
|
|
10465
10482
|
termsig: () => endedBy,
|
|
10466
10483
|
onState: (listener) => process.onState(listener),
|
|
10467
|
-
memory: () => Atomics.load(
|
|
10484
|
+
memory: () => Atomics.load(header3, SAB_I_MEMORY) * 65536,
|
|
10468
10485
|
ignoredSignals: (fork) => process.inheritable(fork),
|
|
10469
10486
|
signalMasks: () => process.signalMasks(),
|
|
10470
10487
|
umask: () => process.umask,
|
|
@@ -10659,6 +10676,89 @@ var JobTable = class {
|
|
|
10659
10676
|
}
|
|
10660
10677
|
};
|
|
10661
10678
|
|
|
10679
|
+
// src/kernel/net/redirect-hops.ts
|
|
10680
|
+
var HELD_MS = 3e4;
|
|
10681
|
+
var HELD_MAX = 64;
|
|
10682
|
+
var HELD_PER_OWNER = 8;
|
|
10683
|
+
var MATCHED = ["range", "if-none-match", "if-modified-since", "if-range", "accept-encoding"];
|
|
10684
|
+
var KERNEL = -1;
|
|
10685
|
+
function header2(headers, name2) {
|
|
10686
|
+
const values = headers.filter(([n]) => n.toLowerCase() === name2).map(([, v]) => v);
|
|
10687
|
+
return values.length > 0 ? values.join(", ") : void 0;
|
|
10688
|
+
}
|
|
10689
|
+
function fingerprint(headers) {
|
|
10690
|
+
const fields = MATCHED.map((name2) => header2(headers, name2) ?? "");
|
|
10691
|
+
return JSON.stringify([...fields, header2(headers, "authorization") !== void 0]);
|
|
10692
|
+
}
|
|
10693
|
+
function followedWith(status, method) {
|
|
10694
|
+
if (status === 303 && method !== "GET" && method !== "HEAD") return "GET";
|
|
10695
|
+
if ((status === 301 || status === 302) && method === "POST") return "GET";
|
|
10696
|
+
return method;
|
|
10697
|
+
}
|
|
10698
|
+
function bodiless(hop) {
|
|
10699
|
+
return {
|
|
10700
|
+
url: hop.url,
|
|
10701
|
+
status: hop.status,
|
|
10702
|
+
statusText: "",
|
|
10703
|
+
headers: hop.headers,
|
|
10704
|
+
body: (async function* () {
|
|
10705
|
+
})(),
|
|
10706
|
+
cancel: async () => void 0
|
|
10707
|
+
};
|
|
10708
|
+
}
|
|
10709
|
+
function replayingHops(inner, heldMs = HELD_MS) {
|
|
10710
|
+
if (!inner.traits.redirectHops || inner.traits.manualRedirects) return inner;
|
|
10711
|
+
const held = /* @__PURE__ */ new Map();
|
|
10712
|
+
const drop = (key) => {
|
|
10713
|
+
const entry = held.get(key);
|
|
10714
|
+
if (!entry) return;
|
|
10715
|
+
held.delete(key);
|
|
10716
|
+
clearTimeout(entry.timer);
|
|
10717
|
+
void entry.final.cancel().catch(() => void 0);
|
|
10718
|
+
};
|
|
10719
|
+
const keyOf2 = (owner, method, url) => `${owner} ${method} ${url}`;
|
|
10720
|
+
const hold = (key, chain) => {
|
|
10721
|
+
drop(key);
|
|
10722
|
+
const mine = [...held.keys()].filter((k) => held.get(k)?.owner === chain.owner);
|
|
10723
|
+
if (mine.length >= HELD_PER_OWNER) drop(mine[0]);
|
|
10724
|
+
if (held.size >= HELD_MAX) drop(held.keys().next().value);
|
|
10725
|
+
const timer = setTimeout(() => drop(key), heldMs);
|
|
10726
|
+
timer.unref?.();
|
|
10727
|
+
held.set(key, { ...chain, timer });
|
|
10728
|
+
};
|
|
10729
|
+
const replay = (chain) => {
|
|
10730
|
+
const [hop, ...rest2] = chain.hops;
|
|
10731
|
+
const location = hop && header2(hop.headers, "location");
|
|
10732
|
+
if (!hop || location === void 0) return chain.final;
|
|
10733
|
+
const next2 = new URL(location, hop.url).href;
|
|
10734
|
+
const method = followedWith(hop.status, chain.method);
|
|
10735
|
+
hold(keyOf2(chain.owner, method, next2), { ...chain, method, hops: rest2 });
|
|
10736
|
+
return bodiless(hop);
|
|
10737
|
+
};
|
|
10738
|
+
return {
|
|
10739
|
+
traits: { ...inner.traits, manualRedirects: true },
|
|
10740
|
+
...inner.websocket ? { websocket: inner.websocket.bind(inner) } : {},
|
|
10741
|
+
async fetch(request2, owner = KERNEL) {
|
|
10742
|
+
const key = keyOf2(owner, request2.method, request2.url);
|
|
10743
|
+
const waiting = held.get(key);
|
|
10744
|
+
if (waiting && waiting.fingerprint === fingerprint(request2.headers)) {
|
|
10745
|
+
held.delete(key);
|
|
10746
|
+
clearTimeout(waiting.timer);
|
|
10747
|
+
return replay(waiting);
|
|
10748
|
+
}
|
|
10749
|
+
const response = await inner.fetch(request2);
|
|
10750
|
+
if (!response.redirects?.length) return response;
|
|
10751
|
+
return replay({
|
|
10752
|
+
owner,
|
|
10753
|
+
method: request2.method,
|
|
10754
|
+
fingerprint: fingerprint(request2.headers),
|
|
10755
|
+
hops: response.redirects,
|
|
10756
|
+
final: response
|
|
10757
|
+
});
|
|
10758
|
+
}
|
|
10759
|
+
};
|
|
10760
|
+
}
|
|
10761
|
+
|
|
10662
10762
|
// src/kernel/settling.ts
|
|
10663
10763
|
var SETUP_OPS = /* @__PURE__ */ new Set([
|
|
10664
10764
|
"proc-list",
|
|
@@ -12075,7 +12175,7 @@ var Launcher = class {
|
|
|
12075
12175
|
this.hostname = hostname;
|
|
12076
12176
|
this.env = { ...networkEnv(hostname), SLICC_CDP_URL: this.cdp.url, ...options.env };
|
|
12077
12177
|
this.ca = kernelCa(options.caStore ?? memoryCaStore());
|
|
12078
|
-
this.transport = options.transport ?? missingTransport();
|
|
12178
|
+
this.transport = replayingHops(options.transport ?? missingTransport());
|
|
12079
12179
|
this.uplink = options.uplink;
|
|
12080
12180
|
this.routes = new Routes(options.uplink?.traits.ipv6 === true);
|
|
12081
12181
|
if (options.uplink?.routes) this.routes.set(options.uplink.routes);
|
|
@@ -12332,7 +12432,7 @@ var Launcher = class {
|
|
|
12332
12432
|
jobs: this.jobs,
|
|
12333
12433
|
ptys: this.ptys,
|
|
12334
12434
|
net: this.net,
|
|
12335
|
-
http: new HttpHandles(this.transport),
|
|
12435
|
+
http: new HttpHandles(this.transport, pid),
|
|
12336
12436
|
locks: this.locks,
|
|
12337
12437
|
resolver: this.resolver,
|
|
12338
12438
|
onReap: (child) => this.reaped(child),
|