@ai-ecoverse/slicc-kernel 1.53.3 → 1.54.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
@@ -10369,9 +10369,11 @@ var JobTable = class {
10369
10369
  const member = this.member(pid);
10370
10370
  const id2 = this.idOf(pid);
10371
10371
  if (member.pgid === id2) throw new KernelError("EPERM");
10372
+ const left = member.pgid;
10372
10373
  member.sid = id2;
10373
10374
  member.pgid = id2;
10374
10375
  this.terminals.delete(id2);
10376
+ this.prune(left);
10375
10377
  return id2;
10376
10378
  }
10377
10379
  terminalNamed(name2) {
@@ -10415,18 +10417,18 @@ var JobTable = class {
10415
10417
  const inSession = [...this.members.values()].some((m) => m.pgid === pgid && m.sid === self.sid);
10416
10418
  if (!inSession) throw new KernelError("EPERM");
10417
10419
  const current = this.foreground.get(tty);
10418
- if (settling && pgid === self.pgid && current !== pgid && this.reclaimed(pgid, self.ppid))
10419
- return;
10420
- if (pgid !== self.pgid) this.handoffs.set(pgid, { by: caller, reclaimed: false });
10420
+ if (settling && pgid === self.pgid && current !== pgid && this.reclaimed(pgid, caller)) return;
10421
+ const by = this.shown(caller);
10422
+ if (pgid !== self.pgid) this.handoffs.set(pgid, { by, reclaimed: false });
10421
10423
  else if (current !== void 0) {
10422
10424
  const handoff = this.handoffs.get(current);
10423
- if (handoff?.by === caller) handoff.reclaimed = true;
10425
+ if (handoff?.by === by) handoff.reclaimed = true;
10424
10426
  }
10425
10427
  this.foreground.set(tty, pgid);
10426
10428
  }
10427
- reclaimed(pgid, parent) {
10429
+ reclaimed(pgid, caller) {
10428
10430
  const handoff = this.handoffs.get(pgid);
10429
- return handoff?.reclaimed === true && handoff.by === parent;
10431
+ return handoff?.reclaimed === true && handoff.by === this.shownParent(caller);
10430
10432
  }
10431
10433
  signalOwnedForeground(tty, sig) {
10432
10434
  const pgid = this.foreground.get(tty);
@@ -11154,7 +11156,7 @@ function hostfsHandlers(current) {
11154
11156
  const handles = /* @__PURE__ */ new Map();
11155
11157
  let nextFh = 0;
11156
11158
  const fresh = (remote) => {
11157
- if (remote.client.token === remote.token) return remote;
11159
+ if (remote.client.token === remote.token && !remote.client.gone) return remote;
11158
11160
  throw fsError2("ESTALE", "the folder was granted again, so this open file is gone");
11159
11161
  };
11160
11162
  const live = (fh) => {
@@ -11359,10 +11361,190 @@ function keepWatching(loop, signal) {
11359
11361
  function invalidation(event) {
11360
11362
  return event.paths ?? true;
11361
11363
  }
11362
- function grantConnect(hook, fetch2) {
11364
+ var PORT_REQUEST_MS = 6e4;
11365
+ var PORT_MS_PER_MIB = 1e3;
11366
+ var nextPortToken = 0;
11367
+ var PortTransport = class {
11368
+ capabilities;
11369
+ token;
11370
+ port;
11371
+ requestMs;
11372
+ waiting = /* @__PURE__ */ new Map();
11373
+ next = 0;
11374
+ dead;
11375
+ constructor(grant, requestMs = PORT_REQUEST_MS) {
11376
+ this.port = grant.port;
11377
+ this.requestMs = requestMs;
11378
+ this.capabilities = grant.capabilities ?? {};
11379
+ this.token = grant.token ?? `port-${++nextPortToken}`;
11380
+ this.port.addEventListener("message", (event) => {
11381
+ this.waiting.get(event.data?.id)?.(event.data);
11382
+ });
11383
+ this.port.addEventListener("close", () => this.fail("the folder's port closed"));
11384
+ this.port.start();
11385
+ }
11386
+ get maxIo() {
11387
+ return this.capabilities.maxIo ?? HOSTFS_IO;
11388
+ }
11389
+ get gone() {
11390
+ return this.dead !== void 0;
11391
+ }
11392
+ fail(why) {
11393
+ if (this.dead === void 0) this.port.close();
11394
+ this.dead ??= why;
11395
+ for (const settle of [...this.waiting.values()])
11396
+ settle({ id: 0, error: { code: "ENOTCONN", message: why } });
11397
+ }
11398
+ ask(message3, bytes = 0, transfer = []) {
11399
+ const id2 = ++this.next;
11400
+ if (this.dead) return Promise.reject(fsError2("ENOTCONN", this.dead));
11401
+ return new Promise((resolve, reject) => {
11402
+ const timer = setTimeout(
11403
+ () => {
11404
+ this.waiting.delete(id2);
11405
+ reject(fsError2("ETIMEDOUT", "the folder's port did not answer"));
11406
+ this.fail("the folder's port stopped answering");
11407
+ },
11408
+ this.requestMs + Math.ceil(bytes / 1048576) * PORT_MS_PER_MIB
11409
+ );
11410
+ this.waiting.set(id2, (reply) => {
11411
+ clearTimeout(timer);
11412
+ this.waiting.delete(id2);
11413
+ if (reply.error) reject(fsError2(reply.error.code ?? "EIO", reply.error.message ?? ""));
11414
+ else resolve(reply);
11415
+ });
11416
+ try {
11417
+ this.port.postMessage({ id: id2, ...message3 }, transfer);
11418
+ } catch (err) {
11419
+ this.fail(`the folder's port is closed: ${err.message}`);
11420
+ }
11421
+ });
11422
+ }
11423
+ async call(op, body = {}) {
11424
+ return (await this.ask({ op: "call", name: op, body })).result;
11425
+ }
11426
+ async read(fh, offset, size, ifMatch) {
11427
+ const reply = await this.ask(
11428
+ { op: "read", fh, offset, size, ...ifMatch ? { ifMatch } : {} },
11429
+ size
11430
+ );
11431
+ return reply.bytes ?? new Uint8Array(0);
11432
+ }
11433
+ async write(fh, offset, bytes) {
11434
+ await this.ask({ op: "write", fh, offset, bytes }, bytes.length);
11435
+ }
11436
+ watch(signal, onEvent, onOpen = () => void 0) {
11437
+ const id2 = ++this.next;
11438
+ if (this.dead) return Promise.reject(fsError2("ENOTCONN", this.dead));
11439
+ if (signal.aborted) {
11440
+ this.fail("the folder's watch ended");
11441
+ return Promise.resolve();
11442
+ }
11443
+ return new Promise((resolve, reject) => {
11444
+ const finish = () => {
11445
+ this.waiting.delete(id2);
11446
+ signal.removeEventListener("abort", stop);
11447
+ };
11448
+ const stop = () => {
11449
+ finish();
11450
+ try {
11451
+ this.port.postMessage({ id: id2, op: "unwatch" });
11452
+ } catch {
11453
+ }
11454
+ resolve();
11455
+ };
11456
+ this.waiting.set(id2, (reply) => {
11457
+ if (reply.open) return onOpen();
11458
+ if (reply.event) return onEvent(reply.event);
11459
+ finish();
11460
+ if (reply.error) reject(fsError2(reply.error.code ?? "ENOTCONN", reply.error.message ?? ""));
11461
+ else resolve();
11462
+ });
11463
+ signal.addEventListener("abort", stop, { once: true });
11464
+ try {
11465
+ this.port.postMessage({ id: id2, op: "watch" });
11466
+ } catch (err) {
11467
+ finish();
11468
+ reject(fsError2("ENOTCONN", `the folder's port is closed: ${err.message}`));
11469
+ }
11470
+ }).finally(() => this.fail("the folder's watch ended"));
11471
+ }
11472
+ };
11473
+ var errorOf = (err) => ({
11474
+ code: typeof codeOf4(err) === "string" ? codeOf4(err) : "EIO",
11475
+ message: err?.message ?? String(err)
11476
+ });
11477
+ function serveHostfsPort(port, transport) {
11478
+ const watches = /* @__PURE__ */ new Map();
11479
+ const send = (reply, transfer = []) => port.postMessage(reply, transfer);
11480
+ const listener = async ({
11481
+ data
11482
+ }) => {
11483
+ const { id: id2, op } = data;
11484
+ if (op === "unwatch") return watches.get(id2)?.abort();
11485
+ if (op === "watch") {
11486
+ const stop2 = new AbortController();
11487
+ watches.set(id2, stop2);
11488
+ try {
11489
+ await transport.watch(
11490
+ stop2.signal,
11491
+ (event) => send({ id: id2, event }),
11492
+ () => send({ id: id2, open: true })
11493
+ );
11494
+ send({ id: id2, end: true });
11495
+ } catch (err) {
11496
+ send({ id: id2, error: errorOf(err) });
11497
+ } finally {
11498
+ watches.delete(id2);
11499
+ }
11500
+ return;
11501
+ }
11502
+ try {
11503
+ if (op === "read") {
11504
+ const read = await transport.read(
11505
+ data.fh,
11506
+ data.offset,
11507
+ data.size,
11508
+ data.ifMatch
11509
+ );
11510
+ const bytes = read.slice();
11511
+ return send({ id: id2, bytes }, [bytes.buffer]);
11512
+ }
11513
+ if (op === "write") {
11514
+ await transport.write(data.fh, data.offset, data.bytes);
11515
+ return send({ id: id2 });
11516
+ }
11517
+ if (op !== "call") throw fsError2("EINVAL", `unknown hostfs port op ${op}`);
11518
+ send({
11519
+ id: id2,
11520
+ result: await transport.call(data.name, data.body)
11521
+ });
11522
+ } catch (err) {
11523
+ send({ id: id2, error: errorOf(err) });
11524
+ }
11525
+ };
11526
+ const stop = () => {
11527
+ port.removeEventListener("message", listener);
11528
+ port.removeEventListener("close", stop);
11529
+ for (const watch of watches.values()) watch.abort();
11530
+ port.close();
11531
+ };
11532
+ port.addEventListener("message", listener);
11533
+ port.addEventListener("close", stop);
11534
+ port.start();
11535
+ return stop;
11536
+ }
11537
+ function grantConnect(hook, fetch2, requestMs) {
11363
11538
  return async (source, options) => {
11364
- const grant = () => hook(source, options);
11365
- return new HostfsClient(await grant(), grant, fetch2);
11539
+ const first = await hook(source, options);
11540
+ if ("port" in first) return new PortTransport(first, requestMs);
11541
+ const grant = async () => {
11542
+ const again = await hook(source, options);
11543
+ if ("port" in again)
11544
+ throw fsError2("ESTALE", "the folder moved to a port, so its open files are gone");
11545
+ return again;
11546
+ };
11547
+ return new HostfsClient(first, grant, fetch2);
11366
11548
  };
11367
11549
  }
11368
11550
  async function openHostfs(spec, connect, timing = {}) {
@@ -12417,7 +12599,11 @@ var Launcher = class {
12417
12599
  throw fsError("ENODEV", "this kernel has no hostfs hook (createKernel({ hostfs }))");
12418
12600
  return openHostfs(
12419
12601
  spec,
12420
- grantConnect(hostfs, hostfsFetch ?? ((url, init) => fetch(url, init))),
12602
+ grantConnect(
12603
+ hostfs,
12604
+ hostfsFetch ?? ((url, init) => fetch(url, init)),
12605
+ hostfsTiming?.requestMs
12606
+ ),
12421
12607
  hostfsTiming
12422
12608
  );
12423
12609
  }
@@ -13874,6 +14060,7 @@ export {
13874
14060
  createNodeKernel,
13875
14061
  fetchTransport,
13876
14062
  memoryRoot,
13877
- nodeTransport
14063
+ nodeTransport,
14064
+ serveHostfsPort
13878
14065
  };
13879
14066
  //# sourceMappingURL=node.js.map