@ai-ecoverse/slicc-kernel 1.132.1 → 1.133.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.
@@ -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.1" : "0.0.0-dev";
2668
2668
  OS_RELEASE = "6.0.0-slicc";
2669
2669
  }
2670
2670
  });
@@ -8413,6 +8413,10 @@ function stdioAlias(path) {
8413
8413
  function deviceOf(path) {
8414
8414
  return deviceAt(path);
8415
8415
  }
8416
+ function namedDevice(path) {
8417
+ if (deviceOf(path) || stdioAlias(path) !== void 0) return true;
8418
+ return path === SEALED_PATH2 || path === CLIPBOARD_PATH2 || path === "/dev/tty";
8419
+ }
8416
8420
  function within(path, root) {
8417
8421
  return path === root || path.startsWith(root === "/" ? "/" : `${root}/`);
8418
8422
  }
@@ -8534,6 +8538,14 @@ var init_wasi_fds = __esm({
8534
8538
  this.table.set(3 + i, entry);
8535
8539
  });
8536
8540
  }
8541
+ adoptCopy(fd) {
8542
+ const at = this.kernel.call({ op: "fd-dup", fd, min: 3 });
8543
+ this.table.set(at, this.stdioEntry(at));
8544
+ return at;
8545
+ }
8546
+ preopenAt(path, name2) {
8547
+ return this.install({ type: "dir", path: normalize(path), preopen: name2 });
8548
+ }
8537
8549
  preopens(cwd, root) {
8538
8550
  const here = normalize(cwd);
8539
8551
  const dot = { type: "dir", path: here, preopen: "." };
@@ -9061,8 +9073,19 @@ var init_wasi_fds = __esm({
9061
9073
  fd = this.openCharDevice(openClipboard, oflags, rights);
9062
9074
  kind = "clipboard";
9063
9075
  } else if (path === "/dev/tty" || /^\/dev\/tty\d+$/.test(path)) {
9064
- fd = openTty?.call(this.kernel.sys, path === "/dev/tty" ? void 0 : path);
9076
+ const exclusive = (oflags & OFLAGS.CREAT) !== 0 && (oflags & OFLAGS.EXCL) !== 0;
9077
+ try {
9078
+ fd = openTty?.call(this.kernel.sys, path === "/dev/tty" ? void 0 : path);
9079
+ } catch (err) {
9080
+ if (exclusive && err.code === "EACCES")
9081
+ throw new WasiError("EEXIST");
9082
+ throw err;
9083
+ }
9065
9084
  if (fd === void 0) throw new WasiError("ENXIO");
9085
+ if (exclusive) {
9086
+ this.kernel.sys.close(fd);
9087
+ throw new WasiError("EEXIST");
9088
+ }
9066
9089
  kind = "tty";
9067
9090
  } else return void 0;
9068
9091
  this.adopt(fd, kind, nonblock);
@@ -9078,13 +9101,14 @@ var init_wasi_fds = __esm({
9078
9101
  open(path, oflags, rights, fdflags, mode) {
9079
9102
  this.made = void 0;
9080
9103
  this.created = false;
9104
+ const exclusive = (oflags & OFLAGS.CREAT) !== 0 && (oflags & OFLAGS.EXCL) !== 0;
9105
+ if (exclusive && namedDevice(path)) throw new WasiError("EEXIST");
9081
9106
  const device2 = deviceOf(path);
9082
9107
  if (device2) return this.install({ type: "device", device: device2 });
9083
9108
  const kernelDevice = this.openKernelDevice(path, oflags, fdflags, rights);
9084
9109
  if (kernelDevice !== void 0) return kernelDevice;
9085
9110
  const alias = stdioAlias(path);
9086
9111
  if (alias !== void 0) return this.reopen(alias);
9087
- const exclusive = (oflags & OFLAGS.CREAT) !== 0 && (oflags & OFLAGS.EXCL) !== 0;
9088
9112
  if (exclusive && !(oflags & OFLAGS.DIRECTORY) && this.madeAtOnce(path, mode)) {
9089
9113
  return this.regular(path, void 0, oflags, rights, fdflags, mode, true);
9090
9114
  }
@@ -10344,7 +10368,7 @@ var init_wasi_host = __esm({
10344
10368
  );
10345
10369
  if (o.shared) this.fds.share(o.shared, true);
10346
10370
  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);
10371
+ else if (!o.bare) this.fds.setup(o.cwd, o.inherited ?? [], o.preopenRoot === true);
10348
10372
  this.listening = o.shared ? [] : this.fds.sockets();
10349
10373
  }
10350
10374
  get cwd() {
@@ -10757,6 +10781,7 @@ var init_wasi_host = __esm({
10757
10781
  return (localCpuNanos() ?? BigInt(Math.round((performance.now() - this.started) * 1e6))) + 1n;
10758
10782
  }
10759
10783
  environ() {
10784
+ if (this.o.bare) return Object.entries(this.o.env).map(([k, v]) => `${k}=${v}`);
10760
10785
  const listen2 = this.listening.length > 0 ? { SLICC_LISTEN_FDS: this.listening.join(" ") } : {};
10761
10786
  const env = { PWD: this.cwd, ...this.o.env, ...listen2 };
10762
10787
  return Object.entries(env).map(([k, v]) => `${k}=${v}`);
@@ -16762,6 +16787,288 @@ var init_js_tty = __esm({
16762
16787
  }
16763
16788
  });
16764
16789
 
16790
+ // src/process/js/js-wasi.ts
16791
+ function ownedFds(sab) {
16792
+ if (!sab) return { add: () => {
16793
+ }, remove: () => {
16794
+ } };
16795
+ const view = new Int32Array(sab);
16796
+ const fds = /* @__PURE__ */ new Set();
16797
+ const publish = () => {
16798
+ Atomics.store(view, 0, 0);
16799
+ let n = 0;
16800
+ for (const fd of fds) {
16801
+ if (1 + n >= view.length) break;
16802
+ view[1 + n++] = fd;
16803
+ }
16804
+ Atomics.store(view, 0, n);
16805
+ };
16806
+ return {
16807
+ add(fd) {
16808
+ fds.add(fd);
16809
+ publish();
16810
+ },
16811
+ remove(fd) {
16812
+ if (fds.delete(fd)) publish();
16813
+ }
16814
+ };
16815
+ }
16816
+ function fdArgsOf(name2) {
16817
+ const paths = PATHS[name2];
16818
+ if (paths) return paths.map(([fd]) => fd);
16819
+ return /^(fd|sock)_/.test(name2) ? [0] : [];
16820
+ }
16821
+ function laneTransport(lane) {
16822
+ return { call: (req) => lane(req) };
16823
+ }
16824
+ function within2(root, dir, path) {
16825
+ if (path.startsWith("/")) return false;
16826
+ const base = dir === root ? [] : dir.slice(root === "/" ? 1 : root.length + 1).split("/");
16827
+ const parts = [...base];
16828
+ for (const seg of path.split("/")) {
16829
+ if (seg === "" || seg === ".") continue;
16830
+ if (seg === "..") {
16831
+ if (parts.length === 0) return false;
16832
+ parts.pop();
16833
+ } else parts.push(seg);
16834
+ }
16835
+ return true;
16836
+ }
16837
+ function preopensOf(given, resolve) {
16838
+ if (given === void 0) return [];
16839
+ if (typeof given !== "object" || given === null) throw new JsCallError("EINVAL", "wasi preopens");
16840
+ return Object.entries(given).map(([name2, path]) => {
16841
+ if (typeof path !== "string" || path === "") throw new JsCallError("EINVAL", "wasi preopens");
16842
+ return [name2, normalize(resolve(path))];
16843
+ });
16844
+ }
16845
+ function createJsWasi(deps, o = {}) {
16846
+ const transport = laneTransport(deps.lane);
16847
+ const sys = kernelSys(transport);
16848
+ const call2 = (req) => {
16849
+ const r = deps.lane(req);
16850
+ if (!r.ok) throw new JsCallError(r.errno, req.op);
16851
+ return r.kind === "json" ? r.json : r.kind === "bytes" ? r.bytes : void 0;
16852
+ };
16853
+ const host = new WasiHost({
16854
+ args: [...o.args ?? []],
16855
+ env: { ...o.env ?? {} },
16856
+ cwd: deps.cwd,
16857
+ pid: deps.pid,
16858
+ kernel: { sys, call: call2 },
16859
+ fs: createSyncFsSabBridge(transport, { ...deps.fs, direct: true }),
16860
+ bare: true
16861
+ });
16862
+ const owned = deps.owned;
16863
+ const guest = /* @__PURE__ */ new Map();
16864
+ const own = (g, k) => {
16865
+ guest.set(g, k);
16866
+ owned.add(k);
16867
+ };
16868
+ const roots = /* @__PURE__ */ new Map();
16869
+ const opened2 = [];
16870
+ const closeKernel = (fd) => {
16871
+ owned.remove(fd);
16872
+ try {
16873
+ host.fds.close(fd);
16874
+ } catch {
16875
+ }
16876
+ };
16877
+ try {
16878
+ (o.stdio ?? [0, 1, 2]).forEach((fd, i) => {
16879
+ const k = host.fds.adoptCopy(fd);
16880
+ opened2.push(k);
16881
+ own(i, k);
16882
+ });
16883
+ for (const [name2, path] of preopensOf(o.preopens, deps.resolve)) {
16884
+ const k = host.fds.preopenAt(path, name2);
16885
+ opened2.push(k);
16886
+ const g = 3 + roots.size;
16887
+ own(g, k);
16888
+ roots.set(g, path);
16889
+ }
16890
+ } catch (err) {
16891
+ for (const k of opened2) closeKernel(k);
16892
+ throw err;
16893
+ }
16894
+ const table = host.imports();
16895
+ const view = () => host.mem.view();
16896
+ const free = () => {
16897
+ let g = 3;
16898
+ while (guest.has(g)) g++;
16899
+ return g;
16900
+ };
16901
+ const confined = (name2, args) => {
16902
+ for (const [fdAt, ptrAt, lenAt] of PATHS[name2] ?? []) {
16903
+ const g = args[fdAt];
16904
+ const root = roots.get(g);
16905
+ const dir = host.fds.find(guest.get(g));
16906
+ if (root === void 0 || dir?.type !== "dir") continue;
16907
+ if (!within2(root, dir.path, host.mem.string(args[ptrAt], args[lenAt]))) return false;
16908
+ }
16909
+ return true;
16910
+ };
16911
+ const opens = (out, root) => {
16912
+ const k = view().getUint32(out, true);
16913
+ const g = free();
16914
+ own(g, k);
16915
+ if (root !== void 0) roots.set(g, root);
16916
+ view().setUint32(out, g, true);
16917
+ };
16918
+ const imports = {};
16919
+ for (const [name2, fn] of Object.entries(table)) {
16920
+ if (SPECIAL.has(name2)) continue;
16921
+ const fdArgs = fdArgsOf(name2);
16922
+ imports[name2] = ((...raw) => {
16923
+ const args = [...raw];
16924
+ for (const at of fdArgs) {
16925
+ const k = guest.get(args[at]);
16926
+ if (k === void 0) return E.BADF;
16927
+ args[at] = k;
16928
+ }
16929
+ if (!confined(name2, raw)) return E.NOTCAPABLE;
16930
+ const out = RESULTS[name2];
16931
+ if (out !== void 0 && (raw[out] >>> 0) + 4 > host.mem.size()) return E.FAULT;
16932
+ const errno2 = fn(...args);
16933
+ if (errno2 !== E.SUCCESS) return errno2;
16934
+ if (out !== void 0) opens(raw[out] >>> 0, roots.get(raw[0]));
16935
+ return errno2;
16936
+ });
16937
+ }
16938
+ imports.fd_close = ((g) => {
16939
+ const k = guest.get(g);
16940
+ if (k === void 0) return E.BADF;
16941
+ guest.delete(g);
16942
+ roots.delete(g);
16943
+ owned.remove(k);
16944
+ return table.fd_close(k);
16945
+ });
16946
+ imports.fd_renumber = ((from, to) => {
16947
+ const kf = guest.get(from);
16948
+ const kt = guest.get(to);
16949
+ if (kf === void 0 || kt === void 0) return E.BADF;
16950
+ if (from === to) return E.SUCCESS;
16951
+ closeKernel(kt);
16952
+ guest.set(to, kf);
16953
+ const root = roots.get(from);
16954
+ if (root === void 0) roots.delete(to);
16955
+ else roots.set(to, root);
16956
+ guest.delete(from);
16957
+ roots.delete(from);
16958
+ return E.SUCCESS;
16959
+ });
16960
+ imports.poll_oneoff = ((inPtr, outPtr, n, nevents) => {
16961
+ const v = view();
16962
+ const swapped = [];
16963
+ for (let i = 0; i < n; i++) {
16964
+ const at = inPtr + i * SUB_SIZE;
16965
+ const tag = v.getUint8(at + SUB_TAG);
16966
+ if (tag !== EVENTTYPE.FD_READ && tag !== EVENTTYPE.FD_WRITE) continue;
16967
+ const g = v.getUint32(at + SUB_FD, true);
16968
+ swapped.push([at + SUB_FD, g]);
16969
+ v.setUint32(at + SUB_FD, guest.get(g) ?? NO_FD, true);
16970
+ }
16971
+ try {
16972
+ return table.poll_oneoff(inPtr, outPtr, n, nevents);
16973
+ } finally {
16974
+ const after = view();
16975
+ for (const [at, g] of swapped) after.setUint32(at, g, true);
16976
+ }
16977
+ });
16978
+ imports.proc_exit = ((code2) => {
16979
+ throw new JsWasiExit(code2);
16980
+ });
16981
+ let closed = false;
16982
+ const run = (instance, entry) => {
16983
+ const memory = instance.exports.memory;
16984
+ if (memory instanceof WebAssembly.Memory) host.mem.bind(memory);
16985
+ const fn = instance.exports[entry];
16986
+ if (typeof fn !== "function") {
16987
+ if (entry === "_initialize") return 0;
16988
+ throw new JsCallError("EINVAL", `wasi: the instance exports no ${entry}`);
16989
+ }
16990
+ try {
16991
+ fn();
16992
+ return 0;
16993
+ } catch (err) {
16994
+ if (err instanceof JsWasiExit && o.returnOnExit !== false) return err.code;
16995
+ throw err;
16996
+ }
16997
+ };
16998
+ const wasi = {
16999
+ imports: { wasi_snapshot_preview1: imports },
17000
+ wasiImport: imports,
17001
+ bind: (memory) => {
17002
+ if (!(memory instanceof WebAssembly.Memory)) throw new JsCallError("EINVAL", "wasi bind");
17003
+ host.mem.bind(memory);
17004
+ },
17005
+ start: (instance) => run(instance, "_start"),
17006
+ initialize: (instance) => void run(instance, "_initialize"),
17007
+ close: () => {
17008
+ if (closed) return;
17009
+ closed = true;
17010
+ deps.live.delete(wasi);
17011
+ for (const k of guest.values()) closeKernel(k);
17012
+ guest.clear();
17013
+ roots.clear();
17014
+ }
17015
+ };
17016
+ deps.live.add(wasi);
17017
+ return wasi;
17018
+ }
17019
+ function wasiFor(o) {
17020
+ const deps = { ...o, live: /* @__PURE__ */ new Set(), owned: ownedFds(o.owned) };
17021
+ return {
17022
+ create: (options) => createJsWasi(deps, options),
17023
+ closeAll: () => {
17024
+ for (const wasi of [...deps.live]) wasi.close();
17025
+ }
17026
+ };
17027
+ }
17028
+ var JsWasiExit, SUB_SIZE, SUB_TAG, SUB_FD, NO_FD, PATHS, RESULTS, SPECIAL;
17029
+ var init_js_wasi = __esm({
17030
+ "src/process/js/js-wasi.ts"() {
17031
+ "use strict";
17032
+ init_sync_sab_bridge();
17033
+ init_process_runtime();
17034
+ init_wasi_abi();
17035
+ init_wasi_files();
17036
+ init_wasi_host();
17037
+ init_js_kernel();
17038
+ JsWasiExit = class extends Error {
17039
+ code;
17040
+ constructor(code2) {
17041
+ super(`wasi exit ${code2}`);
17042
+ this.code = code2;
17043
+ }
17044
+ };
17045
+ SUB_SIZE = 48;
17046
+ SUB_TAG = 8;
17047
+ SUB_FD = 16;
17048
+ NO_FD = 2147483647;
17049
+ PATHS = {
17050
+ path_open: [[0, 2, 3]],
17051
+ path_filestat_get: [[0, 2, 3]],
17052
+ path_filestat_set_times: [[0, 2, 3]],
17053
+ path_create_directory: [[0, 1, 2]],
17054
+ path_remove_directory: [[0, 1, 2]],
17055
+ path_unlink_file: [[0, 1, 2]],
17056
+ path_readlink: [[0, 1, 2]],
17057
+ path_symlink: [[2, 3, 4]],
17058
+ path_rename: [
17059
+ [0, 1, 2],
17060
+ [3, 4, 5]
17061
+ ],
17062
+ path_link: [
17063
+ [0, 2, 3],
17064
+ [4, 5, 6]
17065
+ ]
17066
+ };
17067
+ RESULTS = { path_open: 8, sock_accept: 2 };
17068
+ SPECIAL = /* @__PURE__ */ new Set(["fd_close", "fd_renumber", "poll_oneoff", "proc_exit"]);
17069
+ }
17070
+ });
17071
+
16765
17072
  // src/process/js/js-watch.ts
16766
17073
  function watchRequest(path, options) {
16767
17074
  return { op: "watch-open", path, ...options?.recursive ? { recursive: true } : {} };
@@ -17311,14 +17618,17 @@ function createContext(o) {
17311
17618
  const syncKernel = new JsSyncKernel(lane, kernel, unwind);
17312
17619
  const terminal = ttyOps(kernel, syncKernel);
17313
17620
  const shared = { pid: o.pid, resolve, random, infos, handles, closing };
17621
+ const wasi = wasiFor({ lane, pid: o.pid, cwd: o.cwd, resolve, fs: o.fs, owned: o.owned });
17314
17622
  const sync = {
17315
17623
  kernel: KERNEL_INFO,
17316
17624
  tty: terminal.syncTty,
17317
17625
  ...watchingSyncOps(kernel, syncKernel, shared),
17318
17626
  run: (options) => runSync(syncKernel, { env: o.env, cwd: o.cwd, resolve, signal: signalNumber }, options),
17319
17627
  spawn: (options) => spawnSync(options),
17628
+ wasi: { create: wasi.create },
17320
17629
  exit: (status2 = 0) => {
17321
17630
  exiting ??= status2 & 255;
17631
+ wasi.closeAll();
17322
17632
  return exitAtOnce(lane, [...writes], terminal.modes(), exiting);
17323
17633
  },
17324
17634
  kill: killer({ self: o.pid, kernel, syncKernel, lane, writes, modes: terminal.modes }),
@@ -17390,6 +17700,7 @@ function createContext(o) {
17390
17700
  onUnhandledRejection: (listener) => listen(strays.rejection, listener)
17391
17701
  };
17392
17702
  const drain2 = async () => {
17703
+ wasi.closeAll();
17393
17704
  for (; ; ) {
17394
17705
  await Promise.all([...pending]);
17395
17706
  await new Promise((resolve2) => setTimeout(resolve2, 0));
@@ -17601,6 +17912,7 @@ var init_js_context = __esm({
17601
17912
  init_js_run();
17602
17913
  init_js_sync();
17603
17914
  init_js_tty();
17915
+ init_js_wasi();
17604
17916
  init_js_watch();
17605
17917
  init_js_websocket();
17606
17918
  KERNEL_INFO = Object.freeze({ version: KERNEL_VERSION });
@@ -17782,8 +18094,10 @@ async function runJs(init, port2, deps, thread) {
17782
18094
  cwd: init.cwd,
17783
18095
  exit: (status3) => exited(statusOf(status3)),
17784
18096
  lane: laneOf(init.lane),
18097
+ fs: { owners: init.owners === true, links: init.links === true },
17785
18098
  strays,
17786
- thread: threadContext(port2, thread)
18099
+ thread: threadContext(port2, thread),
18100
+ ...thread?.owned ? { owned: thread.owned } : {}
17787
18101
  });
17788
18102
  const say = (text) => ctx.write(2, `${init.argv0}: ${text}
17789
18103
  `).catch(() => void 0);