@ai-ecoverse/slicc-kernel 1.59.0 → 1.59.1

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
@@ -1323,6 +1323,11 @@ function blockedReason(url, e) {
1323
1323
  }
1324
1324
  return `${url}: ${e instanceof Error ? e.message : String(e)}`;
1325
1325
  }
1326
+ function unopened(url, code) {
1327
+ return Object.assign(new Error(`${url}: the WebSocket closed (${code}) before it opened`), {
1328
+ status: 502
1329
+ });
1330
+ }
1326
1331
  function openWebSocket(Socket, request, withHeaders) {
1327
1332
  const { url, protocols, signal } = request;
1328
1333
  signal.throwIfAborted();
@@ -1336,13 +1341,22 @@ function openWebSocket(Socket, request, withHeaders) {
1336
1341
  const queue = new MessageQueue(() => socket.close(1e3, "too many waiting messages"));
1337
1342
  return new Promise((resolve, reject) => {
1338
1343
  let open = false;
1344
+ let settled = false;
1345
+ const fail3 = (error) => {
1346
+ if (settled) return;
1347
+ settled = true;
1348
+ signal.removeEventListener("abort", abort);
1349
+ reject(error);
1350
+ };
1339
1351
  const abort = () => {
1340
1352
  socket.close(1e3, "aborted");
1341
- reject(signal.reason);
1353
+ fail3(signal.reason);
1342
1354
  };
1343
1355
  signal.addEventListener("abort", abort, { once: true });
1344
1356
  socket.addEventListener("open", () => {
1357
+ if (settled) return;
1345
1358
  open = true;
1359
+ settled = true;
1346
1360
  signal.removeEventListener("abort", abort);
1347
1361
  resolve({
1348
1362
  protocol: socket.protocol,
@@ -1358,15 +1372,19 @@ function openWebSocket(Socket, request, withHeaders) {
1358
1372
  socket.addEventListener("message", (event) => {
1359
1373
  queue.push(typeof event.data === "string" ? event.data : new Uint8Array(event.data));
1360
1374
  });
1375
+ socket.addEventListener("error", () => {
1376
+ if (open || settled) return;
1377
+ try {
1378
+ socket.close();
1379
+ } catch {
1380
+ }
1381
+ queue.end({ code: 1006, reason: "" });
1382
+ fail3(unopened(url, 1006));
1383
+ });
1361
1384
  socket.addEventListener("close", (event) => {
1362
1385
  queue.end({ code: event.code, reason: event.reason });
1363
1386
  if (open) return;
1364
- signal.removeEventListener("abort", abort);
1365
- reject(
1366
- Object.assign(new Error(`${url}: the WebSocket closed (${event.code}) before it opened`), {
1367
- status: 502
1368
- })
1369
- );
1387
+ fail3(unopened(url, event.code));
1370
1388
  });
1371
1389
  });
1372
1390
  }
@@ -8399,7 +8417,7 @@ function enableNetwork(net, options) {
8399
8417
  let proxy;
8400
8418
  const transport = options.transport ?? missingTransport();
8401
8419
  net.activate({ family: "inet", host: "127.0.0.1", port: REALM_PROXY_PORT }, () => {
8402
- const tls = new TlsTerminator({
8420
+ const tls2 = new TlsTerminator({
8403
8421
  ca: options.ca,
8404
8422
  engine: options.engine,
8405
8423
  ...options.now ? { now: options.now } : {}
@@ -8407,7 +8425,7 @@ function enableNetwork(net, options) {
8407
8425
  const started = new RealmProxy({
8408
8426
  net,
8409
8427
  transport,
8410
- tunnel: tls.handler,
8428
+ tunnel: tls2.handler,
8411
8429
  tunnelReady: async () => {
8412
8430
  await options.engine();
8413
8431
  }
@@ -8415,7 +8433,7 @@ function enableNetwork(net, options) {
8415
8433
  proxy = started;
8416
8434
  void started.closed.then(async () => {
8417
8435
  if (proxy === started) proxy = void 0;
8418
- await tls.close();
8436
+ await tls2.close();
8419
8437
  });
8420
8438
  });
8421
8439
  return () => proxy;
@@ -8434,6 +8452,11 @@ var TOKEN3 = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
8434
8452
  function message(e) {
8435
8453
  return e instanceof Error ? e.message : String(e);
8436
8454
  }
8455
+ var ERRNO = /^E[A-Z]+$|^EAI_[A-Z]+$/;
8456
+ function errnoOf(e) {
8457
+ const code = e?.code;
8458
+ return typeof code === "string" && ERRNO.test(code) ? code : "ECONNREFUSED";
8459
+ }
8437
8460
  function fail(errno, text) {
8438
8461
  return { ok: false, errno, message: text };
8439
8462
  }
@@ -8477,13 +8500,13 @@ var WsHandles = class {
8477
8500
  let socket;
8478
8501
  try {
8479
8502
  socket = await transport.websocket({
8480
- url: req.url,
8503
+ url: toHostLoopback(req.url),
8481
8504
  protocols: req.protocols,
8482
8505
  headers: req.headers,
8483
8506
  signal: entry.abort.signal
8484
8507
  });
8485
8508
  } catch (e) {
8486
- return fail("ECONNREFUSED", message(e));
8509
+ return fail(errnoOf(e), message(e));
8487
8510
  }
8488
8511
  if (!this.open.has(handle)) {
8489
8512
  socket.close(1001, "the program went away");
@@ -8838,14 +8861,14 @@ var Resolver = class {
8838
8861
  if (hit && hit.expires > this.now()) return hit.addresses;
8839
8862
  const signal = blocking?.();
8840
8863
  if (signal?.aborted) throw new KernelError("EINTR");
8841
- let lookup = this.pending.get(id2);
8842
- if (!lookup) {
8864
+ let lookup2 = this.pending.get(id2);
8865
+ if (!lookup2) {
8843
8866
  const abort = new AbortController();
8844
- lookup = { work: this.lookup(key, asked, id2, abort.signal), abort, waiters: 0 };
8845
- this.pending.set(id2, lookup);
8846
- void lookup.work.then(() => this.pending.delete(id2));
8867
+ lookup2 = { work: this.lookup(key, asked, id2, abort.signal), abort, waiters: 0 };
8868
+ this.pending.set(id2, lookup2);
8869
+ void lookup2.work.then(() => this.pending.delete(id2));
8847
8870
  }
8848
- return waitFor(lookup, signal);
8871
+ return waitFor(lookup2, signal);
8849
8872
  }
8850
8873
  async lookup(name2, family, id2, abandoned) {
8851
8874
  const uplink = this.uplink;
@@ -8886,17 +8909,17 @@ var Resolver = class {
8886
8909
  }
8887
8910
  }
8888
8911
  };
8889
- function waitFor(lookup, signal) {
8890
- lookup.waiters++;
8912
+ function waitFor(lookup2, signal) {
8913
+ lookup2.waiters++;
8891
8914
  return new Promise((resolve, reject) => {
8892
8915
  const abort = () => {
8893
- if (--lookup.waiters === 0) lookup.abort.abort(new KernelError("EINTR"));
8916
+ if (--lookup2.waiters === 0) lookup2.abort.abort(new KernelError("EINTR"));
8894
8917
  reject(new KernelError("EINTR"));
8895
8918
  };
8896
8919
  signal?.addEventListener("abort", abort, { once: true });
8897
- void lookup.work.then((value) => {
8920
+ void lookup2.work.then((value) => {
8898
8921
  if (signal?.aborted) return;
8899
- lookup.waiters--;
8922
+ lookup2.waiters--;
8900
8923
  signal?.removeEventListener("abort", abort);
8901
8924
  resolve(value);
8902
8925
  });
@@ -14490,6 +14513,62 @@ function isMemoryRoot(handle) {
14490
14513
  return handle instanceof MemoryDirectory;
14491
14514
  }
14492
14515
 
14516
+ // src/node/ws-diagnose.ts
14517
+ import { lookup } from "node:dns/promises";
14518
+ import { isIP, connect as tcp } from "node:net";
14519
+ import { connect as tls } from "node:tls";
14520
+ var PROBE_MS = 3e3;
14521
+ var PASSED = /* @__PURE__ */ new Set(["ECONNREFUSED", "EHOSTUNREACH", "ENETUNREACH", "ETIMEDOUT", "ECONNRESET"]);
14522
+ var NO_NAME = /* @__PURE__ */ new Set(["ENOTFOUND", "EAI_AGAIN", "EAI_NONAME", "EAI_FAIL", "ENODATA"]);
14523
+ function codeOf5(e) {
14524
+ const code = e?.code;
14525
+ return typeof code === "string" ? code : void 0;
14526
+ }
14527
+ function probe(secure, host, port, ms) {
14528
+ return new Promise((resolve) => {
14529
+ const socket = secure ? tls({ host, port, ...isIP(host) ? {} : { servername: host } }) : tcp({ host, port });
14530
+ const done4 = (code) => {
14531
+ clearTimeout(timer);
14532
+ socket.destroy();
14533
+ resolve(code);
14534
+ };
14535
+ const timer = setTimeout(() => done4("ETIMEDOUT"), ms);
14536
+ socket.once(secure ? "secureConnect" : "connect", () => done4("EPROTO"));
14537
+ socket.once("error", (e) => {
14538
+ const code = codeOf5(e) ?? "";
14539
+ done4(PASSED.has(code) ? code : "EPROTO");
14540
+ });
14541
+ });
14542
+ }
14543
+ async function diagnose(url, ms = PROBE_MS) {
14544
+ const at = new URL(url);
14545
+ const host = at.hostname.replace(/^\[(.*)\]$/, "$1");
14546
+ const secure = at.protocol === "wss:";
14547
+ const port = Number(at.port) || (secure ? 443 : 80);
14548
+ try {
14549
+ await lookup(host);
14550
+ } catch (e) {
14551
+ return NO_NAME.has(codeOf5(e) ?? "") ? "EAI_NONAME" : void 0;
14552
+ }
14553
+ return probe(secure, host, port, ms);
14554
+ }
14555
+ function diagnosing(transport, check = diagnose) {
14556
+ const open = transport.websocket;
14557
+ if (!open) return transport;
14558
+ return {
14559
+ ...transport,
14560
+ websocket: async (request) => {
14561
+ try {
14562
+ return await open(request);
14563
+ } catch (e) {
14564
+ if (request.signal.aborted || !(e instanceof Error) || codeOf5(e)) throw e;
14565
+ const code = await check(request.url).catch(() => void 0);
14566
+ throw code ? Object.assign(e, { code }) : e;
14567
+ }
14568
+ }
14569
+ };
14570
+ }
14571
+
14493
14572
  // src/kernel/net/remote-transport.ts
14494
14573
  var TransportError = class extends Error {
14495
14574
  status;
@@ -15284,7 +15363,7 @@ function hostfsFetchOf(options) {
15284
15363
  }
15285
15364
  function nodeTransport() {
15286
15365
  const transport = fetchTransport({ webSocket: true, webSocketHeaders: true, redirect: "manual" });
15287
- return { ...transport, traits: { ...transport.traits, crossOrigin: "any" } };
15366
+ return diagnosing({ ...transport, traits: { ...transport.traits, crossOrigin: "any" } });
15288
15367
  }
15289
15368
  var TERMINATED = "the kernel is terminated";
15290
15369
  var EXIT_GRACE_MS = 50;