@ai-ecoverse/slicc-kernel 1.53.4 → 1.54.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
@@ -10461,6 +10461,9 @@ function fingerprint(headers) {
10461
10461
  const fields = MATCHED.map((name2) => header2(headers, name2) ?? "");
10462
10462
  return JSON.stringify([...fields, header2(headers, "authorization") !== void 0]);
10463
10463
  }
10464
+ function unauthorized(print) {
10465
+ return JSON.stringify([...JSON.parse(print).slice(0, -1), false]);
10466
+ }
10464
10467
  function followedWith(status, method) {
10465
10468
  if (status === 303 && method !== "GET" && method !== "HEAD") return "GET";
10466
10469
  if ((status === 301 || status === 302) && method === "POST") return "GET";
@@ -10501,9 +10504,17 @@ function replayingHops(inner, heldMs = HELD_MS) {
10501
10504
  const [hop, ...rest2] = chain.hops;
10502
10505
  const location = hop && header2(hop.headers, "location");
10503
10506
  if (!hop || location === void 0) return chain.final;
10504
- const next2 = new URL(location, hop.url).href;
10507
+ const target = new URL(location, hop.url);
10508
+ target.hash = "";
10505
10509
  const method = followedWith(hop.status, chain.method);
10506
- hold(keyOf2(chain.owner, method, next2), { ...chain, method, hops: rest2 });
10510
+ const away = target.origin !== new URL(hop.url).origin;
10511
+ const print = away ? unauthorized(chain.fingerprint) : chain.fingerprint;
10512
+ hold(keyOf2(chain.owner, method, target.href), {
10513
+ ...chain,
10514
+ method,
10515
+ fingerprint: print,
10516
+ hops: rest2
10517
+ });
10507
10518
  return bodiless(hop);
10508
10519
  };
10509
10520
  return {
@@ -11156,7 +11167,7 @@ function hostfsHandlers(current) {
11156
11167
  const handles = /* @__PURE__ */ new Map();
11157
11168
  let nextFh = 0;
11158
11169
  const fresh = (remote) => {
11159
- if (remote.client.token === remote.token) return remote;
11170
+ if (remote.client.token === remote.token && !remote.client.gone) return remote;
11160
11171
  throw fsError2("ESTALE", "the folder was granted again, so this open file is gone");
11161
11172
  };
11162
11173
  const live = (fh) => {
@@ -11361,10 +11372,190 @@ function keepWatching(loop, signal) {
11361
11372
  function invalidation(event) {
11362
11373
  return event.paths ?? true;
11363
11374
  }
11364
- function grantConnect(hook, fetch2) {
11375
+ var PORT_REQUEST_MS = 6e4;
11376
+ var PORT_MS_PER_MIB = 1e3;
11377
+ var nextPortToken = 0;
11378
+ var PortTransport = class {
11379
+ capabilities;
11380
+ token;
11381
+ port;
11382
+ requestMs;
11383
+ waiting = /* @__PURE__ */ new Map();
11384
+ next = 0;
11385
+ dead;
11386
+ constructor(grant, requestMs = PORT_REQUEST_MS) {
11387
+ this.port = grant.port;
11388
+ this.requestMs = requestMs;
11389
+ this.capabilities = grant.capabilities ?? {};
11390
+ this.token = grant.token ?? `port-${++nextPortToken}`;
11391
+ this.port.addEventListener("message", (event) => {
11392
+ this.waiting.get(event.data?.id)?.(event.data);
11393
+ });
11394
+ this.port.addEventListener("close", () => this.fail("the folder's port closed"));
11395
+ this.port.start();
11396
+ }
11397
+ get maxIo() {
11398
+ return this.capabilities.maxIo ?? HOSTFS_IO;
11399
+ }
11400
+ get gone() {
11401
+ return this.dead !== void 0;
11402
+ }
11403
+ fail(why) {
11404
+ if (this.dead === void 0) this.port.close();
11405
+ this.dead ??= why;
11406
+ for (const settle of [...this.waiting.values()])
11407
+ settle({ id: 0, error: { code: "ENOTCONN", message: why } });
11408
+ }
11409
+ ask(message3, bytes = 0, transfer = []) {
11410
+ const id2 = ++this.next;
11411
+ if (this.dead) return Promise.reject(fsError2("ENOTCONN", this.dead));
11412
+ return new Promise((resolve, reject) => {
11413
+ const timer = setTimeout(
11414
+ () => {
11415
+ this.waiting.delete(id2);
11416
+ reject(fsError2("ETIMEDOUT", "the folder's port did not answer"));
11417
+ this.fail("the folder's port stopped answering");
11418
+ },
11419
+ this.requestMs + Math.ceil(bytes / 1048576) * PORT_MS_PER_MIB
11420
+ );
11421
+ this.waiting.set(id2, (reply) => {
11422
+ clearTimeout(timer);
11423
+ this.waiting.delete(id2);
11424
+ if (reply.error) reject(fsError2(reply.error.code ?? "EIO", reply.error.message ?? ""));
11425
+ else resolve(reply);
11426
+ });
11427
+ try {
11428
+ this.port.postMessage({ id: id2, ...message3 }, transfer);
11429
+ } catch (err) {
11430
+ this.fail(`the folder's port is closed: ${err.message}`);
11431
+ }
11432
+ });
11433
+ }
11434
+ async call(op, body = {}) {
11435
+ return (await this.ask({ op: "call", name: op, body })).result;
11436
+ }
11437
+ async read(fh, offset, size, ifMatch) {
11438
+ const reply = await this.ask(
11439
+ { op: "read", fh, offset, size, ...ifMatch ? { ifMatch } : {} },
11440
+ size
11441
+ );
11442
+ return reply.bytes ?? new Uint8Array(0);
11443
+ }
11444
+ async write(fh, offset, bytes) {
11445
+ await this.ask({ op: "write", fh, offset, bytes }, bytes.length);
11446
+ }
11447
+ watch(signal, onEvent, onOpen = () => void 0) {
11448
+ const id2 = ++this.next;
11449
+ if (this.dead) return Promise.reject(fsError2("ENOTCONN", this.dead));
11450
+ if (signal.aborted) {
11451
+ this.fail("the folder's watch ended");
11452
+ return Promise.resolve();
11453
+ }
11454
+ return new Promise((resolve, reject) => {
11455
+ const finish = () => {
11456
+ this.waiting.delete(id2);
11457
+ signal.removeEventListener("abort", stop);
11458
+ };
11459
+ const stop = () => {
11460
+ finish();
11461
+ try {
11462
+ this.port.postMessage({ id: id2, op: "unwatch" });
11463
+ } catch {
11464
+ }
11465
+ resolve();
11466
+ };
11467
+ this.waiting.set(id2, (reply) => {
11468
+ if (reply.open) return onOpen();
11469
+ if (reply.event) return onEvent(reply.event);
11470
+ finish();
11471
+ if (reply.error) reject(fsError2(reply.error.code ?? "ENOTCONN", reply.error.message ?? ""));
11472
+ else resolve();
11473
+ });
11474
+ signal.addEventListener("abort", stop, { once: true });
11475
+ try {
11476
+ this.port.postMessage({ id: id2, op: "watch" });
11477
+ } catch (err) {
11478
+ finish();
11479
+ reject(fsError2("ENOTCONN", `the folder's port is closed: ${err.message}`));
11480
+ }
11481
+ }).finally(() => this.fail("the folder's watch ended"));
11482
+ }
11483
+ };
11484
+ var errorOf = (err) => ({
11485
+ code: typeof codeOf4(err) === "string" ? codeOf4(err) : "EIO",
11486
+ message: err?.message ?? String(err)
11487
+ });
11488
+ function serveHostfsPort(port, transport) {
11489
+ const watches = /* @__PURE__ */ new Map();
11490
+ const send = (reply, transfer = []) => port.postMessage(reply, transfer);
11491
+ const listener = async ({
11492
+ data
11493
+ }) => {
11494
+ const { id: id2, op } = data;
11495
+ if (op === "unwatch") return watches.get(id2)?.abort();
11496
+ if (op === "watch") {
11497
+ const stop2 = new AbortController();
11498
+ watches.set(id2, stop2);
11499
+ try {
11500
+ await transport.watch(
11501
+ stop2.signal,
11502
+ (event) => send({ id: id2, event }),
11503
+ () => send({ id: id2, open: true })
11504
+ );
11505
+ send({ id: id2, end: true });
11506
+ } catch (err) {
11507
+ send({ id: id2, error: errorOf(err) });
11508
+ } finally {
11509
+ watches.delete(id2);
11510
+ }
11511
+ return;
11512
+ }
11513
+ try {
11514
+ if (op === "read") {
11515
+ const read = await transport.read(
11516
+ data.fh,
11517
+ data.offset,
11518
+ data.size,
11519
+ data.ifMatch
11520
+ );
11521
+ const bytes = read.slice();
11522
+ return send({ id: id2, bytes }, [bytes.buffer]);
11523
+ }
11524
+ if (op === "write") {
11525
+ await transport.write(data.fh, data.offset, data.bytes);
11526
+ return send({ id: id2 });
11527
+ }
11528
+ if (op !== "call") throw fsError2("EINVAL", `unknown hostfs port op ${op}`);
11529
+ send({
11530
+ id: id2,
11531
+ result: await transport.call(data.name, data.body)
11532
+ });
11533
+ } catch (err) {
11534
+ send({ id: id2, error: errorOf(err) });
11535
+ }
11536
+ };
11537
+ const stop = () => {
11538
+ port.removeEventListener("message", listener);
11539
+ port.removeEventListener("close", stop);
11540
+ for (const watch of watches.values()) watch.abort();
11541
+ port.close();
11542
+ };
11543
+ port.addEventListener("message", listener);
11544
+ port.addEventListener("close", stop);
11545
+ port.start();
11546
+ return stop;
11547
+ }
11548
+ function grantConnect(hook, fetch2, requestMs) {
11365
11549
  return async (source, options) => {
11366
- const grant = () => hook(source, options);
11367
- return new HostfsClient(await grant(), grant, fetch2);
11550
+ const first = await hook(source, options);
11551
+ if ("port" in first) return new PortTransport(first, requestMs);
11552
+ const grant = async () => {
11553
+ const again = await hook(source, options);
11554
+ if ("port" in again)
11555
+ throw fsError2("ESTALE", "the folder moved to a port, so its open files are gone");
11556
+ return again;
11557
+ };
11558
+ return new HostfsClient(first, grant, fetch2);
11368
11559
  };
11369
11560
  }
11370
11561
  async function openHostfs(spec, connect, timing = {}) {
@@ -12419,7 +12610,11 @@ var Launcher = class {
12419
12610
  throw fsError("ENODEV", "this kernel has no hostfs hook (createKernel({ hostfs }))");
12420
12611
  return openHostfs(
12421
12612
  spec,
12422
- grantConnect(hostfs, hostfsFetch ?? ((url, init) => fetch(url, init))),
12613
+ grantConnect(
12614
+ hostfs,
12615
+ hostfsFetch ?? ((url, init) => fetch(url, init)),
12616
+ hostfsTiming?.requestMs
12617
+ ),
12423
12618
  hostfsTiming
12424
12619
  );
12425
12620
  }
@@ -13693,6 +13888,7 @@ function nodeTransport() {
13693
13888
  return { ...transport, traits: { ...transport.traits, crossOrigin: "any" } };
13694
13889
  }
13695
13890
  var TERMINATED = "the kernel is terminated";
13891
+ var EXIT_GRACE_MS = 50;
13696
13892
  function nodeWorker(file, live, closed) {
13697
13893
  const errors = /* @__PURE__ */ new Set();
13698
13894
  const messages = /* @__PURE__ */ new Map();
@@ -13713,7 +13909,9 @@ function nodeWorker(file, live, closed) {
13713
13909
  live.add(kill);
13714
13910
  worker.once("exit", (code) => {
13715
13911
  live.delete(kill);
13716
- if (!ending) fail3(`the process worker exited with ${code}`);
13912
+ setTimeout(() => {
13913
+ if (!ending) fail3(`the process worker exited with ${code}`);
13914
+ }, EXIT_GRACE_MS);
13717
13915
  });
13718
13916
  worker.on("error", (err) => fail3(String(err)));
13719
13917
  } else {
@@ -13876,6 +14074,7 @@ export {
13876
14074
  createNodeKernel,
13877
14075
  fetchTransport,
13878
14076
  memoryRoot,
13879
- nodeTransport
14077
+ nodeTransport,
14078
+ serveHostfsPort
13880
14079
  };
13881
14080
  //# sourceMappingURL=node.js.map