@ai-ecoverse/slicc-kernel 1.27.0 → 1.28.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 +40 -5
- package/dist/driver-worker.js +1 -1
- package/dist/driver-worker.js.map +1 -1
- package/dist/index.js +171 -16
- package/dist/index.js.map +4 -4
- package/dist/kernel-worker.js +434 -131
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-driver-worker.js +1 -1
- package/dist/node-driver-worker.js.map +1 -1
- package/dist/node-process-worker.js +7 -1
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +305 -39
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +7 -1
- package/dist/process-worker.js.map +2 -2
- package/dist/testing.js +196 -0
- package/dist/testing.js.map +3 -3
- package/package.json +1 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -883,7 +883,7 @@ function portCdpHook(ask, gone) {
|
|
|
883
883
|
}
|
|
884
884
|
|
|
885
885
|
// src/client/protocol.ts
|
|
886
|
-
var PROTOCOL = [1,
|
|
886
|
+
var PROTOCOL = [1, 7];
|
|
887
887
|
var FS_METHODS = [
|
|
888
888
|
"readFile",
|
|
889
889
|
"writeFile",
|
|
@@ -1253,6 +1253,170 @@ var FdTable = class _FdTable {
|
|
|
1253
1253
|
}
|
|
1254
1254
|
};
|
|
1255
1255
|
|
|
1256
|
+
// src/process/wasi/wasi-abi.ts
|
|
1257
|
+
var E = {
|
|
1258
|
+
SUCCESS: 0,
|
|
1259
|
+
"2BIG": 1,
|
|
1260
|
+
ACCES: 2,
|
|
1261
|
+
ADDRINUSE: 3,
|
|
1262
|
+
ADDRNOTAVAIL: 4,
|
|
1263
|
+
AFNOSUPPORT: 5,
|
|
1264
|
+
AGAIN: 6,
|
|
1265
|
+
ALREADY: 7,
|
|
1266
|
+
BADF: 8,
|
|
1267
|
+
BADMSG: 9,
|
|
1268
|
+
BUSY: 10,
|
|
1269
|
+
CANCELED: 11,
|
|
1270
|
+
CHILD: 12,
|
|
1271
|
+
CONNABORTED: 13,
|
|
1272
|
+
CONNREFUSED: 14,
|
|
1273
|
+
CONNRESET: 15,
|
|
1274
|
+
DEADLK: 16,
|
|
1275
|
+
DESTADDRREQ: 17,
|
|
1276
|
+
DOM: 18,
|
|
1277
|
+
DQUOT: 19,
|
|
1278
|
+
EXIST: 20,
|
|
1279
|
+
FAULT: 21,
|
|
1280
|
+
FBIG: 22,
|
|
1281
|
+
HOSTUNREACH: 23,
|
|
1282
|
+
IDRM: 24,
|
|
1283
|
+
ILSEQ: 25,
|
|
1284
|
+
INPROGRESS: 26,
|
|
1285
|
+
INTR: 27,
|
|
1286
|
+
INVAL: 28,
|
|
1287
|
+
IO: 29,
|
|
1288
|
+
ISCONN: 30,
|
|
1289
|
+
ISDIR: 31,
|
|
1290
|
+
LOOP: 32,
|
|
1291
|
+
MFILE: 33,
|
|
1292
|
+
MLINK: 34,
|
|
1293
|
+
MSGSIZE: 35,
|
|
1294
|
+
MULTIHOP: 36,
|
|
1295
|
+
NAMETOOLONG: 37,
|
|
1296
|
+
NETDOWN: 38,
|
|
1297
|
+
NETRESET: 39,
|
|
1298
|
+
NETUNREACH: 40,
|
|
1299
|
+
NFILE: 41,
|
|
1300
|
+
NOBUFS: 42,
|
|
1301
|
+
NODEV: 43,
|
|
1302
|
+
NOENT: 44,
|
|
1303
|
+
NOEXEC: 45,
|
|
1304
|
+
NOLCK: 46,
|
|
1305
|
+
NOLINK: 47,
|
|
1306
|
+
NOMEM: 48,
|
|
1307
|
+
NOMSG: 49,
|
|
1308
|
+
NOPROTOOPT: 50,
|
|
1309
|
+
NOSPC: 51,
|
|
1310
|
+
NOSYS: 52,
|
|
1311
|
+
NOTCONN: 53,
|
|
1312
|
+
NOTDIR: 54,
|
|
1313
|
+
NOTEMPTY: 55,
|
|
1314
|
+
NOTRECOVERABLE: 56,
|
|
1315
|
+
NOTSOCK: 57,
|
|
1316
|
+
NOTSUP: 58,
|
|
1317
|
+
NOTTY: 59,
|
|
1318
|
+
NXIO: 60,
|
|
1319
|
+
OVERFLOW: 61,
|
|
1320
|
+
OWNERDEAD: 62,
|
|
1321
|
+
PERM: 63,
|
|
1322
|
+
PIPE: 64,
|
|
1323
|
+
PROTO: 65,
|
|
1324
|
+
PROTONOSUPPORT: 66,
|
|
1325
|
+
PROTOTYPE: 67,
|
|
1326
|
+
RANGE: 68,
|
|
1327
|
+
ROFS: 69,
|
|
1328
|
+
SPIPE: 70,
|
|
1329
|
+
SRCH: 71,
|
|
1330
|
+
STALE: 72,
|
|
1331
|
+
TIMEDOUT: 73,
|
|
1332
|
+
TXTBSY: 74,
|
|
1333
|
+
XDEV: 75,
|
|
1334
|
+
NOTCAPABLE: 76
|
|
1335
|
+
};
|
|
1336
|
+
var RIGHTS = {
|
|
1337
|
+
FD_DATASYNC: 1n << 0n,
|
|
1338
|
+
FD_READ: 1n << 1n,
|
|
1339
|
+
FD_SEEK: 1n << 2n,
|
|
1340
|
+
FD_FDSTAT_SET_FLAGS: 1n << 3n,
|
|
1341
|
+
FD_SYNC: 1n << 4n,
|
|
1342
|
+
FD_TELL: 1n << 5n,
|
|
1343
|
+
FD_WRITE: 1n << 6n,
|
|
1344
|
+
ALL: (1n << 30n) - 1n
|
|
1345
|
+
};
|
|
1346
|
+
var WASI_SIGNAL_TO_POSIX = Object.fromEntries(
|
|
1347
|
+
Array.from({ length: 30 }, (_, i) => [i + 1, i + 1 < 16 ? i + 1 : i + 2])
|
|
1348
|
+
);
|
|
1349
|
+
|
|
1350
|
+
// src/process/wasi-errno.ts
|
|
1351
|
+
var WASI_ERRNO = {
|
|
1352
|
+
...Object.fromEntries(Object.entries(E).map(([name2, errno]) => [`E${name2}`, errno])),
|
|
1353
|
+
EWOULDBLOCK: E.AGAIN,
|
|
1354
|
+
ENOTSUP: 138,
|
|
1355
|
+
EOPNOTSUPP: 138,
|
|
1356
|
+
ENOMEDIUM: 148
|
|
1357
|
+
};
|
|
1358
|
+
function wasiErrno(code) {
|
|
1359
|
+
return WASI_ERRNO[code] ?? E.IO;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
// src/kernel/net/uplink-socket.ts
|
|
1363
|
+
var CHUNK = 64 * 1024;
|
|
1364
|
+
function hostPort(text) {
|
|
1365
|
+
const match = /^\[?([^\]]*?)\]?:(\d{1,5})$/.exec(text);
|
|
1366
|
+
const port = Number(match?.[2]);
|
|
1367
|
+
const host = match?.[1];
|
|
1368
|
+
if (!host || port > 65535) return void 0;
|
|
1369
|
+
return { host, port };
|
|
1370
|
+
}
|
|
1371
|
+
async function inbound(conn, rx) {
|
|
1372
|
+
for (; ; ) {
|
|
1373
|
+
while (!rx.writeReady) await rx.changed();
|
|
1374
|
+
if (rx.readersGone) return;
|
|
1375
|
+
const bytes = await conn.read();
|
|
1376
|
+
if (!bytes) return;
|
|
1377
|
+
await rx.write(bytes);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
async function outbound(conn, tx) {
|
|
1381
|
+
for (; ; ) {
|
|
1382
|
+
const bytes = await tx.read(CHUNK);
|
|
1383
|
+
if (bytes.length === 0) {
|
|
1384
|
+
conn.closeWrite();
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
for (let at = 0; at < bytes.length; ) {
|
|
1388
|
+
const n = await conn.write(bytes.subarray(at));
|
|
1389
|
+
if (!(n > 0)) throw new Error("the uplink wrote nothing");
|
|
1390
|
+
at += n;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
async function released(rx, tx) {
|
|
1395
|
+
while (!(rx.readersGone && tx.writersGone)) await Promise.race([rx.changed(), tx.changed()]);
|
|
1396
|
+
}
|
|
1397
|
+
function uplinkLink(conn, onReset) {
|
|
1398
|
+
const rx = new KernelPipe();
|
|
1399
|
+
const tx = new KernelPipe();
|
|
1400
|
+
for (const pipe of [rx, tx]) {
|
|
1401
|
+
pipe.openRead();
|
|
1402
|
+
pipe.openWrite();
|
|
1403
|
+
}
|
|
1404
|
+
let open = true;
|
|
1405
|
+
const close = () => {
|
|
1406
|
+
if (!open) return;
|
|
1407
|
+
open = false;
|
|
1408
|
+
conn.close();
|
|
1409
|
+
};
|
|
1410
|
+
void inbound(conn, rx).catch(() => {
|
|
1411
|
+
onReset();
|
|
1412
|
+
close();
|
|
1413
|
+
tx.closeRead();
|
|
1414
|
+
}).finally(() => rx.closeWrite());
|
|
1415
|
+
void outbound(conn, tx).catch(close).finally(() => tx.closeRead());
|
|
1416
|
+
void released(rx, tx).then(close);
|
|
1417
|
+
return { rx, tx };
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1256
1420
|
// src/kernel/socket.ts
|
|
1257
1421
|
var SOMAXCONN = 4096;
|
|
1258
1422
|
var EPHEMERAL_FIRST = 32768;
|
|
@@ -1270,6 +1434,21 @@ var AF_INET = 2;
|
|
|
1270
1434
|
var SHUT_RD = 0;
|
|
1271
1435
|
var SHUT_WR = 1;
|
|
1272
1436
|
var SHUT_RDWR = 2;
|
|
1437
|
+
var DIAL_TIMEOUT_MS = 3e4;
|
|
1438
|
+
var DIAL_ERRORS = [
|
|
1439
|
+
"ECONNREFUSED",
|
|
1440
|
+
"ENETUNREACH",
|
|
1441
|
+
"EHOSTUNREACH",
|
|
1442
|
+
"ETIMEDOUT",
|
|
1443
|
+
"ECONNRESET"
|
|
1444
|
+
];
|
|
1445
|
+
function dialError(e, timedOut, closed) {
|
|
1446
|
+
if (timedOut) return new KernelError("ETIMEDOUT");
|
|
1447
|
+
if (closed) return new KernelError("ECONNABORTED");
|
|
1448
|
+
const code = e?.code;
|
|
1449
|
+
const known = DIAL_ERRORS.find((errno) => errno === code);
|
|
1450
|
+
return new KernelError(known ?? "EHOSTUNREACH");
|
|
1451
|
+
}
|
|
1273
1452
|
function isLoopback(host) {
|
|
1274
1453
|
return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host);
|
|
1275
1454
|
}
|
|
@@ -1318,6 +1497,9 @@ var KernelSocket = class _KernelSocket {
|
|
|
1318
1497
|
net;
|
|
1319
1498
|
domain;
|
|
1320
1499
|
state = "open";
|
|
1500
|
+
dialing;
|
|
1501
|
+
failed;
|
|
1502
|
+
reset = false;
|
|
1321
1503
|
local;
|
|
1322
1504
|
peer;
|
|
1323
1505
|
link;
|
|
@@ -1325,7 +1507,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
1325
1507
|
writeShut = false;
|
|
1326
1508
|
queue = [];
|
|
1327
1509
|
backlog = 0;
|
|
1328
|
-
|
|
1510
|
+
boundAt;
|
|
1329
1511
|
changes = new Changes();
|
|
1330
1512
|
options = /* @__PURE__ */ new Map();
|
|
1331
1513
|
constructor(net, domain) {
|
|
@@ -1347,12 +1529,16 @@ var KernelSocket = class _KernelSocket {
|
|
|
1347
1529
|
async read(max, signal) {
|
|
1348
1530
|
const { rx } = this.connection();
|
|
1349
1531
|
if (this.readShut || max <= 0) return new Uint8Array(0);
|
|
1350
|
-
|
|
1532
|
+
const bytes = await pipeCall(() => rx.read(max, signal));
|
|
1533
|
+
if (bytes.length === 0 && this.reset) throw new KernelError("ECONNRESET");
|
|
1534
|
+
return bytes;
|
|
1351
1535
|
}
|
|
1352
1536
|
async peek(max, signal) {
|
|
1353
1537
|
const { rx } = this.connection();
|
|
1354
1538
|
if (this.readShut || max <= 0) return new Uint8Array(0);
|
|
1355
|
-
|
|
1539
|
+
const bytes = await pipeCall(() => rx.peek(max, signal));
|
|
1540
|
+
if (bytes.length === 0 && this.reset) throw new KernelError("ECONNRESET");
|
|
1541
|
+
return bytes;
|
|
1356
1542
|
}
|
|
1357
1543
|
async write(bytes, signal) {
|
|
1358
1544
|
const { tx } = this.connection();
|
|
@@ -1363,6 +1549,8 @@ var KernelSocket = class _KernelSocket {
|
|
|
1363
1549
|
if (this.state === "listening") {
|
|
1364
1550
|
return { readable: this.queue.length > 0, writable: false, hangup: false };
|
|
1365
1551
|
}
|
|
1552
|
+
if (this.state === "connecting") return { readable: false, writable: false, hangup: false };
|
|
1553
|
+
if (this.failed) return { readable: true, writable: true, hangup: true };
|
|
1366
1554
|
if (this.state !== "connected" || !this.link) {
|
|
1367
1555
|
return { readable: false, writable: false, hangup: true };
|
|
1368
1556
|
}
|
|
@@ -1384,7 +1572,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
1384
1572
|
if (this.state !== "open" || this.local) throw new KernelError("EINVAL");
|
|
1385
1573
|
if (addr.family !== this.domain) throw new KernelError("EAFNOSUPPORT");
|
|
1386
1574
|
this.local = this.net.bind(this, addr);
|
|
1387
|
-
this.
|
|
1575
|
+
this.boundAt = this.local;
|
|
1388
1576
|
}
|
|
1389
1577
|
listen(backlog) {
|
|
1390
1578
|
if (this.state === "connected") throw new KernelError("EISCONN");
|
|
@@ -1411,15 +1599,19 @@ var KernelSocket = class _KernelSocket {
|
|
|
1411
1599
|
this.changes.wake();
|
|
1412
1600
|
return true;
|
|
1413
1601
|
}
|
|
1414
|
-
connect(addr) {
|
|
1602
|
+
connect(addr, viaUplink = true) {
|
|
1415
1603
|
if (this.state === "connected") throw new KernelError("EISCONN");
|
|
1604
|
+
if (this.state === "connecting") throw new KernelError("EALREADY");
|
|
1416
1605
|
if (this.state !== "open") throw new KernelError("EINVAL");
|
|
1417
1606
|
if (addr.family !== this.domain) throw new KernelError("EAFNOSUPPORT");
|
|
1607
|
+
this.failed = void 0;
|
|
1608
|
+
const route = viaUplink && addr.family === "inet" ? this.net.uplinkFor(addr.host) : void 0;
|
|
1609
|
+
if (route) return this.dial(addr, route);
|
|
1418
1610
|
const target = this.net.target(addr);
|
|
1419
1611
|
if (!this.local) {
|
|
1420
1612
|
if (addr.family === "inet") {
|
|
1421
1613
|
this.local = this.net.bind(this, { family: "inet", host: "127.0.0.1", port: 0 });
|
|
1422
|
-
this.
|
|
1614
|
+
this.boundAt = this.local;
|
|
1423
1615
|
} else this.local = { family: "unix", path: "" };
|
|
1424
1616
|
}
|
|
1425
1617
|
const server = new _KernelSocket(this.net, this.domain);
|
|
@@ -1432,6 +1624,52 @@ var KernelSocket = class _KernelSocket {
|
|
|
1432
1624
|
server.close();
|
|
1433
1625
|
throw new KernelError("ECONNREFUSED");
|
|
1434
1626
|
}
|
|
1627
|
+
return void 0;
|
|
1628
|
+
}
|
|
1629
|
+
dial(addr, route) {
|
|
1630
|
+
this.state = "connecting";
|
|
1631
|
+
const abort = new AbortController();
|
|
1632
|
+
this.dialing = abort;
|
|
1633
|
+
let timedOut = false;
|
|
1634
|
+
const timer = setTimeout(() => {
|
|
1635
|
+
timedOut = true;
|
|
1636
|
+
abort.abort(new KernelError("ETIMEDOUT"));
|
|
1637
|
+
}, route.timeoutMs ?? DIAL_TIMEOUT_MS);
|
|
1638
|
+
const abandoned = new Promise((_, reject) => {
|
|
1639
|
+
abort.signal.addEventListener("abort", () => reject(abort.signal.reason), { once: true });
|
|
1640
|
+
});
|
|
1641
|
+
const { host, port } = addr;
|
|
1642
|
+
const dialled = new Promise(
|
|
1643
|
+
(resolve) => resolve(route.uplink.dial({ network: "tcp", host, port, signal: abort.signal }))
|
|
1644
|
+
);
|
|
1645
|
+
dialled.then(
|
|
1646
|
+
(conn) => abort.signal.aborted && conn.close(),
|
|
1647
|
+
() => void 0
|
|
1648
|
+
);
|
|
1649
|
+
return Promise.race([dialled, abandoned]).then(
|
|
1650
|
+
(conn) => {
|
|
1651
|
+
if (abort.signal.aborted) throw dialError(abort.signal.reason, timedOut, true);
|
|
1652
|
+
this.local = { family: "inet", host: "0.0.0.0", port: 0, ...hostPort(conn.localAddr) };
|
|
1653
|
+
this.peer = { ...addr, ...hostPort(conn.remoteAddr) };
|
|
1654
|
+
this.dialing = void 0;
|
|
1655
|
+
this.attach(
|
|
1656
|
+
uplinkLink(conn, () => {
|
|
1657
|
+
this.reset = true;
|
|
1658
|
+
this.changes.wake();
|
|
1659
|
+
})
|
|
1660
|
+
);
|
|
1661
|
+
},
|
|
1662
|
+
(e) => {
|
|
1663
|
+
const error = dialError(e, timedOut, abort.signal.aborted);
|
|
1664
|
+
if (this.dialing === abort) {
|
|
1665
|
+
this.dialing = void 0;
|
|
1666
|
+
this.failed = error.code;
|
|
1667
|
+
this.state = "open";
|
|
1668
|
+
this.changes.wake();
|
|
1669
|
+
}
|
|
1670
|
+
throw error;
|
|
1671
|
+
}
|
|
1672
|
+
).finally(() => clearTimeout(timer));
|
|
1435
1673
|
}
|
|
1436
1674
|
unlink() {
|
|
1437
1675
|
const link2 = this.link;
|
|
@@ -1461,8 +1699,11 @@ var KernelSocket = class _KernelSocket {
|
|
|
1461
1699
|
switch (name2) {
|
|
1462
1700
|
case SO_TYPE:
|
|
1463
1701
|
return SOCK_STREAM;
|
|
1464
|
-
case SO_ERROR:
|
|
1465
|
-
|
|
1702
|
+
case SO_ERROR: {
|
|
1703
|
+
const failed = this.failed;
|
|
1704
|
+
this.failed = void 0;
|
|
1705
|
+
return failed ? wasiErrno(failed) : 0;
|
|
1706
|
+
}
|
|
1466
1707
|
case SO_ACCEPTCONN:
|
|
1467
1708
|
return this.state === "listening" ? 1 : 0;
|
|
1468
1709
|
case SO_DOMAIN:
|
|
@@ -1480,6 +1721,8 @@ var KernelSocket = class _KernelSocket {
|
|
|
1480
1721
|
close() {
|
|
1481
1722
|
const was = this.state;
|
|
1482
1723
|
this.state = "closed";
|
|
1724
|
+
this.dialing?.abort(new KernelError("ECONNABORTED"));
|
|
1725
|
+
this.dialing = void 0;
|
|
1483
1726
|
if (was === "listening") {
|
|
1484
1727
|
for (const pending of this.queue.splice(0)) pending.close();
|
|
1485
1728
|
}
|
|
@@ -1489,8 +1732,8 @@ var KernelSocket = class _KernelSocket {
|
|
|
1489
1732
|
this.readShut = true;
|
|
1490
1733
|
this.writeShut = true;
|
|
1491
1734
|
}
|
|
1492
|
-
if (this.
|
|
1493
|
-
this.
|
|
1735
|
+
if (this.boundAt) this.net.release(this.boundAt, this);
|
|
1736
|
+
this.boundAt = void 0;
|
|
1494
1737
|
this.changes.wake();
|
|
1495
1738
|
}
|
|
1496
1739
|
static pair(net, domain) {
|
|
@@ -1513,6 +1756,15 @@ var LoopbackNet = class {
|
|
|
1513
1756
|
activators = /* @__PURE__ */ new Map();
|
|
1514
1757
|
internal = /* @__PURE__ */ new Set();
|
|
1515
1758
|
nextEphemeral = EPHEMERAL_FIRST;
|
|
1759
|
+
route;
|
|
1760
|
+
useUplink(route) {
|
|
1761
|
+
this.route = route;
|
|
1762
|
+
}
|
|
1763
|
+
uplinkFor(host) {
|
|
1764
|
+
const route = this.route;
|
|
1765
|
+
if (!route) return void 0;
|
|
1766
|
+
return route.routes.classify(host) === "uplink" ? route : void 0;
|
|
1767
|
+
}
|
|
1516
1768
|
kernelOnly(port, reserve = false) {
|
|
1517
1769
|
if (reserve) this.internal.add(port);
|
|
1518
1770
|
return this.internal.has(port);
|
|
@@ -1531,7 +1783,7 @@ var LoopbackNet = class {
|
|
|
1531
1783
|
}
|
|
1532
1784
|
connect(addr) {
|
|
1533
1785
|
const socket = this.socket(addr.family);
|
|
1534
|
-
socket.connect(addr);
|
|
1786
|
+
void socket.connect(addr, false);
|
|
1535
1787
|
return socket;
|
|
1536
1788
|
}
|
|
1537
1789
|
bind(socket, addr) {
|
|
@@ -1572,7 +1824,7 @@ var LoopbackNet = class {
|
|
|
1572
1824
|
};
|
|
1573
1825
|
|
|
1574
1826
|
// src/kernel/dial.ts
|
|
1575
|
-
var
|
|
1827
|
+
var CHUNK2 = 64 * 1024;
|
|
1576
1828
|
var LOOPBACK_NAMES = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
|
|
1577
1829
|
function dialSocket(net, port, host = "127.0.0.1") {
|
|
1578
1830
|
if (!Number.isInteger(port) || port < 1 || port > 65535) throw new KernelError("EINVAL");
|
|
@@ -1637,7 +1889,7 @@ function serveSocket(socket, port, onClose) {
|
|
|
1637
1889
|
for (; ; ) {
|
|
1638
1890
|
await turn();
|
|
1639
1891
|
if (closed) return;
|
|
1640
|
-
const chunk2 = await socket.read(
|
|
1892
|
+
const chunk2 = await socket.read(CHUNK2);
|
|
1641
1893
|
if (chunk2.length === 0) break;
|
|
1642
1894
|
credit--;
|
|
1643
1895
|
send(chunk2, [chunk2.buffer]);
|
|
@@ -3570,6 +3822,95 @@ var RemoteTransport = class {
|
|
|
3570
3822
|
}
|
|
3571
3823
|
};
|
|
3572
3824
|
|
|
3825
|
+
// src/kernel/net/routes.ts
|
|
3826
|
+
var HOST_ADDRESS = HOST_LOOPBACK_ADDRESS.join(".");
|
|
3827
|
+
function ipv4Bytes(text) {
|
|
3828
|
+
const parts = text.split(".");
|
|
3829
|
+
if (parts.length !== 4 || !parts.every((p) => /^\d{1,3}$/.test(p))) return void 0;
|
|
3830
|
+
const bytes = parts.map(Number);
|
|
3831
|
+
return bytes.every((b) => b <= 255) ? bytes : void 0;
|
|
3832
|
+
}
|
|
3833
|
+
function ipv6Groups(text) {
|
|
3834
|
+
if (!text.includes(":")) return void 0;
|
|
3835
|
+
let canonical;
|
|
3836
|
+
try {
|
|
3837
|
+
canonical = new URL(`http://[${text}]/`).hostname.slice(1, -1);
|
|
3838
|
+
} catch {
|
|
3839
|
+
return void 0;
|
|
3840
|
+
}
|
|
3841
|
+
const [head, tail] = canonical.split("::");
|
|
3842
|
+
const part = (s) => s ? s.split(":").map((h) => Number.parseInt(h, 16)) : [];
|
|
3843
|
+
const front = part(head);
|
|
3844
|
+
const back = part(tail);
|
|
3845
|
+
return tail === void 0 ? front : [...front, ...new Array(8 - front.length - back.length).fill(0), ...back];
|
|
3846
|
+
}
|
|
3847
|
+
function toBits(values, width) {
|
|
3848
|
+
return values.reduce((acc, v) => acc << BigInt(width) | BigInt(v), 0n);
|
|
3849
|
+
}
|
|
3850
|
+
function addressBits(host) {
|
|
3851
|
+
const v4 = ipv4Bytes(host);
|
|
3852
|
+
if (v4) return { v6: false, bits: toBits(v4, 8) };
|
|
3853
|
+
const v6 = ipv6Groups(host);
|
|
3854
|
+
return v6 ? { v6: true, bits: toBits(v6, 16) } : void 0;
|
|
3855
|
+
}
|
|
3856
|
+
function parsePrefix(text) {
|
|
3857
|
+
const parts = text.trim().split("/");
|
|
3858
|
+
if (parts.length > 2) return void 0;
|
|
3859
|
+
const [address = "", size] = parts;
|
|
3860
|
+
const parsed = addressBits(address);
|
|
3861
|
+
if (!parsed) return void 0;
|
|
3862
|
+
const max = parsed.v6 ? 128 : 32;
|
|
3863
|
+
const length2 = size === void 0 ? max : /^\d{1,3}$/.test(size) ? Number(size) : -1;
|
|
3864
|
+
if (length2 < 0 || length2 > max) return void 0;
|
|
3865
|
+
return { ...parsed, length: length2 };
|
|
3866
|
+
}
|
|
3867
|
+
function within2(prefix, addr) {
|
|
3868
|
+
if (prefix.v6 !== addr.v6) return false;
|
|
3869
|
+
const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);
|
|
3870
|
+
return addr.bits >> shift === prefix.bits >> shift;
|
|
3871
|
+
}
|
|
3872
|
+
var RESERVED = [
|
|
3873
|
+
"0.0.0.0/8",
|
|
3874
|
+
"127.0.0.0/8",
|
|
3875
|
+
"169.254.0.0/16",
|
|
3876
|
+
"224.0.0.0/4",
|
|
3877
|
+
"240.0.0.0/4",
|
|
3878
|
+
"::/96",
|
|
3879
|
+
"::ffff:0:0/96",
|
|
3880
|
+
"fe80::/10",
|
|
3881
|
+
"ff00::/8"
|
|
3882
|
+
].map((p) => parsePrefix(p));
|
|
3883
|
+
var Routes = class {
|
|
3884
|
+
table = [];
|
|
3885
|
+
exit = false;
|
|
3886
|
+
ipv6;
|
|
3887
|
+
constructor(ipv62 = false) {
|
|
3888
|
+
this.ipv6 = ipv62;
|
|
3889
|
+
}
|
|
3890
|
+
set(table) {
|
|
3891
|
+
const parsed = (table.prefixes ?? []).map(parsePrefix);
|
|
3892
|
+
const bad = (table.prefixes ?? []).find((_, i) => !parsed[i]);
|
|
3893
|
+
if (bad !== void 0) throw new Error(`not an address prefix: ${bad}`);
|
|
3894
|
+
this.table = parsed;
|
|
3895
|
+
this.exit = table.exit === true;
|
|
3896
|
+
}
|
|
3897
|
+
classify(host) {
|
|
3898
|
+
const name2 = host.toLowerCase().replace(/\.$/, "");
|
|
3899
|
+
if (name2 === "localhost" || name2.endsWith(".localhost") || name2 === "0.0.0.0") {
|
|
3900
|
+
return "loopback";
|
|
3901
|
+
}
|
|
3902
|
+
if (name2 === HOST_LOOPBACK || name2 === HOST_ADDRESS) return "host";
|
|
3903
|
+
const addr = addressBits(name2);
|
|
3904
|
+
if (!addr) return "unreachable";
|
|
3905
|
+
if (addr.v6 && addr.bits === 1n) return "loopback";
|
|
3906
|
+
if (!addr.v6 && addr.bits >> 24n === 127n) return "loopback";
|
|
3907
|
+
if (RESERVED.some((p) => within2(p, addr))) return "reserved";
|
|
3908
|
+
if (addr.v6 && !this.ipv6) return "unreachable";
|
|
3909
|
+
if (this.exit || this.table.some((p) => within2(p, addr))) return "uplink";
|
|
3910
|
+
return "unreachable";
|
|
3911
|
+
}
|
|
3912
|
+
};
|
|
3913
|
+
|
|
3573
3914
|
// src/kernel/net/uplink.ts
|
|
3574
3915
|
function answerOf(result) {
|
|
3575
3916
|
const answer = Array.isArray(result) ? { addresses: result } : result;
|
|
@@ -3579,6 +3920,7 @@ function answerOf(result) {
|
|
|
3579
3920
|
...typeof answer?.ttl === "number" && answer.ttl >= 0 ? { ttl: answer.ttl } : {}
|
|
3580
3921
|
};
|
|
3581
3922
|
}
|
|
3923
|
+
var NEVER = new Routes(true);
|
|
3582
3924
|
var RemoteUplink = class {
|
|
3583
3925
|
traits;
|
|
3584
3926
|
routes;
|
|
@@ -3596,23 +3938,60 @@ var RemoteUplink = class {
|
|
|
3596
3938
|
this.waiting.delete(reply.uid);
|
|
3597
3939
|
if (reply.uplink === "error") {
|
|
3598
3940
|
waiter.reject(Object.assign(new Error(reply.message), { code: reply.code }));
|
|
3599
|
-
} else waiter.resolve(
|
|
3941
|
+
} else waiter.resolve(reply);
|
|
3600
3942
|
}
|
|
3601
|
-
|
|
3602
|
-
const uid = ++this.nextId;
|
|
3943
|
+
ask(call, signal, transfer) {
|
|
3603
3944
|
const waiter = Promise.withResolvers();
|
|
3604
|
-
this.waiting.set(uid, waiter);
|
|
3945
|
+
this.waiting.set(call.uid, waiter);
|
|
3605
3946
|
const abort = () => {
|
|
3606
|
-
this.waiting.delete(uid);
|
|
3607
|
-
this.port.postMessage({ uplink: "cancel", uid });
|
|
3947
|
+
this.waiting.delete(call.uid);
|
|
3948
|
+
this.port.postMessage({ uplink: "cancel", uid: call.uid });
|
|
3608
3949
|
waiter.reject(signal?.reason);
|
|
3609
3950
|
};
|
|
3610
3951
|
signal?.addEventListener("abort", abort, { once: true });
|
|
3611
3952
|
const settled = () => signal?.removeEventListener("abort", abort);
|
|
3612
3953
|
waiter.promise.then(settled, settled);
|
|
3613
|
-
this.port.postMessage(
|
|
3954
|
+
this.port.postMessage(call, transfer);
|
|
3614
3955
|
return waiter.promise;
|
|
3615
3956
|
}
|
|
3957
|
+
async resolve(name2, family, signal) {
|
|
3958
|
+
const reply = await this.ask(
|
|
3959
|
+
{ uplink: "resolve", uid: ++this.nextId, name: name2, family },
|
|
3960
|
+
signal
|
|
3961
|
+
);
|
|
3962
|
+
return answerOf(reply);
|
|
3963
|
+
}
|
|
3964
|
+
async dial(req) {
|
|
3965
|
+
req.signal.throwIfAborted();
|
|
3966
|
+
const { host, port } = req;
|
|
3967
|
+
const opened2 = await this.ask(
|
|
3968
|
+
{ uplink: "dial", uid: ++this.nextId, host, port },
|
|
3969
|
+
req.signal
|
|
3970
|
+
);
|
|
3971
|
+
const { cid, localAddr, remoteAddr } = opened2;
|
|
3972
|
+
return {
|
|
3973
|
+
localAddr,
|
|
3974
|
+
remoteAddr,
|
|
3975
|
+
read: async () => {
|
|
3976
|
+
const got = await this.ask({
|
|
3977
|
+
uplink: "read",
|
|
3978
|
+
uid: ++this.nextId,
|
|
3979
|
+
cid
|
|
3980
|
+
});
|
|
3981
|
+
return got.bytes;
|
|
3982
|
+
},
|
|
3983
|
+
write: async (bytes) => {
|
|
3984
|
+
const copy = bytes.slice();
|
|
3985
|
+
const call = { uplink: "write", uid: ++this.nextId, cid, bytes: copy };
|
|
3986
|
+
const done4 = await this.ask(call, void 0, [
|
|
3987
|
+
copy.buffer
|
|
3988
|
+
]);
|
|
3989
|
+
return done4.n;
|
|
3990
|
+
},
|
|
3991
|
+
closeWrite: () => this.port.postMessage({ uplink: "close-write", cid }),
|
|
3992
|
+
close: () => this.port.postMessage({ uplink: "close", cid })
|
|
3993
|
+
};
|
|
3994
|
+
}
|
|
3616
3995
|
};
|
|
3617
3996
|
|
|
3618
3997
|
// src/cdp/types.ts
|
|
@@ -4747,9 +5126,9 @@ function parseSize(text) {
|
|
|
4747
5126
|
if (!match) throw errnoError("EINVAL", `not a size: ${text}`);
|
|
4748
5127
|
return Math.floor(Number(match[1]) * UNITS[match[2].toLowerCase()]);
|
|
4749
5128
|
}
|
|
4750
|
-
var
|
|
5129
|
+
var within3 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
4751
5130
|
function heldUnder(held, target) {
|
|
4752
|
-
for (const paths of held) for (const path of paths.keys()) if (
|
|
5131
|
+
for (const paths of held) for (const path of paths.keys()) if (within3(path, target)) return true;
|
|
4753
5132
|
return false;
|
|
4754
5133
|
}
|
|
4755
5134
|
var HeldPaths = class extends Map {
|
|
@@ -4763,11 +5142,11 @@ var HeldPaths = class extends Map {
|
|
|
4763
5142
|
}
|
|
4764
5143
|
}
|
|
4765
5144
|
revoke(prefix) {
|
|
4766
|
-
for (const path of this.keys()) if (
|
|
5145
|
+
for (const path of this.keys()) if (within3(path, prefix)) this.revoked.add(path);
|
|
4767
5146
|
}
|
|
4768
5147
|
renamed(from, to) {
|
|
4769
5148
|
for (const [path, count] of [...this]) {
|
|
4770
|
-
if (!
|
|
5149
|
+
if (!within3(path, from)) continue;
|
|
4771
5150
|
const moved2 = to + path.slice(from.length);
|
|
4772
5151
|
this.delete(path);
|
|
4773
5152
|
this.set(moved2, (this.get(moved2) ?? 0) + count);
|
|
@@ -4865,7 +5244,7 @@ var MountTable = class {
|
|
|
4865
5244
|
locate(path) {
|
|
4866
5245
|
let best;
|
|
4867
5246
|
for (const mount of this.mounts.values()) {
|
|
4868
|
-
if (
|
|
5247
|
+
if (within3(path, mount.target) && (!best || mount.target.length > best.target.length))
|
|
4869
5248
|
best = mount;
|
|
4870
5249
|
}
|
|
4871
5250
|
if (!best) return void 0;
|
|
@@ -4977,10 +5356,10 @@ var MountTable = class {
|
|
|
4977
5356
|
this.deps.changed?.(...full);
|
|
4978
5357
|
}
|
|
4979
5358
|
forget(mount, path) {
|
|
4980
|
-
for (const key of [...mount.attrs.keys()]) if (
|
|
5359
|
+
for (const key of [...mount.attrs.keys()]) if (within3(key, path)) mount.attrs.delete(key);
|
|
4981
5360
|
mount.lists.delete(path);
|
|
4982
5361
|
mount.lists.delete(parentOf4(path));
|
|
4983
|
-
for (const key of [...mount.lists.keys()]) if (
|
|
5362
|
+
for (const key of [...mount.lists.keys()]) if (within3(key, path)) mount.lists.delete(key);
|
|
4984
5363
|
}
|
|
4985
5364
|
async getattr(mount, path, rel2) {
|
|
4986
5365
|
if (mount.conn.failure) throw mount.conn.failure;
|
|
@@ -5943,95 +6322,6 @@ var HttpHandles = class {
|
|
|
5943
6322
|
}
|
|
5944
6323
|
};
|
|
5945
6324
|
|
|
5946
|
-
// src/kernel/net/routes.ts
|
|
5947
|
-
var HOST_ADDRESS = HOST_LOOPBACK_ADDRESS.join(".");
|
|
5948
|
-
function ipv4Bytes(text) {
|
|
5949
|
-
const parts = text.split(".");
|
|
5950
|
-
if (parts.length !== 4 || !parts.every((p) => /^\d{1,3}$/.test(p))) return void 0;
|
|
5951
|
-
const bytes = parts.map(Number);
|
|
5952
|
-
return bytes.every((b) => b <= 255) ? bytes : void 0;
|
|
5953
|
-
}
|
|
5954
|
-
function ipv6Groups(text) {
|
|
5955
|
-
if (!text.includes(":")) return void 0;
|
|
5956
|
-
let canonical;
|
|
5957
|
-
try {
|
|
5958
|
-
canonical = new URL(`http://[${text}]/`).hostname.slice(1, -1);
|
|
5959
|
-
} catch {
|
|
5960
|
-
return void 0;
|
|
5961
|
-
}
|
|
5962
|
-
const [head, tail] = canonical.split("::");
|
|
5963
|
-
const part = (s) => s ? s.split(":").map((h) => Number.parseInt(h, 16)) : [];
|
|
5964
|
-
const front = part(head);
|
|
5965
|
-
const back = part(tail);
|
|
5966
|
-
return tail === void 0 ? front : [...front, ...new Array(8 - front.length - back.length).fill(0), ...back];
|
|
5967
|
-
}
|
|
5968
|
-
function toBits(values, width) {
|
|
5969
|
-
return values.reduce((acc, v) => acc << BigInt(width) | BigInt(v), 0n);
|
|
5970
|
-
}
|
|
5971
|
-
function addressBits(host) {
|
|
5972
|
-
const v4 = ipv4Bytes(host);
|
|
5973
|
-
if (v4) return { v6: false, bits: toBits(v4, 8) };
|
|
5974
|
-
const v6 = ipv6Groups(host);
|
|
5975
|
-
return v6 ? { v6: true, bits: toBits(v6, 16) } : void 0;
|
|
5976
|
-
}
|
|
5977
|
-
function parsePrefix(text) {
|
|
5978
|
-
const parts = text.trim().split("/");
|
|
5979
|
-
if (parts.length > 2) return void 0;
|
|
5980
|
-
const [address = "", size] = parts;
|
|
5981
|
-
const parsed = addressBits(address);
|
|
5982
|
-
if (!parsed) return void 0;
|
|
5983
|
-
const max = parsed.v6 ? 128 : 32;
|
|
5984
|
-
const length2 = size === void 0 ? max : /^\d{1,3}$/.test(size) ? Number(size) : -1;
|
|
5985
|
-
if (length2 < 0 || length2 > max) return void 0;
|
|
5986
|
-
return { ...parsed, length: length2 };
|
|
5987
|
-
}
|
|
5988
|
-
function within3(prefix, addr) {
|
|
5989
|
-
if (prefix.v6 !== addr.v6) return false;
|
|
5990
|
-
const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);
|
|
5991
|
-
return addr.bits >> shift === prefix.bits >> shift;
|
|
5992
|
-
}
|
|
5993
|
-
var RESERVED = [
|
|
5994
|
-
"0.0.0.0/8",
|
|
5995
|
-
"127.0.0.0/8",
|
|
5996
|
-
"169.254.0.0/16",
|
|
5997
|
-
"224.0.0.0/4",
|
|
5998
|
-
"240.0.0.0/4",
|
|
5999
|
-
"::/96",
|
|
6000
|
-
"::ffff:0:0/96",
|
|
6001
|
-
"fe80::/10",
|
|
6002
|
-
"ff00::/8"
|
|
6003
|
-
].map((p) => parsePrefix(p));
|
|
6004
|
-
var Routes = class {
|
|
6005
|
-
table = [];
|
|
6006
|
-
exit = false;
|
|
6007
|
-
ipv6;
|
|
6008
|
-
constructor(ipv62 = false) {
|
|
6009
|
-
this.ipv6 = ipv62;
|
|
6010
|
-
}
|
|
6011
|
-
set(table) {
|
|
6012
|
-
const parsed = (table.prefixes ?? []).map(parsePrefix);
|
|
6013
|
-
const bad = (table.prefixes ?? []).find((_, i) => !parsed[i]);
|
|
6014
|
-
if (bad !== void 0) throw new Error(`not an address prefix: ${bad}`);
|
|
6015
|
-
this.table = parsed;
|
|
6016
|
-
this.exit = table.exit === true;
|
|
6017
|
-
}
|
|
6018
|
-
classify(host) {
|
|
6019
|
-
const name2 = host.toLowerCase().replace(/\.$/, "");
|
|
6020
|
-
if (name2 === "localhost" || name2.endsWith(".localhost") || name2 === "0.0.0.0") {
|
|
6021
|
-
return "loopback";
|
|
6022
|
-
}
|
|
6023
|
-
if (name2 === HOST_LOOPBACK || name2 === HOST_ADDRESS) return "host";
|
|
6024
|
-
const addr = addressBits(name2);
|
|
6025
|
-
if (!addr) return "unreachable";
|
|
6026
|
-
if (addr.v6 && addr.bits === 1n) return "loopback";
|
|
6027
|
-
if (!addr.v6 && addr.bits >> 24n === 127n) return "loopback";
|
|
6028
|
-
if (RESERVED.some((p) => within3(p, addr))) return "reserved";
|
|
6029
|
-
if (addr.v6 && !this.ipv6) return "unreachable";
|
|
6030
|
-
if (this.exit || this.table.some((p) => within3(p, addr))) return "uplink";
|
|
6031
|
-
return "unreachable";
|
|
6032
|
-
}
|
|
6033
|
-
};
|
|
6034
|
-
|
|
6035
6325
|
// src/kernel/net/resolver.ts
|
|
6036
6326
|
var RESOLVE_TTL_MAX = 60;
|
|
6037
6327
|
var RESOLVE_TIMEOUT_MS = 1e4;
|
|
@@ -6676,10 +6966,15 @@ async function socketSyscall(req, proc) {
|
|
|
6676
6966
|
return ok();
|
|
6677
6967
|
case "sock-accept":
|
|
6678
6968
|
return ok(await accept(proc, req.fd, req.nonblock));
|
|
6679
|
-
case "sock-connect":
|
|
6680
|
-
socketAt(fds, req.fd).connect(req.addr);
|
|
6681
|
-
if (req.nonblock)
|
|
6969
|
+
case "sock-connect": {
|
|
6970
|
+
const dialing = socketAt(fds, req.fd).connect(req.addr);
|
|
6971
|
+
if (req.nonblock) {
|
|
6972
|
+
dialing?.catch(() => void 0);
|
|
6973
|
+
throw new KernelError("EINPROGRESS");
|
|
6974
|
+
}
|
|
6975
|
+
if (dialing !== void 0) await interruptible(dialing, proc.blocking());
|
|
6682
6976
|
return ok();
|
|
6977
|
+
}
|
|
6683
6978
|
case "sock-shutdown":
|
|
6684
6979
|
socketAt(fds, req.fd).shutdown(req.how);
|
|
6685
6980
|
return ok();
|
|
@@ -6701,6 +6996,13 @@ async function socketSyscall(req, proc) {
|
|
|
6701
6996
|
}
|
|
6702
6997
|
}
|
|
6703
6998
|
}
|
|
6999
|
+
function interruptible(dialing, signal) {
|
|
7000
|
+
return new Promise((resolve, reject) => {
|
|
7001
|
+
const abort = () => reject(new KernelError("EINTR"));
|
|
7002
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
7003
|
+
dialing.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
7004
|
+
});
|
|
7005
|
+
}
|
|
6704
7006
|
function unnamed(domain) {
|
|
6705
7007
|
return domain === "inet" ? { family: "inet", host: "0.0.0.0", port: 0 } : { family: "unix", path: "" };
|
|
6706
7008
|
}
|
|
@@ -9121,7 +9423,7 @@ async function openHostfs(spec, hook, fetch2, timing = {}) {
|
|
|
9121
9423
|
}
|
|
9122
9424
|
|
|
9123
9425
|
// src/mount/chunked.ts
|
|
9124
|
-
var
|
|
9426
|
+
var CHUNK3 = 1024 * 1024;
|
|
9125
9427
|
var ChunkedBytes = class {
|
|
9126
9428
|
chunks = [];
|
|
9127
9429
|
size = 0;
|
|
@@ -9130,9 +9432,9 @@ var ChunkedBytes = class {
|
|
|
9130
9432
|
if (end <= offset) return new Uint8Array(0);
|
|
9131
9433
|
const out = new Uint8Array(end - offset);
|
|
9132
9434
|
for (let at = offset; at < end; ) {
|
|
9133
|
-
const index = Math.floor(at /
|
|
9134
|
-
const from = at - index *
|
|
9135
|
-
const n = Math.min(
|
|
9435
|
+
const index = Math.floor(at / CHUNK3);
|
|
9436
|
+
const from = at - index * CHUNK3;
|
|
9437
|
+
const n = Math.min(CHUNK3 - from, end - at);
|
|
9136
9438
|
const chunk2 = this.chunks[index];
|
|
9137
9439
|
if (chunk2) out.set(chunk2.subarray(from, Math.min(from + n, chunk2.length)), at - offset);
|
|
9138
9440
|
at += n;
|
|
@@ -9143,10 +9445,10 @@ var ChunkedBytes = class {
|
|
|
9143
9445
|
const whole = owned && bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength;
|
|
9144
9446
|
for (let done4 = 0; done4 < bytes.length; ) {
|
|
9145
9447
|
const at = offset + done4;
|
|
9146
|
-
const index = Math.floor(at /
|
|
9147
|
-
const from = at - index *
|
|
9148
|
-
const n = Math.min(
|
|
9149
|
-
if (whole && n ===
|
|
9448
|
+
const index = Math.floor(at / CHUNK3);
|
|
9449
|
+
const from = at - index * CHUNK3;
|
|
9450
|
+
const n = Math.min(CHUNK3 - from, bytes.length - done4);
|
|
9451
|
+
if (whole && n === CHUNK3 && bytes.length === CHUNK3) this.chunks[index] = bytes;
|
|
9150
9452
|
else this.room(index, from + n).set(bytes.subarray(done4, done4 + n), from);
|
|
9151
9453
|
done4 += n;
|
|
9152
9454
|
}
|
|
@@ -9154,10 +9456,10 @@ var ChunkedBytes = class {
|
|
|
9154
9456
|
}
|
|
9155
9457
|
truncate(size) {
|
|
9156
9458
|
if (size < this.size) {
|
|
9157
|
-
const keep = Math.ceil(size /
|
|
9459
|
+
const keep = Math.ceil(size / CHUNK3);
|
|
9158
9460
|
this.chunks.length = Math.min(this.chunks.length, keep);
|
|
9159
9461
|
const tail = this.chunks[keep - 1];
|
|
9160
|
-
const from = size - (keep - 1) *
|
|
9462
|
+
const from = size - (keep - 1) * CHUNK3;
|
|
9161
9463
|
if (tail && from < tail.length) tail.fill(0, from);
|
|
9162
9464
|
}
|
|
9163
9465
|
this.size = size;
|
|
@@ -9165,7 +9467,7 @@ var ChunkedBytes = class {
|
|
|
9165
9467
|
room(index, need) {
|
|
9166
9468
|
const chunk2 = this.chunks[index];
|
|
9167
9469
|
if (chunk2 && chunk2.length >= need) return chunk2;
|
|
9168
|
-
const grown = new Uint8Array(Math.min(
|
|
9470
|
+
const grown = new Uint8Array(Math.min(CHUNK3, Math.max(need, (chunk2?.length ?? 0) * 2)));
|
|
9169
9471
|
if (chunk2) grown.set(chunk2);
|
|
9170
9472
|
this.chunks[index] = grown;
|
|
9171
9473
|
return grown;
|
|
@@ -9625,6 +9927,7 @@ var Launcher = class {
|
|
|
9625
9927
|
this.routes = new Routes(options.uplink?.traits.ipv6 === true);
|
|
9626
9928
|
if (options.uplink?.routes) this.routes.set(options.uplink.routes);
|
|
9627
9929
|
this.resolver = new Resolver({ uplink: options.uplink, routes: this.routes });
|
|
9930
|
+
if (options.uplink) this.net.useUplink({ uplink: options.uplink, routes: this.routes });
|
|
9628
9931
|
enableNetwork(this.net, {
|
|
9629
9932
|
transport: this.transport,
|
|
9630
9933
|
engine: kernelTlsEngine(packageTlsEngine(options.fs, this.modulesDir)),
|