@ai-ecoverse/slicc-kernel 1.31.2 → 1.32.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.
@@ -1593,6 +1593,8 @@ var init_kernel_streams = __esm({
1593
1593
  refs = /* @__PURE__ */ new Map();
1594
1594
  socketRoot;
1595
1595
  sockets = 0;
1596
+ descriptions = /* @__PURE__ */ new Map();
1597
+ described = 0;
1596
1598
  Fs;
1597
1599
  sys;
1598
1600
  options;
@@ -1673,6 +1675,32 @@ var init_kernel_streams = __esm({
1673
1675
  })
1674
1676
  };
1675
1677
  }
1678
+ sizeFromKernel(stream, kfd) {
1679
+ const { size } = this.sys;
1680
+ if (!size) return;
1681
+ const node = stream.node;
1682
+ this.describe(stream, `${stream.path ?? ""}:${++this.described}`, () => ({
1683
+ ...node.node_ops?.getattr?.(node),
1684
+ size: this.call(() => size.call(this.sys, kfd))
1685
+ }));
1686
+ }
1687
+ describe(stream, name, getattr) {
1688
+ if (this.descriptions.size === 0) this.useDescriptions();
1689
+ this.descriptions.set(name, getattr);
1690
+ stream.path = name;
1691
+ stream.stream_ops = { ...stream.stream_ops, getattr };
1692
+ }
1693
+ useDescriptions() {
1694
+ const fs = this.Fs;
1695
+ for (const name of ["stat", "lstat"]) {
1696
+ const original = fs[name];
1697
+ if (typeof original !== "function") continue;
1698
+ fs[name] = (path, ...rest) => {
1699
+ const getattr = this.descriptions.get(path);
1700
+ return getattr ? getattr() : original.call(fs, path, ...rest);
1701
+ };
1702
+ }
1703
+ }
1676
1704
  useControllingTerminal() {
1677
1705
  if (typeof this.Fs.open !== "function") return;
1678
1706
  this.usePtyPaths();
@@ -1868,252 +1896,6 @@ var init_kernel_streams = __esm({
1868
1896
  }
1869
1897
  });
1870
1898
 
