@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.
@@ -4813,7 +4813,7 @@ function openAccess(existing, oflags, rights) {
4813
4813
  return { readable: (rights & RIGHTS.FD_READ) !== 0n || !writable2, writable: writable2 };
4814
4814
  }
4815
4815
  function promoteRequest(fd, f, handed) {
4816
- const orphan = f.buffer.isOrphan();
4816
+ const orphan = f.buffer.isOrphan() || (f.buffer.handle ?? 0) < 0;
4817
4817
  if (!orphan && f.buffer.isRanged) f.buffer.flush();
4818
4818
  const joins = !orphan && (handed.has(f.buffer) || f.buffer.isRanged);
4819
4819
  return {
@@ -6800,60 +6800,201 @@ var init_wasi_module = __esm({
6800
6800
  function inProc(path) {
6801
6801
  return path === "/proc" || path.startsWith("/proc/");
6802
6802
  }
6803
+ function* procWalk(path, follow2) {
6804
+ let done = [];
6805
+ let todo = path.split("/").filter((part) => part !== "");
6806
+ let hops = 0;
6807
+ while (todo.length > 0) {
6808
+ const part = todo.shift();
6809
+ if (part === ".") continue;
6810
+ if (part === "..") {
6811
+ done.pop();
6812
+ continue;
6813
+ }
6814
+ const at = `/${[...done, part].join("/")}`;
6815
+ const whole = normalize(`/${[...done, part, ...todo].join("/")}`);
6816
+ if (inProc(at) && inProc(whole)) return whole;
6817
+ if (!follow2 && todo.length === 0) return void 0;
6818
+ const target = yield at;
6819
+ if (target === null) return void 0;
6820
+ if (target === void 0) done.push(part);
6821
+ else {
6822
+ if (++hops > MAX_HOPS2) return void 0;
6823
+ if (target.startsWith("/")) done = [];
6824
+ todo = [...target.split("/").filter((part2) => part2 !== ""), ...todo];
6825
+ }
6826
+ }
6827
+ return void 0;
6828
+ }
6829
+ function procPath(fs, path, follow2) {
6830
+ const walk = procWalk(path, follow2);
6831
+ let step = walk.next();
6832
+ while (!step.done) {
6833
+ let target;
6834
+ try {
6835
+ target = fs.lstat(step.value).isSymbolicLink ? fs.readlink(step.value) : void 0;
6836
+ } catch {
6837
+ target = null;
6838
+ }
6839
+ step = walk.next(target);
6840
+ }
6841
+ return step.value;
6842
+ }
6843
+ function frozen(bytes) {
6844
+ const refuse = () => {
6845
+ throw syncError("EROFS", "/proc");
6846
+ };
6847
+ return {
6848
+ readFile: () => bytes,
6849
+ pread: (_p, at, n) => bytes.subarray(at, at + n),
6850
+ writeFile: refuse,
6851
+ pwrite: refuse,
6852
+ truncate: refuse
6853
+ };
6854
+ }
6803
6855
  function procfsBridge(fs, tree) {
6856
+ const toProc = (path, follow2) => procPath(fs, path, follow2);
6857
+ const shadowing = () => {
6858
+ try {
6859
+ return fs.exists("/proc");
6860
+ } catch {
6861
+ return false;
6862
+ }
6863
+ };
6864
+ const via = (p, proc, own, follow2 = true) => {
6865
+ if (inProc(p)) return proc(p);
6866
+ if (shadowing()) {
6867
+ const real = toProc(p, follow2);
6868
+ if (real !== void 0) return proc(real);
6869
+ }
6870
+ try {
6871
+ return own();
6872
+ } catch (err) {
6873
+ const real = toProc(p, follow2);
6874
+ if (real === void 0) throw err;
6875
+ return proc(real);
6876
+ }
6877
+ };
6878
+ const readOnly = (paths, run) => {
6879
+ const physical = shadowing();
6880
+ for (const [p, follow2] of paths) {
6881
+ if (inProc(p) || physical && toProc(p, follow2) !== void 0) throw syncError("EROFS", p);
6882
+ }
6883
+ return run();
6884
+ };
6885
+ const snapshots = /* @__PURE__ */ new Map();
6886
+ let lastSnapshot = 0;
6887
+ const snapshot = (q) => {
6888
+ lastSnapshot--;
6889
+ snapshots.set(lastSnapshot, tree.read(q));
6890
+ return lastSnapshot;
6891
+ };
6892
+ const late = (p) => {
6893
+ const q = toProc(p, true);
6894
+ return q === void 0 ? void 0 : snapshot(q);
6895
+ };
6804
6896
  const over = {
6805
- readFile: (p) => inProc(p) ? tree.read(p) : fs.readFile(p),
6806
- stat: (p) => inProc(p) ? tree.stat(p) : fs.stat(p),
6807
- lstat: (p) => inProc(p) ? tree.stat(p, false) : fs.lstat(p),
6808
- readdir: (p) => {
6809
- if (inProc(p)) return tree.readdir(p);
6810
- const names = fs.readdir(p);
6811
- return p === "/" && !names.includes("proc") ? [...names, "proc"] : names;
6812
- },
6813
- exists: (p) => inProc(p) ? tree.exists(p) : fs.exists(p),
6814
- readlink: (p) => inProc(p) ? tree.readlink(p) : fs.readlink(p),
6815
- readdirStat: (p) => {
6816
- if (!inProc(p)) {
6817
- const listed = fs.readdirStat(p);
6818
- if (p !== "/" || listed.some(([name2]) => name2 === "proc")) return listed;
6819
- return [...listed, ["proc", tree.stat("/proc")]];
6897
+ readFile: (p) => via(
6898
+ p,
6899
+ (q) => tree.read(q),
6900
+ () => fs.readFile(p)
6901
+ ),
6902
+ stat: (p) => via(
6903
+ p,
6904
+ (q) => tree.stat(q),
6905
+ () => fs.stat(p)
6906
+ ),
6907
+ lstat: (p) => via(
6908
+ p,
6909
+ (q) => tree.stat(q, false),
6910
+ () => fs.lstat(p),
6911
+ false
6912
+ ),
6913
+ readdir: (p) => via(
6914
+ p,
6915
+ (q) => tree.readdir(q),
6916
+ () => {
6917
+ const names = fs.readdir(p);
6918
+ return p === "/" && !names.includes("proc") ? [...names, "proc"] : names;
6820
6919
  }
6821
- return tree.readdir(p).map((name2) => {
6920
+ ),
6921
+ exists: (p) => {
6922
+ if (inProc(p)) return tree.exists(p);
6923
+ const real = shadowing() ? toProc(p, true) : void 0;
6924
+ if (real !== void 0) return tree.exists(real);
6925
+ if (fs.exists(p)) return true;
6926
+ const late2 = toProc(p, true);
6927
+ return late2 !== void 0 && tree.exists(late2);
6928
+ },
6929
+ readlink: (p) => via(
6930
+ p,
6931
+ (q) => tree.readlink(q),
6932
+ () => fs.readlink(p),
6933
+ false
6934
+ ),
6935
+ readdirStat: (p) => via(
6936
+ p,
6937
+ (q) => tree.readdir(q).map((name2) => {
6822
6938
  try {
6823
- return [name2, tree.stat(`${p}/${name2}`, false)];
6939
+ return [name2, tree.stat(`${q}/${name2}`, false)];
6824
6940
  } catch {
6825
6941
  return [name2, null];
6826
6942
  }
6827
- });
6943
+ }),
6944
+ () => {
6945
+ const listed = fs.readdirStat(p);
6946
+ if (p !== "/" || listed.some(([name2]) => name2 === "proc")) return listed;
6947
+ return [...listed, ["proc", tree.stat("/proc")]];
6948
+ }
6949
+ ),
6950
+ rename: (from, to) => readOnly(
6951
+ [
6952
+ [from, false],
6953
+ [to, false]
6954
+ ],
6955
+ () => fs.rename(from, to)
6956
+ ),
6957
+ symlink: (target, link) => readOnly([[link, false]], () => fs.symlink(target, link)),
6958
+ hold: (p, held, open, handle) => {
6959
+ if (handle !== void 0 && snapshots.delete(handle)) return void 0;
6960
+ if (!held) return fs.hold?.(p, held, open, handle);
6961
+ return via(p, snapshot, () => fs.hold?.(p, held, open) ?? late(p));
6828
6962
  },
6829
- rename: (from, to) => {
6830
- if (inProc(from) || inProc(to)) throw syncError("EROFS", from);
6831
- fs.rename(from, to);
6963
+ kept: (handle) => snapshots.has(handle) || fs.kept?.(handle) === true,
6964
+ pinned: (handle) => {
6965
+ const bytes = snapshots.get(handle);
6966
+ return bytes ? frozen(bytes) : fs.pinned?.(handle) ?? fs;
6832
6967
  },
6833
- hold: (p, ...rest2) => inProc(p) ? void 0 : fs.hold?.(p, ...rest2),
6834
6968
  ...fs.pread ? {
6835
- pread: (p, at, n, version) => inProc(p) ? tree.read(p).subarray(at, at + n) : fs.pread(p, at, n, version)
6969
+ pread: (p, at, n, version) => via(
6970
+ p,
6971
+ (q) => tree.read(q).subarray(at, at + n),
6972
+ () => fs.pread(p, at, n, version)
6973
+ )
6836
6974
  } : {}
6837
6975
  };
6838
- for (const name2 of READ_ONLY) {
6839
- const fn = fs[name2];
6840
- if (!fn) continue;
6841
- over[name2] = (p, ...rest2) => {
6842
- if (inProc(p)) throw syncError("EROFS", p);
6843
- return fn.call(fs, p, ...rest2);
6844
- };
6976
+ for (const [names, follow2] of [
6977
+ [FOLLOWING, true],
6978
+ [NOT_FOLLOWING, false]
6979
+ ]) {
6980
+ for (const name2 of names) {
6981
+ const fn = fs[name2];
6982
+ if (!fn) continue;
6983
+ over[name2] = (p, ...rest2) => readOnly([[p, follow2]], () => fn.call(fs, p, ...rest2));
6984
+ }
6845
6985
  }
6846
6986
  return new Proxy(fs, {
6847
6987
  get: (target, key, receiver) => key in over ? over[key] : Reflect.get(target, key, receiver)
6848
6988
  });
6849
6989
  }
6850
- var DIR_MODE3, FILE_MODE2, LINK_MODE3, PID_NAMES, SYSTEM_NAMES, ProcTree, READ_ONLY;
6990
+ var DIR_MODE3, FILE_MODE2, LINK_MODE3, PID_NAMES, SYSTEM_NAMES, ProcTree, FOLLOWING, NOT_FOLLOWING, MAX_HOPS2;
6851
6991
  var init_wasi_procfs = __esm({
6852
6992
  "src/process/wasi/wasi-procfs.ts"() {
6853
6993
  "use strict";
6854
6994
  init_sync_fs_wire();
6855
6995
  init_process_fds();
6856
6996
  init_procfs();
6997
+ init_wasi_files();
6857
6998
  DIR_MODE3 = 16749;
6858
6999
  FILE_MODE2 = 33060;
6859
7000
  LINK_MODE3 = 41471;
@@ -6964,20 +7105,9 @@ var init_wasi_procfs = __esm({
6964
7105
  }
6965
7106
  }
6966
7107
  };
6967
- READ_ONLY = [
6968
- "writeFile",
6969
- "mkdir",
6970
- "rm",
6971
- "unlink",
6972
- "rmdir",
6973
- "symlink",
6974
- "chmod",
6975
- "utimes",
6976
- "lutimes",
6977
- "create",
6978
- "pwrite",
6979
- "truncate"
6980
- ];
7108
+ FOLLOWING = ["writeFile", "chmod", "utimes", "pwrite", "truncate"];
7109
+ NOT_FOLLOWING = ["mkdir", "rm", "unlink", "rmdir", "lutimes", "create"];
7110
+ MAX_HOPS2 = 40;
6981
7111
  }
6982
7112
  });
6983
7113
 
@@ -7857,12 +7987,22 @@ var init_wasix_linker = __esm({
7857
7987
  if (this.mainPath === void 0) return false;
7858
7988
  if (path === this.mainPath) return true;
7859
7989
  const real = this.host.real;
7860
- return real !== void 0 && real(path) === real(this.mainPath);
7990
+ if (real === void 0) return false;
7991
+ try {
7992
+ return real(path) === real(this.mainPath);
7993
+ } catch {
7994
+ return false;
7995
+ }
7861
7996
  }
7862
7997
  open(name2, cwd, ldPath) {
7863
7998
  const path = this.locate(name2, cwd, ldPath);
7864
7999
  if (this.isMain(path)) return 0;
7865
- return this.load(path, cwd, ldPath).handle;
8000
+ this.indices?.lock();
8001
+ try {
8002
+ return this.load(path, cwd, ldPath).handle;
8003
+ } finally {
8004
+ this.indices?.unlock();
8005
+ }
7866
8006
  }
7867
8007
  symbol(handle, name2) {
7868
8008
  const found = handle === 0 ? this.find(name2) : this.findIn(this.module(handle), name2, /* @__PURE__ */ new Set());
@@ -7884,15 +8024,17 @@ var init_wasix_linker = __esm({
7884
8024
  allocateClosure() {
7885
8025
  const index2 = this.indices.allocate(this.table.length);
7886
8026
  growTable(this.table, index2 + 1);
8027
+ this.live.add(index2);
7887
8028
  return index2;
7888
8029
  }
7889
8030
  freeClosure(index2) {
7890
8031
  this.indices?.free(index2);
8032
+ this.live.delete(index2);
7891
8033
  this.table.set(index2, null);
7892
8034
  }
8035
+ live = /* @__PURE__ */ new Set();
7893
8036
  prepareClosure(record) {
7894
- if (record.index >= this.table.length)
7895
- throw new DlError(`closure ${record.index}: no such slot`);
8037
+ if (!this.live.has(record.index)) throw new DlError(`closure ${record.index}: not allocated`);
7896
8038
  const full = { kind: "closure-prepare", ...record };
7897
8039
  this.install(full);
7898
8040
  this.publisher?.(full);
@@ -7909,15 +8051,23 @@ var init_wasix_linker = __esm({
7909
8051
  this.table.set(record.index, fn);
7910
8052
  this.types.set(fn, sig);
7911
8053
  }
8054
+ reserveLoad(size) {
8055
+ return this.indices?.load(this.table.length, size) ?? {
8056
+ base: this.table.length,
8057
+ handle: this.nextHandle++
8058
+ };
8059
+ }
7912
8060
  reserve(size) {
7913
8061
  return this.indices?.reserve(this.table.length, size) ?? this.table.length;
7914
8062
  }
7915
8063
  replay(record) {
7916
8064
  if (record.kind === "closure") {
7917
8065
  growTable(this.table, record.index + 1);
8066
+ this.live.add(record.index);
7918
8067
  return;
7919
8068
  }
7920
8069
  if (record.kind === "closure-free") {
8070
+ this.live.delete(record.index);
7921
8071
  if (record.index < this.table.length) this.table.set(record.index, null);
7922
8072
  return;
7923
8073
  }
@@ -7927,7 +8077,8 @@ var init_wasix_linker = __esm({
7927
8077
  }
7928
8078
  if (record.kind === "load") {
7929
8079
  if (this.modules.has(record.handle)) return;
7930
- this.instantiate(record.path, this.moduleAt(record.path), record, false);
8080
+ const linked = this.instantiate(record.path, this.moduleAt(record.path), record, false);
8081
+ linked.needed.push(...record.needed ?? []);
7931
8082
  this.nextHandle = Math.max(this.nextHandle, record.handle + 1);
7932
8083
  return;
7933
8084
  }
@@ -7977,13 +8128,14 @@ var init_wasix_linker = __esm({
7977
8128
  (n) => this.load(this.locate(n, cwd, search), cwd, ldPath).handle
7978
8129
  );
7979
8130
  const memoryBase = this.allocate(info.memorySize, 2 ** info.memoryAlign);
7980
- const tableBase = this.reserve(info.tableSize);
8131
+ const { base: tableBase, handle } = this.reserveLoad(info.tableSize);
7981
8132
  const record = {
7982
8133
  kind: "load",
7983
- handle: this.nextHandle++,
8134
+ handle,
7984
8135
  path,
7985
8136
  memoryBase,
7986
- tableBase
8137
+ tableBase,
8138
+ ...needed.length > 0 ? { needed } : {}
7987
8139
  };
7988
8140
  const linked = this.instantiate(path, module, record, true);
7989
8141
  linked.needed.push(...needed);
@@ -8041,7 +8193,8 @@ var init_wasix_linker = __esm({
8041
8193
  linked.instance = new WebAssembly.Instance(module, imports);
8042
8194
  this.types.register(() => this.host.read(path), linked.instance, this.table, at.tableBase);
8043
8195
  this.modules.set(at.handle, linked);
8044
- this.byPath.set(path, linked);
8196
+ const first = this.byPath.get(path);
8197
+ if (!first || at.handle < first.handle) this.byPath.set(path, linked);
8045
8198
  for (const resolve of pending) resolve();
8046
8199
  if (init) {
8047
8200
  call(linked.instance, "__wasm_apply_data_relocs");
@@ -8721,6 +8874,7 @@ var init_wasix_host = __esm({
8721
8874
  return {
8722
8875
  dlopen: (p, pl, _flags, buf, len, lp, ll, out) => {
8723
8876
  if (p === 0) {
8877
+ if (!this.linker) return failed4("not a dynamically-linked program", buf, len);
8724
8878
  mem.view().setUint32(out, MAIN_HANDLE, true);
8725
8879
  return E.SUCCESS;
8726
8880
  }
@@ -8737,7 +8891,7 @@ var init_wasix_host = __esm({
8737
8891
  (l) => l.symbol(handle === MAIN_HANDLE ? 0 : handle, this.str(s, sl)),
8738
8892
  (v) => void mem.view().setUint32(out, v, true)
8739
8893
  ),
8740
- dl_invalid_handle: (handle) => handle === MAIN_HANDLE || handle !== 0 && this.linker && !this.linker.invalid(handle) ? E.SUCCESS : E.NOEXEC
8894
+ dl_invalid_handle: (handle) => this.linker && (handle === MAIN_HANDLE || handle !== 0 && !this.linker.invalid(handle)) ? E.SUCCESS : E.NOEXEC
8741
8895
  };
8742
8896
  }
8743
8897
  threadImports() {
@@ -8902,6 +9056,7 @@ var init_wasm_names = __esm({
8902
9056
  var wasi_runtime_exports = {};
8903
9057
  __export(wasi_runtime_exports, {
8904
9058
  FALLBACK_MAXIMUM_PAGES: () => FALLBACK_MAXIMUM_PAGES,
9059
+ LinkSync: () => LinkSync,
8905
9060
  captureBacktraces: () => captureBacktraces,
8906
9061
  createImportedMemory: () => createImportedMemory,
8907
9062
  runWasiProcess: () => runWasiProcess,
@@ -9074,7 +9229,7 @@ async function instantiate(host, module, memory, threads, {
9074
9229
  thread
9075
9230
  ),
9076
9231
  (req) => host.o.kernel.call(req),
9077
- threads?.ids
9232
+ threads
9078
9233
  ) : void 0;
9079
9234
  if (sync) {
9080
9235
  ({ preview1, wasix } = sync.guard(preview1, wasix));
@@ -9386,32 +9541,59 @@ var init_wasi_runtime = __esm({
9386
9541
  linker;
9387
9542
  call;
9388
9543
  ids;
9389
- constructor(linker, call2, ids) {
9544
+ owner;
9545
+ constructor(linker, call2, threads) {
9390
9546
  this.linker = linker;
9391
9547
  this.call = call2;
9392
- this.ids = ids;
9548
+ this.ids = threads?.ids;
9549
+ this.owner = threads?.tid ?? 0;
9393
9550
  linker.publisher = (record) => this.publish(record);
9394
9551
  linker.indices = {
9395
9552
  reserve: (floor, size) => this.call({ op: "dl-reserve", floor, size }),
9553
+ load: (floor, size) => this.call({ op: "dl-load-reserve", floor, size }),
9554
+ lock: () => {
9555
+ this.call({ op: "dl-lock", owner: this.owner });
9556
+ try {
9557
+ this.catchUp();
9558
+ } catch (e) {
9559
+ this.call({ op: "dl-unlock", owner: this.owner });
9560
+ throw e;
9561
+ }
9562
+ },
9563
+ unlock: () => this.call({ op: "dl-unlock", owner: this.owner }),
9396
9564
  allocate: (floor) => {
9397
9565
  const index2 = this.call({ op: "dl-closure", floor });
9398
9566
  this.catchUp();
9567
+ this.bump();
9399
9568
  return index2;
9400
9569
  },
9401
- free: (index2) => void this.call({ op: "dl-closure-free", index: index2 })
9570
+ free: (index2) => {
9571
+ this.call({ op: "dl-closure-free", index: index2 });
9572
+ this.bump();
9573
+ }
9402
9574
  };
9403
9575
  }
9576
+ bump() {
9577
+ if (this.ids) Atomics.add(this.ids, DL_GEN, 1);
9578
+ }
9404
9579
  publish(record) {
9405
9580
  const since = this.call({ op: "dl-log", append: record, from: this.count });
9406
9581
  for (const r of since.slice(0, -1)) this.linker.replay(r);
9407
9582
  this.count += since.length;
9408
- if (this.ids) this.gen = Atomics.add(this.ids, DL_GEN, 1) + 1;
9583
+ this.bump();
9584
+ this.catchUp();
9409
9585
  }
9410
9586
  catchUp() {
9411
- const since = this.call({ op: "dl-log", from: this.count });
9412
- for (const r of since) this.linker.replay(r);
9413
- this.count += since.length;
9414
- if (this.ids) this.gen = Atomics.load(this.ids, DL_GEN);
9587
+ for (; ; ) {
9588
+ const gen = this.ids ? Atomics.load(this.ids, DL_GEN) : 0;
9589
+ const since = this.call({ op: "dl-log", from: this.count });
9590
+ for (const r of since) this.linker.replay(r);
9591
+ this.count += since.length;
9592
+ if (!this.ids || Atomics.load(this.ids, DL_GEN) === gen) {
9593
+ this.gen = gen;
9594
+ return;
9595
+ }
9596
+ }
9415
9597
  }
9416
9598
  guard(preview1, wasix) {
9417
9599
  const ids = this.ids;