@ai-ecoverse/slicc-kernel 1.123.2 → 1.124.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/dist/node.js CHANGED
@@ -1404,6 +1404,111 @@ var Routes = class {
1404
1404
  }
1405
1405
  };
1406
1406
 
1407
+ // src/kernel/net/switch-conn.ts
1408
+ var SwitchConn = class {
1409
+ raw;
1410
+ box = [];
1411
+ pulling = false;
1412
+ waiters = [];
1413
+ switching = false;
1414
+ secure;
1415
+ failed;
1416
+ constructor(raw) {
1417
+ this.raw = raw;
1418
+ }
1419
+ get localAddr() {
1420
+ return this.raw.localAddr;
1421
+ }
1422
+ get remoteAddr() {
1423
+ return this.raw.remoteAddr;
1424
+ }
1425
+ get upgraded() {
1426
+ return this.switching || this.secure !== void 0;
1427
+ }
1428
+ wake() {
1429
+ for (const wake of this.waiters.splice(0)) wake();
1430
+ }
1431
+ changed() {
1432
+ return new Promise((resolve2) => this.waiters.push(resolve2));
1433
+ }
1434
+ pull() {
1435
+ if (this.pulling || this.box.length > 0) return;
1436
+ this.pulling = true;
1437
+ this.raw.read().then(
1438
+ (bytes) => this.box.push(bytes),
1439
+ (err) => this.box.push(err instanceof Error ? err : new Error(String(err)))
1440
+ ).finally(() => {
1441
+ this.pulling = false;
1442
+ this.wake();
1443
+ });
1444
+ }
1445
+ take() {
1446
+ const next3 = this.box.shift();
1447
+ if (next3 instanceof Error) throw next3;
1448
+ return next3;
1449
+ }
1450
+ async rawRead() {
1451
+ while (this.box.length === 0) {
1452
+ this.pull();
1453
+ await this.changed();
1454
+ }
1455
+ return this.take();
1456
+ }
1457
+ async read() {
1458
+ for (; ; ) {
1459
+ if (this.failed) throw this.failed;
1460
+ if (this.secure) return this.secure.read();
1461
+ if (!this.switching && this.box.length > 0) return this.take();
1462
+ if (!this.switching) this.pull();
1463
+ await this.changed();
1464
+ }
1465
+ }
1466
+ async settled() {
1467
+ while (this.switching) await this.changed();
1468
+ if (this.failed) throw this.failed;
1469
+ return this.secure ?? this.raw;
1470
+ }
1471
+ async write(bytes) {
1472
+ return (await this.settled()).write(bytes);
1473
+ }
1474
+ closeWrite() {
1475
+ void this.settled().then(
1476
+ (conn) => conn.closeWrite(),
1477
+ () => void 0
1478
+ );
1479
+ }
1480
+ close() {
1481
+ this.failed ??= new Error("closed");
1482
+ this.secure?.close();
1483
+ this.raw.close();
1484
+ this.wake();
1485
+ }
1486
+ async upgrade(make) {
1487
+ if (this.upgraded) throw new Error("already upgraded");
1488
+ this.switching = true;
1489
+ this.wake();
1490
+ const view2 = {
1491
+ localAddr: this.raw.localAddr,
1492
+ remoteAddr: this.raw.remoteAddr,
1493
+ read: () => this.rawRead(),
1494
+ write: (bytes) => this.raw.write(bytes),
1495
+ closeWrite: () => this.raw.closeWrite(),
1496
+ close: () => this.raw.close()
1497
+ };
1498
+ try {
1499
+ const { conn, info } = await make(view2);
1500
+ this.secure = conn;
1501
+ return info;
1502
+ } catch (err) {
1503
+ this.failed = err instanceof Error ? err : new Error(String(err));
1504
+ throw err;
1505
+ } finally {
1506
+ this.switching = false;
1507
+ this.wake();
1508
+ }
1509
+ }
1510
+ };
1511
+
1407
1512
  // src/kernel/net/uplink-socket.ts
1408
1513
  var CHUNK = 64 * 1024;
1409
1514
  function hostPort(text) {
@@ -1728,7 +1833,18 @@ var KernelSocket = class _KernelSocket {
1728
1833
  clearTimeout(timer);
1729
1834
  }
1730
1835
  }