1871
- // src/process/process-children.ts
1872
- function status(r) {
1873
- return r.ok ? 0 : -wasiErrno(r.errno);
1874
- }
1875
- function number(r) {
1876
- if (!r.ok) return -wasiErrno(r.errno);
1877
- return r.kind === "json" && typeof r.json === "number" ? r.json : -wasiErrno("EIO");
1878
- }
1879
- function flushed(beforeSpawn) {
1880
- try {
1881
- beforeSpawn();
1882
- return 0;
1883
- } catch (err) {
1884
- const errno2 = err?.errno;
1885
- if (typeof errno2 !== "number") throw err;
1886
- return -errno2;
1887
- }
1888
- }
1889
- function drain(Fs, stream) {
1890
- const chunks = [];
1891
- const buffer = new Uint8Array(65536);
1892
- try {
1893
- for (let n = Fs.read(stream, buffer, 0, buffer.length); n > 0; ) {
1894
- chunks.push(buffer.slice(0, n));
1895
- n = Fs.read(stream, buffer, 0, buffer.length);
1896
- }
1897
- } catch {
1898
- }
1899
- const out = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));
1900
- let offset = 0;
1901
- for (const chunk of chunks) {
1902
- out.set(chunk, offset);
1903
- offset += chunk.length;
1904
- }
1905
- return out;
1906
- }
1907
- function kernelSelect(Fs, transport, read, write, timeoutMs) {
1908
- const kernel = (fd) => Fs.getStream(fd)?.sliccKernelFd;
1909
- const kr = read.map(kernel);
1910
- const kw = write.map(kernel);
1911
- const r = transport.call({ op: "fd-select", read: kr, write: kw, timeoutMs }, Infinity, "select");
1912
- if (!r.ok) return -wasiErrno(r.errno);
1913
- const got = r.kind === "json" ? r.json : { read: [], write: [] };
1914
- return {
1915
- read: read.filter((_, i) => got.read.includes(kr[i])),
1916
- write: write.filter((_, i) => got.write.includes(kw[i]))
1917
- };
1918
- }
1919
- function ownReady(Fs, read, write) {
1920
- const flags = (fd) => {
1921
- const stream = Fs.getStream(fd);
1922
- if (!stream) return POLLNVAL;
1923
- return stream.stream_ops.poll ? stream.stream_ops.poll(stream) : POLLIN2 | POLLOUT2;
1924
- };
1925
- return {
1926
- read: read.filter((fd) => flags(fd) & (POLLIN2 | POLLHUP2 | POLLERR2 | POLLNVAL)),
1927
- write: write.filter((fd) => flags(fd) & (POLLOUT2 | POLLERR2 | POLLNVAL))
1928
- };
1929
- }
1930
- function anySelect(Fs, transport, read, write, timeoutMs) {
1931
- const kernel = (fd) => Fs.getStream(fd)?.sliccKernelFd;
1932
- const own = (fd) => kernel(fd) === void 0;
1933
- if (![...read, ...write].some(own)) return kernelSelect(Fs, transport, read, write, timeoutMs);
1934
- const deadline = timeoutMs < 0 ? Number.POSITIVE_INFINITY : Date.now() + timeoutMs;
1935
- const kernelRead = read.filter((fd) => !own(fd));
1936
- const kernelWrite = write.filter((fd) => !own(fd));
1937
- for (; ; ) {
1938
- const local = ownReady(Fs, read.filter(own), write.filter(own));
1939
- const pending = local.read.length > 0 || local.write.length > 0;
1940
- const slice = pending ? 0 : Math.min(SELECT_SLICE_MS, Math.max(0, deadline - Date.now()));
1941
- const got = kernelSelect(Fs, transport, kernelRead, kernelWrite, slice);
1942
- if (typeof got === "number") return got;
1943
- const ready = { read: [...local.read, ...got.read], write: [...local.write, ...got.write] };
1944
- if (ready.read.length > 0 || ready.write.length > 0 || Date.now() >= deadline) {
1945
- return ready;
1946
- }
1947
- }
1948
- }
1949
- function createProcessKernel(deps) {
1950
- const { transport, Fs } = deps;
1951
- const reaped = /* @__PURE__ */ new Map();
1952
- const call2 = (req, label) => transport.call(req, Infinity, label);
1953
- const at = (path) => path === "" || path.startsWith("/") ? path : `${Fs.cwd()}/${path}`;
1954
- const slot = (fd, n, promote) => {
1955
- const stream = fd >= 0 ? Fs.getStream(fd) : null;
1956
- if (!stream) return { none: true };
1957
- promote?.(stream);
1958
- if (stream.sliccKernelFd !== void 0) return { fd: stream.sliccKernelFd };
1959
- if (stream.path === "/dev/null") return { none: true };
1960
- return n === 0 ? { input: drain(Fs, stream) } : { capture: true };
1961
- };
1962
- const kernelWait = (pid, nohang, options = 0) => {
1963
- const req = {
1964
- op: "proc-wait",
1965
- pid,
1966
- nohang,
1967
- ...options & WUNTRACED ? { untraced: true } : {},
1968
- ...options & WCONTINUED ? { continued: true } : {}
1969
- };
1970
- let r = transport.call(req, Infinity, `proc-wait ${pid}`);
1971
- while (!r.ok && r.errno === "EINTR" && deps.restartable?.()) {
1972
- r = transport.call(req, Infinity, `proc-wait ${pid}`);
1973
- }
1974
- if (!r.ok) return -wasiErrno(r.errno);
1975
- const waited = r.kind === "json" ? r.json : [0, 0];
1976
- if (waited[0] > 0) deps.afterChild();
1977
- return [waited[0], waited[1]];
1978
- };
1979
- const deliver = (pid, n, fd) => {
1980
- const r = transport.call(
1981
- { op: "proc-captured", pid, slot: n },
1982
- Infinity,
1983
- `proc-captured ${pid}`
1984
- );
1985
- const stream = Fs.getStream(fd);
1986
- if (r.ok && r.kind === "bytes" && r.bytes.length > 0 && stream) {
1987
- Fs.write(stream, r.bytes, 0, r.bytes.length);
1988
- }
1989
- };
1990
- const execCaptures = /* @__PURE__ */ new Map();
1991
- const execWait = (pid) => {
1992
- const r = transport.call({ op: "proc-exec", pid }, Infinity, `exec ${pid}`);
1993
- if (!r.ok) return -wasiErrno(r.errno);
1994
- deps.afterChild();
1995
- return r.kind === "json" ? r.json[1] : 0;
1996
- };
1997
- const spawnChild = (file, argv, env, cwd, fds, actions, exec) => {
1998
- const unflushed = flushed(deps.beforeSpawn);
1999
- if (unflushed < 0) return unflushed;
2000
- const promote = deps.stdioPromoter?.();
2001
- const stdio = [0, 1, 2].map((n) => slot(fds[n] ?? -1, n, promote));
2002
- const inherit = deps.inherit?.(actions) ?? [];
2003
- const r = transport.call(
2004
- {
2005
- op: "proc-spawn",
2006
- file,
2007
- argv,
2008
- env: env ?? deps.env,
2009
- cwd: cwd ?? Fs.cwd(),
2010
- stdio,
2011
- ...inherit.length > 0 ? { inherit } : {},
2012
- ...exec ? { exec } : {}
2013
- },
2014
- Infinity,
2015
- `proc-spawn ${file}`
2016
- );
2017
- if (!r.ok) return -wasiErrno(r.errno);
2018
- const pid = r.kind === "json" ? r.json : 0;
2019
- const captures = [1, 2].filter((n) => "capture" in stdio[n]);
2020
- if (captures.length === 0) return pid;
2021
- if (exec) {
2022
- execCaptures.set(pid, () => {
2023
- for (const n of captures) deliver(pid, n, fds[n]);
2024
- });
2025
- return pid;
2026
- }
2027
- const waited = kernelWait(pid, false);
2028
- if (typeof waited === "number") return waited;
2029
- for (const n of captures) deliver(pid, n, fds[n]);
2030
- reaped.set(pid, waited[1]);
2031
- return pid;
2032
- };
2033
- return {
2034
- spawn(file, argv, env, cwd, fds, actions) {
2035
- return spawnChild(file, argv, env, cwd, fds, actions, false);
2036
- },
2037
- fork(state) {
2038
- const unflushed = flushed(deps.beforeSpawn);
2039
- if (unflushed < 0) return unflushed;
2040
- const streams = deps.describeFork();
2041
- const r = transport.call(
2042
- { op: "proc-fork", state: { ...state, streams, cwd: Fs.cwd() } },
2043
- Infinity,
2044
- "proc-fork"
2045
- );
2046
- if (!r.ok) return -wasiErrno(r.errno);
2047
- return r.kind === "json" ? r.json : -wasiErrno("EIO");
2048
- },
2049
- select: (read, write, timeoutMs) => anySelect(Fs, transport, read, write, timeoutMs),
2050
- execWait,
2051
- execve(file, argv, env, cwd) {
2052
- const pid = spawnChild(file, argv, env, cwd, [0, 1, 2], void 0, true);
2053
- if (pid < 0) return pid;
2054
- const status2 = execWait(pid);
2055
- execCaptures.get(pid)?.();
2056
- execCaptures.delete(pid);
2057
- return status2;
2058
- },
2059
- pause() {
2060
- return status(call2({ op: "sig-pause" }, "pause"));
2061
- },
2062
- mount(source, target, type, flags, data) {
2063
- const req = { op: "mount", source, target: at(target), type, flags, data };
2064
- return status(call2(req, `mount ${target}`));
2065
- },
2066
- umount2(target, flags) {
2067
- return status(call2({ op: "umount", target: at(target), flags }, `umount ${target}`));
2068
- },
2069
- kill(pid, sig) {
2070
- if (pid === deps.pid) {
2071
- if (sig !== 0) deps.raise?.(sig);
2072
- return 0;
2073
- }
2074
- return status(call2({ op: "proc-kill", pid, sig }, `kill ${pid}`));
2075
- },
2076
- setpgid: (pid, pgid) => status(call2({ op: "proc-setpgid", pid, pgid }, "setpgid")),
2077
- setsid: () => number(call2({ op: "proc-setsid" }, "setsid")),
2078
- getpgid: (pid) => number(call2({ op: "proc-getpgid", pid }, "getpgid")),
2079
- getsid: (pid) => number(call2({ op: "proc-getsid", pid }, "getsid")),
2080
- tcgetpgrp(fd) {
2081
- const kfd = Fs.getStream(fd)?.sliccKernelFd;
2082
- if (kfd === void 0) return -wasiErrno("ENOTTY");
2083
- return number(call2({ op: "tty-pgrp-get", fd: kfd }, "tcgetpgrp"));
2084
- },
2085
- tcsetpgrp(fd, pgrp) {
2086
- const kfd = Fs.getStream(fd)?.sliccKernelFd;
2087
- if (kfd === void 0) return -wasiErrno("ENOTTY");
2088
- return status(call2({ op: "tty-pgrp-set", fd: kfd, pgrp }, "tcsetpgrp"));
2089
- },
2090
- wait(pid, nohang, options) {
2091
- const key = pid > 0 ? reaped.has(pid) ? pid : void 0 : reaped.keys().next().value;
2092
- if (key !== void 0) {
2093
- const status2 = reaped.get(key);
2094
- reaped.delete(key);
2095
- return [key, status2];
2096
- }
2097
- return kernelWait(pid, nohang, options);
2098
- }
2099
- };
2100
- }
2101
- var POLLIN2, POLLOUT2, POLLERR2, POLLHUP2, POLLNVAL, SELECT_SLICE_MS, WUNTRACED, WCONTINUED;
2102
- var init_process_children = __esm({
2103
- "src/process/process-children.ts"() {
2104
- "use strict";
2105
- init_wasi_errno();
2106
- POLLIN2 = 1;
2107
- POLLOUT2 = 4;
2108
- POLLERR2 = 8;
2109
- POLLHUP2 = 16;
2110
- POLLNVAL = 32;
2111
- SELECT_SLICE_MS = 20;
2112
- WUNTRACED = 2;
2113
- WCONTINUED = 8;
2114
- }
2115
- });
2116
-
2117
1899
  // src/process/process-pty.ts
