@ai-ecoverse/slicc-kernel 1.25.0 → 1.26.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.
@@ -3749,6 +3749,7 @@ Sec-WebSocket-Accept: ${accept2}\r
3749
3749
  // src/cdp/facade.ts
3750
3750
  var MAX_HEAD = 64 * 1024;
3751
3751
  var LIST_TIMEOUT = 1e4;
3752
+ var CLOSE_WAIT_MS = 1e3;
3752
3753
  function respond(status, body, type = "text/plain; charset=utf-8") {
3753
3754
  const bytes = new TextEncoder().encode(body);
3754
3755
  const head = latin1Bytes(
@@ -3894,7 +3895,11 @@ var CdpFacade = class {
3894
3895
  async upgrade(conn, incoming, req, runtime) {
3895
3896
  const accept2 = await acceptKey(req.headers);
3896
3897
  const host = await this.host(runtime);
3897
- await new Relay(conn, incoming, host, this.options.maxMessage ?? MAX_MESSAGE, this.stop.signal).start(switchingHead(accept2)).finally(() => host.close());
3898
+ const limits = {
3899
+ max: this.options.maxMessage ?? MAX_MESSAGE,
3900
+ closeWaitMs: this.options.closeWaitMs ?? CLOSE_WAIT_MS
3901
+ };
3902
+ await new Relay(conn, incoming, host, limits, this.stop.signal).start(switchingHead(accept2)).finally(() => host.close());
3898
3903
  }
3899
3904
  };
3900
3905
  var Relay = class {
@@ -3904,12 +3909,14 @@ var Relay = class {
3904
3909
  incoming;
3905
3910
  host;
3906
3911
  max;
3912
+ closeWaitMs;
3907
3913
  stop;
3908
- constructor(conn, incoming, host, max, stop) {
3914
+ constructor(conn, incoming, host, limits, stop) {
3909
3915
  this.conn = conn;
3910
3916
  this.incoming = incoming;
3911
3917
  this.host = host;
3912
- this.max = max;
3918
+ this.max = limits.max;
3919
+ this.closeWaitMs = limits.closeWaitMs;
3913
3920
  this.stop = stop;
3914
3921
  }
3915
3922
  send(bytes) {
@@ -3935,8 +3942,15 @@ var Relay = class {
3935
3942
  void this.end(CLOSE.tooBig, `a message is over ${this.max} bytes`);
3936
3943
  else void this.send(frame(OP_TEXT, bytes));
3937
3944
  };
3938
- await Promise.race([this.pump(), hostGone]);
3945
+ const pumping = this.pump();
3946
+ await Promise.race([pumping, hostGone]);
3939
3947
  await this.writes;
3948
+ let timer;
3949
+ const waited = new Promise((resolve) => {
3950
+ timer = setTimeout(resolve, this.closeWaitMs);
3951
+ });
3952
+ await Promise.race([pumping, waited]);
3953
+ clearTimeout(timer);
3940
3954
  }
3941
3955
  async pump() {
3942
3956
  const reader = new WsReader(this.incoming, this.max);
@@ -4736,7 +4750,8 @@ function statOf(attr, path, mount) {
4736
4750
  dev: mount.dev,
4737
4751
  ...readonly(mount) ? { readonly: true } : {},
4738
4752
  ...mount.maxFile > 0 ? { maxFile: mount.maxFile } : {},
4739
- ...mount.caps.ranges ? { ranged: true } : {}
4753
+ ...mount.caps.ranges ? { ranged: true } : {},
4754
+ ...attr.etag !== void 0 ? { version: attr.etag } : {}
4740
4755
  };
4741
4756
  }
4742
4757
  function concat4(chunks, total) {
@@ -5071,7 +5086,7 @@ var MountFs = class {
5071
5086
  this.table.forget(mount, real);
5072
5087
  }
5073
5088
  }
5074
- async pread(path, offset, length2) {
5089
+ async pread(path, offset, length2, version) {
5075
5090
  const real = await this.follow(path);
5076
5091
  const found = this.at(real);
5077
5092
  if (!found && this.base.pread) return this.base.pread(real, offset, length2);
@@ -5080,7 +5095,15 @@ var MountFs = class {
5080
5095
  if ((await this.table.getattr(mount, real, rel2)).kind === "directory") {
5081
5096
  throw errnoError("EISDIR", real);
5082
5097
  }
5083
- const fh = await this.open(mount, rel2, false);
5098
+ const fh = await mount.conn.call({
5099
+ op: "open",
5100
+ path: rel2,
5101
+ write: false,
5102
+ create: false,
5103
+ truncate: false,
5104
+ exclusive: false,
5105
+ ...version !== void 0 ? { ifMatch: version } : {}
5106
+ });
5084
5107
  const chunk2 = mount.caps.maxIo ?? DEFAULT_IO;
5085
5108
  const chunks = [];
5086
5109
  let total = 0;
@@ -5342,7 +5365,8 @@ function statJson(s) {
5342
5365
  ...s.dev !== void 0 ? { dev: s.dev } : {},
5343
5366
  ...s.readonly ? { readonly: true } : {},
5344
5367
  ...s.maxFile ? { maxFile: s.maxFile } : {},
5345
- ...s.ranged ? { ranged: true } : {}
5368
+ ...s.ranged ? { ranged: true } : {},
5369
+ ...s.version !== void 0 ? { version: s.version } : {}
5346
5370
  };
5347
5371
  }
5348
5372
  async function readdirStat(fs, dir) {
@@ -5420,7 +5444,11 @@ async function ranged(fs, path, req) {
5420
5444
  if (!ops) throw syncError("ENOSYS", path);
5421
5445
  const offset = req.offset ?? 0;
5422
5446
  if (req.op === "pread")
5423
- return { ok: true, kind: "bytes", bytes: await ops.pread(path, offset, req.length ?? 0) };
5447
+ return {
5448
+ ok: true,
5449
+ kind: "bytes",
5450
+ bytes: await ops.pread(path, offset, req.length ?? 0, req.version)
5451
+ };
5424
5452
  if (req.op === "pwrite") await ops.pwrite(path, offset, req.body ?? new Uint8Array(0), true);
5425
5453
  else await ops.truncate(path, req.length ?? 0);
5426
5454
  return done;
@@ -6611,17 +6639,21 @@ var AsyncRangedFile = class {
6611
6639
  pages;
6612
6640
  io;
6613
6641
  pinned = false;
6642
+ version;
6614
6643
  path;
6615
- constructor(io, path, size) {
6644
+ constructor(io, path, size, version) {
6616
6645
  this.io = io;
6617
6646
  this.path = path;
6647
+ this.version = version;
6618
6648
  this.pages = new Pages(size);
6619
6649
  }
6620
6650
  size() {
6621
6651
  return this.pages.length;
6622
6652
  }
6623
6653
  async fetch(runs) {
6624
- for (const [start, n] of runs) this.pages.fill(start, await this.io.pread(this.path, start, n));
6654
+ for (const [start, n] of runs) {
6655
+ this.pages.fill(start, await this.io.pread(this.path, start, n, this.version));
6656
+ }
6625
6657
  }
6626
6658
  async read(at, length2) {
6627
6659
  await this.fetch(this.pages.missing(at, length2));
@@ -6641,6 +6673,7 @@ var AsyncRangedFile = class {
6641
6673
  if (plan.shrink !== void 0) await this.io.truncate(this.path, plan.shrink);
6642
6674
  for (const run2 of plan.runs) await this.io.pwrite(this.path, run2.offset, run2.bytes, true);
6643
6675
  if (plan.extend !== void 0) await this.io.truncate(this.path, plan.extend);
6676
+ this.version = void 0;
6644
6677
  this.pages.flushed();
6645
6678
  }
6646
6679
  async pin() {
@@ -6708,7 +6741,7 @@ var VfsNode = class {
6708
6741
  const io = rangedOps(this.fs);
6709
6742
  const st = io && !this.orphaned ? await this.fs.stat?.(this.path).catch(() => void 0) : void 0;
6710
6743
  if (io && st?.ranged) {
6711
- this.ranged = new AsyncRangedFile(io, this.path, st.size ?? 0);
6744
+ this.ranged = new AsyncRangedFile(io, this.path, st.size ?? 0, st.version);
6712
6745
  return this.ranged;
6713
6746
  }
6714
6747
  await this.load();
@@ -8002,7 +8035,8 @@ async function dispatch(h, req) {
8002
8035
  write: req.write,
8003
8036
  create: req.create,
8004
8037
  truncate: req.truncate,
8005
- exclusive: req.exclusive
8038
+ exclusive: req.exclusive,
8039
+ ...req.ifMatch !== void 0 ? { ifMatch: req.ifMatch } : {}
8006
8040
  });
8007
8041
  case "read":
8008
8042
  return h.read(req.fh, req.offset, req.size);
@@ -8543,7 +8577,8 @@ function hostfsHandlers(current) {
8543
8577
  };
8544
8578
  const call = (op, body = {}) => current().call(op, body);
8545
8579
  async function writable(client, path, flags) {
8546
- const opening = () => client.call("open", { path: rel(path), ...flags });
8580
+ const { ifMatch: _, ...asked } = flags;
8581
+ const opening = () => client.call("open", { path: rel(path), ...asked });
8547
8582
  try {
8548
8583
  return { opened: await opening(), restore: void 0 };
8549
8584
  } catch (err) {
@@ -8559,7 +8594,7 @@ function hostfsHandlers(current) {
8559
8594
  return { opened: opened2, restore };
8560
8595
  }
8561
8596
  }
8562
- return {
8597
+ const handlers = {
8563
8598
  getattr: async (path) => await call("stat", { path: rel(path) }),
8564
8599
  async readdir(path) {
8565
8600
  const { entries } = await call(
@@ -8572,6 +8607,10 @@ function hostfsHandlers(current) {
8572
8607
  const client = current();
8573
8608
  const token = client.token;
8574
8609
  const { opened: opened2, restore } = await writable(client, path, flags);
8610
+ if (flags.ifMatch !== void 0 && opened2.attr?.etag !== flags.ifMatch) {
8611
+ await client.call("release", { fh: opened2.fh }, true);
8612
+ throw fsError2("ESTALE", `${path} changed on the host while it was being read`);
8613
+ }
8575
8614
  handles.set(++nextFh, {
8576
8615
  client,
8577
8616
  token,
@@ -8613,9 +8652,44 @@ function hostfsHandlers(current) {
8613
8652
  rename: async (from, to) => void await call("rename", { from: rel(from), to: rel(to) }),
8614
8653
  symlink: async (target, path) => void await call("symlink", { target, path: rel(path) }),
8615
8654
  readlink: async (path) => (await call("readlink", { path: rel(path) })).target,
8616
- setattr: async (path, change) => void await call("setattr", { path: rel(path), ...change }),
8655
+ async setattr(path, { size, ...change }) {
8656
+ if (size !== void 0 && !current().capabilities.ranges) await resize(handlers, path, size);
8657
+ else if (size !== void 0) change = { ...change, size };
8658
+ if (Object.keys(change).length > 0) await call("setattr", { path: rel(path), ...change });
8659
+ },
8617
8660
  statfs: () => call("statfs")
8618
8661
  };
8662
+ return handlers;
8663
+ }
8664
+ var KEEP = { write: false, create: false, truncate: false, exclusive: false };
8665
+ async function resize(h, path, size) {
8666
+ const was = (await h.getattr(path)).size;
8667
+ if (size === was) return;
8668
+ const kept = [];
8669
+ if (size < was && size > 0) {
8670
+ const fh2 = await h.open(path, KEEP);
8671
+ try {
8672
+ for (let at = 0; at < size; ) {
8673
+ const bytes = await h.read(fh2, at, size - at);
8674
+ if (bytes.length === 0) break;
8675
+ kept.push(bytes);
8676
+ at += bytes.length;
8677
+ }
8678
+ } finally {
8679
+ await h.release(fh2);
8680
+ }
8681
+ }
8682
+ const fh = await h.open(path, { ...KEEP, write: true, truncate: size < was });
8683
+ try {
8684
+ if (size > was) await h.write(fh, size - 1, new Uint8Array(1));
8685
+ let at = 0;
8686
+ for (const bytes of kept) {
8687
+ await h.write(fh, at, bytes);
8688
+ at += bytes.length;
8689
+ }
8690
+ } finally {
8691
+ await h.release(fh);
8692
+ }
8619
8693
  }
8620
8694
  function sleep(ms, signal) {
8621
8695
  return new Promise((resolve) => {
@@ -8709,13 +8783,18 @@ async function openHostfs(spec, hook, fetch2, timing = {}) {
8709
8783
  const grant = () => hook(spec.source, { readonly: readonly2 });
8710
8784
  let active;
8711
8785
  const handlers = hostfsHandlers(() => active);
8712
- const served = serveFilesystem(port2, slot.handlers, {
8713
- symlinks: true,
8714
- chmod: true,
8715
- listingStats: true,
8716
- maxIo: HOSTFS_IO,
8717
- ...readonly2 ? { readonly: true } : {}
8718
- });
8786
+ const ranged2 = () => active?.capabilities.ranges === true ? { ranges: true } : {};
8787
+ const served = serveFilesystem(
8788
+ port2,
8789
+ { ...slot.handlers, mount: ranged2 },
8790
+ {
8791
+ symlinks: true,
8792
+ chmod: true,
8793
+ listingStats: true,
8794
+ maxIo: HOSTFS_IO,
8795
+ ...readonly2 ? { readonly: true } : {}
8796
+ }
8797
+ );
8719
8798
  const watching = keepWatching(
8720
8799
  {
8721
8800
  connect: async () => new HostfsClient(await grant(), grant, fetch2),