@ai-ecoverse/slicc-kernel 1.54.2 → 1.54.4

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.
@@ -1022,7 +1022,7 @@ function openAccess(existing, oflags, rights) {
1022
1022
  return { readable: (rights & RIGHTS.FD_READ) !== 0n || !writable2, writable: writable2 };
1023
1023
  }
1024
1024
  function promoteRequest(fd, f, handed) {
1025
- const orphan = f.buffer.isOrphan();
1025
+ const orphan = f.buffer.isOrphan() || (f.buffer.handle ?? 0) < 0;
1026
1026
  if (!orphan && f.buffer.isRanged) f.buffer.flush();
1027
1027
  const joins = !orphan && (handed.has(f.buffer) || f.buffer.isRanged);
1028
1028
  return {
@@ -8713,60 +8713,201 @@ var init_wasi_module = __esm({
8713
8713
  function inProc(path) {
8714
8714
  return path === "/proc" || path.startsWith("/proc/");
8715
8715
  }
8716
+ function* procWalk(path, follow2) {
8717
+ let done = [];
8718
+ let todo = path.split("/").filter((part) => part !== "");
8719
+ let hops = 0;
8720
+ while (todo.length > 0) {
8721
+ const part = todo.shift();
8722
+ if (part === ".") continue;
8723
+ if (part === "..") {
8724
+ done.pop();
8725
+ continue;
8726
+ }
8727
+ const at = `/${[...done, part].join("/")}`;
8728
+ const whole = normalize(`/${[...done, part, ...todo].join("/")}`);
8729
+ if (inProc(at) && inProc(whole)) return whole;
8730
+ if (!follow2 && todo.length === 0) return void 0;
8731
+ const target = yield at;
8732
+ if (target === null) return void 0;
8733
+ if (target === void 0) done.push(part);
8734
+ else {
8735
+ if (++hops > MAX_HOPS2) return void 0;
8736
+ if (target.startsWith("/")) done = [];
8737
+ todo = [...target.split("/").filter((part2) => part2 !== ""), ...todo];
8738
+ }
8739
+ }
8740
+ return void 0;
8741
+ }
8742
+ function procPath(fs, path, follow2) {
8743
+ const walk = procWalk(path, follow2);
8744
+ let step = walk.next();
8745
+ while (!step.done) {
8746
+ let target;
8747
+ try {
8748
+ target = fs.lstat(step.value).isSymbolicLink ? fs.readlink(step.value) : void 0;
8749
+ } catch {
8750
+ target = null;
8751
+ }
8752
+ step = walk.next(target);
8753
+ }
8754
+ return step.value;
8755
+ }
8756
+ function frozen(bytes) {
8757
+ const refuse = () => {
8758
+ throw syncError("EROFS", "/proc");
8759
+ };
8760
+ return {
8761
+ readFile: () => bytes,
8762
+ pread: (_p, at, n) => bytes.subarray(at, at + n),
8763
+ writeFile: refuse,
8764
+ pwrite: refuse,
8765
+ truncate: refuse
8766
+ };
8767
+ }
8716
8768
  function procfsBridge(fs, tree) {
8769
+ const toProc = (path, follow2) => procPath(fs, path, follow2);
8770
+ const shadowing = () => {
8771
+ try {
8772
+ return fs.exists("/proc");
8773
+ } catch {
8774
+ return false;
8775
+ }
8776
+ };
8777
+ const via = (p, proc, own, follow2 = true) => {
8778
+ if (inProc(p)) return proc(p);
8779
+ if (shadowing()) {
8780
+ const real = toProc(p, follow2);
8781
+ if (real !== void 0) return proc(real);
8782
+ }
8783
+ try {
8784
+ return own();
8785
+ } catch (err) {
8786
+ const real = toProc(p, follow2);
8787
+ if (real === void 0) throw err;
8788
+ return proc(real);
8789
+ }
8790
+ };
8791
+ const readOnly = (paths, run) => {
8792
+ const physical = shadowing();
8793
+ for (const [p, follow2] of paths) {
8794
+ if (inProc(p) || physical && toProc(p, follow2) !== void 0) throw syncError("EROFS", p);
8795
+ }
8796
+ return run();
8797
+ };
8798
+ const snapshots = /* @__PURE__ */ new Map();
8799
+ let lastSnapshot = 0;
8800
+ const snapshot = (q) => {
8801
+ lastSnapshot--;
8802
+ snapshots.set(lastSnapshot, tree.read(q));
8803
+ return lastSnapshot;
8804
+ };
8805
+ const late = (p) => {
8806
+ const q = toProc(p, true);
8807
+ return q === void 0 ? void 0 : snapshot(q);
8808
+ };
8717
8809
  const over = {
8718
- readFile: (p) => inProc(p) ? tree.read(p) : fs.readFile(p),
8719
- stat: (p) => inProc(p) ? tree.stat(p) : fs.stat(p),
8720
- lstat: (p) => inProc(p) ? tree.stat(p, false) : fs.lstat(p),
8721
- readdir: (p) => {
8722
- if (inProc(p)) return tree.readdir(p);
8723
- const names = fs.readdir(p);
8724
- return p === "/" && !names.includes("proc") ? [...names, "proc"] : names;
8725
- },
8726
- exists: (p) => inProc(p) ? tree.exists(p) : fs.exists(p),
8727
- readlink: (p) => inProc(p) ? tree.readlink(p) : fs.readlink(p),
8728
- readdirStat: (p) => {
8729
- if (!inProc(p)) {
8730
- const listed = fs.readdirStat(p);
8731
- if (p !== "/" || listed.some(([name2]) => name2 === "proc")) return listed;
8732
- return [...listed, ["proc", tree.stat("/proc")]];
8810
+ readFile: (p) => via(
8811
+ p,
8812
+ (q) => tree.read(q),
8813
+ () => fs.readFile(p)
8814
+ ),
8815
+ stat: (p) => via(
8816
+ p,
8817
+ (q) => tree.stat(q),
8818
+ () => fs.stat(p)
8819
+ ),
8820
+ lstat: (p) => via(
8821
+ p,
8822
+ (q) => tree.stat(q, false),
8823
+ () => fs.lstat(p),
8824
+ false
8825
+ ),
8826
+ readdir: (p) => via(
8827
+ p,
8828
+ (q) => tree.readdir(q),
8829
+ () => {
8830
+ const names = fs.readdir(p);
8831
+ return p === "/" && !names.includes("proc") ? [...names, "proc"] : names;
8733
8832
  }
8734
- return tree.readdir(p).map((name2) => {
8833
+ ),
8834
+ exists: (p) => {
8835
+ if (inProc(p)) return tree.exists(p);
8836
+ const real = shadowing() ? toProc(p, true) : void 0;
8837
+ if (real !== void 0) return tree.exists(real);
8838
+ if (fs.exists(p)) return true;
8839
+ const late2 = toProc(p, true);
8840
+ return late2 !== void 0 && tree.exists(late2);
8841
+ },
8842
+ readlink: (p) => via(
8843
+ p,
8844
+ (q) => tree.readlink(q),
8845
+ () => fs.readlink(p),
8846
+ false
8847
+ ),
8848
+ readdirStat: (p) => via(
8849
+ p,
8850
+ (q) => tree.readdir(q).map((name2) => {
8735
8851
  try {
8736
- return [name2, tree.stat(`${p}/${name2}`, false)];
8852
+ return [name2, tree.stat(`${q}/${name2}`, false)];
8737
8853
  } catch {
8738
8854
  return [name2, null];
8739
8855
  }
8740
- });
8856
+ }),
8857
+ () => {
8858
+ const listed = fs.readdirStat(p);
8859
+ if (p !== "/" || listed.some(([name2]) => name2 === "proc")) return listed;
8860
+ return [...listed, ["proc", tree.stat("/proc")]];
8861
+ }
8862
+ ),
8863
+ rename: (from, to) => readOnly(
8864
+ [
8865
+ [from, false],
8866
+ [to, false]
8867
+ ],
8868
+ () => fs.rename(from, to)
8869
+ ),
8870
+ symlink: (target, link) => readOnly([[link, false]], () => fs.symlink(target, link)),
8871
+ hold: (p, held, open, handle) => {
8872
+ if (handle !== void 0 && snapshots.delete(handle)) return void 0;
8873
+ if (!held) return fs.hold?.(p, held, open, handle);
8874
+ return via(p, snapshot, () => fs.hold?.(p, held, open) ?? late(p));
8741
8875
  },
8742
- rename: (from, to) => {
8743
- if (inProc(from) || inProc(to)) throw syncError("EROFS", from);
8744
- fs.rename(from, to);
8876
+ kept: (handle) => snapshots.has(handle) || fs.kept?.(handle) === true,
8877
+ pinned: (handle) => {
8878
+ const bytes = snapshots.get(handle);
8879
+ return bytes ? frozen(bytes) : fs.pinned?.(handle) ?? fs;
8745
8880
  },
8746
- hold: (p, ...rest2) => inProc(p) ? void 0 : fs.hold?.(p, ...rest2),
8747
8881
  ...fs.pread ? {
8748
- pread: (p, at, n, version) => inProc(p) ? tree.read(p).subarray(at, at + n) : fs.pread(p, at, n, version)
8882
+ pread: (p, at, n, version) => via(
8883
+ p,
8884
+ (q) => tree.read(q).subarray(at, at + n),
8885
+ () => fs.pread(p, at, n, version)
8886
+ )
8749
8887
  } : {}
8750
8888
  };
8751
- for (const name2 of READ_ONLY) {
8752
- const fn = fs[name2];
8753
- if (!fn) continue;
8754
- over[name2] = (p, ...rest2) => {
8755
- if (inProc(p)) throw syncError("EROFS", p);
8756
- return fn.call(fs, p, ...rest2);
8757
- };
8889
+ for (const [names, follow2] of [
8890
+ [FOLLOWING, true],
8891
+ [NOT_FOLLOWING, false]
8892
+ ]) {
8893
+ for (const name2 of names) {
8894
+ const fn = fs[name2];
8895
+ if (!fn) continue;
8896
+ over[name2] = (p, ...rest2) => readOnly([[p, follow2]], () => fn.call(fs, p, ...rest2));
8897
+ }
8758
8898
  }
8759
8899
  return new Proxy(fs, {
8760
8900
  get: (target, key, receiver) => key in over ? over[key] : Reflect.get(target, key, receiver)
8761
8901
  });
8762
8902
  }
8763
- var DIR_MODE3, FILE_MODE2, LINK_MODE3, PID_NAMES, SYSTEM_NAMES, ProcTree, READ_ONLY;
8903
+ var DIR_MODE3, FILE_MODE2, LINK_MODE3, PID_NAMES, SYSTEM_NAMES, ProcTree, FOLLOWING, NOT_FOLLOWING, MAX_HOPS2;
8764
8904
  var init_wasi_procfs = __esm({
8765
8905
  "src/process/wasi/wasi-procfs.ts"() {
8766
8906
  "use strict";
8767
8907
  init_sync_fs_wire();
8768
8908
  init_process_fds();
8769
8909
  init_procfs();
8910
+ init_wasi_files();
8770
8911
  DIR_MODE3 = 16749;
8771
8912
  FILE_MODE2 = 33060;
8772
8913
  LINK_MODE3 = 41471;
@@ -8877,20 +9018,9 @@ var init_wasi_procfs = __esm({
8877
9018
  }
8878
9019
  }
8879
9020
  };
8880
- READ_ONLY = [
8881
- "writeFile",
8882
- "mkdir",
8883
- "rm",
8884
- "unlink",
8885
- "rmdir",
8886
- "symlink",
8887
- "chmod",
8888
- "utimes",
8889
- "lutimes",
8890
- "create",
8891
- "pwrite",
8892
- "truncate"
8893
- ];
9021
+ FOLLOWING = ["writeFile", "chmod", "utimes", "pwrite", "truncate"];
9022
+ NOT_FOLLOWING = ["mkdir", "rm", "unlink", "rmdir", "lutimes", "create"];
9023
+ MAX_HOPS2 = 40;
8894
9024
  }
8895
9025
  });
8896
9026
 
@@ -9770,12 +9900,22 @@ var init_wasix_linker = __esm({
9770
9900
  if (this.mainPath === void 0) return false;
9771
9901
  if (path === this.mainPath) return true;
9772
9902
  const real = this.host.real;
9773
- return real !== void 0 && real(path) === real(this.mainPath);
9903
+ if (real === void 0) return false;
9904
+ try {
9905
+ return real(path) === real(this.mainPath);
9906
+ } catch {
9907
+ return false;
9908
+ }
9774
9909
  }
9775
9910
  open(name2, cwd, ldPath) {
9776
9911
  const path = this.locate(name2, cwd, ldPath);
9777
9912
  if (this.isMain(path)) return 0;
9778
- return this.load(path, cwd, ldPath).handle;
9913
+ this.indices?.lock();
9914
+ try {
9915
+ return this.load(path, cwd, ldPath).handle;
9916
+ } finally {
9917
+ this.indices?.unlock();
9918
+ }
9779
9919
  }
9780
9920
  symbol(handle, name2) {
9781
9921
  const found = handle === 0 ? this.find(name2) : this.findIn(this.module(handle), name2, /* @__PURE__ */ new Set());
@@ -9797,15 +9937,17 @@ var init_wasix_linker = __esm({
9797
9937
  allocateClosure() {
9798
9938
  const index2 = this.indices.allocate(this.table.length);
9799
9939
  growTable(this.table, index2 + 1);
9940
+ this.live.add(index2);
9800
9941
  return index2;
9801
9942
  }
9802
9943
  freeClosure(index2) {
9803
9944
  this.indices?.free(index2);
9945
+ this.live.delete(index2);
9804
9946
  this.table.set(index2, null);
9805
9947
  }
9948
+ live = /* @__PURE__ */ new Set();
9806
9949
  prepareClosure(record) {
9807
- if (record.index >= this.table.length)
9808
- throw new DlError(`closure ${record.index}: no such slot`);
9950
+ if (!this.live.has(record.index)) throw new DlError(`closure ${record.index}: not allocated`);
9809
9951
  const full = { kind: "closure-prepare", ...record };
9810
9952
  this.install(full);
9811
9953
  this.publisher?.(full);
@@ -9822,15 +9964,23 @@ var init_wasix_linker = __esm({
9822
9964
  this.table.set(record.index, fn);
9823
9965
  this.types.set(fn, sig);
9824
9966
  }
9967
+ reserveLoad(size) {
9968
+ return this.indices?.load(this.table.length, size) ?? {
9969
+ base: this.table.length,
9970
+ handle: this.nextHandle++
9971
+ };
9972
+ }
9825
9973
  reserve(size) {
9826
9974
  return this.indices?.reserve(this.table.length, size) ?? this.table.length;
9827
9975
  }
9828
9976
  replay(record) {
9829
9977
  if (record.kind === "closure") {
9830
9978
  growTable(this.table, record.index + 1);
9979
+ this.live.add(record.index);
9831
9980
  return;
9832
9981
  }
9833
9982
  if (record.kind === "closure-free") {
9983
+ this.live.delete(record.index);
9834
9984
  if (record.index < this.table.length) this.table.set(record.index, null);
9835
9985
  return;
9836
9986
  }
@@ -9840,7 +9990,8 @@ var init_wasix_linker = __esm({
9840
9990
  }
9841
9991
  if (record.kind === "load") {
9842
9992
  if (this.modules.has(record.handle)) return;
9843
- this.instantiate(record.path, this.moduleAt(record.path), record, false);
9993
+ const linked = this.instantiate(record.path, this.moduleAt(record.path), record, false);
9994
+ linked.needed.push(...record.needed ?? []);
9844
9995
  this.nextHandle = Math.max(this.nextHandle, record.handle + 1);
9845
9996
  return;
9846
9997
  }
@@ -9890,13 +10041,14 @@ var init_wasix_linker = __esm({
9890
10041
  (n) => this.load(this.locate(n, cwd, search), cwd, ldPath).handle
9891
10042
  );
9892
10043
  const memoryBase = this.allocate(info.memorySize, 2 ** info.memoryAlign);
9893
- const tableBase = this.reserve(info.tableSize);
10044
+ const { base: tableBase, handle } = this.reserveLoad(info.tableSize);
9894
10045
  const record = {
9895
10046
  kind: "load",
9896
- handle: this.nextHandle++,
10047
+ handle,
9897
10048
  path,
9898
10049
  memoryBase,
9899
- tableBase
10050
+ tableBase,
10051
+ ...needed.length > 0 ? { needed } : {}
9900
10052
  };
9901
10053
  const linked = this.instantiate(path, module, record, true);
9902
10054
  linked.needed.push(...needed);
@@ -9954,7 +10106,8 @@ var init_wasix_linker = __esm({
9954
10106
  linked.instance = new WebAssembly.Instance(module, imports);
9955
10107
  this.types.register(() => this.host.read(path), linked.instance, this.table, at.tableBase);
9956
10108
  this.modules.set(at.handle, linked);
9957
- this.byPath.set(path, linked);
10109
+ const first = this.byPath.get(path);
10110
+ if (!first || at.handle < first.handle) this.byPath.set(path, linked);
9958
10111
  for (const resolve of pending) resolve();
9959
10112
  if (init) {
9960
10113
  call(linked.instance, "__wasm_apply_data_relocs");
@@ -10634,6 +10787,7 @@ var init_wasix_host = __esm({
10634
10787
  return {
10635
10788
  dlopen: (p, pl, _flags, buf, len, lp, ll, out) => {
10636
10789
  if (p === 0) {
10790
+ if (!this.linker) return failed4("not a dynamically-linked program", buf, len);
10637
10791
  mem.view().setUint32(out, MAIN_HANDLE, true);
10638
10792
  return E.SUCCESS;
10639
10793
  }
@@ -10650,7 +10804,7 @@ var init_wasix_host = __esm({
10650
10804
  (l) => l.symbol(handle === MAIN_HANDLE ? 0 : handle, this.str(s, sl)),
10651
10805
  (v) => void mem.view().setUint32(out, v, true)
10652
10806
  ),
10653
- dl_invalid_handle: (handle) => handle === MAIN_HANDLE || handle !== 0 && this.linker && !this.linker.invalid(handle) ? E.SUCCESS : E.NOEXEC
10807
+ dl_invalid_handle: (handle) => this.linker && (handle === MAIN_HANDLE || handle !== 0 && !this.linker.invalid(handle)) ? E.SUCCESS : E.NOEXEC
10654
10808
  };
10655
10809
  }
10656
10810
  threadImports() {
@@ -10815,6 +10969,7 @@ var init_wasm_names = __esm({
10815
10969
  var wasi_runtime_exports = {};
10816
10970
  __export(wasi_runtime_exports, {
10817
10971
  FALLBACK_MAXIMUM_PAGES: () => FALLBACK_MAXIMUM_PAGES,
10972
+ LinkSync: () => LinkSync,
10818
10973
  captureBacktraces: () => captureBacktraces,
10819
10974
  createImportedMemory: () => createImportedMemory,
10820
10975
  runWasiProcess: () => runWasiProcess,
@@ -10987,7 +11142,7 @@ async function instantiate(host, module, memory, threads, {
10987
11142
  thread
10988
11143
  ),
10989
11144
  (req) => host.o.kernel.call(req),
10990
- threads?.ids
11145
+ threads
10991
11146
  ) : void 0;
10992
11147
  if (sync) {
10993
11148
  ({ preview1, wasix } = sync.guard(preview1, wasix));
@@ -11299,32 +11454,59 @@ var init_wasi_runtime = __esm({
11299
11454
  linker;
11300
11455
  call;
11301
11456
  ids;
11302
- constructor(linker, call2, ids) {
11457
+ owner;
11458
+ constructor(linker, call2, threads) {
11303
11459
  this.linker = linker;
11304
11460
  this.call = call2;
11305
- this.ids = ids;
11461
+ this.ids = threads?.ids;
11462
+ this.owner = threads?.tid ?? 0;
11306
11463
  linker.publisher = (record) => this.publish(record);
11307
11464
  linker.indices = {
11308
11465
  reserve: (floor, size) => this.call({ op: "dl-reserve", floor, size }),
11466
+ load: (floor, size) => this.call({ op: "dl-load-reserve", floor, size }),
11467
+ lock: () => {
11468
+ this.call({ op: "dl-lock", owner: this.owner });
11469
+ try {
11470
+ this.catchUp();
11471
+ } catch (e) {
11472
+ this.call({ op: "dl-unlock", owner: this.owner });
11473
+ throw e;
11474
+ }
11475
+ },
11476
+ unlock: () => this.call({ op: "dl-unlock", owner: this.owner }),
11309
11477
  allocate: (floor) => {
11310
11478
  const index2 = this.call({ op: "dl-closure", floor });
11311
11479
  this.catchUp();
11480
+ this.bump();
11312
11481
  return index2;
11313
11482
  },
11314
- free: (index2) => void this.call({ op: "dl-closure-free", index: index2 })
11483
+ free: (index2) => {
11484
+ this.call({ op: "dl-closure-free", index: index2 });
11485
+ this.bump();
11486
+ }
11315
11487
  };
11316
11488
  }
11489
+ bump() {
11490
+ if (this.ids) Atomics.add(this.ids, DL_GEN, 1);
11491
+ }
11317
11492
  publish(record) {
11318
11493
  const since = this.call({ op: "dl-log", append: record, from: this.count });
11319
11494
  for (const r of since.slice(0, -1)) this.linker.replay(r);
11320
11495
  this.count += since.length;
11321
- if (this.ids) this.gen = Atomics.add(this.ids, DL_GEN, 1) + 1;
11496
+ this.bump();
11497
+ this.catchUp();
11322
11498
  }
11323
11499
  catchUp() {
11324
- const since = this.call({ op: "dl-log", from: this.count });
11325
- for (const r of since) this.linker.replay(r);
11326
- this.count += since.length;
11327
- if (this.ids) this.gen = Atomics.load(this.ids, DL_GEN);
11500
+ for (; ; ) {
11501
+ const gen = this.ids ? Atomics.load(this.ids, DL_GEN) : 0;
11502
+ const since = this.call({ op: "dl-log", from: this.count });
11503
+ for (const r of since) this.linker.replay(r);
11504
+ this.count += since.length;
11505
+ if (!this.ids || Atomics.load(this.ids, DL_GEN) === gen) {
11506
+ this.gen = gen;
11507
+ return;
11508
+ }
11509
+ }
11328
11510
  }
11329
11511
  guard(preview1, wasix) {
11330
11512
  const ids = this.ids;