2118
1900
  function failed(e) {
2119
1901
  const code2 = e?.code;
@@ -2487,7 +2269,46 @@ function describeFdDir(Fs) {
2487
2269
  };
2488
2270
  return entry;
2489
2271
  }
2490
- };
2272
+ };
2273
+ }
2274
+ function useZeroDevices(Fs) {
2275
+ const { analyzePath, registerDevice, mkdev, makedev } = Fs;
2276
+ if (!analyzePath || !registerDevice || !mkdev || !makedev) return;
2277
+ const zeros = (_s, buffer, offset, length) => {
2278
+ buffer.fill(0, offset, offset + length);
2279
+ return length;
2280
+ };
2281
+ const devices = [
2282
+ ["/dev/zero", 5, (_s, _b, _o, length) => length],
2283
+ [
2284
+ "/dev/full",
2285
+ 7,
2286
+ (_s, _b, _o, length) => {
2287
+ if (length > 0) throw new Fs.ErrnoError(wasiErrno("ENOSPC"));
2288
+ return 0;
2289
+ }
2290
+ ]
2291
+ ];
2292
+ for (const [path, minor, write] of devices) {
2293
+ if (analyzePath.call(Fs, path).exists) continue;
2294
+ const dev = makedev.call(Fs, 1, minor);
2295
+ registerDevice.call(Fs, dev, { read: zeros, write, llseek: () => 0 });
2296
+ mkdev.call(Fs, path, CHAR_DEVICE, dev);
2297
+ }
2298
+ }
2299
+ function linkStdio(Fs) {
2300
+ const { unlink, symlink } = Fs;
2301
+ if (!unlink || !symlink) return;
2302
+ for (const [fd, name] of ["stdin", "stdout", "stderr"].entries()) {
2303
+ try {
2304
+ unlink.call(Fs, `/dev/${name}`);
2305
+ } catch {
2306
+ }
2307
+ try {
2308
+ symlink.call(Fs, `/proc/self/fd/${fd}`, `/dev/${name}`);
2309
+ } catch {
2310
+ }
2311
+ }
2491
2312
  }
