@ai-ecoverse/slicc-kernel 1.44.0 → 1.46.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
@@ -735,6 +735,9 @@ var KernelSocket = class _KernelSocket {
735
735
  get listening() {
736
736
  return this.state === "listening";
737
737
  }
738
+ get unconnected() {
739
+ return this.state === "open" || this.state === "listening";
740
+ }
738
741
  connection() {
739
742
  if (!this.link || this.state !== "connected") throw new KernelError("ENOTCONN");
740
743
  return this.link;
@@ -1061,8 +1064,8 @@ function serveSocket(socket, port, onClose) {
1061
1064
  let writes = Promise.resolve();
1062
1065
  let credit = 0;
1063
1066
  let granted2;
1064
- const send = (message2, transfer) => {
1065
- if (!closed) port.postMessage(message2, transfer);
1067
+ const send = (message3, transfer) => {
1068
+ if (!closed) port.postMessage(message3, transfer);
1066
1069
  };
1067
1070
  const close = (reset = false) => {
1068
1071
  if (closed) return;
@@ -1194,8 +1197,8 @@ async function readWithin(reader, ms) {
1194
1197
  var INBOUND_LIMIT = 16 * 1024 * 1024;
1195
1198
  var MESSAGE_LIMIT = 64 * 1024 * 1024;
1196
1199
  var TOO_BIG = 1009;
1197
- function payloadSize(message2) {
1198
- return typeof message2 === "string" ? new TextEncoder().encode(message2).length : message2.length;
1200
+ function payloadSize(message3) {
1201
+ return typeof message3 === "string" ? new TextEncoder().encode(message3).length : message3.length;
1199
1202
  }
1200
1203
  var MessageQueue = class {
1201
1204
  items = [];
@@ -1215,9 +1218,9 @@ var MessageQueue = class {
1215
1218
  this.settle = resolve;
1216
1219
  });
1217
1220
  }
1218
- push(message2) {
1221
+ push(message3) {
1219
1222
  if (this.ended) return;
1220
- const size = payloadSize(message2);
1223
+ const size = payloadSize(message3);
1221
1224
  const huge = size > MESSAGE_LIMIT;
1222
1225
  if (huge || this.items.length > 0 && this.size + size > this.limit) {
1223
1226
  const reason = huge ? `a message is over ${MESSAGE_LIMIT} bytes` : `over ${this.limit} bytes of messages are waiting`;
@@ -1226,7 +1229,7 @@ var MessageQueue = class {
1226
1229
  return;
1227
1230
  }
1228
1231
  this.size += size;
1229
- this.items.push(message2);
1232
+ this.items.push(message3);
1230
1233
  this.wake();
1231
1234
  }
1232
1235
  end(close) {
@@ -1399,6 +1402,7 @@ function fetchTransport(options = {}) {
1399
1402
  });
1400
1403
  const body = chunks(response.body, options.bodyIdleMs ?? BODY_IDLE_MS);
1401
1404
  return {
1405
+ ...response.redirected ? { url: response.url, redirected: true } : {},
1402
1406
  status: response.status,
1403
1407
  statusText: response.statusText,
1404
1408
  headers: headers2,
@@ -1413,7 +1417,7 @@ function fetchTransport(options = {}) {
1413
1417
  }
1414
1418
  function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
1415
1419
  const open = /* @__PURE__ */ new Map();
1416
- const fail2 = (nid, e) => {
1420
+ const fail3 = (nid, e) => {
1417
1421
  open.delete(nid);
1418
1422
  const { status, code } = e;
1419
1423
  peer.postMessage({
@@ -1444,12 +1448,13 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
1444
1448
  peer.postMessage({
1445
1449
  net: "head",
1446
1450
  nid: call.nid,
1451
+ ...response.redirected ? { url: response.url, redirected: true } : {},
1447
1452
  status: response.status,
1448
1453
  statusText: response.statusText,
1449
1454
  headers: response.headers
1450
1455
  });
1451
1456
  } catch (e) {
1452
- fail2(call.nid, e);
1457
+ fail3(call.nid, e);
1453
1458
  }
1454
1459
  };
1455
1460
  const sockets = /* @__PURE__ */ new Map();
@@ -1483,7 +1488,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
1483
1488
  peer.postMessage({ net: "ws-opened", nid: call.nid, protocol: socket.protocol });
1484
1489
  void relay(call.nid, socket);
1485
1490
  } catch (e) {
1486
- fail2(call.nid, e);
1491
+ fail3(call.nid, e);
1487
1492
  }
1488
1493
  };
1489
1494
  const relay = async (nid, socket) => {
@@ -1555,7 +1560,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
1555
1560
  peer.postMessage({ net: "chunk", nid, bytes }, [bytes.buffer]);
1556
1561
  }
1557
1562
  } catch (e) {
1558
- fail2(nid, e);
1563
+ fail3(nid, e);
1559
1564
  }
1560
1565
  };
1561
1566
  const drop = (nid) => {
@@ -2059,8 +2064,8 @@ function serveClient(port, host) {
2059
2064
  const watches = /* @__PURE__ */ new Map();
2060
2065
  let net;
2061
2066
  const ended = Promise.withResolvers();
2062
- const send = (message2, transfer = []) => {
2063
- if (state !== "closed") port.postMessage(message2, transfer);
2067
+ const send = (message3, transfer = []) => {
2068
+ if (state !== "closed") port.postMessage(message3, transfer);
2064
2069
  };
2065
2070
  const reply = (id2, body, transfer) => send({ id: id2, ...body }, transfer);
2066
2071
  const cdps = cdpRegistry(send, ended.promise);
@@ -2079,8 +2084,8 @@ function serveClient(port, host) {
2079
2084
  port.close?.();
2080
2085
  ended.resolve();
2081
2086
  }
2082
- async function hello(message2) {
2083
- const refused = versionError(message2.protocol);
2087
+ async function hello(message3) {
2088
+ const refused = versionError(message3.protocol);
2084
2089
  if (refused) {
2085
2090
  send({ hello: { protocol: PROTOCOL, error: refused } });
2086
2091
  detach();
@@ -2091,7 +2096,7 @@ function serveClient(port, host) {
2091
2096
  const transport = host.transport?.() ?? launcher.transport;
2092
2097
  net = serveTransport({ postMessage: (m, t) => send(m, t) }, transport);
2093
2098
  state = "open";
2094
- if (message2.lock && host.locks) void host.locks.request(message2.lock, () => detach());
2099
+ if (message3.lock && host.locks) void host.locks.request(message3.lock, () => detach());
2095
2100
  send({
2096
2101
  hello: {
2097
2102
  protocol: PROTOCOL,
@@ -3124,8 +3129,8 @@ var UnlinkedKeeper = class {
3124
3129
  // src/kernel/net/http1.ts
3125
3130
  var HttpError = class extends Error {
3126
3131
  status;
3127
- constructor(status, message2) {
3128
- super(message2);
3132
+ constructor(status, message3) {
3133
+ super(message3);
3129
3134
  this.status = status;
3130
3135
  }
3131
3136
  };
@@ -3392,8 +3397,8 @@ var OP = {
3392
3397
  };
3393
3398
  var WsError = class extends Error {
3394
3399
  code;
3395
- constructor(code, message2) {
3396
- super(message2);
3400
+ constructor(code, message3) {
3401
+ super(message3);
3397
3402
  this.code = code;
3398
3403
  }
3399
3404
  };
@@ -3690,8 +3695,8 @@ var CdpFacade = class {
3690
3695
  clearTimeout(timer);
3691
3696
  reject(new HttpError(502, `the CDP host closed: ${reason ?? "no reason"}`));
3692
3697
  };
3693
- conn.onmessage = (message2) => {
3694
- const parsed2 = JSON.parse(message2);
3698
+ conn.onmessage = (message3) => {
3699
+ const parsed2 = JSON.parse(message3);
3695
3700
  if (parsed2.id !== 1) return;
3696
3701
  clearTimeout(timer);
3697
3702
  resolve(parsed2);
@@ -3759,9 +3764,9 @@ var Relay = class {
3759
3764
  void this.end(reason ? CLOSE.error : CLOSE.normal, reason ?? "").then(() => resolve());
3760
3765
  };
3761
3766
  });
3762
- this.host.onmessage = (message2) => {
3767
+ this.host.onmessage = (message3) => {
3763
3768
  if (this.ended) return;
3764
- const bytes = new TextEncoder().encode(message2);
3769
+ const bytes = new TextEncoder().encode(message3);
3765
3770
  if (bytes.length > this.max)
3766
3771
  void this.end(CLOSE.tooBig, `a message is over ${this.max} bytes`);
3767
3772
  else void this.send(frame(OP_TEXT, bytes));
@@ -4349,10 +4354,10 @@ var SpawnError = class extends Error {
4349
4354
  };
4350
4355
  function interrupted(signal) {
4351
4356
  const { promise, reject } = Promise.withResolvers();
4352
- const fail2 = () => reject(new KernelError("EINTR"));
4353
- if (signal?.aborted) fail2();
4354
- else signal?.addEventListener("abort", fail2, { once: true });
4355
- return { promise, done: () => signal?.removeEventListener("abort", fail2) };
4357
+ const fail3 = () => reject(new KernelError("EINTR"));
4358
+ if (signal?.aborted) fail3();
4359
+ else signal?.addEventListener("abort", fail3, { once: true });
4360
+ return { promise, done: () => signal?.removeEventListener("abort", fail3) };
4356
4361
  }
4357
4362
  function stoppedStatus(sig) {
4358
4363
  return (sig & 255) << 8 | 127;
@@ -4543,8 +4548,8 @@ function unref(timer) {
4543
4548
  timer.unref?.();
4544
4549
  return timer;
4545
4550
  }
4546
- function errnoError(code, message2) {
4547
- return Object.assign(new Error(`${code}: ${message2}`), { code });
4551
+ function errnoError(code, message3) {
4552
+ return Object.assign(new Error(`${code}: ${message3}`), { code });
4548
4553
  }
4549
4554
  var DriverConnection = class _DriverConnection {
4550
4555
  capabilities;
@@ -5526,12 +5531,12 @@ function syncError(code, label) {
5526
5531
 
5527
5532
  // src/realm/sync-fs-dispatch.ts
5528
5533
  function toErrno(err) {
5529
- const message2 = err instanceof Error ? err.message : String(err);
5534
+ const message3 = err instanceof Error ? err.message : String(err);
5530
5535
  const code = err?.code;
5531
5536
  if (typeof code === "string" && /^E[A-Z]+$/.test(code)) {
5532
- return { ok: false, errno: code, message: message2 };
5537
+ return { ok: false, errno: code, message: message3 };
5533
5538
  }
5534
- return { ok: false, errno: "EIO", message: message2 };
5539
+ return { ok: false, errno: "EIO", message: message3 };
5535
5540
  }
5536
5541
  function statJson(s) {
5537
5542
  return {
@@ -6228,8 +6233,8 @@ function untilAborted(response, signal) {
6228
6233
  response.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
6229
6234
  });
6230
6235
  }
6231
- function plainResponse(status, message2) {
6232
- const body = latin1Bytes(`slicc realm proxy: ${message2}
6236
+ function plainResponse(status, message3) {
6237
+ const body = latin1Bytes(`slicc realm proxy: ${message3}
6233
6238
  `);
6234
6239
  return {
6235
6240
  status,
@@ -6411,10 +6416,10 @@ var RealmProxy = class {
6411
6416
  return await untilAborted(fetching, signal);
6412
6417
  } catch (e) {
6413
6418
  if (signal.aborted) throw e;
6414
- const message2 = e instanceof Error ? e.message : String(e);
6419
+ const message3 = e instanceof Error ? e.message : String(e);
6415
6420
  const status = e?.status;
6416
6421
  const own = typeof status === "number" && status >= 400 && status <= 599 ? status : 502;
6417
- return plainResponse(own, message2 || "upstream request failed");
6422
+ return plainResponse(own, message3 || "upstream request failed");
6418
6423
  }
6419
6424
  }
6420
6425
  async relay(conn, method, minor, response, keepAlive) {
@@ -6875,8 +6880,8 @@ var SCRATCH = 64 * 1024;
6875
6880
  var EOF = -1;
6876
6881
  var TlsError = class extends Error {
6877
6882
  code;
6878
- constructor(code, message2) {
6879
- super(message2);
6883
+ constructor(code, message3) {
6884
+ super(message3);
6880
6885
  this.code = code;
6881
6886
  }
6882
6887
  };
@@ -7257,10 +7262,135 @@ function enableNetwork(net, options) {
7257
7262
  return () => proxy;
7258
7263
  }
7259
7264
 
7265
+ // src/kernel/net/ws-syscalls.ts
7266
+ var WS_OPS = [
7267
+ "net-ws-open",
7268
+ "net-ws-ready",
7269
+ "net-ws-recv",
7270
+ "net-ws-wait",
7271
+ "net-ws-send",
7272
+ "net-ws-close"
7273
+ ];
7274
+ var TOKEN3 = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
7275
+ function message(e) {
7276
+ return e instanceof Error ? e.message : String(e);
7277
+ }
7278
+ function fail(errno, text) {
7279
+ return { ok: false, errno, message: text };
7280
+ }
7281
+ var WsHandles = class {
7282
+ transport;
7283
+ open = /* @__PURE__ */ new Map();
7284
+ next;
7285
+ constructor(transport, next2) {
7286
+ this.transport = transport;
7287
+ this.next = next2;
7288
+ }
7289
+ owns(handle) {
7290
+ return this.open.has(handle);
7291
+ }
7292
+ syscall(req) {
7293
+ if (req.op === "net-ws-open") return Promise.resolve(this.start(req));
7294
+ const entry = this.open.get(req.handle);
7295
+ if (!entry) return Promise.resolve(fail("EBADF", `no websocket ${req.handle}`));
7296
+ if (req.op === "net-ws-ready") return entry.ready;
7297
+ if (!entry.socket) return Promise.resolve(fail("ENOTCONN", "websocket not open"));
7298
+ if (req.op === "net-ws-recv") return this.recv(entry.socket, entry);
7299
+ if (req.op === "net-ws-wait") return this.closed(entry.socket);
7300
+ if (req.op === "net-ws-send") return Promise.resolve(this.send(entry.socket, req, entry));
7301
+ entry.ended = true;
7302
+ entry.socket.close(req.code ?? 1e3, req.reason ?? "");
7303
+ return Promise.resolve({ ok: true, kind: "void" });
7304
+ }
7305
+ start(req) {
7306
+ const handle = this.next();
7307
+ const entry = {
7308
+ abort: new AbortController(),
7309
+ ready: Promise.resolve({ ok: true, kind: "void" })
7310
+ };
7311
+ this.open.set(handle, entry);
7312
+ entry.ready = this.connect(handle, req, entry);
7313
+ return { ok: true, kind: "json", json: handle };
7314
+ }
7315
+ async connect(handle, req, entry) {
7316
+ const { transport } = this;
7317
+ if (!transport.traits.websocket || !transport.websocket) return fail("ENOTSUP", NO_WEBSOCKET2);
7318
+ let socket;
7319
+ try {
7320
+ socket = await transport.websocket({
7321
+ url: req.url,
7322
+ protocols: req.protocols,
7323
+ headers: req.headers,
7324
+ signal: entry.abort.signal
7325
+ });
7326
+ } catch (e) {
7327
+ return fail("ECONNREFUSED", message(e));
7328
+ }
7329
+ if (!this.open.has(handle)) {
7330
+ socket.close(1001, "the program went away");
7331
+ return fail("EBADF", `no websocket ${handle}`);
7332
+ }
7333
+ if (socket.protocol && !(req.protocols.includes(socket.protocol) && TOKEN3.test(socket.protocol))) {
7334
+ socket.close(1002, "subprotocol not offered");
7335
+ return fail("EPROTO", "the far end chose a subprotocol the program did not offer");
7336
+ }
7337
+ entry.socket = socket;
7338
+ void socket.closed.then(() => {
7339
+ entry.ended = true;
7340
+ });
7341
+ entry.messages = socket.messages[Symbol.asyncIterator]();
7342
+ return { ok: true, kind: "json", json: { protocol: socket.protocol } };
7343
+ }
7344
+ async recv(socket, entry) {
7345
+ try {
7346
+ const next2 = await entry.messages.next();
7347
+ if (!next2.done) {
7348
+ return typeof next2.value === "string" ? { ok: true, kind: "json", json: { text: next2.value } } : { ok: true, kind: "bytes", bytes: next2.value };
7349
+ }
7350
+ const closed = await socket.closed;
7351
+ return { ok: true, kind: "json", json: { code: closed.code, reason: closed.reason } };
7352
+ } catch (e) {
7353
+ return fail("ECONNRESET", message(e));
7354
+ }
7355
+ }
7356
+ async closed(socket) {
7357
+ const { code, reason } = await socket.closed;
7358
+ return { ok: true, kind: "json", json: { code, reason } };
7359
+ }
7360
+ send(socket, req, entry) {
7361
+ const data = req.text ?? req.body;
7362
+ if (entry.ended) return fail("EPIPE", "the websocket is closed");
7363
+ try {
7364
+ if (data !== void 0) socket.send(data);
7365
+ } catch (e) {
7366
+ return fail("EPIPE", message(e));
7367
+ }
7368
+ return { ok: true, kind: "json", json: socket.buffered };
7369
+ }
7370
+ close(handle) {
7371
+ const entry = this.open.get(handle);
7372
+ if (!entry) return;
7373
+ this.open.delete(handle);
7374
+ entry.abort.abort();
7375
+ entry.socket?.close(1001, "the program went away");
7376
+ }
7377
+ closeAll() {
7378
+ for (const handle of [...this.open.keys()]) this.close(handle);
7379
+ }
7380
+ };
7381
+
7260
7382
  // src/kernel/net/http-syscalls.ts
7261
- var HTTP_OPS = ["net-request", "net-read", "net-close", "net-traits"];
7383
+ var HTTP_OPS = [
7384
+ "net-request",
7385
+ "net-open",
7386
+ "net-head",
7387
+ "net-read",
7388
+ "net-close",
7389
+ "net-traits",
7390
+ ...WS_OPS
7391
+ ];
7262
7392
  var EMPTY = new Uint8Array(0);
7263
- function message(e) {
7393
+ function message2(e) {
7264
7394
  return e instanceof Error ? e.message : String(e);
7265
7395
  }
7266
7396
  async function* once(bytes) {
@@ -7270,11 +7400,16 @@ var HttpHandles = class {
7270
7400
  transport;
7271
7401
  open = /* @__PURE__ */ new Map();
7272
7402
  nextHandle = 0;
7403
+ ws;
7273
7404
  constructor(transport) {
7274
7405
  this.transport = transport;
7406
+ this.ws = new WsHandles(transport, () => ++this.nextHandle);
7275
7407
  }
7276
7408
  syscall(req) {
7409
+ if (req.op.startsWith("net-ws-")) return this.ws.syscall(req);
7277
7410
  if (req.op === "net-request") return this.request(req);
7411
+ if (req.op === "net-open") return Promise.resolve(this.opened(req));
7412
+ if (req.op === "net-head") return this.head(req.handle);
7278
7413
  if (req.op === "net-read") return this.read(req.handle, req.max);
7279
7414
  if (req.op === "net-traits") return Promise.resolve(this.traits());
7280
7415
  return this.close(req.handle);
@@ -7284,56 +7419,70 @@ var HttpHandles = class {
7284
7419
  if (unavailable) return { ok: false, errno: "ENETUNREACH", message: NO_TRANSPORT };
7285
7420
  return { ok: true, kind: "json", json: { ...rest2, crossOrigin } };
7286
7421
  }
7287
- add(abort, body, cancel) {
7422
+ async request(req) {
7423
+ const { handle, head } = this.start(req);
7424
+ const result = await head;
7425
+ if (!result.ok) this.open.delete(handle);
7426
+ return result;
7427
+ }
7428
+ opened(req) {
7429
+ return { ok: true, kind: "json", json: this.start(req).handle };
7430
+ }
7431
+ start(req) {
7288
7432
  const handle = ++this.nextHandle;
7289
- this.open.set(handle, {
7433
+ const abort = new AbortController();
7434
+ const entry = {
7290
7435
  abort,
7291
- body: body[Symbol.asyncIterator](),
7436
+ head: Promise.resolve({ ok: true, kind: "void" }),
7437
+ body: once(EMPTY),
7292
7438
  left: EMPTY,
7293
7439
  done: false,
7294
7440
  reading: Promise.resolve(),
7295
- cancel
7296
- });
7297
- return handle;
7441
+ cancel: async () => void 0
7442
+ };
7443
+ this.open.set(handle, entry);
7444
+ entry.head = this.respond(handle, req, entry);
7445
+ return { handle, head: entry.head };
7298
7446
  }
7299
- async request(req) {
7300
- const abort = new AbortController();
7447
+ async respond(handle, req, entry) {
7301
7448
  try {
7302
7449
  const response = await this.transport.fetch({
7303
7450
  url: req.url,
7304
7451
  method: req.method,
7305
7452
  headers: req.headers,
7306
7453
  ...req.body ? { body: req.body } : {},
7307
- signal: abort.signal
7454
+ signal: entry.abort.signal
7308
7455
  });
7309
- const handle = this.add(abort, response.body, () => response.cancel());
7310
- const head = {
7311
- handle,
7312
- status: response.status,
7313
- statusText: response.statusText,
7314
- url: req.url,
7315
- headers: response.headers
7316
- };
7317
- return { ok: true, kind: "json", json: head };
7456
+ entry.body = response.body[Symbol.asyncIterator]();
7457
+ entry.cancel = () => response.cancel();
7458
+ if (!this.open.has(handle)) await entry.cancel().catch(() => void 0);
7459
+ const head = this.headOf(handle, response.url ?? req.url, response);
7460
+ return response.redirected ? { ...head, json: { ...head.json, redirected: true } } : head;
7318
7461
  } catch (e) {
7319
- const text = message(e);
7320
- if (text === NO_TRANSPORT) return { ok: false, errno: "ENETUNREACH", message: text };
7462
+ const text = message2(e);
7321
7463
  const status = e.status;
7322
- if (typeof status !== "number" || status === 502) {
7323
- return { ok: false, errno: "ECONNREFUSED", message: text };
7464
+ if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
7465
+ const errno = text === NO_TRANSPORT ? "ENETUNREACH" : "ECONNREFUSED";
7466
+ return { ok: false, errno, message: text };
7324
7467
  }
7325
- const body = new TextEncoder().encode(text);
7326
- const handle = this.add(abort, once(body), async () => void 0);
7327
- const head = {
7328
- handle,
7468
+ entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
7469
+ return this.headOf(handle, req.url, {
7329
7470
  status,
7330
7471
  statusText: "",
7331
- url: req.url,
7332
7472
  headers: [["content-type", "text/plain; charset=utf-8"]]
7333
- };
7334
- return { ok: true, kind: "json", json: head };
7473
+ });
7335
7474
  }
7336
7475
  }
7476
+ headOf(handle, url, response) {
7477
+ const { status, statusText, headers } = response;
7478
+ return { ok: true, kind: "json", json: { handle, status, statusText, url, headers } };
7479
+ }
7480
+ head(handle) {
7481
+ const entry = this.open.get(handle);
7482
+ if (!entry)
7483
+ return Promise.resolve({ ok: false, errno: "EBADF", message: `no request ${handle}` });
7484
+ return entry.head;
7485
+ }
7337
7486
  async read(handle, max) {
7338
7487
  const entry = this.open.get(handle);
7339
7488
  if (!entry) return { ok: false, errno: "EBADF", message: `no request ${handle}` };
@@ -7350,7 +7499,7 @@ var HttpHandles = class {
7350
7499
  } catch (e) {
7351
7500
  entry.done = true;
7352
7501
  const timedOut = e?.code === "ETIMEDOUT";
7353
- return { ok: false, errno: timedOut ? "ETIMEDOUT" : "EIO", message: message(e) };
7502
+ return { ok: false, errno: timedOut ? "ETIMEDOUT" : "EIO", message: message2(e) };
7354
7503
  }
7355
7504
  }
7356
7505
  const bytes = entry.left.subarray(0, Math.max(0, max));
@@ -7358,6 +7507,10 @@ var HttpHandles = class {
7358
7507
  return { ok: true, kind: "bytes", bytes };
7359
7508
  }
7360
7509
  async close(handle) {
7510
+ if (this.ws.owns(handle)) {
7511
+ this.ws.close(handle);
7512
+ return { ok: true, kind: "void" };
7513
+ }
7361
7514
  const entry = this.open.get(handle);
7362
7515
  if (!entry) return { ok: false, errno: "EBADF", message: `no request ${handle}` };
7363
7516
  this.open.delete(handle);
@@ -7366,6 +7519,7 @@ var HttpHandles = class {
7366
7519
  return { ok: true, kind: "void" };
7367
7520
  }
7368
7521
  async closeAll() {
7522
+ this.ws.closeAll();
7369
7523
  await Promise.all([...this.open.keys()].map((handle) => this.close(handle)));
7370
7524
  }
7371
7525
  };
@@ -7498,7 +7652,7 @@ var Resolver = class {
7498
7652
  this.routes = options.routes;
7499
7653
  this.now = options.now ?? Date.now;
7500
7654
  this.timeoutMs = options.timeoutMs ?? RESOLVE_TIMEOUT_MS;
7501
- this.log = options.log ?? ((message2) => console.warn(message2));
7655
+ this.log = options.log ?? ((message3) => console.warn(message3));
7502
7656
  this.own = ownNames(options.hostname ?? DEFAULT_HOSTNAME);
7503
7657
  }
7504
7658
  async resolve(name2, family, blocking) {
@@ -8058,10 +8212,10 @@ function ready(fds, read, write) {
8058
8212
  }
8059
8213
  function interruption(signal) {
8060
8214
  const { promise, reject } = Promise.withResolvers();
8061
- const fail2 = () => reject(new KernelError("EINTR"));
8062
- if (signal.aborted) fail2();
8063
- else signal.addEventListener("abort", fail2, { once: true });
8064
- return { promise, done: () => signal.removeEventListener("abort", fail2) };
8215
+ const fail3 = () => reject(new KernelError("EINTR"));
8216
+ if (signal.aborted) fail3();
8217
+ else signal.addEventListener("abort", fail3, { once: true });
8218
+ return { promise, done: () => signal.removeEventListener("abort", fail3) };
8065
8219
  }
8066
8220
  async function selectFds(fds, read, write, timeoutMs, interrupt) {
8067
8221
  const deadline = timeoutMs < 0 ? Number.POSITIVE_INFINITY : Date.now() + timeoutMs;
@@ -9211,6 +9365,9 @@ var WasmProcess = class {
9211
9365
  throw e;
9212
9366
  }
9213
9367
  }
9368
+ refuseIfPending(restart) {
9369
+ if (restart && this.options.hasPending?.()) throw new KernelError("EINTR");
9370
+ }
9214
9371
  blockingSignal() {
9215
9372
  if (this.options.hasPending?.()) throw new KernelError("EINTR");
9216
9373
  return this.interrupt.signal;
@@ -9221,6 +9378,7 @@ var WasmProcess = class {
9221
9378
  if (!read) throw new KernelError(req.peek && file.read ? "EOPNOTSUPP" : "EBADF");
9222
9379
  if (file.tty) this.checkForeground(file.tty);
9223
9380
  if (req.max <= 0) return new Uint8Array(0);
9381
+ if (file instanceof KernelSocket && file.unconnected) throw new KernelError("ENOTCONN");
9224
9382
  const ready2 = pollFile(file).readable;
9225
9383
  if (!ready2 && req.nonblock) throw new KernelError("EAGAIN");
9226
9384
  const signal = ready2 ? this.interrupt.signal : this.blockingSignal();
@@ -9543,8 +9701,10 @@ var WasmProcess = class {
9543
9701
  async procSyscall(req) {
9544
9702
  switch (req.op) {
9545
9703
  case "proc-fork":
9704
+ this.refuseIfPending(req.restart);
9546
9705
  return { ok: true, kind: "json", json: await this.children.fork(req.state) };
9547
9706
  case "proc-spawn":
9707
+ this.refuseIfPending(req.restart);
9548
9708
  return { ok: true, kind: "json", json: await this.spawn(req) };
9549
9709
  case "proc-wait": {
9550
9710
  const signal = req.nohang ? this.interrupt.signal : this.blockingSignal();
@@ -10210,8 +10370,8 @@ var SettlingChildren = class {
10210
10370
  };
10211
10371
 
10212
10372
  // src/mount/driver.ts
10213
- function fsError2(code, message2 = code) {
10214
- return Object.assign(new Error(message2), { code });
10373
+ function fsError2(code, message3 = code) {
10374
+ return Object.assign(new Error(message3), { code });
10215
10375
  }
10216
10376
  async function dispatch(h, req) {
10217
10377
  switch (req.op) {
@@ -10261,15 +10421,15 @@ async function dispatch(h, req) {
10261
10421
  }
10262
10422
  function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
10263
10423
  let open = false;
10264
- const reply = (message2, transfer = []) => port.postMessage(message2, transfer);
10265
- async function hello(message2) {
10266
- const refused = driverVersionError(message2.protocol);
10424
+ const reply = (message3, transfer = []) => port.postMessage(message3, transfer);
10425
+ async function hello(message3) {
10426
+ const refused = driverVersionError(message3.protocol);
10267
10427
  if (refused) {
10268
10428
  reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused, errno: "EPROTO" } });
10269
10429
  return;
10270
10430
  }
10271
10431
  try {
10272
- const refined = await handlers.mount?.(message2.mount);
10432
+ const refined = await handlers.mount?.(message3.mount);
10273
10433
  open = true;
10274
10434
  reply({
10275
10435
  hello: { protocol: DRIVER_PROTOCOL, capabilities: { ...capabilities, ...refined } }
@@ -11601,10 +11761,10 @@ var Launcher = class {
11601
11761
  }
11602
11762
  interpreters() {
11603
11763
  this.binfmts ??= this.roots().then(
11604
- (roots) => scanBinfmts(this.base, roots, (message2) => {
11605
- if (this.warned.has(message2)) return;
11606
- this.warned.add(message2);
11607
- console.warn(message2);
11764
+ (roots) => scanBinfmts(this.base, roots, (message3) => {
11765
+ if (this.warned.has(message3)) return;
11766
+ this.warned.add(message3);
11767
+ console.warn(message3);
11608
11768
  })
11609
11769
  );
11610
11770
  return this.binfmts;
@@ -12231,7 +12391,7 @@ var Launcher = class {
12231
12391
  },
12232
12392
  account
12233
12393
  );
12234
- const report = (message2) => options.onData(encoder3.encode(`${message2}\r
12394
+ const report = (message3) => options.onData(encoder3.encode(`${message3}\r
12235
12395
  `));
12236
12396
  const handle = await this.launch(planned, { env, cwd, fds, report, ...this.identity(account) });
12237
12397
  leader = handle.pid;
@@ -12261,7 +12421,7 @@ var Launcher = class {
12261
12421
  };
12262
12422
  const stdout = collect(out, options.onStdout);
12263
12423
  const stderr = collect(err, options.onStderr);
12264
- const report = (message2) => stderr(encoder3.encode(`${message2}
12424
+ const report = (message3) => stderr(encoder3.encode(`${message3}
12265
12425
  `));
12266
12426
  if (!planned) {
12267
12427
  report(`${file}: command not found`);
@@ -12287,7 +12447,7 @@ var Launcher = class {
12287
12447
  };
12288
12448
 
12289
12449
  // src/node/memory-root.ts
12290
- var fail = (name2) => {
12450
+ var fail2 = (name2) => {
12291
12451
  throw new DOMException(name2, name2);
12292
12452
  };
12293
12453
  function valid(name2) {
@@ -12400,7 +12560,7 @@ var MemoryFile = class {
12400
12560
  }
12401
12561
  async move(parent, name2) {
12402
12562
  valid(name2);
12403
- if (parent.children.get(name2)?.kind === "directory") fail("InvalidModificationError");
12563
+ if (parent.children.get(name2)?.kind === "directory") fail2("InvalidModificationError");
12404
12564
  this.parent.children.delete(this.name);
12405
12565
  this.name = name2;
12406
12566
  this.parent = parent;
@@ -12418,15 +12578,15 @@ var MemoryDirectory = class _MemoryDirectory {
12418
12578
  this.parent = parent;
12419
12579
  }
12420
12580
  present() {
12421
- if (this.removed) fail("NotFoundError");
12581
+ if (this.removed) fail2("NotFoundError");
12422
12582
  }
12423
12583
  async getDirectoryHandle(name2, { create = false } = {}) {
12424
12584
  this.present();
12425
12585
  valid(name2);
12426
12586
  const found = this.children.get(name2);
12427
- if (found?.kind === "file") fail("TypeMismatchError");
12587
+ if (found?.kind === "file") fail2("TypeMismatchError");
12428
12588
  if (found) return found;
12429
- if (!create) fail("NotFoundError");
12589
+ if (!create) fail2("NotFoundError");
12430
12590
  const dir = new _MemoryDirectory(name2, this);
12431
12591
  this.children.set(name2, dir);
12432
12592
  return dir;
@@ -12435,9 +12595,9 @@ var MemoryDirectory = class _MemoryDirectory {
12435
12595
  this.present();
12436
12596
  valid(name2);
12437
12597
  const found = this.children.get(name2);
12438
- if (found?.kind === "directory") fail("TypeMismatchError");
12598
+ if (found?.kind === "directory") fail2("TypeMismatchError");
12439
12599
  if (found) return found;
12440
- if (!create) fail("NotFoundError");
12600
+ if (!create) fail2("NotFoundError");
12441
12601
  const file = new MemoryFile(name2, this);
12442
12602
  this.children.set(name2, file);
12443
12603
  return file;
@@ -12446,9 +12606,9 @@ var MemoryDirectory = class _MemoryDirectory {
12446
12606
  this.present();
12447
12607
  valid(name2);
12448
12608
  const found = this.children.get(name2);
12449
- if (!found) return fail("NotFoundError");
12609
+ if (!found) return fail2("NotFoundError");
12450
12610
  if (found.kind === "directory" && found.children.size > 0 && !recursive) {
12451
- fail("InvalidModificationError");
12611
+ fail2("InvalidModificationError");
12452
12612
  }
12453
12613
  this.children.delete(name2);
12454
12614
  if (found.kind === "directory") found.remove();
@@ -12477,7 +12637,7 @@ var MemoryDirectory = class _MemoryDirectory {
12477
12637
  }
12478
12638
  async move(parent, name2) {
12479
12639
  valid(name2);
12480
- if (parent.children.has(name2)) fail("InvalidModificationError");
12640
+ if (parent.children.has(name2)) fail2("InvalidModificationError");
12481
12641
  this.parent?.children.delete(this.name);
12482
12642
  this.name = name2;
12483
12643
  this.parent = parent;
@@ -12495,8 +12655,8 @@ function isMemoryRoot(handle) {
12495
12655
  var TransportError = class extends Error {
12496
12656
  status;
12497
12657
  code;
12498
- constructor(message2, status, code) {
12499
- super(message2);
12658
+ constructor(message3, status, code) {
12659
+ super(message3);
12500
12660
  this.status = status;
12501
12661
  this.code = code;
12502
12662
  }
@@ -12581,7 +12741,7 @@ var RemoteTransport = class {
12581
12741
  finish();
12582
12742
  throw e;
12583
12743
  }
12584
- const { status, statusText, headers } = head;
12744
+ const { status, statusText, headers, url, redirected } = head;
12585
12745
  const read = async () => {
12586
12746
  if (finished) return void 0;
12587
12747
  const reply = await this.ask({ net: "read", nid }).catch((e) => {
@@ -12598,6 +12758,7 @@ var RemoteTransport = class {
12598
12758
  this.cancel(nid);
12599
12759
  };
12600
12760
  return {
12761
+ ...redirected ? { url, redirected } : {},
12601
12762
  status,
12602
12763
  statusText,
12603
12764
  headers,
@@ -12667,9 +12828,9 @@ function signalNumber(name2) {
12667
12828
  }
12668
12829
 
12669
12830
  // src/client/dial-stream.ts
12670
- function errorWithCode(message2) {
12671
- const code = /^E[A-Z]+/.exec(message2)?.[0];
12672
- return Object.assign(new Error(message2), code ? { code } : {});
12831
+ function errorWithCode(message3) {
12832
+ const code = /^E[A-Z]+/.exec(message3)?.[0];
12833
+ return Object.assign(new Error(message3), code ? { code } : {});
12673
12834
  }
12674
12835
  function dialStream(port, onClose) {
12675
12836
  let closed = false;
@@ -12687,15 +12848,15 @@ function dialStream(port, onClose) {
12687
12848
  close();
12688
12849
  }
12689
12850
  });
12690
- const finish = (fail3) => {
12851
+ const finish = (fail4) => {
12691
12852
  const controller = reader;
12692
12853
  reader = void 0;
12693
12854
  for (const ack of acks.splice(0)) {
12694
- if (fail3) ack.reject(fail3);
12855
+ if (fail4) ack.reject(fail4);
12695
12856
  else ack.resolve();
12696
12857
  }
12697
12858
  if (!controller) return;
12698
- if (fail3) controller.error(fail3);
12859
+ if (fail4) controller.error(fail4);
12699
12860
  else controller.close();
12700
12861
  };
12701
12862
  function shut() {
@@ -12731,11 +12892,11 @@ function dialStream(port, onClose) {
12731
12892
  close();
12732
12893
  }
12733
12894
  });
12734
- const fail2 = (error) => {
12895
+ const fail3 = (error) => {
12735
12896
  shut();
12736
12897
  finish(error);
12737
12898
  };
12738
- return { readable, writable, close, fail: fail2 };
12899
+ return { readable, writable, close, fail: fail3 };
12739
12900
  }
12740
12901
 
12741
12902
  // src/client/loopback-fetch.ts
@@ -12907,15 +13068,15 @@ async function loopbackFetch(dial, input, options) {
12907
13068
 
12908
13069
  // src/client/attach.ts
12909
13070
  var KernelGoneError = class extends Error {
12910
- constructor(message2 = "the slicc-kernel this client was attached to is gone") {
12911
- super(message2);
13071
+ constructor(message3 = "the slicc-kernel this client was attached to is gone") {
13072
+ super(message3);
12912
13073
  this.name = "KernelGoneError";
12913
13074
  }
12914
13075
  };
12915
13076
  var KernelCallError = class extends Error {
12916
13077
  code;
12917
- constructor(message2, code) {
12918
- super(message2);
13078
+ constructor(message3, code) {
13079
+ super(message3);
12919
13080
  this.name = "KernelCallError";
12920
13081
  this.code = code;
12921
13082
  }
@@ -12971,8 +13132,8 @@ var Channel = class {
12971
13132
  port.addEventListener("close", () => this.end(new KernelGoneError()));
12972
13133
  port.start?.();
12973
13134
  }
12974
- post(message2) {
12975
- if (!this.failure) this.port.postMessage(message2);
13135
+ post(message3) {
13136
+ if (!this.failure) this.port.postMessage(message3);
12976
13137
  }
12977
13138
  end(error) {
12978
13139
  if (this.failure) return;
@@ -13288,9 +13449,9 @@ var TERMINATED = "the kernel is terminated";
13288
13449
  function nodeWorker(file, live, closed) {
13289
13450
  const errors = /* @__PURE__ */ new Set();
13290
13451
  const messages = /* @__PURE__ */ new Map();
13291
- const fail2 = (message2) => {
13452
+ const fail3 = (message3) => {
13292
13453
  for (const handler of [...errors]) {
13293
- handler({ message: message2, preventDefault() {
13454
+ handler({ message: message3, preventDefault() {
13294
13455
  } });
13295
13456
  }
13296
13457
  };
@@ -13298,16 +13459,16 @@ function nodeWorker(file, live, closed) {
13298
13459
  if (worker) {
13299
13460
  const kill = () => {
13300
13461
  void worker.terminate();
13301
- fail2(TERMINATED);
13462
+ fail3(TERMINATED);
13302
13463
  };
13303
13464
  live.add(kill);
13304
13465
  worker.once("exit", () => live.delete(kill));
13305
- worker.on("error", (err) => fail2(String(err)));
13466
+ worker.on("error", (err) => fail3(String(err)));
13306
13467
  } else {
13307
- setTimeout(() => fail2(TERMINATED), 0);
13468
+ setTimeout(() => fail3(TERMINATED), 0);
13308
13469
  }
13309
13470
  return {
13310
- postMessage: (message2, transfer) => worker?.postMessage(message2, transfer),
13471
+ postMessage: (message3, transfer) => worker?.postMessage(message3, transfer),
13311
13472
  addEventListener(type, handler) {
13312
13473
  if (type === "error") {
13313
13474
  errors.add(handler);