@ai-ecoverse/slicc-kernel 1.132.1 → 1.133.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.
@@ -2664,7 +2664,7 @@ var KERNEL_VERSION, OS_RELEASE;
2664
2664
  var init_version = __esm({
2665
2665
  "src/version.ts"() {
2666
2666
  "use strict";
2667
- KERNEL_VERSION = true ? "1.132.1" : "0.0.0-dev";
2667
+ KERNEL_VERSION = true ? "1.133.0" : "0.0.0-dev";
2668
2668
  OS_RELEASE = "6.0.0-slicc";
2669
2669
  }
2670
2670
  });
@@ -8534,6 +8534,14 @@ var init_wasi_fds = __esm({
8534
8534
  this.table.set(3 + i, entry);
8535
8535
  });
8536
8536
  }
8537
+ adoptCopy(fd) {
8538
+ const at = this.kernel.call({ op: "fd-dup", fd, min: 3 });
8539
+ this.table.set(at, this.stdioEntry(at));
8540
+ return at;
8541
+ }
8542
+ preopenAt(path, name2) {
8543
+ return this.install({ type: "dir", path: normalize(path), preopen: name2 });
8544
+ }
8537
8545
  preopens(cwd, root) {
8538
8546
  const here = normalize(cwd);
8539
8547
  const dot = { type: "dir", path: here, preopen: "." };
@@ -10344,7 +10352,7 @@ var init_wasi_host = __esm({
10344
10352
  );
10345
10353
  if (o.shared) this.fds.share(o.shared, true);
10346
10354
  else if (o.forked) this.fds.restore(o.forked.fds, o.forked.cloexec);
10347
- else this.fds.setup(o.cwd, o.inherited ?? [], o.preopenRoot === true);
10355
+ else if (!o.bare) this.fds.setup(o.cwd, o.inherited ?? [], o.preopenRoot === true);
10348
10356
  this.listening = o.shared ? [] : this.fds.sockets();
10349
10357
  }
10350
10358
  get cwd() {
@@ -10757,6 +10765,7 @@ var init_wasi_host = __esm({
10757
10765
  return (localCpuNanos() ?? BigInt(Math.round((performance.now() - this.started) * 1e6))) + 1n;
10758
10766
  }
10759
10767
  environ() {
10768
+ if (this.o.bare) return Object.entries(this.o.env).map(([k, v]) => `${k}=${v}`);
10760
10769
  const listen2 = this.listening.length > 0 ? { SLICC_LISTEN_FDS: this.listening.join(" ") } : {};
10761
10770
  const env = { PWD: this.cwd, ...this.o.env, ...listen2 };
10762
10771
  return Object.entries(env).map(([k, v]) => `${k}=${v}`);
@@ -16762,6 +16771,288 @@ var init_js_tty = __esm({
16762
16771
  }
16763
16772
  });
16764
16773
 
16774
+ // src/process/js/js-wasi.ts
16775
+ function ownedFds(sab) {
16776
+ if (!sab) return { add: () => {
16777
+ }, remove: () => {
16778
+ } };
16779
+ const view = new Int32Array(sab);
16780
+ const fds = /* @__PURE__ */ new Set();
16781
+ const publish = () => {
16782
+ Atomics.store(view, 0, 0);
16783
+ let n = 0;
16784
+ for (const fd of fds) {
16785
+ if (1 + n >= view.length) break;
16786
+ view[1 + n++] = fd;
16787
+ }
16788
+ Atomics.store(view, 0, n);
16789
+ };
16790
+ return {
16791
+ add(fd) {
16792
+ fds.add(fd);
16793
+ publish();
16794
+ },
16795
+ remove(fd) {
16796
+ if (fds.delete(fd)) publish();
16797
+ }
16798
+ };
16799
+ }
16800
+ function fdArgsOf(name2) {
16801
+ const paths = PATHS[name2];
16802
+ if (paths) return paths.map(([fd]) => fd);
16803
+ return /^(fd|sock)_/.test(name2) ? [0] : [];
16804
+ }
16805
+ function laneTransport(lane) {
16806
+ return { call: (req) => lane(req) };
16807
+ }
16808
+ function within2(root, dir, path) {
16809
+ if (path.startsWith("/")) return false;
16810
+ const base = dir === root ? [] : dir.slice(root === "/" ? 1 : root.length + 1).split("/");
16811
+ const parts = [...base];
16812
+ for (const seg of path.split("/")) {
16813
+ if (seg === "" || seg === ".") continue;
16814
+ if (seg === "..") {
16815
+ if (parts.length === 0) return false;
16816
+ parts.pop();
16817
+ } else parts.push(seg);
16818
+ }
16819
+ return true;
16820
+ }
16821
+ function preopensOf(given, resolve) {
16822
+ if (given === void 0) return [];
16823
+ if (typeof given !== "object" || given === null) throw new JsCallError("EINVAL", "wasi preopens");
16824
+ return Object.entries(given).map(([name2, path]) => {
16825
+ if (typeof path !== "string" || path === "") throw new JsCallError("EINVAL", "wasi preopens");
16826
+ return [name2, normalize(resolve(path))];
16827
+ });
16828
+ }
16829
+ function createJsWasi(deps, o = {}) {
16830
+ const transport = laneTransport(deps.lane);
16831
+ const sys = kernelSys(transport);
16832
+ const call2 = (req) => {
16833
+ const r = deps.lane(req);
16834
+ if (!r.ok) throw new JsCallError(r.errno, req.op);
16835
+ return r.kind === "json" ? r.json : r.kind === "bytes" ? r.bytes : void 0;
16836
+ };
16837
+ const host = new WasiHost({
16838
+ args: [...o.args ?? []],
16839
+ env: { ...o.env ?? {} },
16840
+ cwd: deps.cwd,
16841
+ pid: deps.pid,
16842
+ kernel: { sys, call: call2 },
16843
+ fs: createSyncFsSabBridge(transport, { ...deps.fs, direct: true }),
16844
+ bare: true
16845
+ });
16846
+ const owned = deps.owned;
16847
+ const guest = /* @__PURE__ */ new Map();
16848
+ const own = (g, k) => {
16849
+ guest.set(g, k);
16850
+ owned.add(k);
16851
+ };
16852
+ const roots = /* @__PURE__ */ new Map();
16853
+ const opened2 = [];
16854
+ const closeKernel = (fd) => {
16855
+ owned.remove(fd);
16856
+ try {
16857
+ host.fds.close(fd);
16858
+ } catch {
16859
+ }
16860
+ };
16861
+ try {
16862
+ (o.stdio ?? [0, 1, 2]).forEach((fd, i) => {
16863
+ const k = host.fds.adoptCopy(fd);
16864
+ opened2.push(k);
16865
+ own(i, k);
16866
+ });
16867
+ for (const [name2, path] of preopensOf(o.preopens, deps.resolve)) {
16868
+ const k = host.fds.preopenAt(path, name2);
16869
+ opened2.push(k);
16870
+ const g = 3 + roots.size;
16871
+ own(g, k);
16872
+ roots.set(g, path);
16873
+ }
16874
+ } catch (err) {
16875
+ for (const k of opened2) closeKernel(k);
16876
+ throw err;
16877
+ }
16878
+ const table = host.imports();
16879
+ const view = () => host.mem.view();
16880
+ const free = () => {
16881
+ let g = 3;
16882
+ while (guest.has(g)) g++;
16883
+ return g;
16884
+ };
16885
+ const confined = (name2, args) => {
16886
+ for (const [fdAt, ptrAt, lenAt] of PATHS[name2] ?? []) {
16887
+ const g = args[fdAt];
16888
+ const root = roots.get(g);
16889
+ const dir = host.fds.find(guest.get(g));
16890
+ if (root === void 0 || dir?.type !== "dir") continue;
16891
+ if (!within2(root, dir.path, host.mem.string(args[ptrAt], args[lenAt]))) return false;
16892
+ }
16893
+ return true;
16894
+ };
16895
+ const opens = (out, root) => {
16896
+ const k = view().getUint32(out, true);
16897
+ const g = free();
16898
+ own(g, k);
16899
+ if (root !== void 0) roots.set(g, root);
16900
+ view().setUint32(out, g, true);
16901
+ };
16902
+ const imports = {};
16903
+ for (const [name2, fn] of Object.entries(table)) {
16904
+ if (SPECIAL.has(name2)) continue;
16905
+ const fdArgs = fdArgsOf(name2);
16906
+ imports[name2] = ((...raw) => {
16907
+ const args = [...raw];
16908
+ for (const at of fdArgs) {
16909
+ const k = guest.get(args[at]);
16910
+ if (k === void 0) return E.BADF;
16911
+ args[at] = k;
16912
+ }
16913
+ if (!confined(name2, raw)) return E.NOTCAPABLE;
16914
+ const out = RESULTS[name2];
16915
+ if (out !== void 0 && (raw[out] >>> 0) + 4 > host.mem.size()) return E.FAULT;
16916
+ const errno2 = fn(...args);
16917
+ if (errno2 !== E.SUCCESS) return errno2;
16918
+ if (out !== void 0) opens(raw[out] >>> 0, roots.get(raw[0]));
16919
+ return errno2;
16920
+ });
16921
+ }
16922
+ imports.fd_close = ((g) => {
16923
+ const k = guest.get(g);
16924
+ if (k === void 0) return E.BADF;
16925
+ guest.delete(g);
16926
+ roots.delete(g);
16927
+ owned.remove(k);
16928
+ return table.fd_close(k);
16929
+ });
16930
+ imports.fd_renumber = ((from, to) => {
16931
+ const kf = guest.get(from);
16932
+ const kt = guest.get(to);
16933
+ if (kf === void 0 || kt === void 0) return E.BADF;
16934
+ if (from === to) return E.SUCCESS;
16935
+ closeKernel(kt);
16936
+ guest.set(to, kf);
16937
+ const root = roots.get(from);
16938
+ if (root === void 0) roots.delete(to);
16939
+ else roots.set(to, root);
16940
+ guest.delete(from);
16941
+ roots.delete(from);
16942
+ return E.SUCCESS;
16943
+ });
16944
+ imports.poll_oneoff = ((inPtr, outPtr, n, nevents) => {
16945
+ const v = view();
16946
+ const swapped = [];
16947
+ for (let i = 0; i < n; i++) {
16948
+ const at = inPtr + i * SUB_SIZE;
16949
+ const tag = v.getUint8(at + SUB_TAG);
16950
+ if (tag !== EVENTTYPE.FD_READ && tag !== EVENTTYPE.FD_WRITE) continue;
16951
+ const g = v.getUint32(at + SUB_FD, true);
16952
+ swapped.push([at + SUB_FD, g]);
16953
+ v.setUint32(at + SUB_FD, guest.get(g) ?? NO_FD, true);
16954
+ }
16955
+ try {
16956
+ return table.poll_oneoff(inPtr, outPtr, n, nevents);
16957
+ } finally {
16958
+ const after = view();
16959
+ for (const [at, g] of swapped) after.setUint32(at, g, true);
16960
+ }
16961
+ });
16962
+ imports.proc_exit = ((code2) => {
16963
+ throw new JsWasiExit(code2);
16964
+ });
16965
+ let closed = false;
16966
+ const run = (instance, entry) => {
16967
+ const memory = instance.exports.memory;
16968
+ if (memory instanceof WebAssembly.Memory) host.mem.bind(memory);
16969
+ const fn = instance.exports[entry];
16970
+ if (typeof fn !== "function") {
16971
+ if (entry === "_initialize") return 0;
16972
+ throw new JsCallError("EINVAL", `wasi: the instance exports no ${entry}`);
16973
+ }
16974
+ try {
16975
+ fn();
16976
+ return 0;
16977
+ } catch (err) {
16978
+ if (err instanceof JsWasiExit && o.returnOnExit !== false) return err.code;
16979
+ throw err;
16980
+ }
16981
+ };
16982
+ const wasi = {
16983
+ imports: { wasi_snapshot_preview1: imports },
16984
+ wasiImport: imports,
16985
+ bind: (memory) => {
16986
+ if (!(memory instanceof WebAssembly.Memory)) throw new JsCallError("EINVAL", "wasi bind");
16987
+ host.mem.bind(memory);
16988
+ },
16989
+ start: (instance) => run(instance, "_start"),
16990
+ initialize: (instance) => void run(instance, "_initialize"),
16991
+ close: () => {
16992
+ if (closed) return;
16993
+ closed = true;
16994
+ deps.live.delete(wasi);
16995
+ for (const k of guest.values()) closeKernel(k);
16996
+ guest.clear();
16997
+ roots.clear();
16998
+ }
16999
+ };
17000
+ deps.live.add(wasi);
17001
+ return wasi;
17002
+ }
17003
+ function wasiFor(o) {
17004
+ const deps = { ...o, live: /* @__PURE__ */ new Set(), owned: ownedFds(o.owned) };
17005
+ return {
17006
+ create: (options) => createJsWasi(deps, options),
17007
+ closeAll: () => {
17008
+ for (const wasi of [...deps.live]) wasi.close();
17009
+ }
17010
+ };
17011
+ }
17012
+ var JsWasiExit, SUB_SIZE, SUB_TAG, SUB_FD, NO_FD, PATHS, RESULTS, SPECIAL;
17013
+ var init_js_wasi = __esm({
17014
+ "src/process/js/js-wasi.ts"() {
17015
+ "use strict";
17016
+ init_sync_sab_bridge();
17017
+ init_process_runtime();
17018
+ init_wasi_abi();
17019
+ init_wasi_files();
17020
+ init_wasi_host();
17021
+ init_js_kernel();
17022
+ JsWasiExit = class extends Error {
17023
+ code;
17024
+ constructor(code2) {
17025
+ super(`wasi exit ${code2}`);
17026
+ this.code = code2;
17027
+ }
17028
+ };
17029
+ SUB_SIZE = 48;
17030
+ SUB_TAG = 8;
17031
+ SUB_FD = 16;
17032
+ NO_FD = 2147483647;
17033
+ PATHS = {
17034
+ path_open: [[0, 2, 3]],
17035
+ path_filestat_get: [[0, 2, 3]],
17036
+ path_filestat_set_times: [[0, 2, 3]],
17037
+ path_create_directory: [[0, 1, 2]],
17038
+ path_remove_directory: [[0, 1, 2]],
17039
+ path_unlink_file: [[0, 1, 2]],
17040
+ path_readlink: [[0, 1, 2]],
17041
+ path_symlink: [[2, 3, 4]],
17042
+ path_rename: [
17043
+ [0, 1, 2],
17044
+ [3, 4, 5]
17045
+ ],
17046
+ path_link: [
17047
+ [0, 2, 3],
17048
+ [4, 5, 6]
17049
+ ]
17050
+ };
17051
+ RESULTS = { path_open: 8, sock_accept: 2 };
17052
+ SPECIAL = /* @__PURE__ */ new Set(["fd_close", "fd_renumber", "poll_oneoff", "proc_exit"]);
17053
+ }
17054
+ });
17055
+
16765
17056
  // src/process/js/js-watch.ts
16766
17057
  function watchRequest(path, options) {
16767
17058
  return { op: "watch-open", path, ...options?.recursive ? { recursive: true } : {} };
@@ -17311,14 +17602,17 @@ function createContext(o) {
17311
17602
  const syncKernel = new JsSyncKernel(lane, kernel, unwind);
17312
17603
  const terminal = ttyOps(kernel, syncKernel);
17313
17604
  const shared = { pid: o.pid, resolve, random, infos, handles, closing };
17605
+ const wasi = wasiFor({ lane, pid: o.pid, cwd: o.cwd, resolve, fs: o.fs, owned: o.owned });
17314
17606
  const sync = {
17315
17607
  kernel: KERNEL_INFO,
17316
17608
  tty: terminal.syncTty,
17317
17609
  ...watchingSyncOps(kernel, syncKernel, shared),
17318
17610
  run: (options) => runSync(syncKernel, { env: o.env, cwd: o.cwd, resolve, signal: signalNumber }, options),
17319
17611
  spawn: (options) => spawnSync(options),
17612
+ wasi: { create: wasi.create },
17320
17613
  exit: (status2 = 0) => {
17321
17614
  exiting ??= status2 & 255;
17615
+ wasi.closeAll();
17322
17616
  return exitAtOnce(lane, [...writes], terminal.modes(), exiting);
17323
17617
  },
17324
17618
  kill: killer({ self: o.pid, kernel, syncKernel, lane, writes, modes: terminal.modes }),
@@ -17390,6 +17684,7 @@ function createContext(o) {
17390
17684
  onUnhandledRejection: (listener) => listen(strays.rejection, listener)
17391
17685
  };
17392
17686
  const drain2 = async () => {
17687
+ wasi.closeAll();
17393
17688
  for (; ; ) {
17394
17689
  await Promise.all([...pending]);
17395
17690
  await new Promise((resolve2) => setTimeout(resolve2, 0));
@@ -17601,6 +17896,7 @@ var init_js_context = __esm({
17601
17896
  init_js_run();
17602
17897
  init_js_sync();
17603
17898
  init_js_tty();
17899
+ init_js_wasi();
17604
17900
  init_js_watch();
17605
17901
  init_js_websocket();
17606
17902
  KERNEL_INFO = Object.freeze({ version: KERNEL_VERSION });
@@ -17782,8 +18078,10 @@ async function runJs(init, port2, deps, thread) {
17782
18078
  cwd: init.cwd,
17783
18079
  exit: (status3) => exited(statusOf(status3)),
17784
18080
  lane: laneOf(init.lane),
18081
+ fs: { owners: init.owners === true, links: init.links === true },
17785
18082
  strays,
17786
- thread: threadContext(port2, thread)
18083
+ thread: threadContext(port2, thread),
18084
+ ...thread?.owned ? { owned: thread.owned } : {}
17787
18085
  });
17788
18086
  const say = (text) => ctx.write(2, `${init.argv0}: ${text}
17789
18087
  `).catch(() => void 0);