2492
2313
  function useDevFd(Fs) {
2493
2314
  if (typeof Fs.open !== "function") return;
@@ -2495,6 +2316,7 @@ function useDevFd(Fs) {
2495
2316
  Fs.symlink?.("/proc/self/fd", "/dev/fd");
2496
2317
  } catch {
2497
2318
  }
2319
+ linkStdio(Fs);
2498
2320
  describeFdDir(Fs);
2499
2321
  const fdOf = (path) => typeof path === "string" ? fdOfPath(path, Fs.cwd()) : void 0;
2500
2322
  const target = (fd) => {
@@ -2581,7 +2403,7 @@ function useMounts(Fs, env = {}, live = false) {
2581
2403
  }
2582
2404
  };
2583
2405
  }
2584
- var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, AT_SYMLINK_NOFOLLOW, EMSCRIPTEN_EPERM, DIR_MODE, LINK_MODE, O_ACCMODE, O_CREAT2, field, NAME;
2406
+ var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, AT_SYMLINK_NOFOLLOW, EMSCRIPTEN_EPERM, DIR_MODE, LINK_MODE, CHAR_DEVICE, O_ACCMODE, O_CREAT2, field, NAME;
2585
2407
  var init_process_fds = __esm({
2586
2408
  "src/process/process-fds.ts"() {
2587
2409
  "use strict";
@@ -2610,6 +2432,7 @@ var init_process_fds = __esm({
2610
2432
  EMSCRIPTEN_EPERM = 63;
2611
2433
  DIR_MODE = 16749;
2612
2434
  LINK_MODE = 41408;
2435
+ CHAR_DEVICE = 8630;
2613
2436
  O_ACCMODE = 3;
2614
2437
  O_CREAT2 = 64;
2615
2438
  field = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
@@ -2696,12 +2519,16 @@ function describeInherited(Fs, sys, streams, livePath, actions = []) {
2696
2519
  }
2697
2520
  return out;
2698
2521
  }
2522
+ function deviceOfStream(stream) {
2523
+ const device = stream.path === void 0 ? void 0 : DEVICES[stream.path];
2524
+ if (!device || stream.sliccKernelFd !== void 0) return void 0;
2525
+ const access = ACCESS[stream.flags & O_ACCMODE2];
2526
+ return { device, ...access ? { access } : {} };
2527
+ }
2699
2528
  function inheritedSlot(fd, stream) {
2700
2529
  if (stream.sliccKernelFd === void 0) {
2701
- const device = stream.path === void 0 ? void 0 : DEVICES[stream.path];
2702
- if (!device) return void 0;
2703
- const access = ACCESS[stream.flags & O_ACCMODE2];
2704
- return { fd, device, ...access ? { access } : {} };
2530
+ const device = deviceOfStream(stream);
2531
+ return device ? { fd, ...device } : void 0;
2705
2532
  }
2706
2533
  const flags = stream.sliccKernelSocket ? { flags: stream.flags } : {};
2707
2534
  return { fd, kernel: stream.sliccKernelFd, ...flags };
@@ -2725,15 +2552,19 @@ function asFifo(stream, streams, identity) {
2725
2552
  const fixed = inos.get(identity) ?? nextStreamIno++;
2726
2553
  inos.set(identity, fixed);
2727
2554
  const node = stream.node;
2728
- stream.stream_ops = {
2729
- ...stream.stream_ops,
2730
- getattr: () => ({ ...node.node_ops?.getattr?.(node), mode: FIFO_MODE, ino: fixed, size: 0 })
2731
- };
2555
+ streams.describe(stream, `pipe:[${fixed}]`, () => ({
2556
+ ...node.node_ops?.getattr?.(node),
2557
+ mode: FIFO_MODE,
2558
+ ino: fixed,
2559
+ size: 0
2560
+ }));
2732
2561
  }
2733
2562
  function placeKernelStream(Fs, streams, entry) {
2734
2563
  const stream = place(Fs, placeholder(Fs, streams, entry), entry.fd);
2735
- if (entry.kind === "file") streams.attachFile(stream, entry.kernel);
2736
- else if (entry.kind === "socket") streams.attachSocket(stream, entry.kernel);
2564
+ if (entry.kind === "file") {
2565
+ streams.attachFile(stream, entry.kernel);
2566
+ streams.sizeFromKernel(stream, entry.kernel);
2567
+ } else if (entry.kind === "socket") streams.attachSocket(stream, entry.kernel);
2737
2568
  else streams.attach(stream, entry.kernel, entry.kind === "tty");
2738
2569
  if (entry.kind === "tty") streams.nameTerminal(stream);
2739
2570
  if (entry.kind === "stream") {
@@ -2775,6 +2606,7 @@ var init_process_fork = __esm({
2775
2606
  DEVICES = {
2776
2607
  "/dev/null": "null",
2777
2608
  "/dev/zero": "zero",
2609
+ "/dev/full": "full",
2778
2610
  "/dev/urandom": "urandom",
2779
2611
  "/dev/random": "urandom"
2780
2612
  };
@@ -2784,6 +2616,255 @@ var init_process_fork = __esm({
2784
2616
  }
2785
2617
  });
2786
2618
 
2619
+ // src/process/process-children.ts
2620
+ function status(r) {
2621
+ return r.ok ? 0 : -wasiErrno(r.errno);
2622
+ }
2623
+ function number(r) {
2624
+ if (!r.ok) return -wasiErrno(r.errno);
2625
+ return r.kind === "json" && typeof r.json === "number" ? r.json : -wasiErrno("EIO");
2626
+ }
2627
+ function flushed(beforeSpawn) {
2628
+ try {
2629
+ beforeSpawn();
2630
+ return 0;
2631
+ } catch (err) {
2632
+ const errno2 = err?.errno;
2633
+ if (typeof errno2 !== "number") throw err;
2634
+ return -errno2;
2635
+ }
2636
+ }
2637
+ function drain(Fs, stream) {
2638
+ const chunks = [];
2639
+ const buffer = new Uint8Array(65536);
2640
+ try {
2641
+ for (let n = Fs.read(stream, buffer, 0, buffer.length); n > 0; ) {
2642
+ chunks.push(buffer.slice(0, n));
2643
+ n = Fs.read(stream, buffer, 0, buffer.length);
2644
+ }
2645
+ } catch {
2646
+ }
2647
+ const out = new Uint8Array(chunks.reduce((n, c) => n + c.length, 0));
2648
+ let offset = 0;
2649
+ for (const chunk of chunks) {
2650
+ out.set(chunk, offset);
2651
+ offset += chunk.length;
2652
+ }
2653
+ return out;
2654
+ }
2655
+ function kernelSelect(Fs, transport, read, write, timeoutMs) {
2656
+ const kernel = (fd) => Fs.getStream(fd)?.sliccKernelFd;
2657
+ const kr = read.map(kernel);
2658
+ const kw = write.map(kernel);
2659
+ const r = transport.call({ op: "fd-select", read: kr, write: kw, timeoutMs }, Infinity, "select");
2660
+ if (!r.ok) return -wasiErrno(r.errno);
2661
+ const got = r.kind === "json" ? r.json : { read: [], write: [] };
2662
+ return {
2663
+ read: read.filter((_, i) => got.read.includes(kr[i])),
2664
+ write: write.filter((_, i) => got.write.includes(kw[i]))
2665
+ };
2666
+ }
2667
+ function ownReady(Fs, read, write) {
2668
+ const flags = (fd) => {
2669
+ const stream = Fs.getStream(fd);
2670
+ if (!stream) return POLLNVAL;
2671
+ return stream.stream_ops.poll ? stream.stream_ops.poll(stream) : POLLIN2 | POLLOUT2;
2672
+ };
2673
+ return {
2674
+ read: read.filter((fd) => flags(fd) & (POLLIN2 | POLLHUP2 | POLLERR2 | POLLNVAL)),
2675
+ write: write.filter((fd) => flags(fd) & (POLLOUT2 | POLLERR2 | POLLNVAL))
2676
+ };
2677
+ }
2678
+ function anySelect(Fs, transport, read, write, timeoutMs) {
2679
+ const kernel = (fd) => Fs.getStream(fd)?.sliccKernelFd;
2680
+ const own = (fd) => kernel(fd) === void 0;
2681
+ if (![...read, ...write].some(own)) return kernelSelect(Fs, transport, read, write, timeoutMs);
2682
+ const deadline = timeoutMs < 0 ? Number.POSITIVE_INFINITY : Date.now() + timeoutMs;
2683
+ const kernelRead = read.filter((fd) => !own(fd));
2684
+ const kernelWrite = write.filter((fd) => !own(fd));
2685
+ for (; ; ) {
2686
+ const local = ownReady(Fs, read.filter(own), write.filter(own));
2687
+ const pending = local.read.length > 0 || local.write.length > 0;
2688
+ const slice = pending ? 0 : Math.min(SELECT_SLICE_MS, Math.max(0, deadline - Date.now()));
2689
+ const got = kernelSelect(Fs, transport, kernelRead, kernelWrite, slice);
2690
+ if (typeof got === "number") return got;
2691
+ const ready = { read: [...local.read, ...got.read], write: [...local.write, ...got.write] };
2692
+ if (ready.read.length > 0 || ready.write.length > 0 || Date.now() >= deadline) {
2693
+ return ready;
2694
+ }
2695
+ }
2696
+ }
2697
+ function createProcessKernel(deps) {
2698
+ const { transport, Fs } = deps;
2699
+ const reaped = /* @__PURE__ */ new Map();
2700
+ const call2 = (req, label) => transport.call(req, Infinity, label);
2701
+ const at = (path) => path === "" || path.startsWith("/") ? path : `${Fs.cwd()}/${path}`;
2702
+ const slot = (fd, n, promote) => {
2703
+ const stream = fd >= 0 ? Fs.getStream(fd) : null;
2704
+ if (!stream) return { none: true };
2705
+ promote?.(stream);
2706
+ if (stream.sliccKernelFd !== void 0) return { fd: stream.sliccKernelFd };
2707
+ if (stream.path === "/dev/null") return { none: true };
2708
+ const device = deviceOfStream(stream);
2709
+ if (device) return device;
2710
+ return n === 0 ? { input: drain(Fs, stream) } : { capture: true };
2711
+ };
2712
+ const kernelWait = (pid, nohang, options = 0) => {
2713
+ const req = {
2714
+ op: "proc-wait",
2715
+ pid,
2716
+ nohang,
2717
+ ...options & WUNTRACED ? { untraced: true } : {},
2718
+ ...options & WCONTINUED ? { continued: true } : {}
2719
+ };
2720
+ let r = transport.call(req, Infinity, `proc-wait ${pid}`);
2721
+ while (!r.ok && r.errno === "EINTR" && deps.restartable?.()) {
2722
+ r = transport.call(req, Infinity, `proc-wait ${pid}`);
2723
+ }
2724
+ if (!r.ok) return -wasiErrno(r.errno);
2725
+ const waited = r.kind === "json" ? r.json : [0, 0];
2726
+ if (waited[0] > 0) deps.afterChild();
2727
+ return [waited[0], waited[1]];
2728
+ };
2729
+ const deliver = (pid, n, fd) => {
2730
+ const r = transport.call(
2731
+ { op: "proc-captured", pid, slot: n },
2732
+ Infinity,
2733
+ `proc-captured ${pid}`
2734
+ );
2735
+ const stream = Fs.getStream(fd);
2736
+ if (r.ok && r.kind === "bytes" && r.bytes.length > 0 && stream) {
2737
+ Fs.write(stream, r.bytes, 0, r.bytes.length);
2738
+ }
2739
+ };
2740
+ const execCaptures = /* @__PURE__ */ new Map();
2741
+ const execWait = (pid) => {
2742
+ const r = transport.call({ op: "proc-exec", pid }, Infinity, `exec ${pid}`);
2743
+ if (!r.ok) return -wasiErrno(r.errno);
2744
+ deps.afterChild();
2745
+ return r.kind === "json" ? r.json[1] : 0;
2746
+ };
2747
+ const spawnChild = (file, argv, env, cwd, fds, actions, exec) => {
2748
+ const unflushed = flushed(deps.beforeSpawn);
2749
+ if (unflushed < 0) return unflushed;
2750
+ const promote = deps.stdioPromoter?.();
2751
+ const stdio = [0, 1, 2].map((n) => slot(fds[n] ?? -1, n, promote));
2752
+ const inherit = deps.inherit?.(actions) ?? [];
2753
+ const r = transport.call(
2754
+ {
2755
+ op: "proc-spawn",
2756
+ file,
2757
+ argv,
2758
+ env: env ?? deps.env,
2759
+ cwd: cwd ?? Fs.cwd(),
2760
+ stdio,
2761
+ ...inherit.length > 0 ? { inherit } : {},
2762
+ ...exec ? { exec } : {}
2763
+ },
2764
+ Infinity,
2765
+ `proc-spawn ${file}`
2766
+ );
2767
+ if (!r.ok) return -wasiErrno(r.errno);
2768
+ const pid = r.kind === "json" ? r.json : 0;
2769
+ const captures = [1, 2].filter((n) => "capture" in stdio[n]);
2770
+ if (captures.length === 0) return pid;
2771
+ if (exec) {
2772
+ execCaptures.set(pid, () => {
2773
+ for (const n of captures) deliver(pid, n, fds[n]);
2774
+ });
2775
+ return pid;
2776
+ }
2777
+ const waited = kernelWait(pid, false);
2778
+ if (typeof waited === "number") return waited;
2779
+ for (const n of captures) deliver(pid, n, fds[n]);
2780
+ reaped.set(pid, waited[1]);
2781
+ return pid;
2782
+ };
2783
+ return {
2784
+ spawn(file, argv, env, cwd, fds, actions) {
2785
+ return spawnChild(file, argv, env, cwd, fds, actions, false);
2786
+ },
2787
+ fork(state) {
2788
+ const unflushed = flushed(deps.beforeSpawn);
2789
+ if (unflushed < 0) return unflushed;
2790
+ const streams = deps.describeFork();
2791
+ const r = transport.call(
2792
+ { op: "proc-fork", state: { ...state, streams, cwd: Fs.cwd() } },
2793
+ Infinity,
2794
+ "proc-fork"
2795
+ );
2796
+ if (!r.ok) return -wasiErrno(r.errno);
2797
+ return r.kind === "json" ? r.json : -wasiErrno("EIO");
2798
+ },
2799
+ select: (read, write, timeoutMs) => anySelect(Fs, transport, read, write, timeoutMs),
2800
+ execWait,
2801
+ execve(file, argv, env, cwd) {
2802
+ const pid = spawnChild(file, argv, env, cwd, [0, 1, 2], void 0, true);
2803
+ if (pid < 0) return pid;
2804
+ const status2 = execWait(pid);
2805
+ execCaptures.get(pid)?.();
2806
+ execCaptures.delete(pid);
2807
+ return status2;
2808
+ },
2809
+ pause() {
2810
+ return status(call2({ op: "sig-pause" }, "pause"));
2811
+ },
2812
+ mount(source, target, type, flags, data) {
2813
+ const req = { op: "mount", source, target: at(target), type, flags, data };
2814
+ return status(call2(req, `mount ${target}`));
2815
+ },
2816
+ umount2(target, flags) {
2817
+ return status(call2({ op: "umount", target: at(target), flags }, `umount ${target}`));
2818
+ },
2819
+ kill(pid, sig) {
2820
+ if (pid === deps.pid) {
2821
+ if (sig !== 0) deps.raise?.(sig);
2822
+ return 0;
2823
+ }
2824
+ return status(call2({ op: "proc-kill", pid, sig }, `kill ${pid}`));
2825
+ },
2826
+ setpgid: (pid, pgid) => status(call2({ op: "proc-setpgid", pid, pgid }, "setpgid")),
2827
+ setsid: () => number(call2({ op: "proc-setsid" }, "setsid")),
2828
+ getpgid: (pid) => number(call2({ op: "proc-getpgid", pid }, "getpgid")),
2829
+ getsid: (pid) => number(call2({ op: "proc-getsid", pid }, "getsid")),
2830
+ tcgetpgrp(fd) {
2831
+ const kfd = Fs.getStream(fd)?.sliccKernelFd;
2832
+ if (kfd === void 0) return -wasiErrno("ENOTTY");
2833
+ return number(call2({ op: "tty-pgrp-get", fd: kfd }, "tcgetpgrp"));
2834
+ },
2835
+ tcsetpgrp(fd, pgrp) {
2836
+ const kfd = Fs.getStream(fd)?.sliccKernelFd;
2837
+ if (kfd === void 0) return -wasiErrno("ENOTTY");
2838
+ return status(call2({ op: "tty-pgrp-set", fd: kfd, pgrp }, "tcsetpgrp"));
2839
+ },
2840
+ wait(pid, nohang, options) {
2841
+ const key = pid > 0 ? reaped.has(pid) ? pid : void 0 : reaped.keys().next().value;
2842
+ if (key !== void 0) {
2843
+ const status2 = reaped.get(key);
2844
+ reaped.delete(key);
2845
+ return [key, status2];
2846
+ }
2847
+ return kernelWait(pid, nohang, options);
2848
+ }
2849
+ };
2850
+ }
2851
+ var POLLIN2, POLLOUT2, POLLERR2, POLLHUP2, POLLNVAL, SELECT_SLICE_MS, WUNTRACED, WCONTINUED;
2852
+ var init_process_children = __esm({
2853
+ "src/process/process-children.ts"() {
2854
+ "use strict";
2855
+ init_process_fork();
2856
+ init_wasi_errno();
2857
+ POLLIN2 = 1;
2858
+ POLLOUT2 = 4;
2859
+ POLLERR2 = 8;
2860
+ POLLHUP2 = 16;
2861
+ POLLNVAL = 32;
2862
+ SELECT_SLICE_MS = 20;
2863
+ WUNTRACED = 2;
2864
+ WCONTINUED = 8;
2865
+ }
2866
+ });
2867
+
2787
2868
  // src/process/process-http.ts
2788
2869
  function createHttpKernel(transport) {
2789
2870
  const call2 = (req) => {
@@ -3468,6 +3549,12 @@ function kernelSys(transport) {
3468
3549
  ttyName(fd) {
3469
3550
  return json(call2({ op: "fd-info", fd }, `fd-info ${fd}`))?.name;
3470
3551
  },
3552
+ kind(fd) {
3553
+ return json(call2({ op: "fd-info", fd }, `fd-info ${fd}`))?.kind;
3554
+ },
3555
+ size(fd) {
3556
+ return json(call2({ op: "fd-vfs-stat", fd }, `fd-vfs-stat ${fd}`)).size;
3557
+ },
3471
3558
  openTty(name) {
3472
3559
  const req = name === void 0 ? { op: "fd-open-tty" } : { op: "fd-open-tty", name };
3473
3560
  return json(call2(req, `fd-open-tty ${name ?? ""}`));
@@ -3535,10 +3622,18 @@ function openDevice(Fs, fd, meta) {
3535
3622
  }
3536
3623
  return true;
3537
3624
  }
3538
- function wireKernelStdio(Fs, streams) {
3625
+ function wireKernelStdio(Fs, streams, sys) {
3539
3626
  for (const fd of [0, 1, 2]) {
3540
3627
  const stream = Fs.getStream(fd);
3541
3628
  if (!stream) continue;
3629
+ const kind = sys?.kind?.(fd);
3630
+ if (kind && PLACED.has(kind)) {
3631
+ const { flags } = stream;
3632
+ Fs.closeStream(fd);
3633
+ const kernel = { fd, kernel: fd, kind, flags };
3634
+ placeKernelStream(Fs, streams, kernel).flags = flags;
3635
+ continue;
3636
+ }
3542
3637
  streams.attach(stream, fd);
3543
3638
  streams.nameTerminal(stream);
3544
3639
  }
@@ -3679,10 +3774,11 @@ async function runWasmProcess(init, port2, deps = {}) {
3679
3774
  trackCloseOnExec(running.FS);
3680
3775
  quietQuit(running.FS);
3681
3776
  useMounts(running.FS, init.env, true);
3777
+ useZeroDevices(running.FS);
3682
3778
  useProcfs(running.FS, sys, init.pid);
3683
3779
  if (init.fork) restoreForkedStreams(running.FS, streams, init.fork.streams ?? []);
3684
3780
  else {
3685
- wireKernelStdio(running.FS, streams);
3781
+ wireKernelStdio(running.FS, streams, sys);
3686
3782
  for (const entry of init.fds ?? []) wireKernelFd(running.FS, streams, entry);
3687
3783
  }
3688
3784
  const pipefs = ownValue(running, "PIPEFS");
@@ -3760,7 +3856,7 @@ function runMain(running, init) {
3760
3856
  return status2;
3761
3857
  }
3762
3858
  }
3763
- var O_RDONLY, O_WRONLY2, O_RDWR3, GLUE_TRAILER, evaluateGlue, EVAL_BLOCKED;
3859
+ var O_RDONLY, O_WRONLY2, O_RDWR3, PLACED, GLUE_TRAILER, evaluateGlue, EVAL_BLOCKED;
3764
3860
  var init_process_runtime = __esm({
3765
3861
  "src/process/process-runtime.ts"() {
3766
3862
  "use strict";
@@ -3783,6 +3879,7 @@ var init_process_runtime = __esm({
3783
3879
  O_RDONLY = 0;
3784
3880
  O_WRONLY2 = 1;
3785
3881
  O_RDWR3 = 2;
3882
+ PLACED = /* @__PURE__ */ new Set(["stream", "file", "socket"]);
3786
3883
  GLUE_TRAILER = [
3787
3884
  "if (typeof ENV !== 'undefined') Object.assign(ENV, Module.sliccEnv);",
3788
3885
  "const __sliccTake = (name, value) => {",
@@ -4262,6 +4359,7 @@ var init_wasi_fds = __esm({
4262
4359
  DEVICES2 = {
4263
4360
  "/dev/null": "null",
4264
4361
  "/dev/zero": "zero",
4362
+ "/dev/full": "full",
4265
4363
  "/dev/urandom": "urandom",
4266
4364
  "/dev/random": "urandom"
4267
4365
  };
@@ -5299,6 +5397,7 @@ var init_wasi_host = __esm({
5299
5397
  }
5300
5398
  if (e.type === "device") {
5301
5399
  if (e.access === "read") throw new WasiError("EBADF");
5400
+ if (e.device === "full" && data.length > 0) throw new WasiError("ENOSPC");
5302
5401
  return data.length;
5303
5402
  }
5304
5403
  return this.file(fd, "write").write(data);
@@ -5312,7 +5411,7 @@ var init_wasi_host = __esm({
5312
5411
  if (e.access === "write") throw new WasiError("EBADF");
5313
5412
  if (e.device === "null") return new Uint8Array(0);
5314
5413
  const out = new Uint8Array(Math.min(max, 65536));
5315
- return e.device === "zero" ? out : crypto.getRandomValues(out);
5414
+ return e.device === "urandom" ? crypto.getRandomValues(out) : out;
5316
5415
  }
5317
5416
  return this.file(fd, "read").read(max);
5318
5417
  }