@ai-ecoverse/slicc-kernel 1.23.0 → 1.25.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
@@ -1499,6 +1499,56 @@ function prefixes(path) {
1499
1499
  function within(path, root) {
1500
1500
  return path === root || path.startsWith(`${root}/`);
1501
1501
  }
1502
+ var LOCKED = /* @__PURE__ */ new Set(["NotReadableError", "NoModificationAllowedError", "InvalidStateError"]);
1503
+ var SYNC_BACKOFF_MS = [5, 10, 20, 40, 80];
1504
+ async function openSync(handle) {
1505
+ const sync = handle.createSyncAccessHandle;
1506
+ if (!sync) return void 0;
1507
+ for (let attempt = 0; ; attempt++) {
1508
+ try {
1509
+ return await sync.call(handle, { mode: "readwrite-unsafe" });
1510
+ } catch (err) {
1511
+ const delay = SYNC_BACKOFF_MS[attempt];
1512
+ if (!LOCKED.has(err?.name)) throw err;
1513
+ if (delay === void 0) return void 0;
1514
+ await new Promise((resolve) => setTimeout(resolve, delay));
1515
+ }
1516
+ }
1517
+ }
1518
+ function writeAll(access, at, bytes) {
1519
+ for (let done4 = 0; done4 < bytes.length; ) {
1520
+ const n = access.write(bytes.subarray(done4), { at: at + done4 });
1521
+ if (!(n > 0))
1522
+ throw Object.assign(new Error("the file system took no more bytes"), { code: "ENOSPC" });
1523
+ done4 += n;
1524
+ }
1525
+ }
1526
+ async function positioned(handle, op) {
1527
+ const access = await openSync(handle);
1528
+ if (access) {
1529
+ try {
1530
+ op({
1531
+ write: (at, bytes) => writeAll(access, at, bytes),
1532
+ truncate: (n) => access.truncate(n)
1533
+ });
1534
+ access.flush();
1535
+ } finally {
1536
+ access.close();
1537
+ }
1538
+ return;
1539
+ }
1540
+ const writable = await handle.createWritable({ keepExistingData: true });
1541
+ try {
1542
+ await op({
1543
+ write: (at, bytes) => writable.write({ type: "write", position: at, data: bytes }),
1544
+ truncate: (n) => writable.truncate(n)
1545
+ });
1546
+ } catch (err) {
1547
+ await writable.abort();
1548
+ throw err;
1549
+ }
1550
+ await writable.close();
1551
+ }
1502
1552
  function isHandle(child) {
1503
1553
  return "kind" in child;
1504
1554
  }
@@ -1508,9 +1558,11 @@ var OpfsFs = class {
1508
1558
  dirs = /* @__PURE__ */ new Map();
1509
1559
  checked = /* @__PURE__ */ new WeakMap();
1510
1560
  channel;
1511
- constructor(root, meta = new MemoryMeta(), channel) {
1561
+ ranged;
1562
+ constructor(root, meta = new MemoryMeta(), channel, options = {}) {
1512
1563
  this.root = root;
1513
1564
  this.meta = meta;
1565
+ this.ranged = options.ranged === true;
1514
1566
  this.channel = channel === void 0 ? void 0 : new BroadcastChannel(channel);
1515
1567
  if (this.channel) {
1516
1568
  this.channel.onmessage = ({ data }) => {
@@ -1647,7 +1699,8 @@ var OpfsFs = class {
1647
1699
  mtime: new Date(mtime),
1648
1700
  atime: new Date(meta?.atimeMs ?? mtime),
1649
1701
  ctime: new Date(Math.max(meta?.ctimeMs ?? mtime, modified)),
1650
- ino: meta?.ino ?? inodeOf(path)
1702
+ ino: meta?.ino ?? inodeOf(path),
1703
+ ...this.ranged && !directory ? { ranged: true } : {}
1651
1704
  };
1652
1705
  }
1653
1706
  linkStat(entry) {
@@ -1681,20 +1734,47 @@ var OpfsFs = class {
1681
1734
  () => false
1682
1735
  );
1683
1736
  }
1684
- async readFileBuffer(path) {
1685
- const handle = (await this.locate(path, true)).handle;
1686
- if (handle.kind === "directory") throw fsError("EISDIR", path);
1737
+ async retrying(path, op, locks) {
1687
1738
  for (let attempt = 1; ; attempt++) {
1688
1739
  try {
1689
- return new Uint8Array(await (await handle.getFile()).arrayBuffer());
1740
+ return await op();
1690
1741
  } catch (err) {
1691
- if (err?.name !== "NotReadableError" || attempt >= READ_ATTEMPTS) {
1692
- throw translate(err, path);
1693
- }
1742
+ const name2 = err?.name;
1743
+ const again = name2 === "NotReadableError" || locks && LOCKED.has(name2);
1744
+ if (!again || attempt >= READ_ATTEMPTS) throw translate(err, path);
1694
1745
  await new Promise((resolve) => setTimeout(resolve, attempt * 10));
1695
1746
  }
1696
1747
  }
1697
1748
  }
1749
+ async existing(path) {
1750
+ const handle = (await this.locate(path, true)).handle;
1751
+ if (handle.kind === "directory") throw fsError("EISDIR", path);
1752
+ return handle;
1753
+ }
1754
+ async readFileBuffer(path) {
1755
+ const handle = await this.existing(path);
1756
+ return this.retrying(
1757
+ path,
1758
+ async () => new Uint8Array(await (await handle.getFile()).arrayBuffer()),
1759
+ false
1760
+ );
1761
+ }
1762
+ async pread(path, offset, length2) {
1763
+ const handle = await this.existing(path);
1764
+ return this.retrying(
1765
+ path,
1766
+ async () => new Uint8Array(await (await handle.getFile()).slice(offset, offset + length2).arrayBuffer()),
1767
+ false
1768
+ );
1769
+ }
1770
+ async pwrite(path, offset, bytes) {
1771
+ const handle = (await this.fileFor(path))[0];
1772
+ await this.retrying(path, () => positioned(handle, (io) => io.write(offset, bytes)), true);
1773
+ }
1774
+ async truncate(path, size) {
1775
+ const handle = await this.existing(path);
1776
+ await this.retrying(path, () => positioned(handle, (io) => io.truncate(size)), true);
1777
+ }
1698
1778
  async readFile(path) {
1699
1779
  return new TextDecoder().decode(await this.readFileBuffer(path));
1700
1780
  }
@@ -1708,16 +1788,21 @@ var OpfsFs = class {
1708
1788
  const wanted = entry?.link === void 0 ? path : resolvePath(parentOf2(path), entry.link);
1709
1789
  return [resolvePath((await this.locate(parentOf2(wanted), true)).path, baseOf(wanted)), false];
1710
1790
  }
1711
- async writeFile(path, content) {
1791
+ async fileFor(path) {
1712
1792
  const [target, existed] = await this.writeTarget(path);
1713
1793
  const [dir, name2] = await this.parent(target);
1714
- let file;
1715
1794
  try {
1716
- file = await this.inDir(dir, (parent) => parent.getFileHandle(name2, { create: true }));
1795
+ return [
1796
+ await this.inDir(dir, (parent) => parent.getFileHandle(name2, { create: true })),
1797
+ existed
1798
+ ];
1717
1799
  } catch (err) {
1718
1800
  const code = err?.name === "TypeMismatchError" ? "EISDIR" : null;
1719
1801
  throw code ? fsError(code, path) : translate(err, path);
1720
1802
  }
1803
+ }
1804
+ async writeFile(path, content) {
1805
+ const [file, existed] = await this.fileFor(path);
1721
1806
  if (!existed && content.length === 0) return;
1722
1807
  const writable = await file.createWritable();
1723
1808
  await writable.write(content);
@@ -3694,6 +3779,7 @@ var MountFs = class {
3694
3779
  async pread(path, offset, length2) {
3695
3780
  const real = await this.follow(path);
3696
3781
  const found = this.at(real);
3782
+ if (!found && this.base.pread) return this.base.pread(real, offset, length2);
3697
3783
  if (!found) return (await this.base.readFileBuffer(real)).slice(offset, offset + length2);
3698
3784
  const { mount, rel: rel2 } = found;
3699
3785
  if ((await this.table.getattr(mount, real, rel2)).kind === "directory") {
@@ -3731,6 +3817,7 @@ var MountFs = class {
3731
3817
  async pwrite(path, offset, bytes, transfer = false) {
3732
3818
  const real = await this.follow(path, 0, true);
3733
3819
  const found = this.at(real);
3820
+ if (!found && this.base.pwrite) return this.base.pwrite(real, offset, bytes);
3734
3821
  if (!found)
3735
3822
  return this.base.writeFile(
3736
3823
  real,
@@ -3762,6 +3849,7 @@ var MountFs = class {
3762
3849
  async truncate(path, size) {
3763
3850
  const real = await this.follow(path);
3764
3851
  const found = this.at(real);
3852
+ if (!found && this.base.truncate) return this.base.truncate(real, size);
3765
3853
  if (!found?.mount.caps.ranges) {
3766
3854
  return this.writeFile(real, resized(await this.readFileBuffer(real), size));
3767
3855
  }
@@ -9491,40 +9579,106 @@ function valid(name2) {
9491
9579
  throw new TypeError(`invalid name: ${name2}`);
9492
9580
  }
9493
9581
  }
9582
+ var CHUNK3 = 1024 * 1024;
9494
9583
  function bytesOf(data) {
9495
9584
  if (typeof data === "string") return new TextEncoder().encode(data);
9496
9585
  if (data instanceof Blob) return data.arrayBuffer().then((buffer) => new Uint8Array(buffer));
9497
9586
  if (ArrayBuffer.isView(data)) {
9498
- return new Uint8Array(data.buffer, data.byteOffset, data.byteLength).slice();
9587
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
9499
9588
  }
9500
- return new Uint8Array(data).slice();
9589
+ return new Uint8Array(data);
9501
9590
  }
9591
+ var isParams = (data) => ["write", "seek", "truncate"].includes(data?.type) && !(data instanceof Blob);
9592
+ var Chunks = class {
9593
+ blobs;
9594
+ size;
9595
+ constructor(blobs = [], size = 0) {
9596
+ this.blobs = blobs;
9597
+ this.size = size;
9598
+ }
9599
+ pad(index, length2) {
9600
+ const blob = this.blobs[index] ?? new Blob([]);
9601
+ if (blob.size < length2)
9602
+ this.blobs[index] = new Blob([blob, new Uint8Array(length2 - blob.size)]);
9603
+ }
9604
+ grow(end) {
9605
+ if (end <= this.size) return;
9606
+ const last = Math.floor((end - 1) / CHUNK3);
9607
+ for (let i = 0; i < last; i++) this.pad(i, CHUNK3);
9608
+ this.pad(last, end - last * CHUNK3);
9609
+ this.size = end;
9610
+ }
9611
+ async write(at, bytes) {
9612
+ if (bytes.length === 0) return;
9613
+ const first = Math.floor(at / CHUNK3);
9614
+ for (let i = 0; i < first; i++) this.pad(i, CHUNK3);
9615
+ for (let done4 = 0; done4 < bytes.length; ) {
9616
+ const index = Math.floor((at + done4) / CHUNK3);
9617
+ const from = at + done4 - index * CHUNK3;
9618
+ const n = Math.min(CHUNK3 - from, bytes.length - done4);
9619
+ const view = bytes.subarray(done4, done4 + n);
9620
+ const part = view.buffer instanceof ArrayBuffer ? view : view.slice();
9621
+ const old = this.blobs[index];
9622
+ if (from === 0 && n >= (old?.size ?? 0)) this.blobs[index] = new Blob([part]);
9623
+ else {
9624
+ const merged = new Uint8Array(Math.max(old?.size ?? 0, from + n));
9625
+ if (old) merged.set(new Uint8Array(await old.arrayBuffer()));
9626
+ merged.set(part, from);
9627
+ this.blobs[index] = new Blob([merged]);
9628
+ }
9629
+ done4 += n;
9630
+ }
9631
+ this.size = Math.max(this.size, at + bytes.length);
9632
+ }
9633
+ truncate(size) {
9634
+ if (size >= this.size) {
9635
+ this.grow(size);
9636
+ return;
9637
+ }
9638
+ const keep = Math.ceil(size / CHUNK3);
9639
+ this.blobs.length = keep;
9640
+ if (keep > 0)
9641
+ this.blobs[keep - 1] = this.blobs[keep - 1].slice(0, size - (keep - 1) * CHUNK3);
9642
+ this.size = size;
9643
+ }
9644
+ };
9502
9645
  var MemoryFile = class {
9503
9646
  kind = "file";
9504
9647
  name;
9505
9648
  parent;
9506
- bytes = new Uint8Array(0);
9649
+ data = new Chunks();
9507
9650
  lastModified = Date.now();
9508
9651
  constructor(name2, parent) {
9509
9652
  this.name = name2;
9510
9653
  this.parent = parent;
9511
9654
  }
9512
9655
  async getFile() {
9513
- return new File([this.bytes], this.name, { lastModified: this.lastModified });
9514
- }
9515
- async createWritable() {
9516
- const chunks2 = [];
9656
+ return new File(this.data.blobs, this.name, { lastModified: this.lastModified });
9657
+ }
9658
+ async createWritable({ keepExistingData = false } = {}) {
9659
+ const next = keepExistingData ? new Chunks([...this.data.blobs], this.data.size) : new Chunks();
9660
+ let position = 0;
9661
+ const put = async (data) => {
9662
+ const bytes = await bytesOf(data);
9663
+ await next.write(position, bytes);
9664
+ position += bytes.length;
9665
+ };
9517
9666
  return {
9518
- write: async (data) => void chunks2.push(await bytesOf(data)),
9667
+ write: async (data) => {
9668
+ if (!isParams(data)) return put(data);
9669
+ if (data.type === "truncate") return next.truncate(data.size ?? 0);
9670
+ position = data.position ?? position;
9671
+ if (data.type === "write") await put(data.data);
9672
+ },
9673
+ seek: async (at) => {
9674
+ position = at;
9675
+ },
9676
+ truncate: async (size) => next.truncate(size),
9519
9677
  close: async () => {
9520
- const out = new Uint8Array(chunks2.reduce((n, chunk2) => n + chunk2.length, 0));
9521
- let at = 0;
9522
- for (const chunk2 of chunks2) {
9523
- out.set(chunk2, at);
9524
- at += chunk2.length;
9525
- }
9526
- this.bytes = out;
9678
+ this.data = next;
9527
9679
  this.lastModified = Date.now();
9680
+ },
9681
+ abort: async () => {
9528
9682
  }
9529
9683
  };
9530
9684
  }
@@ -9617,6 +9771,9 @@ var MemoryDirectory = class _MemoryDirectory {
9617
9771
  function memoryRoot() {
9618
9772
  return new MemoryDirectory("", null);
9619
9773
  }
9774
+ function isMemoryRoot(handle) {
9775
+ return handle instanceof MemoryDirectory;
9776
+ }
9620
9777
 
9621
9778
  // src/kernel/net/remote-transport.ts
9622
9779
  var TransportError = class extends Error {
@@ -10388,7 +10545,7 @@ function textOf(on) {
10388
10545
  }
10389
10546
  async function createNodeKernel(options = {}) {
10390
10547
  const root = options.root ?? memoryRoot();
10391
- const fs = new OpfsFs(root);
10548
+ const fs = new OpfsFs(root, void 0, void 0, { ranged: isMemoryRoot(root) });
10392
10549
  await fs.reconcile();
10393
10550
  const live = /* @__PURE__ */ new Set();
10394
10551
  const pending = /* @__PURE__ */ new Set();