1731
- dial(addr, route) {
1836
+ switch;
1837
+ connectSecure(addr, route, secure2) {
1838
+ if (this.state !== "open") throw new KernelError("EISCONN");
1839
+ return this.dial(addr, route, secure2);
1840
+ }
1841
+ upgradeSecure(make) {
1842
+ if (this.state !== "connected") throw new KernelError("ENOTCONN");
1843
+ if (!this.switch) throw new KernelError("EOPNOTSUPP");
1844
+ if (this.switch.upgraded || this.writeShut || this.readShut) throw new KernelError("EINVAL");
1845
+ return this.switch.upgrade(make);
1846
+ }
1847
+ dial(addr, route, secure2) {
1732
1848
  this.state = "connecting";
1733
1849
  const abort = new AbortController();
1734
1850
  this.dialing = abort;
@@ -1749,11 +1865,25 @@ var KernelSocket = class _KernelSocket {
1749
1865
  () => void 0
1750
1866
  );
1751
1867
  return Promise.race([dialled, abandoned]).then(
1752
- (conn) => {
1868
+ async (raw) => {
1753
1869
  if (abort.signal.aborted) throw dialError(abort.signal.reason, timedOut, true);
1870
+ const conn = new SwitchConn(raw);
1871
+ if (secure2) {
1872
+ clearTimeout(timer);
1873
+ try {
1874
+ await Promise.race([secure2(conn), abandoned]);
1875
+ } catch (e) {
1876
+ conn.close();
1877
+ throw this.dialFailed(
1878
+ abort,
1879
+ e instanceof KernelError ? e : new KernelError("ENOTSUP", e instanceof Error ? e.message : String(e))
1880
+ );
1881
+ }
1882
+ }
1754
1883
  this.local = { family: "inet", host: "0.0.0.0", port: 0, ...hostPort(conn.localAddr) };
1755
1884
  this.peer = { ...addr, ...hostPort(conn.remoteAddr) };
1756
1885
  this.dialing = void 0;
1886
+ this.switch = conn;
1757
1887
  this.attach(
1758
1888
  uplinkLink(conn, () => {
1759
1889
  this.reset = true;
@@ -1762,17 +1892,19 @@ var KernelSocket = class _KernelSocket {
1762
1892
  );
1763
1893
  },
1764
1894
  (e) => {
1765
- const error = dialError(e, timedOut, abort.signal.aborted);
1766
- if (this.dialing === abort) {
1767
- this.dialing = void 0;
1768
- this.failed = error.code;
1769
- this.state = "open";
1770
- this.changes.wake();
1771
- }
1772
- throw error;
1895
+ throw this.dialFailed(abort, dialError(e, timedOut, abort.signal.aborted));
1773
1896
  }
1774
1897
  ).finally(() => clearTimeout(timer));
1775
1898
  }
1899
+ dialFailed(abort, error) {
1900
+ if (this.dialing === abort) {
1901
+ this.dialing = void 0;
1902
+ this.failed = error.code;
1903
+ this.state = "open";
1904
+ this.changes.wake();
1905
+ }
1906
+ return error;
1907
+ }
1776
1908
  unlink() {
1777
1909
  const link2 = this.link;
1778
1910
  if (link2) {
@@ -1878,6 +2010,7 @@ var LoopbackNet = class {
1878
2010
  useUplink(route) {
1879
2011
  this.route = route;
1880
2012
  }
2013
+ tlsClient;
1881
2014
  uplinkFor(host) {
1882
2015
  const route = this.route;
1883
2016
  if (!route) return void 0;
@@ -2019,12 +2152,12 @@ function serveSocket(socket, port, onClose) {
2019
2152
  let writes = Promise.resolve();
2020
2153
  let credit = 0;
2021
2154
  let granted2;
2022
- const send = (message3, transfer) => {
2155
+ const send2 = (message3, transfer) => {
2023
2156
  if (!closed) port.postMessage(message3, transfer);
2024
2157
  };
2025
2158
  const close = (reset = false) => {
2026
2159
  if (closed) return;
2027
- if (reset) send({ error: "ECONNRESET" });
2160
+ if (reset) send2({ error: "ECONNRESET" });
2028
2161
  closed = true;
2029
2162
  granted2?.();
2030
2163
  socket.close();
@@ -2036,9 +2169,9 @@ function serveSocket(socket, port, onClose) {
2036
2169
  if (closed) return;
2037
2170
  try {
2038
2171
  await socket.write(data);
2039
- send({ ack: true });
2172
+ send2({ ack: true });
2040
2173
  } catch (err) {
2041
- send({ error: codeOf(err) });
2174
+ send2({ error: codeOf(err) });
2042
2175
  }
2043
2176
  });
2044
2177
  };
@@ -2063,11 +2196,11 @@ function serveSocket(socket, port, onClose) {
2063
2196
  const chunk2 = await socket.read(CHUNK2);
2064
2197
  if (chunk2.length === 0) break;
2065
2198
  credit--;
2066
- send(chunk2, [chunk2.buffer]);
2199
+ send2(chunk2, [chunk2.buffer]);
2067
2200
  }
2068
- send({ end: true });
2201
+ send2({ end: true });
2069
2202
  } catch (err) {
2070
- send({ error: codeOf(err) });
2203
+ send2({ error: codeOf(err) });
2071
2204
  }
2072
2205
  })();
2073
2206
  return () => close(true);
@@ -2382,7 +2515,7 @@ function requestBody(request) {
2382
2515
  return request.body ? { body: request.body } : {};
2383
2516
  }
2384
2517
  function fetchTransport(options = {}) {
2385
- const send = options.fetch ?? globalThis.fetch.bind(globalThis);
2518
+ const send2 = options.fetch ?? globalThis.fetch.bind(globalThis);
2386
2519
  const Socket = options.webSocket === true ? globalThis.WebSocket : options.webSocket || void 0;
2387
2520
  const headers = options.webSocketHeaders === true;
2388
2521
  const redirect = options.redirect ?? "follow";
@@ -2399,7 +2532,7 @@ function fetchTransport(options = {}) {
2399
2532
  async fetch(request) {
2400
2533
  let response;
2401
2534
  try {
2402
- response = await send(request.url, {
2535
+ response = await send2(request.url, {
2403
2536
  method: request.method,
2404
2537
  headers: joinHeaders(request.headers),
2405
2538
  ...requestBody(request),
@@ -3199,7 +3332,7 @@ function joinable(l, pgid, ours) {
3199
3332
  if (sid === void 0) throw fsError("ESRCH", `no process group ${pgid}`);
3200
3333
  if (!ours(sid)) throw fsError("EPERM", `process group ${pgid} is in another session`);
3201
3334
  }
3202
- function cdpRegistry(send, gone) {
3335
+ function cdpRegistry(send2, gone) {
3203
3336
  const registered = /* @__PURE__ */ new Map();
3204
3337
  const drop = (id2) => {
3205
3338
  registered.get(id2)?.();
@@ -3208,7 +3341,7 @@ function cdpRegistry(send, gone) {
3208
3341
  return {
3209
3342
  serve(l, req) {
3210
3343
  const hook = portCdpHook(
3211
- (request, cdp) => send({ cdpOpen: { ...request, registration: req.id }, port: cdp }, [
3344
+ (request, cdp) => send2({ cdpOpen: { ...request, registration: req.id }, port: cdp }, [
3212
3345
  cdp
3213
3346
  ]),
3214
3347
  gone
@@ -3222,7 +3355,7 @@ function cdpRegistry(send, gone) {
3222
3355
  }
3223
3356
  };
3224
3357
  }
3225
- function facadeRegistry(send, gone) {
3358
+ function facadeRegistry(send2, gone) {
3226
3359
  const registered = /* @__PURE__ */ new Map();
3227
3360
  const drop = (id2) => {
3228
3361
  registered.get(id2)?.();
@@ -3231,7 +3364,7 @@ function facadeRegistry(send, gone) {
3231
3364
  return {
3232
3365
  serve(l, req) {
3233
3366
  const hook = portFacadeHook(
3234
- (request, facade) => send({ facadeOpen: { ...request, registration: req.id }, port: facade }, [
3367
+ (request, facade) => send2({ facadeOpen: { ...request, registration: req.id }, port: facade }, [
3235
3368
  facade
3236
3369
  ]),
3237
3370
  gone
@@ -3245,9 +3378,9 @@ function facadeRegistry(send, gone) {
3245
3378
  }
3246
3379
  };
3247
3380
  }
3248
- function hostRegistries(send, gone) {
3249
- const cdps = cdpRegistry(send, gone);
3250
- const facades = facadeRegistry(send, gone);
3381
+ function hostRegistries(send2, gone) {
3382
+ const cdps = cdpRegistry(send2, gone);
3383
+ const facades = facadeRegistry(send2, gone);
3251
3384
  return {
3252
3385
  answer(l, req) {
3253
3386
  if (req.op === "serve-cdp") return cdps.serve(l, req);
@@ -3274,21 +3407,21 @@ function visibleTo(g, notify) {
3274
3407
  });
3275
3408
  };
3276
3409
  }
3277
- async function watchOp(l, req, watches, send, g) {
3410
+ async function watchOp(l, req, watches, send2, g) {
3278
3411
  if (req.op === "unwatch") {
3279
3412
  watches.get(req.watch)?.();
3280
3413
  watches.delete(req.watch);
3281
3414
  return { result: true };
3282
3415
  }
3283
3416
  if (g) for (const path of req.paths) await readable(g, "watch", l.fs.resolvePath("/", path));
3284
- const notify = visibleTo(g, (change) => send({ watch: req.id, change }));
3417
+ const notify = visibleTo(g, (change) => send2({ watch: req.id, change }));
3285
3418
  const unwatch = l.watchers.watch(req.paths, { recursive: req.recursive }, notify);
3286
3419
  watches.set(req.id, unwatch);
3287
3420
  return { result: req.id };
3288
3421
  }
3289
3422
  var TRAITS_WATCH = -1;
3290
- function traitsWatch(launcher, transport, send) {
3291
- return launcher.onTraits(() => send({ traits: transport.traits }));
3423
+ function traitsWatch(launcher, transport, send2) {
3424
+ return launcher.onTraits(() => send2({ traits: transport.traits }));
3292
3425
  }
3293
3426
  function serveClient(port, host) {
3294
3427
  let state = "new";
@@ -3300,14 +3433,14 @@ function serveClient(port, host) {
3300
3433
  const watches = /* @__PURE__ */ new Map();
3301
3434
  let net;
3302
3435
  const ended = Promise.withResolvers();
3303
- const send = (message3, transfer = []) => {
3436
+ const send2 = (message3, transfer = []) => {
3304
3437
  if (state !== "closed") port.postMessage(message3, transfer);
3305
3438
  };
3306
- const reply = (id2, body, transfer) => send({ id: id2, ...body }, transfer);
3307
- const hosts = hostRegistries(send, ended.promise);
3439
+ const reply = (id2, body, transfer) => send2({ id: id2, ...body }, transfer);
3440
+ const hosts = hostRegistries(send2, ended.promise);
3308
3441
  function detach(kill = false, bye = "the slicc-kernel detached this client") {
3309
3442
  if (state === "closed") return;
3310
- send({ bye });
3443
+ send2({ bye });
3311
3444
  state = "closed";
3312
3445
  net?.close();
3313
3446
  for (const unwatch of watches.values()) unwatch();
@@ -3321,19 +3454,19 @@ function serveClient(port, host) {
3321
3454
  ended.resolve();
3322
3455
  }
3323
3456
  async function hello(message3) {
3324
- const refused2 = versionError(message3.protocol);
3325
- if (refused2) {
3326
- send({ hello: { protocol: PROTOCOL, error: refused2 } });
3457
+ const refused3 = versionError(message3.protocol);
3458
+ if (refused3) {
3459
+ send2({ hello: { protocol: PROTOCOL, error: refused3 } });
3327
3460
  detach();
3328
3461
  return;
3329
3462
  }
3330
3463
  const launcher = await host.launcher();
3331
3464
  if (host.scope !== "transport") self = await accountOf(launcher, host.user ?? 0);
3332
3465
  const transport = host.transport?.() ?? launcher.transport;
3333
- net = serveTransport({ postMessage: (m, t) => send(m, t) }, transport);
3466
+ net = serveTransport({ postMessage: (m, t) => send2(m, t) }, transport);
3334
3467
  state = "open";
3335
3468
  if (message3.lock && host.locks) void host.locks.request(message3.lock, () => detach());
3336
- send({
3469
+ send2({
3337
3470
  hello: {
3338
3471
  protocol: PROTOCOL,
3339
3472
  traits: transport.traits,
@@ -3341,7 +3474,7 @@ function serveClient(port, host) {
3341
3474
  ...host.lock ? { lock: host.lock } : {}
3342
3475
  }
3343
3476
  });
3344
- watches.set(TRAITS_WATCH, traitsWatch(launcher, transport, send));
3477
+ watches.set(TRAITS_WATCH, traitsWatch(launcher, transport, send2));
3345
3478
  }
3346
3479
  async function terminal(req, l) {
3347
3480
  const session = await l.openTerminal(req.argv, {
@@ -3405,7 +3538,7 @@ function serveClient(port, host) {
3405
3538
  return clientFs(l, host.tag, self, req);
3406
3539
  case "watch":
3407
3540
  case "unwatch":
3408
- return watchOp(l, req, watches, send, guard2(l));
3541
+ return watchOp(l, req, watches, send2, guard2(l));
3409
3542
  case "mount":
3410
3543
  return { result: await l.mountAs(clientCred(self), req.spec) };
3411
3544
  case "umount":
@@ -3431,7 +3564,7 @@ function serveClient(port, host) {
3431
3564
  if (data.hello) {
3432
3565
  if (state === "new") {
3433
3566
  hello(data.hello).catch((err) => {
3434
- send({ hello: { protocol: PROTOCOL, error: String(err?.message ?? err) } });
3567
+ send2({ hello: { protocol: PROTOCOL, error: String(err?.message ?? err) } });
3435
3568
  detach();
3436
3569
  });
3437
3570
  }
@@ -6802,7 +6935,7 @@ function satisfies(version, range2) {
6802
6935
  }
6803
6936
 
6804
6937
  // src/version.ts
6805
- var KERNEL_VERSION = true ? "1.123.2" : "0.0.0-dev";
6938
+ var KERNEL_VERSION = true ? "1.124.0" : "0.0.0-dev";
6806
6939
  var OS_RELEASE = "6.0.0-slicc";
6807
6940
  function procVersion() {
6808
6941
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -7084,13 +7217,13 @@ async function tierPackages(fs, physical, roots, bins, kernel) {
7084
7217
  const own = commandsOf(pkg, manifest);
7085
7218
  const named = new Set(own.map((command) => command.name));
7086
7219
  const extra = bins ? await binCommandsOf(physical, pkg, manifest, named) : [];
7087
- const refused2 = engineRefusal(manifest, kernel);
7220
+ const refused3 = engineRefusal(manifest, kernel);
7088
7221
  const commands = [...own, ...extra];
7089
7222
  out.push({
7090
7223
  name: pkg.slice(root.length + 1),
7091
7224
  pkg,
7092
7225
  replaces: replacesOf(manifest),
7093
- commands: refused2 ? commands.map((command) => ({ ...command, refused: refused2 })) : commands
7226
+ commands: refused3 ? commands.map((command) => ({ ...command, refused: refused3 })) : commands
7094
7227
  });
7095
7228
  }
7096
7229
  }
@@ -8400,8 +8533,8 @@ var RealmProxy = class {
8400
8533
  }
8401
8534
  async connect(conn, incoming, req, idle) {
8402
8535
  const target = tunnelTarget(req);
8403
- const refused2 = target.port === 443 ? await this.tunnelReady(target) : void 0;
8404
- if (refused2) throw refused2;
8536
+ const refused3 = target.port === 443 ? await this.tunnelReady(target) : void 0;
8537
+ if (refused3) throw refused3;
8405
8538
  await conn.write(latin1Bytes("HTTP/1.1 200 Connection Established\r\n\r\n"), this.stop.signal);
8406
8539
  try {
8407
8540
  const first = await incoming.peek(this.stop.signal);
@@ -10055,8 +10188,8 @@ var DriverConnection = class _DriverConnection {
10055
10188
  } finally {
10056
10189
  clearTimeout(timer);
10057
10190
  }
10058
- const refused2 = driverVersionError(hello.protocol);
10059
- if (refused2) throw errnoError("EPROTO", refused2);
10191
+ const refused3 = driverVersionError(hello.protocol);
10192
+ if (refused3) throw errnoError("EPROTO", refused3);
10060
10193
  if (hello.error) throw errnoError(hello.errno ?? "EIO", hello.error);
10061
10194
  return new _DriverConnection(port, hello.capabilities ?? {}, waiting, timeoutMs, options);
10062
10195
  }
@@ -11878,8 +12011,8 @@ async function guarded(entry, path, req) {
11878
12011
  return { paths };
11879
12012
  } catch (err) {
11880
12013
  const refusal2 = err.code === "EACCES";
11881
- const refused2 = req.op === "exists" && refusal2 ? json2(false) : toErrno(err);
11882
- return { refused: refused2 };
12014
+ const refused3 = req.op === "exists" && refusal2 ? json2(false) : toErrno(err);
12015
+ return { refused: refused3 };
11883
12016
  }
11884
12017
  }
11885
12018
  async function createExclusive(fs, path, owner) {
@@ -11990,13 +12123,13 @@ async function dispatchSyncFs(req) {
11990
12123
  }
11991
12124
  }
11992
12125
  var DENIED = /* @__PURE__ */ new Set(["EACCES", "EPERM"]);
11993
- async function rmPermitted(entry, path, req, refused2) {
12126
+ async function rmPermitted(entry, path, req, refused3) {
11994
12127
  const st = await entry.fs.lstat(path).catch(() => void 0);
11995
- if (!st?.isDirectory) return refused2;
12128
+ if (!st?.isDirectory) return refused3;
11996
12129
  const unlisted = await guarded(entry, path, { ...req, op: "readdir" });
11997
12130
  if ("refused" in unlisted) return unlisted.refused;
11998
12131
  const names = await entry.fs.readdir(path).catch(() => void 0);
11999
- if (!names) return refused2;
12132
+ if (!names) return refused3;
12000
12133
  let first;
12001
12134
  for (const name2 of names) {
12002
12135
  const child = await dispatchOne(entry, {
@@ -12047,14 +12180,14 @@ async function newDevName(entry, path, req) {
12047
12180
  const named = NAMING.has(req.op);
12048
12181
  if (!named && !CREATIONS.has(req.op)) return void 0;
12049
12182
  const target = named ? entry.fs.resolvePath(entry.cwd, req.arg2 ?? "") : path;
12050
- const refused2 = devCreation(target, entry.cred?.());
12051
- if (!refused2) return void 0;
12183
+ const refused3 = devCreation(target, entry.cred?.());
12184
+ if (!refused3) return void 0;
12052
12185
  const there = await entry.fs.lstat(target).then(
12053
12186
  () => true,
12054
12187
  () => false
12055
12188
  );
12056
12189
  if (there) return void 0;
12057
- return { ok: false, errno: refused2, message: `${target}: no new names in /dev or /proc` };
12190
+ return { ok: false, errno: refused3, message: `${target}: no new names in /dev or /proc` };
12058
12191
  }
12059
12192
  async function dispatchOne(entry, req) {
12060
12193
  const { fs, cwd } = entry;
@@ -13457,6 +13590,9 @@ var FlockTable = class {
13457
13590
  held = /* @__PURE__ */ new Map();
13458
13591
  keys = /* @__PURE__ */ new WeakMap();
13459
13592
  wakers = /* @__PURE__ */ new Map();
13593
+ isFree(key, owner, kind) {
13594
+ return this.free(key, owner, kind);
13595
+ }
13460
13596
  free(key, owner, kind) {
13461
13597
  for (const [other, has] of this.held.get(key) ?? [])
13462
13598
  if (other !== owner && (kind === "exclusive" || has === "exclusive")) return false;
@@ -13583,9 +13719,18 @@ var LockTable = class {
13583
13719
  );
13584
13720
  this.wake(key);
13585
13721
  }
13722
+ wholeFree(pid, path, exclusive) {
13723
+ for (const [other, h] of this.held.get(path) ?? []) {
13724
+ if (other !== pid && (exclusive || h.exclusive)) return false;
13725
+ }
13726
+ return true;
13727
+ }
13728
+ flockFree(key, owner, kind) {
13729
+ return this.flocks.isFree(key, owner, kind);
13730
+ }
13586
13731
  lock(pid, path, exclusive, fd) {
13732
+ if (!this.wholeFree(pid, path, exclusive)) return false;
13587
13733
  const holders = this.held.get(path) ?? /* @__PURE__ */ new Map();
13588
- for (const [other, h] of holders) if (other !== pid && (exclusive || h.exclusive)) return false;
13589
13734
  const mine = holders.get(pid) ?? { exclusive, fds: /* @__PURE__ */ new Set() };
13590
13735
  mine.exclusive = exclusive;
13591
13736
  mine.fds.add(fd);
@@ -13770,12 +13915,12 @@ var AsyncOps = class {
13770
13915
  async function hostSyscall(req, ctx) {
13771
13916
  switch (req.op) {
13772
13917
  case "lock":
13773
- if (!ctx.locks) throw new KernelError("ENOSYS");
13774
- if (!ctx.locks.lock(ctx.pid, req.path, req.exclusive, req.fd))
13775
- throw new KernelError("EAGAIN");
13776
- return done2;
13918
+ return wholeLock(req, ctx);
13777
13919
  case "unlock":
13778
13920
  ctx.locks?.unlock(ctx.pid, req.path);
13921
+ if (req.fd !== void 0 && ctx.locks?.shared?.() && ctx.flockOf) {
13922
+ return flock({ op: "flock", fd: req.fd, kind: "unlock" }, ctx);
13923
+ }
13779
13924
  return done2;
13780
13925
  case "lk-set":
13781
13926
  case "lk-get":
@@ -13805,6 +13950,23 @@ async function hostSyscall(req, ctx) {
13805
13950
  return done2;
13806
13951
  }
13807
13952
  }
13953
+ async function wholeLock(req, ctx) {
13954
+ const { locks, flockOf } = ctx;
13955
+ if (!locks) throw new KernelError("ENOSYS");
13956
+ const kind = req.exclusive ? "exclusive" : "shared";
13957
+ if (locks.shared?.() && flockOf) {
13958
+ if (locks.wholeFree?.(ctx.pid, req.path, req.exclusive) === false) {
13959
+ throw new KernelError("EAGAIN");
13960
+ }
13961
+ return flock({ op: "flock", fd: req.fd, kind }, ctx);
13962
+ }
13963
+ if (flockOf && locks.flockFree) {
13964
+ const { key, owner } = await flockOf(req.fd);
13965
+ if (!locks.flockFree(key, owner, kind)) throw new KernelError("EAGAIN");
13966
+ }
13967
+ if (!locks.lock(ctx.pid, req.path, req.exclusive, req.fd)) throw new KernelError("EAGAIN");
13968
+ return done2;
13969
+ }
13808
13970
  var FLOCK_KINDS = /* @__PURE__ */ new Set(["shared", "exclusive", "unlock"]);
13809
13971
  async function flock(req, ctx) {
13810
13972
  const { locks, flockOf } = ctx;
@@ -13991,8 +14153,8 @@ var KernelLoopback = class {
13991
14153
  );
13992
14154
  } catch (err) {
13993
14155
  socket.close();
13994
- const refused2 = err instanceof KernelError && err.code === "ECONNREFUSED";
13995
- throw refused2 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
14156
+ const refused3 = err instanceof KernelError && err.code === "ECONNREFUSED";
14157
+ throw refused3 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
13996
14158
  }
13997
14159
  signal.addEventListener("abort", () => socket.close(), { once: true });
13998
14160
  return socket;
@@ -14484,6 +14646,7 @@ function realmCa(owner, store) {
14484
14646
  }
14485
14647
 
14486
14648
  // src/kernel/net/tls-engine.ts
14649
+ var TLS_CLIENT_INSECURE_SKIP_VERIFY = 1;
14487
14650
  var SCRATCH = 64 * 1024;
14488
14651
  var EOF = -1;
14489
14652
  var TlsError = class extends Error {
@@ -14544,6 +14707,76 @@ var TlsEngine = class {
14544
14707
  const n = fn(this.scratch, SCRATCH);
14545
14708
  return n > 0 ? this.taken(n) : n;
14546
14709
  }
14710
+ get client() {
14711
+ return typeof this.m._tls_client_new === "function" ? this.m : void 0;
14712
+ }
14713
+ clientModule() {
14714
+ const m = this.client;
14715
+ if (!m) throw new TlsError(0, "tls client: the installed tls engine has no client sessions");
14716
+ return m;
14717
+ }
14718
+ store() {
14719
+ const m = this.clientModule();
14720
+ const ptr = m._tls_ca_new();
14721
+ if (!ptr) throw this.error(m._tls_last_error(), "trust store");
14722
+ return new TlsStore(this, m, ptr);
14723
+ }
14724
+ clientSession(store, servername, alpn, flags2) {
14725
+ const m = this.clientModule();
14726
+ const wire = alpnWire(alpn);
14727
+ const name2 = this.put(new TextEncoder().encode(servername));
14728
+ try {
14729
+ const at = store?.ptr ?? 0;
14730
+ const ptr = this.withBytes(wire, (p) => m._tls_client_new(at, name2, p, wire.length, flags2));
14731
+ if (!ptr) throw this.error(m._tls_last_error(), "tls client");
14732
+ return new TlsSession(this, m, ptr);
14733
+ } finally {
14734
+ this.m._free(name2);
14735
+ }
14736
+ }
14737
+ verifyInfo(flags2) {
14738
+ const m = this.clientModule();
14739
+ const n = m._tls_verify_info(flags2, this.scratch, SCRATCH);
14740
+ const end = this.m.HEAPU8.indexOf(0, this.scratch);
14741
+ const text = new TextDecoder().decode(this.m.HEAPU8.subarray(this.scratch, end));
14742
+ return n < 0 ? `${text}\u2026` : text;
14743
+ }
14744
+ };
14745
+ function alpnWire(names) {
14746
+ const parts2 = names.map((name2) => new TextEncoder().encode(name2));
14747
+ const out = new Uint8Array(parts2.reduce((n, p) => n + p.length + 1, 0));
14748
+ let at = 0;
14749
+ for (const part of parts2) {
14750
+ out[at++] = part.length;
14751
+ out.set(part, at);
14752
+ at += part.length;
14753
+ }
14754
+ return out;
14755
+ }
14756
+ var TlsStore = class {
14757
+ engine;
14758
+ m;
14759
+ ptr;
14760
+ constructor(engine, m, ptr) {
14761
+ this.engine = engine;
14762
+ this.m = m;
14763
+ this.ptr = ptr;
14764
+ }
14765
+ add(der) {
14766
+ const ret = this.engine.withBytes(der, (p) => this.m._tls_ca_add_der(this.ptr, p, der.length));
14767
+ if (ret !== 0) throw this.engine.error(ret, "trust store certificate");
14768
+ }
14769
+ addBundle(bytes) {
14770
+ const n = this.engine.withBytes(
14771
+ bytes,
14772
+ (p) => this.m._tls_ca_add_bundle(this.ptr, p, bytes.length)
14773
+ );
14774
+ if (n < 0) throw this.engine.error(n, "trust store bundle");
14775
+ return n;
14776
+ }
14777
+ release() {
14778
+ this.m._tls_ca_free(this.ptr);
14779
+ }
14547
14780
  };
14548
14781
  var TlsLeaf = class {
14549
14782
  engine;
@@ -14608,6 +14841,33 @@ var TlsSession = class {
14608
14841
  free() {
14609
14842
  this.m._tls_session_free(this.ptr);
14610
14843
  }
14844
+ get c() {
14845
+ return this.m;
14846
+ }
14847
+ handshake() {
14848
+ const ret = this.c._tls_handshake(this.ptr);
14849
+ if (ret < 0) throw this.engine.error(ret, "tls handshake");
14850
+ return ret === 1;
14851
+ }
14852
+ get verifyResult() {
14853
+ return this.c._tls_verify_result(this.ptr);
14854
+ }
14855
+ get version() {
14856
+ return this.c._tls_version(this.ptr);
14857
+ }
14858
+ get alpn() {
14859
+ const out = this.engine.intoScratch((p, max) => this.c._tls_alpn(this.ptr, p, max));
14860
+ return out instanceof Uint8Array ? new TextDecoder().decode(out) : void 0;
14861
+ }
14862
+ peerChain() {
14863
+ const chain2 = [];
14864
+ const count2 = this.c._tls_peer_count(this.ptr);
14865
+ for (let i = 0; i < count2; i++) {
14866
+ const der = this.engine.intoScratch((p, max) => this.c._tls_peer_der(this.ptr, i, p, max));
14867
+ if (der instanceof Uint8Array) chain2.push(der);
14868
+ }
14869
+ return chain2;
14870
+ }
14611
14871
  };
14612
14872
  var loading = /* @__PURE__ */ new WeakMap();
14613
14873
  function loadTlsEngine(load) {
@@ -14816,6 +15076,16 @@ function packageTlsEngine(fs, modules) {
14816
15076
  return factory.default({ wasmBinary, locateFile: (path) => path });
14817
15077
  };
14818
15078
  }
15079
+ function packageTlsRoots(fs, modules) {
15080
+ const file = `${modules.replace(/\/+$/, "")}/${TLS_ENGINE_PACKAGE}/dist/roots.der`;
15081
+ return async () => {
15082
+ try {
15083
+ return await fs.readFileBuffer(file);
15084
+ } catch {
15085
+ throw new Error(`TLS client sessions need ${TLS_ENGINE_PACKAGE}'s roots.der in ${modules}`);
15086
+ }
15087
+ };
15088
+ }
14819
15089
  function kernelCa(store) {
14820
15090
  return () => realmCa(CA_OWNER, store);
14821
15091
  }
@@ -14847,6 +15117,7 @@ async function writeCaFile(fs, ca, locks = globalThis.navigator?.locks) {
14847
15117
  function enableNetwork(net, options) {
14848
15118
  let proxy;
14849
15119
  const transport = options.transport ?? missingTransport();
15120
+ if (options.roots) net.tlsClient = { engine: options.engine, roots: options.roots };
14850
15121
  const start2 = () => {
14851
15122
  const tls2 = new TlsTerminator({
14852
15123
  ca: options.ca,
@@ -16516,6 +16787,285 @@ function encodeReceived(got) {
16516
16787
  return out;
16517
16788
  }
16518
16789
 
16790
+ // src/kernel/net/tls-client.ts
16791
+ var WRITE_CHUNK = 16 * 1024;
16792
+ var BADCERT = [
16793
+ [8, "UNABLE_TO_GET_ISSUER_CERT_LOCALLY"],
16794
+ [1, "CERT_HAS_EXPIRED"],
16795
+ [512, "CERT_NOT_YET_VALID"],
16796
+ [2, "CERT_REVOKED"],
16797
+ [4, "ERR_TLS_CERT_ALTNAME_INVALID"],
16798
+ [2048, "INVALID_PURPOSE"],
16799
+ [4096, "INVALID_PURPOSE"]
16800
+ ];
16801
+ function verifyCode(flags2) {
16802
+ if (flags2 === 0) return void 0;
16803
+ if (flags2 === -1) return "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
16804
+ return BADCERT.find(([bit]) => (flags2 & bit) !== 0)?.[1] ?? "UNABLE_TO_VERIFY_LEAF_SIGNATURE";
16805
+ }
16806
+ var Ciphertext = class {
16807
+ queue = [];
16808
+ ended = false;
16809
+ conn;
16810
+ session;
16811
+ constructor(conn, session) {
16812
+ this.conn = conn;
16813
+ this.session = session;
16814
+ }
16815
+ hand(bytes) {
16816
+ if (bytes.length > 0) this.queue.push(bytes);
16817
+ }
16818
+ async more() {
16819
+ if (this.queue.length === 0 && !this.ended) {
16820
+ const bytes = await this.conn.read();
16821
+ if (bytes) this.queue.push(bytes);
16822
+ else this.ended = true;
16823
+ }
16824
+ if (this.queue.length === 0) {
16825
+ this.session.feedEnd();
16826
+ return false;
16827
+ }
16828
+ while (this.queue.length > 0) {
16829
+ const head = this.queue[0];
16830
+ const n = this.session.feed(head);
16831
+ if (n < head.length) {
16832
+ this.queue[0] = head.subarray(n);
16833
+ break;
16834
+ }
16835
+ this.queue.shift();
16836
+ }
16837
+ return true;
16838
+ }
16839
+ };
16840
+ async function send(conn, session) {
16841
+ for (; ; ) {
16842
+ const out = session.take();
16843
+ if (out.length === 0) return;
16844
+ for (let at = 0; at < out.length; ) {
16845
+ const n = await conn.write(out.subarray(at));
16846
+ if (!(n > 0)) throw new KernelError("EPIPE");
16847
+ at += n;
16848
+ }
16849
+ }
16850
+ }
16851
+ function refused2(engine, session, err) {
16852
+ const flags2 = session.verifyResult;
16853
+ const code = verifyCode(flags2);
16854
+ if (code && flags2 !== -1)
16855
+ return new KernelError("EPROTO", `${code}: ${engine.verifyInfo(flags2).trim()}`);
16856
+ const text = err instanceof TlsError ? err.message : String(err);
16857
+ return new KernelError("EPROTO", `ERR_SSL_HANDSHAKE_FAILURE: ${text}`);
16858
+ }
16859
+ async function handshake(conn, o, session, inbox) {
16860
+ for (; ; ) {
16861
+ let done4;
16862
+ try {
16863
+ done4 = session.handshake();
16864
+ } catch (err) {
16865
+ await send(conn, session).catch(() => void 0);
16866
+ throw refused2(o.engine, session, err);
16867
+ }
16868
+ await send(conn, session);
16869
+ if (done4) return;
16870
+ if (!await inbox.more()) {
16871
+ throw new KernelError(
16872
+ "ECONNRESET",
16873
+ "the server closed the connection during the TLS handshake"
16874
+ );
16875
+ }
16876
+ }
16877
+ }
16878
+ function infoOf(o, session) {
16879
+ const flags2 = session.verifyResult;
16880
+ const code = verifyCode(flags2);
16881
+ return {
16882
+ protocol: session.version === 772 ? "TLSv1.3" : "TLSv1.2",
16883
+ alpnProtocol: session.alpn ?? false,
16884
+ authorized: code === void 0,
16885
+ ...code ? { authorizationError: code, authorizationText: o.engine.verifyInfo(flags2).trim() } : {},
16886
+ peerCertificates: session.peerChain()
16887
+ };
16888
+ }
16889
+ function plaintext(conn, session, inbox) {
16890
+ let freed = false;
16891
+ let writeClosed = false;
16892
+ const free = () => {
16893
+ if (freed) return;
16894
+ freed = true;
16895
+ session.free();
16896
+ };
16897
+ return {
16898
+ localAddr: conn.localAddr,
16899
+ remoteAddr: conn.remoteAddr,
16900
+ async read() {
16901
+ for (; ; ) {
16902
+ if (freed) return null;
16903
+ const got = session.read();
16904
+ await send(conn, session);
16905
+ if (got instanceof Uint8Array) return got;
16906
+ if (got === "eof") return null;
16907
+ await inbox.more();
16908
+ }
16909
+ },
16910
+ async write(bytes) {
16911
+ if (freed) throw new KernelError("EPIPE");
16912
+ for (; ; ) {
16913
+ const n = session.write(bytes.subarray(0, WRITE_CHUNK));
16914
+ await send(conn, session);
16915
+ if (n > 0) return n;
16916
+ }
16917
+ },
16918
+ closeWrite() {
16919
+ if (writeClosed || freed) return;
16920
+ writeClosed = true;
16921
+ session.close();
16922
+ void send(conn, session).catch(() => void 0).finally(() => conn.closeWrite());
16923
+ },
16924
+ close() {
16925
+ free();
16926
+ conn.close();
16927
+ }
16928
+ };
16929
+ }
16930
+ async function tlsClient(conn, o, taken = new Uint8Array(0)) {
16931
+ const flags2 = o.insecure ? TLS_CLIENT_INSECURE_SKIP_VERIFY : 0;
16932
+ const session = o.engine.clientSession(o.store, o.servername, o.alpn, flags2);
16933
+ const inbox = new Ciphertext(conn, session);
16934
+ inbox.hand(taken);
16935
+ try {
16936
+ await handshake(conn, o, session, inbox);
16937
+ return { conn: plaintext(conn, session, inbox), info: infoOf(o, session) };
16938
+ } catch (err) {
16939
+ session.free();
16940
+ throw err;
16941
+ }
16942
+ }
16943
+
16944
+ // src/kernel/net/tls-uplink.ts
16945
+ var isIP = (text) => ipv4Bytes(text) !== void 0 || text.includes(":") && ipv6Groups(text) !== void 0;
16946
+ var LABEL2 = /^(?!-)[A-Za-z0-9-]{1,63}(?<!-)$/;
16947
+ function serverName(name2) {
16948
+ if (isIP(name2.replace(/^\[|\]$/g, ""))) return name2.replace(/^\[|\]$/g, "");
16949
+ const bare = name2.endsWith(".") ? name2.slice(0, -1) : name2;
16950
+ if (bare.length === 0 || bare.length > 253 || !bare.split(".").every((l) => LABEL2.test(l))) {
16951
+ throw new KernelError(
16952
+ "EINVAL",
16953
+ `ERR_INVALID_ARG_VALUE: not a host name: ${JSON.stringify(name2)}`
16954
+ );
16955
+ }
16956
+ return name2;
16957
+ }
16958
+ var defaults = /* @__PURE__ */ new WeakMap();
16959
+ function defaultStore(engine, roots) {
16960
+ let store = defaults.get(engine);
16961
+ if (!store) {
16962
+ const made2 = roots().then((bundle) => {
16963
+ const s = engine.store();
16964
+ s.addBundle(bundle);
16965
+ return s;
16966
+ });
16967
+ store = made2;
16968
+ defaults.set(engine, made2);
16969
+ made2.catch(() => {
16970
+ if (defaults.get(engine) === made2) defaults.delete(engine);
16971
+ });
16972
+ }
16973
+ return store;
16974
+ }
16975
+ function base64Der(text) {
16976
+ const bin = atob(text);
16977
+ const out = new Uint8Array(bin.length);
16978
+ for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
16979
+ return out;
16980
+ }
16981
+ function encode(bytes) {
16982
+ let bin = "";
16983
+ for (const b of bytes) bin += String.fromCharCode(b);
16984
+ return btoa(bin);
16985
+ }
16986
+ function sessionOf(info, servername) {
16987
+ return {
16988
+ path: "kernel",
16989
+ substitutes: false,
16990
+ protocol: info.protocol,
16991
+ alpnProtocol: info.alpnProtocol,
16992
+ authorized: info.authorized,
16993
+ ...info.authorizationError ? {
16994
+ authorizationError: info.authorizationError,
16995
+ authorizationText: info.authorizationText
16996
+ } : {},
16997
+ servername,
16998
+ peerCertificates: info.peerCertificates.map(encode)
16999
+ };
17000
+ }
17001
+ async function setUp(support, req) {
17002
+ const engine = await support.engine();
17003
+ if (!engine.client)
17004
+ throw new KernelError("ENOTSUP", "the installed tls engine has no client sessions");
17005
+ const custom = Array.isArray(req.ca) ? req.ca : void 0;
17006
+ if (!custom) return { engine, store: await defaultStore(engine, support.roots), own: void 0 };
17007
+ if (custom.length === 0)
17008
+ throw new KernelError("EINVAL", "ERR_INVALID_ARG_VALUE: ca has no certificate");
17009
+ const own = engine.store();
17010
+ try {
17011
+ for (const der of custom) own.add(base64Der(der));
17012
+ } catch (err) {
17013
+ own.release();
17014
+ throw new KernelError("EINVAL", `ERR_INVALID_ARG_VALUE: ca: ${err.message}`);
17015
+ }
17016
+ return { engine, store: own, own };
17017
+ }
17018
+ function secure(support, req, servername) {
17019
+ return async (raw) => {
17020
+ const { engine, store, own } = await setUp(support, req);
17021
+ try {
17022
+ return await tlsClient(raw, {
17023
+ engine,
17024
+ store,
17025
+ servername,
17026
+ alpn: req.alpn ?? [],
17027
+ insecure: req.insecure === true
17028
+ });
17029
+ } finally {
17030
+ own?.release();
17031
+ }
17032
+ };
17033
+ }
17034
+ function supportOf(net) {
17035
+ const support = net.tlsClient;
17036
+ if (!support) throw new KernelError("ENOTSUP", "no tls engine for client sessions");
17037
+ return support;
17038
+ }
17039
+ async function uplinkAddress(proc, host) {
17040
+ const bare = host.replace(/^\[|\]$/g, "");
17041
+ if (isIP(bare)) return bare;
17042
+ const [first] = await proc.resolve(host, 0, () => proc.blocking());
17043
+ if (!first) throw new KernelError("ENOENT", `ENOTFOUND: ${host}`);
17044
+ return first;
17045
+ }
17046
+ async function connectSecure(proc, socket, host, port, req) {
17047
+ const servername = serverName(req.servername || host);
17048
+ if (isLoopbackHost(servername) || isLoopbackHost(host)) throw new KernelError("ENOTSUP");
17049
+ const address = await uplinkAddress(proc, host);
17050
+ const route = proc.net.uplinkFor(address);
17051
+ if (!route)
17052
+ throw new KernelError("ENOTSUP", "TLS in the kernel needs a destination the uplink routes");
17053
+ const support = supportOf(proc.net);
17054
+ let info;
17055
+ const make = secure(support, req, servername);
17056
+ await socket.connectSecure({ family: "inet", host: address, port }, route, async (conn) => {
17057
+ info = await conn.upgrade(make);
17058
+ });
17059
+ return sessionOf(info, servername);
17060
+ }
17061
+ async function upgradeSecure(proc, socket, req) {
17062
+ const peer = socket.peer;
17063
+ const host = req.servername || (peer?.family === "inet" ? peer.host : "");
17064
+ const servername = serverName(host);
17065
+ const info = await socket.upgradeSecure(secure(supportOf(proc.net), req, servername));
17066
+ return sessionOf(info, servername);
17067
+ }
17068
+
16519
17069
  // src/kernel/unix-dgram.ts
16520
17070
  var SOL_SOCKET3 = 1;
16521
17071
  var SO_TYPE3 = 3;
@@ -16677,7 +17227,8 @@ var SOCKET_OPS = [
16677
17227
  "sock-resolve",
16678
17228
  "sock-sendto",
16679
17229
  "sock-recvfrom",
16680
- "sock-tls"
17230
+ "sock-tls",
17231
+ "sock-tls-upgrade"
16681
17232
  ];
16682
17233
  function socketAt(fds, fd) {
16683
17234
  const file = anySocketAt(fds, fd);
@@ -16750,7 +17301,9 @@ async function socketSyscall(req, proc) {
16750
17301
  return ok3(addresses);
16751
17302
  }
16752
17303
  case "sock-tls":
16753
- return ok3(tlsOverTransport(req, proc));
17304
+ return ok3(await secureConnect(req, proc));
17305
+ case "sock-tls-upgrade":
17306
+ return ok3(await upgradeSecure(proc, socketAt(fds, req.fd), req));
16754
17307
  default:
16755
17308
  return datagram(req, proc);
16756
17309
  }
@@ -16872,6 +17425,36 @@ var NOT_HTTP_PORTS = /* @__PURE__ */ new Set([
16872
17425
  8883
16873
17426
  ]);
16874
17427
  var HOST_NAME = /^[A-Za-z0-9.-]+$|^\[?[0-9A-Fa-f:.]+\]?$/;
17428
+ function wantsKernel(req) {
17429
+ if (req.path === "kernel") return true;
17430
+ if (req.path === "transport") return false;
17431
+ return Array.isArray(req.ca) || req.alpn !== void 0 && req.alpn.length > 0 && !req.alpn.includes("http/1.1") || NOT_HTTP_PORTS.has(req.port);
17432
+ }
17433
+ async function secureConnect(req, proc) {
17434
+ if (!Number.isInteger(req.port) || req.port < 1 || req.port > 65535)
17435
+ throw new KernelError("EINVAL");
17436
+ const kernelPath = wantsKernel(req) && await uplinked(proc, req.host);
17437
+ if (!kernelPath) {
17438
+ if (req.path === "kernel" || Array.isArray(req.ca)) throw new KernelError("ENOTSUP");
17439
+ return { ...tlsOverTransport(req, proc), path: "transport", substitutes: true };
17440
+ }
17441
+ const socket = proc.net.socket("inet");
17442
+ const fd = proc.fds.install(new OpenFile(socket), 3);
17443
+ try {
17444
+ return { fd, ...await connectSecure(proc, socket, req.host, req.port, req) };
17445
+ } catch (e) {
17446
+ await Promise.resolve(proc.fds.close(fd));
17447
+ throw e;
17448
+ }
17449
+ }
17450
+ async function uplinked(proc, host) {
17451
+ if (!proc.net.tlsClient || isLoopbackHost(host)) return false;
17452
+ try {
17453
+ return proc.net.uplinkFor(await uplinkAddress(proc, host)) !== void 0;
17454
+ } catch {
17455
+ return false;
17456
+ }
17457
+ }
16875
17458
  function tlsOverTransport(req, proc) {
16876
17459
  if (req.ca) throw new KernelError("ENOTSUP");
16877
17460
  if (req.alpn && req.alpn.length > 0 && !req.alpn.includes("http/1.1")) {
@@ -19872,10 +20455,10 @@ var JobTable = class {
19872
20455
  signalForeground(tty, fallback, sig) {
19873
20456
  this.killGroup(this.tcgetpgrp(tty, fallback), sig);
19874
20457
  }
19875
- fromKeyboard(send) {
20458
+ fromKeyboard(send2) {
19876
20459
  this.keyboard = true;
19877
20460
  try {
19878
- send();
20461
+ send2();
19879
20462
  } finally {
19880
20463
  this.keyboard = false;
19881
20464
  }
@@ -20186,6 +20769,12 @@ var LockService = class {
20186
20769
  lock(pid, path, exclusive, fd) {
20187
20770
  return this.table.lock(pid, path, exclusive, fd);
20188
20771
  }
20772
+ wholeFree(pid, path, exclusive) {
20773
+ return this.table.wholeFree(pid, path, exclusive);
20774
+ }
20775
+ flockFree(key, owner, kind) {
20776
+ return this.table.flockFree(key, owner, kind);
20777
+ }
20189
20778
  unlock(pid, path) {
20190
20779
  this.table.unlock(pid, path);
20191
20780
  }
@@ -20861,7 +21450,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
20861
21450
  await changed(signal);
20862
21451
  }
20863
21452
  };
20864
- const send = async (out, signal) => {
21453
+ const send2 = async (out, signal) => {
20865
21454
  const write = file.write;
20866
21455
  for (let at = 0; at < out.length; ) {
20867
21456
  try {
@@ -20896,7 +21485,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
20896
21485
  raise();
20897
21486
  if (timer !== void 0) clearTimeout(timer);
20898
21487
  timer = void 0;
20899
- await send(stream2.push(taken), signal);
21488
+ await send2(stream2.push(taken), signal);
20900
21489
  } finally {
20901
21490
  busy = false;
20902
21491
  if (quiet3()) wake();
@@ -21242,19 +21831,19 @@ var SettlingChildren = class {
21242
21831
  this.held = this.held.filter((h) => this.blocking(h.pgid));
21243
21832
  for (const h of ready2) h.send();
21244
21833
  }
21245
- deliver(sig, pgid, send, foreground) {
21834
+ deliver(sig, pgid, send2, foreground) {
21246
21835
  if (!KEY_SIGNALS.has(sig)) {
21247
- send();
21836
+ send2();
21248
21837
  } else if (this.blocking(pgid)) {
21249
- this.held.push({ pgid, send });
21838
+ this.held.push({ pgid, send: send2 });
21250
21839
  } else if (foreground) {
21251
- send();
21840
+ send2();
21252
21841
  const moved2 = () => {
21253
- if (foreground() !== pgid) send();
21842
+ if (foreground() !== pgid) send2();
21254
21843
  };
21255
21844
  this.parked.push({ pgid, send: moved2 });
21256
21845
  } else {
21257
- send();
21846
+ send2();
21258
21847
  }
21259
21848
  }
21260
21849
  blocking(pgid) {
@@ -21399,9 +21988,9 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
21399
21988
  let open = false;
21400
21989
  const reply = (message3, transfer = []) => port.postMessage(message3, transfer);
21401
21990
  async function hello(message3) {
21402
- const refused2 = driverVersionError(message3.protocol);
21403
- if (refused2) {
21404
- reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused2, errno: "EPROTO" } });
21991
+ const refused3 = driverVersionError(message3.protocol);
21992
+ if (refused3) {
21993
+ reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused3, errno: "EPROTO" } });
21405
21994
  return;
21406
21995
  }
21407
21996
  try {
@@ -22386,7 +22975,7 @@ function serveHostfsPort(port, transport) {
22386
22975
  });
22387
22976
  handles.clear();
22388
22977
  };
22389
- const send = (reply, transfer = []) => port.postMessage(reply, transfer);
22978
+ const send2 = (reply, transfer = []) => port.postMessage(reply, transfer);
22390
22979
  const pending = /* @__PURE__ */ new Set();
22391
22980
  const track = (work) => {
22392
22981
  pending.add(work);
@@ -22406,7 +22995,7 @@ function serveHostfsPort(port, transport) {
22406
22995
  data
22407
22996
  }) => {
22408
22997
  const { id: id2, op } = data;
22409
- if (op === "ping") return send({ id: id2, pong: true });
22998
+ if (op === "ping") return send2({ id: id2, pong: true });
22410
22999
  if (op === "bye") return stop();
22411
23000
  if (op === "cleanup")
22412
23001
  return void Promise.allSettled([...pending]).then(() => answer(data.name, data.body)).catch(() => {
@@ -22418,12 +23007,12 @@ function serveHostfsPort(port, transport) {
22418
23007
  try {
22419
23008
  await transport.watch(
22420
23009
  stop2.signal,
22421
- (event) => send({ id: id2, event }),
22422
- () => send({ id: id2, open: true })
23010
+ (event) => send2({ id: id2, event }),
23011
+ () => send2({ id: id2, open: true })
22423
23012
  );
22424
- send({ id: id2, end: true });
23013
+ send2({ id: id2, end: true });
22425
23014
  } catch (err) {
22426
- send({ id: id2, error: errorOf(err) });
23015
+ send2({ id: id2, error: errorOf(err) });
22427
23016
  } finally {
22428
23017
  watches.delete(id2);
22429
23018
  }
@@ -22440,18 +23029,18 @@ function serveHostfsPort(port, transport) {
22440
23029
  )
22441
23030
  );
22442
23031
  const bytes = read.slice();
22443
- return send({ id: id2, bytes }, [bytes.buffer]);
23032
+ return send2({ id: id2, bytes }, [bytes.buffer]);
22444
23033
  }
22445
23034
  if (op === "write") {
22446
23035
  await track(
22447
23036
  transport.write(data.fh, data.offset, data.bytes)
22448
23037
  );
22449
- return send({ id: id2 });
23038
+ return send2({ id: id2 });
22450
23039
  }
22451
23040
  if (op !== "call") throw fsError2("EINVAL", `unknown hostfs port op ${op}`);
22452
- send({ id: id2, result: await answer(data.name, data.body) });
23041
+ send2({ id: id2, result: await answer(data.name, data.body) });
22453
23042
  } catch (err) {
22454
- send({ id: id2, error: errorOf(err) });
23043
+ send2({ id: id2, error: errorOf(err) });
22455
23044
  }
22456
23045
  };
22457
23046
  const stop = () => {
@@ -23538,9 +24127,9 @@ function interpreter(head) {
23538
24127
  if (words2[0] === "-S") words2.shift();
23539
24128
  return baseName2(words2[0] ?? "");
23540
24129
  }
23541
- function expandDefaults(defaults, env) {
24130
+ function expandDefaults(defaults2, env) {
23542
24131
  const out = {};
23543
- for (const [key, value2] of Object.entries(defaults ?? {})) {
24132
+ for (const [key, value2] of Object.entries(defaults2 ?? {})) {
23544
24133
  let missing4 = false;
23545
24134
  const expanded = value2.replace(ENV_REFERENCE, (_, name2) => {
23546
24135
  const set3 = Object.hasOwn(env, name2) ? env[name2] : void 0;
@@ -23790,6 +24379,7 @@ var Launcher = class {
23790
24379
  enableNetwork(this.net, {
23791
24380
  transport: this.transport,
23792
24381
  engine: kernelTlsEngine(packageTlsEngine(this.verifiedFs(options.fs), this.modulesDir)),
24382
+ roots: packageTlsRoots(this.verifiedFs(options.fs), this.modulesDir),
23793
24383
  ca: this.ca
23794
24384
  });
23795
24385
  enableCdp(this.net, this.cdp);
@@ -24202,13 +24792,13 @@ var Launcher = class {
24202
24792
  if (planned?.target.copy) await need(g, "exec", planned.target.copy, R_OK | X_OK);
24203
24793
  }
24204
24794
  async checkedPlan(req, { ppid, cred, scope }, fds) {
24205
- const refused2 = async (err) => {
24795
+ const refused3 = async (err) => {
24206
24796
  await fds.closeAll();
24207
24797
  throw err.code === "EACCES" ? new SpawnError("EACCES") : err;
24208
24798
  };
24209
- const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused2);
24799
+ const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused3);
24210
24800
  const planned = await this.plan(file, req.argv, req.cwd, scope, req.argv0);
24211
- await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused2);
24801
+ await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused3);
24212
24802
  if (planned) return planned;
24213
24803
  await fds.closeAll();
24214
24804
  throw new SpawnError(await this.unrunnable(file, req.cwd, scope));
@@ -25043,10 +25633,10 @@ var Launcher = class {
25043
25633
  return childHandle(await this.admitted(parent.program.abi !== "js", given, fresh2));
25044
25634
  };
25045
25635
  }
25046
- keySignal(tty, fallback, sig, send) {
25636
+ keySignal(tty, fallback, sig, send2) {
25047
25637
  const pgid = this.jobs.tcgetpgrp(tty, fallback);
25048
25638
  const foreground = () => this.jobs.tcgetpgrp(tty, fallback);
25049
- const keyed = () => this.jobs.fromKeyboard(send);
25639
+ const keyed = () => this.jobs.fromKeyboard(send2);
25050
25640
  this.settling.deliver(sig, pgid, keyed, tty.reading ? void 0 : foreground);
25051
25641
  }
25052
25642
  async resolvePrefixes() {
@@ -25691,7 +26281,7 @@ function cronLocks() {
25691
26281
  import { AsyncLocalStorage } from "node:async_hooks";
25692
26282
  import { subscribe } from "node:diagnostics_channel";
25693
26283
  import { lookup as lookup2 } from "node:dns/promises";
25694
- import { isIP } from "node:net";
26284
+ import { isIP as isIP2 } from "node:net";
25695
26285
  var DEVTOOLS_PORTS = [9222, 9223, 9224, 9225, 9226, 9227, 9228, 9229];
25696
26286
  var METADATA_V6 = [64768, 3778, 0, 0, 0, 0, 0, 596].join(":");
25697
26287
  var resolveHost = async (host) => (await lookup2(host, { all: true, verbatim: true })).map((a) => a.address);
@@ -25703,7 +26293,7 @@ function ipv4Place(address) {
25703
26293
  }
25704
26294
  function placeOf(address) {
25705
26295
  const plain2 = address.replace(/^\[(.*)\]$/, "$1").toLowerCase();
25706
- const kind = isIP(plain2);
26296
+ const kind = isIP2(plain2);
25707
26297
  if (kind === 4) return ipv4Place(plain2);
25708
26298
  if (kind !== 6) return void 0;
25709
26299
  const words2 = hextets2(plain2);
@@ -25756,7 +26346,7 @@ function connectRefusal(address, port, place) {
25756
26346
  }
25757
26347
  async function addressesOf(host, resolve2) {
25758
26348
  const plain2 = host.replace(/^\[(.*)\]$/, "$1");
25759
- if (isIP(plain2)) return [plain2];
26349
+ if (isIP2(plain2)) return [plain2];
25760
26350
  if (loopbackName2(plain2)) return ["127.0.0.1"];
25761
26351
  return resolve2(plain2).catch(() => []);
25762
26352
  }
@@ -26091,7 +26681,7 @@ function isMemoryRoot(handle) {
26091
26681
 
26092
26682
  // src/node/ws-diagnose.ts
26093
26683
  import { lookup as lookup3 } from "node:dns/promises";
26094
- import { isIP as isIP2, connect as tcp } from "node:net";
26684
+ import { isIP as isIP3, connect as tcp } from "node:net";
26095
26685
  import { connect as tls } from "node:tls";
26096
26686
  var PROBE_MS = 3e3;
26097
26687
  var PASSED = /* @__PURE__ */ new Set(["ECONNREFUSED", "EHOSTUNREACH", "ENETUNREACH", "ETIMEDOUT", "ECONNRESET"]);
@@ -26111,9 +26701,9 @@ function abortable(work, signal) {
26111
26701
  });
26112
26702
  return Promise.race([work, aborted2]).finally(() => signal.removeEventListener("abort", stop));
26113
26703
  }
26114
- function probe(secure, host, port, ms, signal) {
26704
+ function probe(secure2, host, port, ms, signal) {
26115
26705
  return new Promise((resolve2) => {
26116
- const socket = secure ? tls({ host, port, ...isIP2(host) ? {} : { servername: host } }) : tcp({ host, port });
26706
+ const socket = secure2 ? tls({ host, port, ...isIP3(host) ? {} : { servername: host } }) : tcp({ host, port });
26117
26707
  const stop = () => done4("ABORTED");
26118
26708
  const done4 = (code) => {
26119
26709
  clearTimeout(timer);
@@ -26123,7 +26713,7 @@ function probe(secure, host, port, ms, signal) {
26123
26713
  };
26124
26714
  const timer = setTimeout(() => done4("ETIMEDOUT"), ms);
26125
26715
  signal?.addEventListener("abort", stop, { once: true });
26126
- socket.once(secure ? "secureConnect" : "connect", () => done4("EPROTO"));
26716
+ socket.once(secure2 ? "secureConnect" : "connect", () => done4("EPROTO"));
26127
26717
  socket.once("error", (e) => {
26128
26718
  const code = codeOf7(e) ?? "";
26129
26719
  done4(PASSED.has(code) ? code : "EPROTO");
@@ -26133,8 +26723,8 @@ function probe(secure, host, port, ms, signal) {
26133
26723
  async function diagnose(url, ms = PROBE_MS, signal) {
26134
26724
  const at = new URL(url);
26135
26725
  const host = at.hostname.replace(/^\[(.*)\]$/, "$1");
26136
- const secure = at.protocol === "wss:";
26137
- const port = Number(at.port) || (secure ? 443 : 80);
26726
+ const secure2 = at.protocol === "wss:";
26727
+ const port = Number(at.port) || (secure2 ? 443 : 80);
26138
26728
  signal?.throwIfAborted();
26139
26729
  try {
26140
26730
  await abortable(lookup3(host), signal);
@@ -26142,7 +26732,7 @@ async function diagnose(url, ms = PROBE_MS, signal) {
26142
26732
  if (signal?.aborted) throw signal.reason;
26143
26733
  return NO_NAME.has(codeOf7(e) ?? "") ? "EAI_NONAME" : void 0;
26144
26734
  }
26145
- const code = await probe(secure, host, port, ms, signal);
26735
+ const code = await probe(secure2, host, port, ms, signal);
26146
26736
  signal?.throwIfAborted();
26147
26737
  return code;
26148
26738
  }
@@ -26912,7 +27502,7 @@ async function terminalOn(channel, argv, opts) {
26912
27502
  );
26913
27503
  done4.catch(started.reject);
26914
27504
  const pid = await started.promise;
26915
- const send = (action) => void channel.call({ op: "terminal", terminal: id2, ...action }).catch(() => void 0);
27505
+ const send2 = (action) => void channel.call({ op: "terminal", terminal: id2, ...action }).catch(() => void 0);
26916
27506
  return {
26917
27507
  pid,
26918
27508
  exited: done4,
@@ -26924,10 +27514,10 @@ async function terminalOn(channel, argv, opts) {
26924
27514
  listener = next3;
26925
27515
  if (next3) for (const bytes of backlog.splice(0)) next3(bytes);
26926
27516
  },
26927
- write: (data) => send({ action: "write", bytes: bytesOf2(data) }),
26928
- resize: (cols, rows) => send({ action: "resize", cols, rows }),
26929
- signal: (name2) => send({ action: "signal", signal: name2 }),
26930
- close: () => send({ action: "close" })
27517
+ write: (data) => send2({ action: "write", bytes: bytesOf2(data) }),
27518
+ resize: (cols, rows) => send2({ action: "resize", cols, rows }),
27519
+ signal: (name2) => send2({ action: "signal", signal: name2 }),
27520
+ close: () => send2({ action: "close" })
26931
27521
  };
26932
27522
  }
26933
27523
  function fsOn(channel) {
@@ -27000,9 +27590,9 @@ async function greet(channel, lock, timeoutMs) {
27000
27590
  } finally {
27001
27591
  clearTimeout(timer);
27002
27592
  }
27003
- const refused2 = hello.error ?? versionError(hello.protocol);
27004
- if (refused2) {
27005
- const error = new Error(refused2);
27593
+ const refused3 = hello.error ?? versionError(hello.protocol);
27594
+ if (refused3) {
27595
+ const error = new Error(refused3);
27006
27596
  channel.end(error);
27007
27597
  throw error;
27008
27598
  }