@ai-ecoverse/slicc-kernel 1.12.0 → 1.14.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.
@@ -253,7 +253,7 @@ function createNodeOps(h) {
253
253
  const size = Fs.isDir(node.mode) ? 4096 : s.loaded ? s.len : st.size;
254
254
  const mtime = new Date(st.mtimeMs ?? 0);
255
255
  return {
256
- dev: 1,
256
+ dev: st.dev ?? 1,
257
257
  ino: st.ino ?? inodeOf(liveNodePath(node)),
258
258
  mode: node.mode,
259
259
  nlink: 1,
@@ -383,28 +383,46 @@ function createNodeOps(h) {
383
383
  };
384
384
  }
385
385
  function createStreamOps(h) {
386
- const { Fs, statOf, ensureLoaded, ensureCapacity, flushNode } = h;
386
+ const { Fs, statOf, ensureLoaded, ensureCapacity, flushNode, bridgeOf } = h;
387
+ const held = (stream, change) => {
388
+ const s = stream.node.live;
389
+ if ((stream.flags & 3) === 0 || s.orphan) return;
390
+ const before = s.writers ?? 0;
391
+ s.writers = Math.max(0, before + change);
392
+ if (before === 0 !== (s.writers === 0)) {
393
+ try {
394
+ bridgeOf(stream.node).hold?.(liveNodePath(stream.node), s.writers > 0);
395
+ } catch {
396
+ }
397
+ }
398
+ };
387
399
  return {
388
400
  open(stream) {
389
401
  if (!Fs.isFile(stream.node.mode)) return;
390
402
  stream.node.live.openCount++;
403
+ held(stream, 1);
391
404
  },
392
405
  dup(stream) {
393
406
  if (!Fs.isFile(stream.node.mode)) return;
394
407
  stream.node.live.openCount++;
408
+ held(stream, 1);
395
409
  },
396
410
  close(stream) {
397
411
  const node = stream.node;
398
412
  if (!Fs.isFile(node.mode)) return;
399
413
  const s = node.live;
400
414
  s.openCount = Math.max(0, s.openCount - 1);
401
- if (s.openCount > 0) return;
415
+ if (s.openCount > 0) {
416
+ held(stream, -1);
417
+ return;
418
+ }
402
419
  try {
403
420
  flushNode(node);
404
421
  } finally {
405
422
  s.data = void 0;
406
423
  s.len = 0;
407
424
  s.loaded = false;
425
+ held(stream, -1);
408
426
  }
409
427
  },
410
428
  read(stream, buffer, offset, length, position) {
@@ -587,7 +605,7 @@ function guardStatfs(Fs) {
587
605
  const defaults = statfsNode(node);
588
606
  let usage;
589
607
  try {
590
- usage = node.live ? node.mount?.opts?.bridge?.statfs?.() : void 0;
608
+ usage = node.live ? node.mount?.opts?.bridge?.statfs?.(liveNodePath(node)) : void 0;
591
609
  } catch {
592
610
  return defaults;
593
611
  }
@@ -718,7 +736,8 @@ function parseSyncFsStat(json) {
718
736
  ...typeof s.mtimeMs === "number" ? { mtimeMs: s.mtimeMs } : {},
719
737
  ...typeof s.atimeMs === "number" ? { atimeMs: s.atimeMs } : {},
720
738
  ...typeof s.ctimeMs === "number" ? { ctimeMs: s.ctimeMs } : {},
721
- ...typeof s.ino === "number" ? { ino: s.ino } : {}
739
+ ...typeof s.ino === "number" ? { ino: s.ino } : {},
740
+ ...typeof s.dev === "number" ? { dev: s.dev } : {}
722
741
  };
723
742
  }
724
743
  var SYNC_FS_REQUEST_TIMEOUT_MS;
@@ -949,7 +968,10 @@ function createSyncFsSabBridge(transport, opts = {}) {
949
968
  utimes: (path, atimeMs, mtimeMs) => {
950
969
  run({ op: "utimes", path, atimeMs, mtimeMs }, path);
951
970
  },
952
- statfs: () => parseSyncFsUsage(json({ op: "statfs", path: "/" }, "/"))
971
+ hold: (path, held) => {
972
+ run({ op: "hold", path, mode: held ? 1 : 0 }, path);
973
+ },
974
+ statfs: (path = "/") => parseSyncFsUsage(json({ op: "statfs", path }, path))
953
975
  };
954
976
  }
955
977
  var init_sync_sab_bridge = __esm({
@@ -1916,11 +1938,18 @@ function useDevFd(Fs) {
1916
1938
  return fstat.call(Fs, fd);
1917
1939
  };
1918
1940
  }
1919
- function mountTable() {
1941
+ function mountTable(mounts = []) {
1920
1942
  const root = globalThis.navigator?.storage ? "opfs" : "memory";
1921
- return [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0", ""].join(
1922
- "\n"
1923
- );
1943
+ const lines = [`${root} / ${root} rw 0 0`, "devfs /dev devfs rw 0 0", "proc /proc proc rw 0 0"];
1944
+ for (const m of mounts) {
1945
+ const options = Object.entries(m.options).map(([k, v]) => v === "" ? k : `${k}=${v}`);
1946
+ const access = options.includes("ro") ? [] : ["rw"];
1947
+ lines.push(
1948
+ `${field(m.source)} ${field(m.target)} ${m.type} ${[...access, ...options].join(",")} 0 0`
1949
+ );
1950
+ }
1951
+ return `${lines.join("\n")}
1952
+ `;
1924
1953
  }
1925
1954
  function accounts(env = {}) {
1926
1955
  const user = env.USER ?? "web_user";
@@ -1935,13 +1964,13 @@ ${name}:x:1000:
1935
1964
  `
1936
1965
  };
1937
1966
  }
1938
- function useMounts(Fs, env = {}) {
1967
+ function useMounts(Fs, env = {}, live = false) {
1939
1968
  const { writeFile, mkdirTree } = Fs;
1940
1969
  if (typeof Fs.open !== "function" || typeof writeFile !== "function") return;
1941
1970
  const { passwd, group } = accounts(env);
1942
1971
  const backing = { "/etc/mtab": "/proc/mounts" };
1943
1972
  try {
1944
- writeFile.call(Fs, "/proc/mounts", mountTable());
1973
+ if (!live) writeFile.call(Fs, "/proc/mounts", mountTable());
1945
1974
  } catch {
1946
1975
  return;
1947
1976
  }
@@ -1965,7 +1994,7 @@ function useMounts(Fs, env = {}) {
1965
1994
  }
1966
1995
  };
1967
1996
  }
1968
- var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, DIR_MODE, LINK_MODE, O_ACCMODE, O_CREAT2, NAME;
1997
+ var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, DIR_MODE, LINK_MODE, O_ACCMODE, O_CREAT2, field, NAME;
1969
1998
  var init_process_fds = __esm({
1970
1999
  "src/process/process-fds.ts"() {
1971
2000
  "use strict";
@@ -1993,6 +2022,7 @@ var init_process_fds = __esm({
1993
2022
  LINK_MODE = 41408;
1994
2023
  O_ACCMODE = 3;
1995
2024
  O_CREAT2 = 64;
2025
+ field = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
1996
2026
  NAME = /^[a-z_][a-z0-9_-]*$/i;
1997
2027
  }
1998
2028
  });
@@ -2685,6 +2715,7 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
2685
2715
  if (!infoOf(Number(name))) throw error();
2686
2716
  return pidDir(name, Number(name));
2687
2717
  }
2718
+ if (name === "mounts") return file(parent, name, () => mountTable(sys.mountList?.() ?? []));
2688
2719
  if (SYSTEM_FILES.includes(name)) {
2689
2720
  return file(
2690
2721
  parent,
@@ -2697,7 +2728,7 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
2697
2728
  },
2698
2729
  readdir: (node) => {
2699
2730
  const names = new Set(readdir ? readdir(node) : [".", ".."]);
2700
- for (const name of SYSTEM_FILES) names.add(name);
2731
+ for (const name of [...SYSTEM_FILES, "mounts"]) names.add(name);
2701
2732
  for (const p of procList().processes) names.add(String(p.pid));
2702
2733
  return [...names];
2703
2734
  }
@@ -2721,6 +2752,7 @@ var HZ, DIR_MODE2, FILE_MODE, ENOENT, ESRCH, EINVAL, UID, KIB, FALLBACK_MEMORY,
2721
2752
  var init_procfs = __esm({
2722
2753
  "src/process/procfs.ts"() {
2723
2754
  "use strict";
2755
+ init_process_fds();
2724
2756
  HZ = 100;
2725
2757
  DIR_MODE2 = 16749;
2726
2758
  FILE_MODE = 33060;
@@ -2852,6 +2884,9 @@ function kernelSys(transport) {
2852
2884
  procList() {
2853
2885
  return json(call2({ op: "proc-list" }, "proc-list"));
2854
2886
  },
2887
+ mountList() {
2888
+ return json(call2({ op: "mount-list" }, "mount-list"));
2889
+ },
2855
2890
  ptyNumber(fd) {
2856
2891
  return json(call2({ op: "pty-number", fd }, `pty-number ${fd}`));
2857
2892
  },
@@ -3017,7 +3052,7 @@ async function runWasmProcess(init, port, deps = {}) {
3017
3052
  const restartable = () => signals.restartable();
3018
3053
  const streams = new KernelStreams(running.FS, sys, { sigpipe, restartable });
3019
3054
  trackCloseOnExec(running.FS);
3020
- useMounts(running.FS, init.env);
3055
+ useMounts(running.FS, init.env, true);
3021
3056
  useProcfs(running.FS, sys, init.pid);
3022
3057
  if (init.fork) restoreForkedStreams(running.FS, streams, init.fork.streams ?? []);
3023
3058
  else {
@@ -6421,7 +6456,7 @@ function enosys(module, name, foreign) {
6421
6456
  }
6422
6457
  function firstOther(foreign) {
6423
6458
  for (const [module, fields] of Object.entries(foreign)) {
6424
- const name = Object.keys(fields).find((field) => fields[field] === "other");
6459
+ const name = Object.keys(fields).find((field2) => fields[field2] === "other");
6425
6460
  if (name !== void 0) return `${module}.${name}`;
6426
6461
  }
6427
6462
  return void 0;