@ai-ecoverse/slicc-kernel 1.103.3 → 1.106.2

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.
Files changed (37) hide show
  1. package/README.md +56 -15
  2. package/dist/driver-worker.js +36 -1
  3. package/dist/driver-worker.js.map +2 -2
  4. package/dist/index.js +89 -5
  5. package/dist/index.js.map +2 -2
  6. package/dist/kernel-worker.js +783 -289
  7. package/dist/kernel-worker.js.map +4 -4
  8. package/dist/meta.js.map +2 -2
  9. package/dist/node-driver-worker.js +36 -1
  10. package/dist/node-driver-worker.js.map +2 -2
  11. package/dist/node-process-worker.js +447 -224
  12. package/dist/node-process-worker.js.map +4 -4
  13. package/dist/node.js +831 -309
  14. package/dist/node.js.map +4 -4
  15. package/dist/process-worker.js +384 -161
  16. package/dist/process-worker.js.map +4 -4
  17. package/dist/types/commands.d.ts +6 -1
  18. package/dist/types/fs/command-stat.d.ts +3 -0
  19. package/dist/types/fs/commands.d.ts +7 -1
  20. package/dist/types/fs/engines.d.ts +5 -0
  21. package/dist/types/fs/types.d.ts +1 -0
  22. package/dist/types/kernel/host.d.ts +1 -0
  23. package/dist/types/kernel/net/http-syscalls.d.ts +10 -0
  24. package/dist/types/kernel/net/http1.d.ts +1 -0
  25. package/dist/types/kernel/net/remote-transport.d.ts +18 -0
  26. package/dist/types/kernel/net/transport.d.ts +2 -0
  27. package/dist/types/kernel/process.d.ts +8 -0
  28. package/dist/types/launcher.d.ts +4 -0
  29. package/dist/types/process/process-signals.d.ts +3 -0
  30. package/dist/types/process/wasi/wasi-cred.d.ts +11 -0
  31. package/dist/types/process/wasi/wasi-files.d.ts +1 -0
  32. package/dist/types/process/wasi/wasi-host.d.ts +9 -0
  33. package/dist/types/process/wasi/wasi-sigmask.d.ts +7 -1
  34. package/dist/types/process/wasi/wasix-epoll.d.ts +3 -0
  35. package/dist/types/refused-command.d.ts +4 -0
  36. package/dist/types/transport.d.ts +1 -0
  37. package/package.json +17 -12
@@ -887,7 +887,7 @@ function pinnedIo(bridge, handle, rewriting) {
887
887
  } : {}
888
888
  };
889
889
  }
890
- var WasiError, FileBuffer, LocalFile, MAX_LINKS, MISS_TTL_MS, FS_GEN, RING, RING_SIZE, SLOT, SHARED_IDS_BYTES, StatCache;
890
+ var WasiError, FileBuffer, LocalFile, MAX_LINKS, MISS_TTL_MS, FS_GEN, CRED_GEN, RING, RING_SIZE, SLOT, SHARED_IDS_BYTES, StatCache;
891
891
  var init_wasi_files = __esm({
892
892
  "src/process/wasi/wasi-files.ts"() {
893
893
  "use strict";
@@ -1109,6 +1109,7 @@ var init_wasi_files = __esm({
1109
1109
  MAX_LINKS = 40;
1110
1110
  MISS_TTL_MS = 20;
1111
1111
  FS_GEN = 4;
1112
+ CRED_GEN = 5;
1112
1113
  RING = 8;
1113
1114
  RING_SIZE = 64;
1114
1115
  SLOT = 3;
@@ -1598,6 +1599,69 @@ var init_cred = __esm({
1598
1599
  }
1599
1600
  });
1600
1601
 
1602
+ // src/kernel/signals.ts
1603
+ function defaultAction(sig) {
1604
+ if (sig === SIG.CONT) return "continue";
1605
+ if (STOPPING.has(sig)) return "stop";
1606
+ return IGNORED_BY_DEFAULT.has(sig) ? "ignore" : "terminate";
1607
+ }
1608
+ function sigbit(sig) {
1609
+ return 1 << sig;
1610
+ }
1611
+ function signalsIn(mask) {
1612
+ const out = [];
1613
+ for (let sig = 1; sig <= 31; sig++) if (mask & sigbit(sig)) out.push(sig);
1614
+ return out;
1615
+ }
1616
+ var SIG, IGNORED_BY_DEFAULT, STOPPING, SIGNAL_BY_NAME;
1617
+ var init_signals = __esm({
1618
+ "src/kernel/signals.ts"() {
1619
+ "use strict";
1620
+ SIG = {
1621
+ HUP: 1,
1622
+ INT: 2,
1623
+ QUIT: 3,
1624
+ ILL: 4,
1625
+ TRAP: 5,
1626
+ ABRT: 6,
1627
+ BUS: 7,
1628
+ FPE: 8,
1629
+ KILL: 9,
1630
+ USR1: 10,
1631
+ SEGV: 11,
1632
+ USR2: 12,
1633
+ PIPE: 13,
1634
+ ALRM: 14,
1635
+ TERM: 15,
1636
+ STKFLT: 16,
1637
+ CHLD: 17,
1638
+ CONT: 18,
1639
+ STOP: 19,
1640
+ TSTP: 20,
1641
+ TTIN: 21,
1642
+ TTOU: 22,
1643
+ URG: 23,
1644
+ XCPU: 24,
1645
+ XFSZ: 25,
1646
+ VTALRM: 26,
1647
+ PROF: 27,
1648
+ WINCH: 28,
1649
+ POLL: 29,
1650
+ PWR: 30,
1651
+ SYS: 31
1652
+ };
1653
+ IGNORED_BY_DEFAULT = /* @__PURE__ */ new Set([SIG.CHLD, SIG.URG, SIG.WINCH]);
1654
+ STOPPING = /* @__PURE__ */ new Set([SIG.STOP, SIG.TSTP, SIG.TTIN, SIG.TTOU]);
1655
+ SIGNAL_BY_NAME = {
1656
+ SIGINT: SIG.INT,
1657
+ SIGTERM: SIG.TERM,
1658
+ SIGKILL: SIG.KILL,
1659
+ SIGSTOP: SIG.STOP,
1660
+ SIGCONT: SIG.CONT
1661
+ };
1662
+ }
1663
+ });
1664
+
1601
1665
  // src/process/wasi/slicc-lock.ts
1602
1666
  function kindOf(type) {
1603
1667
  if (type === F_RDLCK) return "read";
@@ -1712,6 +1776,48 @@ var init_slicc_sem = __esm({
1712
1776
  }
1713
1777
  });
1714
1778
 
1779
+ // src/process/wasi/wasi-cred.ts
1780
+ var CredCache;
1781
+ var init_wasi_cred = __esm({
1782
+ "src/process/wasi/wasi-cred.ts"() {
1783
+ "use strict";
1784
+ init_wasi_files();
1785
+ CredCache = class {
1786
+ cred;
1787
+ stamp = 0;
1788
+ fetch;
1789
+ shared;
1790
+ constructor(fetch, shared) {
1791
+ this.fetch = fetch;
1792
+ this.shared = shared;
1793
+ }
1794
+ gen() {
1795
+ return this.shared ? Atomics.load(this.shared, CRED_GEN) : 0;
1796
+ }
1797
+ get() {
1798
+ const gen = this.gen();
1799
+ if (this.cred === void 0 || this.stamp !== gen) {
1800
+ this.cred = this.fetch();
1801
+ this.stamp = gen;
1802
+ }
1803
+ return this.cred;
1804
+ }
1805
+ change(apply2) {
1806
+ const seen = this.gen();
1807
+ const cred = apply2();
1808
+ if (!this.shared) {
1809
+ this.cred = cred;
1810
+ return cred;
1811
+ }
1812
+ const was = Atomics.add(this.shared, CRED_GEN, 1);
1813
+ this.cred = was === seen ? cred : void 0;
1814
+ this.stamp = was + 1;
1815
+ return cred;
1816
+ }
1817
+ };
1818
+ }
1819
+ });
1820
+
1715
1821
  // src/kernel/pipe.ts
1716
1822
  var PIPE_CAPACITY;
1717
1823
  var init_pipe = __esm({
@@ -2800,6 +2906,92 @@ var init_wasi_termios = __esm({
2800
2906
  }
2801
2907
  });
2802
2908
 
2909
+ // src/process/wasi/wasix-epoll.ts
2910
+ function timeoutMs(ns) {
2911
+ const value2 = BigInt.asUintN(64, ns);
2912
+ if (value2 === FOREVER) return -1;
2913
+ const ms = (value2 + NS_PER_MS2 - 1n) / NS_PER_MS2;
2914
+ return ms > BigInt(MAX_TIMEOUT_MS) ? -1 : Number(ms);
2915
+ }
2916
+ function wasixEpollImports(host) {
2917
+ const { mem, fds, o } = host;
2918
+ const call2 = (req) => o.kernel.call(req);
2919
+ const kernelFd = (fd, refusal2) => {
2920
+ const e = fds.find(fd);
2921
+ if (!e) throw new WasiError("EBADF");
2922
+ if (e.type !== "kernel") throw new WasiError(refusal2);
2923
+ };
2924
+ const writeEvents2 = (ptr, events) => {
2925
+ const view = mem.view();
2926
+ events.forEach((ev, i) => {
2927
+ const at = ptr + i * EVENT_SIZE;
2928
+ mem.bytes(at, EVENT_SIZE).fill(0);
2929
+ view.setUint32(at, ev.events, true);
2930
+ mem.bytes(at + DATA_OFFSET, DATA_SIZE).set(ev.data);
2931
+ });
2932
+ };
2933
+ return {
2934
+ epoll_create: (out) => {
2935
+ const fd = call2({ op: "epoll-create" });
2936
+ fds.adopt(fd, "stream", false);
2937
+ mem.view().setUint32(out, fd, true);
2938
+ },
2939
+ epoll_ctl: (epfd, op, fd, event) => {
2940
+ const how = (host.strictEpoll ? WASIX_OPS : DUAL_OPS)[op];
2941
+ if (!how) throw new WasiError("EINVAL");
2942
+ kernelFd(epfd, "EINVAL");
2943
+ kernelFd(fd, "EPERM");
2944
+ if (how !== "del" && event === 0) throw new WasiError("EINVAL");
2945
+ const events = event === 0 ? 0 : mem.view().getUint32(event, true);
2946
+ const data = event === 0 ? [] : [...mem.bytes(event + DATA_OFFSET, DATA_SIZE)];
2947
+ call2({ op: "epoll-ctl", epfd, how, fd, events, data });
2948
+ },
2949
+ epoll_wait: (epfd, ptr, maxevents, timeout, out) => {
2950
+ mem.view().setUint32(out, 0, true);
2951
+ if ((maxevents | 0) <= 0) throw new WasiError("EINVAL");
2952
+ kernelFd(epfd, "EINVAL");
2953
+ const max = Math.min(maxevents | 0, MAX_EVENTS);
2954
+ const ms = host.entered ? 0 : timeoutMs(timeout);
2955
+ const events = call2({ op: "epoll-wait", epfd, max, timeoutMs: ms });
2956
+ if (host.entered && events.length === 0 && timeoutMs(timeout) !== 0) return E.INTR;
2957
+ writeEvents2(ptr, events);
2958
+ mem.view().setUint32(out, events.length, true);
2959
+ return E.SUCCESS;
2960
+ },
2961
+ fd_event: (initial, flags, out) => {
2962
+ const value2 = BigInt.asUintN(64, initial);
2963
+ if (value2 > EVENTFD_MAX) throw new WasiError("EINVAL");
2964
+ const fd = call2({
2965
+ op: "eventfd-open",
2966
+ initial: value2.toString(),
2967
+ semaphore: (flags & EVENTFD_SEMAPHORE) !== 0
2968
+ });
2969
+ fds.adopt(fd, "stream", (flags & EVENTFD_NONBLOCK) !== 0);
2970
+ mem.view().setUint32(out, fd, true);
2971
+ }
2972
+ };
2973
+ }
2974
+ var EVENT_SIZE, DATA_OFFSET, DATA_SIZE, MAX_EVENTS, FOREVER, MAX_TIMEOUT_MS, NS_PER_MS2, EVENTFD_SEMAPHORE, EVENTFD_NONBLOCK, EVENTFD_MAX, WASIX_OPS, DUAL_OPS;
2975
+ var init_wasix_epoll = __esm({
2976
+ "src/process/wasi/wasix-epoll.ts"() {
2977
+ "use strict";
2978
+ init_wasi_abi();
2979
+ init_wasi_files();
2980
+ EVENT_SIZE = 32;
2981
+ DATA_OFFSET = 8;
2982
+ DATA_SIZE = 24;
2983
+ MAX_EVENTS = 4096;
2984
+ FOREVER = 0xffffffffffffffffn;
2985
+ MAX_TIMEOUT_MS = 2147483647;
2986
+ NS_PER_MS2 = 1000000n;
2987
+ EVENTFD_SEMAPHORE = 1;
2988
+ EVENTFD_NONBLOCK = 4;
2989
+ EVENTFD_MAX = 0xfffffffffffffffen;
2990
+ WASIX_OPS = ["add", "mod", "del"];
2991
+ DUAL_OPS = ["add", "set", "del", "mod"];
2992
+ }
2993
+ });
2994
+
2803
2995
  // src/kernel/net/datagram-wire.ts
2804
2996
  function decodeReceived(raw) {
2805
2997
  const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);
@@ -3232,7 +3424,7 @@ function filestatOf(path, s) {
3232
3424
  size: BigInt(s.size),
3233
3425
  ino: s.ino !== void 0 ? BigInt(s.ino) : pathInode(path),
3234
3426
  ...s.nlink !== void 0 ? { nlink: BigInt(s.nlink) } : {},
3235
- mtimeNs: BigInt(Math.round(s.mtimeMs ?? 0)) * NS_PER_MS2
3427
+ mtimeNs: BigInt(Math.round(s.mtimeMs ?? 0)) * NS_PER_MS3
3236
3428
  };
3237
3429
  }
3238
3430
  function kernelFiletype(kind) {
@@ -3282,7 +3474,7 @@ function wrap(table) {
3282
3474
  }
3283
3475
  return out;
3284
3476
  }
3285
- var WasiExit, IDS, NS_PER_MS2, AT_SYMLINK_NOFOLLOW, AT_EACCESS, ROOT_IDS, GONE, S_IFIFO, DEFAULT_UMASK, MONOTONIC_BASE, MAX_READ, SIGPIPE_EXIT, SIG_IGN, SEALED_MODE, WasiHost;
3477
+ var WasiExit, IDS, NS_PER_MS3, AT_SYMLINK_NOFOLLOW, AT_EACCESS, ROOT_IDS, GONE, S_IFIFO, DEFAULT_UMASK, MONOTONIC_BASE, MAX_READ, SIGPIPE_EXIT, SIG_IGN, SEALED_MODE, WasiHost;
3286
3478
  var init_wasi_host = __esm({
3287
3479
  "src/process/wasi/wasi-host.ts"() {
3288
3480
  "use strict";
@@ -3290,14 +3482,17 @@ var init_wasi_host = __esm({
3290
3482
  init_physical_path();
3291
3483
  init_cpu_clock();
3292
3484
  init_cred();
3485
+ init_signals();
3293
3486
  init_slicc_lock();
3294
3487
  init_slicc_sem();
3295
3488
  init_wasi_abi();
3489
+ init_wasi_cred();
3296
3490
  init_wasi_fds();
3297
3491
  init_wasi_files();
3298
3492
  init_wasi_memory();
3299
3493
  init_wasi_poll();
3300
3494
  init_wasi_termios();
3495
+ init_wasix_epoll();
3301
3496
  init_wasix_sockets();
3302
3497
  WasiExit = class extends Error {
3303
3498
  code;
@@ -3307,26 +3502,30 @@ var init_wasi_host = __esm({
3307
3502
  }
3308
3503
  };
3309
3504
  IDS = ["ruid", "euid", "suid", "rgid", "egid", "sgid"];
3310
- NS_PER_MS2 = 1000000n;
3505
+ NS_PER_MS3 = 1000000n;
3311
3506
  AT_SYMLINK_NOFOLLOW = 1;
3312
3507
  AT_EACCESS = 2;
3313
3508
  ROOT_IDS = Object.freeze({ uid: 0, gid: 0 });
3314
3509
  GONE = /* @__PURE__ */ new Set(["ENOENT", "ENOTDIR"]);
3315
3510
  S_IFIFO = 4096;
3316
3511
  DEFAULT_UMASK = 18;
3317
- MONOTONIC_BASE = BigInt(Math.round(performance.timeOrigin)) * NS_PER_MS2;
3512
+ MONOTONIC_BASE = BigInt(Math.round(performance.timeOrigin)) * NS_PER_MS3;
3318
3513
  MAX_READ = 1024 * 1024;
3319
- SIGPIPE_EXIT = 141;
3514
+ SIGPIPE_EXIT = 128 + SIG.PIPE;
3320
3515
  SIG_IGN = 1;
3321
3516
  SEALED_MODE = 8630;
3322
3517
  WasiHost = class {
3323
3518
  mem = new WasiMemory();
3324
3519
  fds;
3520
+ creds;
3325
3521
  started = performance.now();
3326
3522
  cache;
3327
3523
  startCwd;
3328
3524
  interruptWakes = false;
3525
+ strictEpoll = false;
3329
3526
  entered = false;
3527
+ enteredSignals = 0;
3528
+ raisedOnEntry;
3330
3529
  onRaise;
3331
3530
  muted;
3332
3531
  signals;
@@ -3357,6 +3556,10 @@ var init_wasi_host = __esm({
3357
3556
  this.o = { ...o, kernel: { sys, call: call2 } };
3358
3557
  this.startCwd = o.cwd;
3359
3558
  this.fds = new WasiFds(this.o.kernel, o.fs);
3559
+ this.creds = new CredCache(
3560
+ () => this.o.kernel.call({ op: "proc-cred" }),
3561
+ o.credGen ?? o.shared
3562
+ );
3360
3563
  if (o.shared) this.fds.share(o.shared, true);
3361
3564
  else if (o.forked) this.fds.restore(o.forked.fds, o.forked.cloexec);
3362
3565
  else this.fds.setup(o.cwd, o.inherited ?? [], o.preopenRoot === true);
@@ -3396,7 +3599,7 @@ var init_wasi_host = __esm({
3396
3599
  own.call(this.o.fs, path, idOf(uid), idOf(gid), follow2, handle);
3397
3600
  };
3398
3601
  const caller = () => {
3399
- const cred = this.o.kernel.call({ op: "proc-cred" });
3602
+ const cred = this.creds.get();
3400
3603
  return [cred.euid, cred.egid];
3401
3604
  };
3402
3605
  const owner = (st, out) => {
@@ -3501,7 +3704,7 @@ var init_wasi_host = __esm({
3501
3704
  }),
3502
3705
  umount2: (tp, tl, flags) => void this.o.kernel.call({ op: "umount", target: path(tp, tl), flags }),
3503
3706
  cred_get: (out) => {
3504
- const cred = this.o.kernel.call({ op: "proc-cred" });
3707
+ const cred = this.creds.get();
3505
3708
  const view = mem.view();
3506
3709
  view.getUint32(out + 20, true);
3507
3710
  IDS.forEach((key, i) => void view.setUint32(out + i * 4, cred[key], true));
@@ -3511,7 +3714,7 @@ var init_wasi_host = __esm({
3511
3714
  IDS.forEach((key, i) => {
3512
3715
  if (ids[i] !== -1) change[key] = ids[i] >>> 0;
3513
3716
  });
3514
- void this.o.kernel.call({ op: "proc-setcred", change });
3717
+ void this.creds.change(() => this.o.kernel.call({ op: "proc-setcred", change }));
3515
3718
  },
3516
3719
  ...semImports(this),
3517
3720
  ...lockImports({
@@ -3535,7 +3738,7 @@ var init_wasi_host = __esm({
3535
3738
  }
3536
3739
  }),
3537
3740
  groups_get: (buf, cap, count) => {
3538
- const { groups } = this.o.kernel.call({ op: "proc-cred" });
3741
+ const { groups } = this.creds.get();
3539
3742
  if (cap !== 0 && cap < groups.length) throw new WasiError("EINVAL");
3540
3743
  const shown = cap === 0 ? [] : groups;
3541
3744
  const view = mem.view();
@@ -3548,7 +3751,9 @@ var init_wasi_host = __esm({
3548
3751
  if (n < 0 || n > MAX_GROUPS) throw new WasiError("EINVAL");
3549
3752
  const view = mem.view();
3550
3753
  const groups = Array.from({ length: n }, (_, i) => view.getUint32(buf + i * 4, true));
3551
- void this.o.kernel.call({ op: "proc-setcred", change: { groups } });
3754
+ void this.creds.change(
3755
+ () => this.o.kernel.call({ op: "proc-setcred", change: { groups } })
3756
+ );
3552
3757
  },
3553
3758
  sigaction_set: (sig, disposition, flags) => {
3554
3759
  if (!this.signals) return E.NOSYS;
@@ -3563,6 +3768,24 @@ var init_wasi_host = __esm({
3563
3768
  view.setUint32(old + 4, oldHi, true);
3564
3769
  }) : E.NOSYS,
3565
3770
  sigmask_poll: (lo, hi, inPtr, outPtr, n, nevents) => this.sigmask ? this.maskedPoll(this.sigmask, [lo, hi], [inPtr, outPtr, n, nevents]) : E.NOSYS,
3771
+ sigmask_epoll_wait: (lo, hi, epfd, events, max, timeout, nevents) => this.sigmask ? this.maskedEpoll(
3772
+ this.sigmask,
3773
+ [lo, hi],
3774
+ nevents,
3775
+ (epoll) => epoll(epfd, events, max, timeout, nevents)
3776
+ ) : E.NOSYS,
3777
+ sigwait: (lo, _hi, timeout, out) => {
3778
+ const mask = this.sigmask;
3779
+ if (!mask) return E.NOSYS;
3780
+ mem.view().setUint32(out, 0, true);
3781
+ return mask.sigwait(
3782
+ lo,
3783
+ timeout,
3784
+ (set) => void this.o.kernel.call({ op: "sig-waiting", tid: mask.tid, set }),
3785
+ (sig) => void mem.view().setUint32(out, sig, true),
3786
+ this.entered
3787
+ );
3788
+ },
3566
3789
  sigpending_get: (out) => {
3567
3790
  if (!this.sigmask) return E.NOSYS;
3568
3791
  mem.view().setBigUint64(out, BigInt(this.sigmask.pending()), true);
@@ -3595,6 +3818,7 @@ var init_wasi_host = __esm({
3595
3818
  try {
3596
3819
  this.mem.view().setUint32(nevents, 0, true);
3597
3820
  if (mask.deliverUnblocked()) return E.INTR;
3821
+ this.settleEntry(mask);
3598
3822
  if (n > 0) return this.poll(inPtr, outPtr, n, nevents);
3599
3823
  return this.entered ? E.INTR : this.suspend();
3600
3824
  } finally {
@@ -3602,6 +3826,23 @@ var init_wasi_host = __esm({
3602
3826
  mask.restore(old);
3603
3827
  }
3604
3828
  }
3829
+ epollWait;
3830
+ settleEntry(mask) {
3831
+ if (this.entered && (this.enteredSignals & ~mask.blockedBits()) === 0) this.entered = false;
3832
+ }
3833
+ maskedEpoll(mask, set, nevents, wait2) {
3834
+ const old = mask.swap(set[0], set[1]);
3835
+ try {
3836
+ this.mem.view().setUint32(nevents, 0, true);
3837
+ if (mask.deliverUnblocked()) return E.INTR;
3838
+ this.settleEntry(mask);
3839
+ this.epollWait ??= wasixEpollImports(this).epoll_wait;
3840
+ return wait2(this.epollWait) ?? E.SUCCESS;
3841
+ } finally {
3842
+ mask.deliverUnblocked();
3843
+ mask.restore(old);
3844
+ }
3845
+ }
3605
3846
  suspend() {
3606
3847
  for (; ; ) {
3607
3848
  try {
@@ -3624,7 +3865,7 @@ var init_wasi_host = __esm({
3624
3865
  return this.cache;
3625
3866
  }
3626
3867
  now(id) {
3627
- if (id === CLOCK.REALTIME) return BigInt(Date.now()) * NS_PER_MS2;
3868
+ if (id === CLOCK.REALTIME) return BigInt(Date.now()) * NS_PER_MS3;
3628
3869
  if (id === CLOCK.MONOTONIC) {
3629
3870
  return MONOTONIC_BASE + BigInt(Math.round(performance.now() * 1e6));
3630
3871
  }
@@ -3958,7 +4199,7 @@ var init_wasi_host = __esm({
3958
4199
  return this.fds.kind(fd, e) === "file" ? this.changed(fd, e, n) : n;
3959
4200
  } catch (err) {
3960
4201
  const broken = err.code === "EPIPE";
3961
- if (broken && this.fds.kind(fd, e) !== "socket") throw new WasiExit(SIGPIPE_EXIT);
4202
+ if (broken && this.fds.kind(fd, e) !== "socket") this.brokenPipe();
3962
4203
  throw err;
3963
4204
  }
3964
4205
  }
@@ -3970,6 +4211,18 @@ var init_wasi_host = __esm({
3970
4211
  }
3971
4212
  return this.file(fd, "write").write(data);
3972
4213
  }
4214
+ brokenPipe() {
4215
+ let action;
4216
+ try {
4217
+ action = this.o.kernel.call({ op: "proc-kill-self", sig: SIG.PIPE, probe: true });
4218
+ } catch {
4219
+ action = "terminate";
4220
+ }
4221
+ if (action !== "terminate") return;
4222
+ const mask = this.sigmask;
4223
+ if (!mask?.blocks(SIG.PIPE)) throw new WasiExit(SIGPIPE_EXIT);
4224
+ this.o.kernel.call({ op: "thread-kill", tid: mask.tid, sig: SIG.PIPE });
4225
+ }
3973
4226
  read(fd, max) {
3974
4227
  const e = this.fds.get(fd);
3975
4228
  if (e.type === "kernel") {
@@ -4153,7 +4406,7 @@ var init_wasi_host = __esm({
4153
4406
  current ??= statOf(path);
4154
4407
  return current[field2] ?? current.mtimeMs ?? now;
4155
4408
  };
4156
- const pick = (set, setNow, value2, field2) => flags & setNow ? now : flags & set ? Number(value2 / NS_PER_MS2) : kept(field2);
4409
+ const pick = (set, setNow, value2, field2) => flags & setNow ? now : flags & set ? Number(value2 / NS_PER_MS3) : kept(field2);
4157
4410
  (follow2 ? this.o.fs.utimes : this.o.fs.lutimes).call(
4158
4411
  this.o.fs,
4159
4412
  path,
@@ -4744,69 +4997,6 @@ var init_async_sab = __esm({
4744
4997
  }
4745
4998
  });
4746
4999
 
4747
- // src/kernel/signals.ts
4748
- function defaultAction(sig) {
4749
- if (sig === SIG.CONT) return "continue";
4750
- if (STOPPING.has(sig)) return "stop";
4751
- return IGNORED_BY_DEFAULT.has(sig) ? "ignore" : "terminate";
4752
- }
4753
- function sigbit(sig) {
4754
- return 1 << sig;
4755
- }
4756
- function signalsIn(mask) {
4757
- const out = [];
4758
- for (let sig = 1; sig <= 31; sig++) if (mask & sigbit(sig)) out.push(sig);
4759
- return out;
4760
- }
4761
- var SIG, IGNORED_BY_DEFAULT, STOPPING, SIGNAL_BY_NAME;
4762
- var init_signals = __esm({
4763
- "src/kernel/signals.ts"() {
4764
- "use strict";
4765
- SIG = {
4766
- HUP: 1,
4767
- INT: 2,
4768
- QUIT: 3,
4769
- ILL: 4,
4770
- TRAP: 5,
4771
- ABRT: 6,
4772
- BUS: 7,
4773
- FPE: 8,
4774
- KILL: 9,
4775
- USR1: 10,
4776
- SEGV: 11,
4777
- USR2: 12,
4778
- PIPE: 13,
4779
- ALRM: 14,
4780
- TERM: 15,
4781
- STKFLT: 16,
4782
- CHLD: 17,
4783
- CONT: 18,
4784
- STOP: 19,
4785
- TSTP: 20,
4786
- TTIN: 21,
4787
- TTOU: 22,
4788
- URG: 23,
4789
- XCPU: 24,
4790
- XFSZ: 25,
4791
- VTALRM: 26,
4792
- PROF: 27,
4793
- WINCH: 28,
4794
- POLL: 29,
4795
- PWR: 30,
4796
- SYS: 31
4797
- };
4798
- IGNORED_BY_DEFAULT = /* @__PURE__ */ new Set([SIG.CHLD, SIG.URG, SIG.WINCH]);
4799
- STOPPING = /* @__PURE__ */ new Set([SIG.STOP, SIG.TSTP, SIG.TTIN, SIG.TTOU]);
4800
- SIGNAL_BY_NAME = {
4801
- SIGINT: SIG.INT,
4802
- SIGTERM: SIG.TERM,
4803
- SIGKILL: SIG.KILL,
4804
- SIGSTOP: SIG.STOP,
4805
- SIGCONT: SIG.CONT
4806
- };
4807
- }
4808
- });
4809
-
4810
5000
  // src/version.ts
4811
5001
  function procVersion() {
4812
5002
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -4816,7 +5006,7 @@ var KERNEL_VERSION, OS_RELEASE;
4816
5006
  var init_version = __esm({
4817
5007
  "src/version.ts"() {
4818
5008
  "use strict";
4819
- KERNEL_VERSION = true ? "1.103.3" : "0.0.0-dev";
5009
+ KERNEL_VERSION = true ? "1.106.2" : "0.0.0-dev";
4820
5010
  OS_RELEASE = "6.0.0-slicc";
4821
5011
  }
4822
5012
  });
@@ -5823,6 +6013,9 @@ function rewrite(hop, status2, location) {
5823
6013
  );
5824
6014
  }
5825
6015
  const toGet = (status2 === 301 || status2 === 302) && hop.method === "POST" || status2 === 303 && hop.method !== "GET" && hop.method !== "HEAD";
6016
+ if (hop.stream && !toGet) {
6017
+ throw failed(new JsCallError("EIO", `a ${status2} redirect would send a streamed body again`));
6018
+ }
5826
6019
  const crossOrigin = next2.origin !== new URL(hop.url).origin;
5827
6020
  const headers = hop.headers.filter(
5828
6021
  ([name2]) => !(toGet && BODY_HEADERS.has(name2.toLowerCase())) && !(crossOrigin && CREDENTIALS.has(name2.toLowerCase()))
@@ -5989,6 +6182,44 @@ async function bodyOf(request, cap, signal) {
5989
6182
  }
5990
6183
  return out;
5991
6184
  }
6185
+ function streams(known, request, init, url) {
6186
+ if (known.streamingBodies !== true || !(init?.body instanceof ReadableStream)) return false;
6187
+ return request.method !== "GET" && request.method !== "HEAD" && !local2(url);
6188
+ }
6189
+ async function pump(kernel, handle, stream, signal) {
6190
+ const reader = stream.getReader();
6191
+ const stop = () => void reader.cancel(signal.reason).catch(() => void 0);
6192
+ signal.addEventListener("abort", stop, { once: true });
6193
+ try {
6194
+ await pumpFrom(kernel, handle, reader, signal);
6195
+ } finally {
6196
+ signal.removeEventListener("abort", stop);
6197
+ }
6198
+ }
6199
+ async function pumpFrom(kernel, handle, reader, signal) {
6200
+ for (; ; ) {
6201
+ let bytes;
6202
+ try {
6203
+ const next2 = await reader.read();
6204
+ if (next2.done) break;
6205
+ bytes = bytesOf(next2.value);
6206
+ } catch (err) {
6207
+ await reader.cancel(err).catch(() => void 0);
6208
+ await kernel.raw({ op: "net-close", handle });
6209
+ return;
6210
+ }
6211
+ if (bytes.length === 0) continue;
6212
+ const taken = await kernel.blocking({ op: "net-write", handle, bytes }, signal).then(
6213
+ () => true,
6214
+ () => false
6215
+ );
6216
+ if (!taken) {
6217
+ await reader.cancel().catch(() => void 0);
6218
+ return;
6219
+ }
6220
+ }
6221
+ await kernel.raw({ op: "net-end", handle });
6222
+ }
5992
6223
  function fetchOp(kernel) {
5993
6224
  const traits = /* @__PURE__ */ new Map();
5994
6225
  const traitsOf = (url) => {
@@ -6008,8 +6239,9 @@ function fetchOp(kernel) {
6008
6239
  url: hop.url,
6009
6240
  method: hop.method,
6010
6241
  headers: hop.headers,
6011
- ...hop.body ? { body: hop.body } : {}
6242
+ ...hop.stream ? { stream: true } : hop.body ? { body: hop.body } : {}
6012
6243
  });
6244
+ if (hop.stream) void pump(kernel, handle, hop.stream, signal);
6013
6245
  try {
6014
6246
  const r = await kernel.blocking({ op: "net-head", handle }, signal);
6015
6247
  signal.throwIfAborted();
@@ -6103,7 +6335,8 @@ function fetchOp(kernel) {
6103
6335
  throw failed(new JsCallError("ENOTSUP", `redirect: ${request.redirect}`));
6104
6336
  }
6105
6337
  const url = withoutFragment(new URL(request.url));
6106
- const bytes = await bodyOf(request, known.maxRequestBody, signal);
6338
+ const streamed = streams(known, request, init, url);
6339
+ const bytes = streamed ? void 0 : await bodyOf(request, known.maxRequestBody, signal);
6107
6340
  if (bytes === OVER) {
6108
6341
  return withMeta(plain(413, `request body over ${known.maxRequestBody} bytes`), url, false);
6109
6342
  }
@@ -6111,7 +6344,8 @@ function fetchOp(kernel) {
6111
6344
  url,
6112
6345
  method: request.method,
6113
6346
  headers: [...request.headers],
6114
- body: bytes
6347
+ body: bytes,
6348
+ ...streamed && request.body ? { stream: request.body } : {}
6115
6349
  };
6116
6350
  for (let hops = 0; ; hops++) {
6117
6351
  const head = await send(hop, signal);
@@ -11807,7 +12041,7 @@ function orphanContents(stream) {
11807
12041
  if (live.ranged) return live.ranged.read(0, live.ranged.size());
11808
12042
  return live.data?.slice(0, live.len ?? live.data.length) ?? new Uint8Array(0);
11809
12043
  }
11810
- function vfsPromoter(Fs, sys, streams, livePath) {
12044
+ function vfsPromoter(Fs, sys, streams2, livePath) {
11811
12045
  const promoted = /* @__PURE__ */ new Map();
11812
12046
  return (stream) => {
11813
12047
  if (stream.sliccKernelFd !== void 0 || !isVfsFile(Fs, stream)) return;
@@ -11827,11 +12061,11 @@ function vfsPromoter(Fs, sys, streams, livePath) {
11827
12061
  );
11828
12062
  promoted.set(stream.shared, kfd);
11829
12063
  }
11830
- streams.attachFile(stream, kfd);
12064
+ streams2.attachFile(stream, kfd);
11831
12065
  };
11832
12066
  }
11833
- function describeForFork(Fs, sys, streams, livePath) {
11834
- const promote = vfsPromoter(Fs, sys, streams, livePath);
12067
+ function describeForFork(Fs, sys, streams2, livePath) {
12068
+ const promote = vfsPromoter(Fs, sys, streams2, livePath);
11835
12069
  const out = [];
11836
12070
  for (const stream of Fs.streams) {
11837
12071
  if (!stream) continue;
@@ -11855,7 +12089,7 @@ function kernelEntry2(stream, kernel) {
11855
12089
  const access = kind === "tty" ? O_RDWR4 : (stream.flags ?? O_RDWR4) & O_ACCMODE4;
11856
12090
  return { fd: stream.fd, kernel, kind, flags: access, ...cloexec };
11857
12091
  }
11858
- function describeInherited(Fs, sys, streams, livePath, actions = []) {
12092
+ function describeInherited(Fs, sys, streams2, livePath, actions = []) {
11859
12093
  const table = /* @__PURE__ */ new Map();
11860
12094
  for (const stream of Fs.streams) {
11861
12095
  if (stream) table.set(stream.fd, { stream, cloexec: closesOnExec(stream) });
@@ -11870,7 +12104,7 @@ function describeInherited(Fs, sys, streams, livePath, actions = []) {
11870
12104
  for (const [fd, { stream, cloexec }] of table) {
11871
12105
  if (fd > 2 && !cloexec) slots3.set(fd, stream);
11872
12106
  }
11873
- const promote = vfsPromoter(Fs, sys, streams, livePath);
12107
+ const promote = vfsPromoter(Fs, sys, streams2, livePath);
11874
12108
  const out = [];
11875
12109
  for (const [fd, stream] of slots3) {
11876
12110
  promote(stream);
@@ -11899,50 +12133,50 @@ function place(Fs, stream, fd) {
11899
12133
  Fs.closeStream(stream.fd);
11900
12134
  return moved;
11901
12135
  }
11902
- function placeholder(Fs, streams, entry) {
12136
+ function placeholder(Fs, streams2, entry) {
11903
12137
  const access = entry.flags ?? O_RDWR4;
11904
- if (entry.kind === "socket") return streams.socketStream(access);
12138
+ if (entry.kind === "socket") return streams2.socketStream(access);
11905
12139
  if (entry.kind === "tty") return Fs.open("/dev/tty", O_RDWR4);
11906
12140
  if (entry.kind === "stream" || entry.kind === "clipboard" || entry.kind === "sealed")
11907
12141
  return Fs.open("/dev/null", access);
11908
12142
  Fs.mkdirTree(PLACEHOLDER_DIR);
11909
12143
  return Fs.open(`${PLACEHOLDER_DIR}/${entry.fd}`, access | O_CREAT3);
11910
12144
  }
11911
- function asFifo(stream, streams, identity) {
11912
- const inos = streamInos.get(streams) ?? /* @__PURE__ */ new Map();
11913
- streamInos.set(streams, inos);
12145
+ function asFifo(stream, streams2, identity) {
12146
+ const inos = streamInos.get(streams2) ?? /* @__PURE__ */ new Map();
12147
+ streamInos.set(streams2, inos);
11914
12148
  const fixed = inos.get(identity) ?? nextStreamIno++;
11915
12149
  inos.set(identity, fixed);
11916
12150
  const node = stream.node;
11917
- streams.describe(stream, `pipe:[${fixed}]`, () => ({
12151
+ streams2.describe(stream, `pipe:[${fixed}]`, () => ({
11918
12152
  ...node.node_ops?.getattr?.(node),
11919
12153
  mode: FIFO_MODE,
11920
12154
  ino: fixed,
11921
12155
  size: 0
11922
12156
  }));
11923
12157
  }
11924
- function placeKernelStream(Fs, streams, entry) {
11925
- const stream = place(Fs, placeholder(Fs, streams, entry), entry.fd);
12158
+ function placeKernelStream(Fs, streams2, entry) {
12159
+ const stream = place(Fs, placeholder(Fs, streams2, entry), entry.fd);
11926
12160
  if (entry.kind === "file") {
11927
- streams.attachFile(stream, entry.kernel);
11928
- streams.sizeFromKernel(stream, entry.kernel);
11929
- } else if (entry.kind === "socket") streams.attachSocket(stream, entry.kernel);
11930
- else streams.attach(stream, entry.kernel, entry.kind === "tty");
11931
- if (entry.kind === "clipboard") streams.reportClose(entry.kernel);
11932
- if (entry.kind === "sealed" || entry.kind === "clipboard") streams.nameDevice(stream, entry.kind);
11933
- if (entry.kind === "tty") streams.nameTerminal(stream);
12161
+ streams2.attachFile(stream, entry.kernel);
12162
+ streams2.sizeFromKernel(stream, entry.kernel);
12163
+ } else if (entry.kind === "socket") streams2.attachSocket(stream, entry.kernel);
12164
+ else streams2.attach(stream, entry.kernel, entry.kind === "tty");
12165
+ if (entry.kind === "clipboard") streams2.reportClose(entry.kernel);
12166
+ if (entry.kind === "sealed" || entry.kind === "clipboard") streams2.nameDevice(stream, entry.kind);
12167
+ if (entry.kind === "tty") streams2.nameTerminal(stream);
11934
12168
  if (entry.kind === "stream") {
11935
- asFifo(stream, streams, entry.desc !== void 0 ? `d${entry.desc}` : `k${entry.kernel}`);
12169
+ asFifo(stream, streams2, entry.desc !== void 0 ? `d${entry.desc}` : `k${entry.kernel}`);
11936
12170
  }
11937
12171
  setCloseOnExec(stream, entry.cloexec === true);
11938
12172
  return stream;
11939
12173
  }
11940
- function restoreForkedStreams(Fs, streams, table) {
12174
+ function restoreForkedStreams(Fs, streams2, table) {
11941
12175
  for (const stream of Fs.streams) if (stream) Fs.closeStream(stream.fd);
11942
12176
  for (const entry of table) {
11943
12177
  try {
11944
12178
  if ("kernel" in entry) {
11945
- placeKernelStream(Fs, streams, entry);
12179
+ placeKernelStream(Fs, streams2, entry);
11946
12180
  } else {
11947
12181
  const placed = place(
11948
12182
  Fs,
@@ -12010,14 +12244,14 @@ function forkRestarted(deps, state, snapshotAt) {
12010
12244
  let memory = state.memory;
12011
12245
  let seen = snapshotAt;
12012
12246
  return restarted2(() => {
12013
- const streams = deps.describeFork();
12247
+ const streams2 = deps.describeFork();
12014
12248
  const now = deps.deliveries?.();
12015
12249
  if (now !== seen) {
12016
12250
  seen = now;
12017
12251
  const live = deps.memory?.();
12018
12252
  if (live) memory = new Uint8Array(live.buffer).slice();
12019
12253
  }
12020
- const forked = { ...state, memory, streams, cwd: deps.Fs.cwd() };
12254
+ const forked = { ...state, memory, streams: streams2, cwd: deps.Fs.cwd() };
12021
12255
  return deps.transport.call(
12022
12256
  { op: "proc-fork", state: forked, restart: true },
12023
12257
  Infinity,
@@ -12329,6 +12563,8 @@ var init_process_signals = __esm({
12329
12563
  unwinding = false;
12330
12564
  quieted = 0;
12331
12565
  delivered = 0;
12566
+ raised = 0;
12567
+ entering = 0;
12332
12568
  raw;
12333
12569
  header;
12334
12570
  hooks;
@@ -12391,9 +12627,18 @@ var init_process_signals = __esm({
12391
12627
  const header = this.header;
12392
12628
  const pending = Atomics.load(header, SAB_I_SIGNALS) & ~Atomics.load(header, SAB_I_BLOCKED) | Atomics.load(header, SAB_I_TIMERS) | Atomics.load(header, SAB_I_KILLED);
12393
12629
  if (pending === 0) return false;
12394
- this.deliver();
12630
+ if (this.entering === 0) this.raised = this.quieted > 0 ? -1 : 0;
12631
+ this.entering++;
12632
+ try {
12633
+ this.deliver();
12634
+ } finally {
12635
+ this.entering--;
12636
+ }
12395
12637
  return true;
12396
12638
  }
12639
+ raisedOnEntry() {
12640
+ return this.raised;
12641
+ }
12397
12642
  deliver() {
12398
12643
  if (this.quieted > 0) return;
12399
12644
  const killed = Atomics.load(this.header, SAB_I_KILLED);
@@ -12406,6 +12651,7 @@ var init_process_signals = __esm({
12406
12651
  const pending = blocked === 0 ? Atomics.exchange(this.header, SAB_I_SIGNALS, 0) : Atomics.and(this.header, SAB_I_SIGNALS, blocked) & ~blocked;
12407
12652
  if (this.depth <= 1) this.lastDelivered = pending | (timers & 1 ? sigbit(SIG.ALRM) : 0);
12408
12653
  if (pending !== 0 || timers !== 0) this.delivered++;
12654
+ this.raised |= pending | (timers & 1 ? sigbit(SIG.ALRM) : 0) | (timers & ~1 ? -1 : 0);
12409
12655
  for (let which = 0; which < 3; which++) {
12410
12656
  if (timers & 1 << which) this.hooks.timer?.(which);
12411
12657
  }
@@ -12428,7 +12674,7 @@ function resolved(Fs, addr) {
12428
12674
  return { family: "unix", path: normalizePath(path) };
12429
12675
  }
12430
12676
  function createSocketKernel(deps) {
12431
- const { transport, Fs, sys, streams } = deps;
12677
+ const { transport, Fs, sys, streams: streams2 } = deps;
12432
12678
  const call2 = (req) => {
12433
12679
  const r = transport.call(req, Number.POSITIVE_INFINITY, req.op);
12434
12680
  if (!r.ok) throw new SyscallError(r.errno);
@@ -12464,12 +12710,12 @@ function createSocketKernel(deps) {
12464
12710
  const install = (k, nonblock, cloexec = false) => {
12465
12711
  let stream;
12466
12712
  try {
12467
- stream = streams.socketStream(O_RDWR5 | (nonblock ? O_NONBLOCK2 : 0));
12713
+ stream = streams2.socketStream(O_RDWR5 | (nonblock ? O_NONBLOCK2 : 0));
12468
12714
  } catch (e) {
12469
12715
  sys.close(k);
12470
12716
  throw e;
12471
12717
  }
12472
- streams.attachSocket(stream, k);
12718
+ streams2.attachSocket(stream, k);
12473
12719
  setCloseOnExec(stream, cloexec);
12474
12720
  return stream.fd;
12475
12721
  };
@@ -12748,9 +12994,9 @@ function kernelSys(transport) {
12748
12994
  }
12749
12995
  };
12750
12996
  }
12751
- function wireKernelFd(Fs, streams, entry) {
12997
+ function wireKernelFd(Fs, streams2, entry) {
12752
12998
  if (entry.device && openDevice(Fs, entry.fd, entry.device)) return;
12753
- placeKernelStream(Fs, streams, {
12999
+ placeKernelStream(Fs, streams2, {
12754
13000
  ...entry,
12755
13001
  kind: entry.device ? "stream" : entry.kind,
12756
13002
  kernel: entry.fd
@@ -12775,7 +13021,7 @@ function openAt(Fs, fd, path, flags) {
12775
13021
  }
12776
13022
  return true;
12777
13023
  }
12778
- function wireKernelStdio(Fs, streams, sys) {
13024
+ function wireKernelStdio(Fs, streams2, sys) {
12779
13025
  for (const fd of [0, 1, 2]) {
12780
13026
  const stream = Fs.getStream(fd);
12781
13027
  if (!stream) continue;
@@ -12786,11 +13032,11 @@ function wireKernelStdio(Fs, streams, sys) {
12786
13032
  const flags = sys?.access ? stream.flags & ~O_ACCMODE5 | accessMode(sys.access(fd)) : stream.flags;
12787
13033
  Fs.closeStream(fd);
12788
13034
  const kernel = { fd, kernel: fd, kind, flags };
12789
- placeKernelStream(Fs, streams, kernel).flags = flags;
13035
+ placeKernelStream(Fs, streams2, kernel).flags = flags;
12790
13036
  continue;
12791
13037
  }
12792
- streams.attach(stream, fd);
12793
- streams.nameTerminal(stream);
13038
+ streams2.attach(stream, fd);
13039
+ streams2.nameTerminal(stream);
12794
13040
  }
12795
13041
  }
12796
13042
  function glueBody(glue) {
@@ -12889,6 +13135,11 @@ function credSyncTransport(gated, early, cred) {
12889
13135
  }
12890
13136
  };
12891
13137
  }
13138
+ function sigpipeSpared(transport) {
13139
+ const req = { op: "proc-kill-self", sig: SIG.PIPE, probe: true };
13140
+ const r = transport.call(req, Number.POSITIVE_INFINITY, "proc-kill-self");
13141
+ return r.ok && !(r.kind === "json" && r.json === "terminate");
13142
+ }
12892
13143
  async function runWasmProcess(init, port3, deps = {}) {
12893
13144
  const signals = new SignalGate(
12894
13145
  createSyncSabTransport(init.sab, port3, {
@@ -12996,10 +13247,10 @@ async function runWasmProcess(init, port3, deps = {}) {
12996
13247
  });
12997
13248
  early = () => signals.quiet(() => vfs.flushDirty());
12998
13249
  closeDropsLocks(running.FS, sys);
12999
- const sigpipe = () => running.sliccSigpipe?.() === 1;
13250
+ const sigpipe = () => running.sliccSigpipe?.() === 1 || sigpipeSpared(gated);
13000
13251
  const restartable = () => signals.restartable();
13001
13252
  const owners = init.owners ? { owners: true } : {};
13002
- const streams = new KernelStreams(running.FS, sys, {
13253
+ const streams2 = new KernelStreams(running.FS, sys, {
13003
13254
  sigpipe,
13004
13255
  restartable,
13005
13256
  ...owners,
@@ -13007,21 +13258,21 @@ async function runWasmProcess(init, port3, deps = {}) {
13007
13258
  });
13008
13259
  trackCloseOnExec(running.FS);
13009
13260
  quietQuit(running.FS, (on) => {
13010
- streams.quitting = on;
13261
+ streams2.quitting = on;
13011
13262
  });
13012
- atExit = () => streams.exiting();
13263
+ atExit = () => streams2.exiting();
13013
13264
  useMounts(running.FS, init.env, true);
13014
13265
  useZeroDevices(running.FS);
13015
13266
  useProcfs(running.FS, sys, init.pid);
13016
- if (init.fork) restoreForkedStreams(running.FS, streams, init.fork.streams ?? []);
13267
+ if (init.fork) restoreForkedStreams(running.FS, streams2, init.fork.streams ?? []);
13017
13268
  else {
13018
- wireKernelStdio(running.FS, streams, sys);
13019
- for (const entry of init.fds ?? []) wireKernelFd(running.FS, streams, entry);
13269
+ wireKernelStdio(running.FS, streams2, sys);
13270
+ for (const entry of init.fds ?? []) wireKernelFd(running.FS, streams2, entry);
13020
13271
  }
13021
13272
  const pipefs = ownValue(running, "PIPEFS");
13022
- if (pipefs) streams.usePipes(pipefs);
13023
- streams.useControllingTerminal();
13024
- streams.useKernelFdMetadata();
13273
+ if (pipefs) streams2.usePipes(pipefs);
13274
+ streams2.useControllingTerminal();
13275
+ streams2.useKernelFdMetadata();
13025
13276
  useDevFd(running.FS);
13026
13277
  useDevRemoval(running.FS);
13027
13278
  useFileMmap(running.FS, {
@@ -13041,9 +13292,9 @@ async function runWasmProcess(init, port3, deps = {}) {
13041
13292
  restartable,
13042
13293
  memory: () => memory,
13043
13294
  deliveries: () => signals.deliveries(),
13044
- describeFork: () => describeForFork(running.FS, sys, streams, livePath),
13045
- inherit: (actions) => describeInherited(running.FS, sys, streams, livePath, actions),
13046
- stdioPromoter: () => vfsPromoter(running.FS, sys, streams, livePath),
13295
+ describeFork: () => describeForFork(running.FS, sys, streams2, livePath),
13296
+ inherit: (actions) => describeInherited(running.FS, sys, streams2, livePath, actions),
13297
+ stdioPromoter: () => vfsPromoter(running.FS, sys, streams2, livePath),
13047
13298
  ...callerOwner(running.FS, init)
13048
13299
  });
13049
13300
  running.sliccKernel.http = createHttpKernel(transport);
@@ -13052,15 +13303,15 @@ async function runWasmProcess(init, port3, deps = {}) {
13052
13303
  transport,
13053
13304
  Fs: running.FS,
13054
13305
  sys,
13055
- streams,
13306
+ streams: streams2,
13056
13307
  sigpipe,
13057
13308
  restartable
13058
13309
  });
13059
- return runWithFlush(running, init, streams, vfs);
13310
+ return runWithFlush(running, init, streams2, vfs);
13060
13311
  }
13061
- function runWithFlush(running, init, streams, vfs) {
13312
+ function runWithFlush(running, init, streams2, vfs) {
13062
13313
  try {
13063
- return streams.exitStatus(runMain(running, init));
13314
+ return streams2.exitStatus(runMain(running, init));
13064
13315
  } finally {
13065
13316
  try {
13066
13317
  vfs.flush();
@@ -13312,7 +13563,7 @@ var init_wasi_module = __esm({
13312
13563
  });
13313
13564
 
13314
13565
  // src/process/wasi/wasi-sigmask.ts
13315
- var UNBLOCKABLE, LIBC_UNBLOCKABLE, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK, kernelBits, libcBits, apply, WasiSigmask;
13566
+ var UNBLOCKABLE, LIBC_UNBLOCKABLE, FOREVER2, NS_PER_MS4, POLL_MS, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK, kernelBits, libcBits, apply, WasiSigmask;
13316
13567
  var init_wasi_sigmask = __esm({
13317
13568
  "src/process/wasi/wasi-sigmask.ts"() {
13318
13569
  "use strict";
@@ -13321,6 +13572,9 @@ var init_wasi_sigmask = __esm({
13321
13572
  init_wasi_abi();
13322
13573
  UNBLOCKABLE = sigbit(SIG.KILL) | sigbit(SIG.STOP);
13323
13574
  LIBC_UNBLOCKABLE = 1 << SIG.KILL - 1 | 1 << SIG.STOP - 1;
13575
+ FOREVER2 = 0xffffffffffffffffn;
13576
+ NS_PER_MS4 = 1000000n;
13577
+ POLL_MS = 50;
13324
13578
  SIG_BLOCK = 0;
13325
13579
  SIG_UNBLOCK = 1;
13326
13580
  SIG_SETMASK = 2;
@@ -13337,10 +13591,12 @@ var init_wasi_sigmask = __esm({
13337
13591
  header;
13338
13592
  deliver;
13339
13593
  process;
13340
- constructor(header, deliver, process) {
13594
+ tid;
13595
+ constructor(header, deliver, process, tid = 1) {
13341
13596
  this.header = header;
13342
13597
  this.deliver = deliver;
13343
13598
  this.process = process;
13599
+ this.tid = tid;
13344
13600
  this.lo = libcBits(Atomics.load(header, SAB_I_BLOCKED));
13345
13601
  this.hi = Atomics.load(header, SAB_I_BLOCKED_HI);
13346
13602
  }
@@ -13374,6 +13630,12 @@ var init_wasi_sigmask = __esm({
13374
13630
  this.set(SIG_SETMASK, lo, hi, () => {
13375
13631
  });
13376
13632
  }
13633
+ blockedBits() {
13634
+ return Atomics.load(this.header, SAB_I_BLOCKED);
13635
+ }
13636
+ blocks(sig) {
13637
+ return (Atomics.load(this.header, SAB_I_BLOCKED) & sigbit(sig)) !== 0;
13638
+ }
13377
13639
  inherited() {
13378
13640
  return [kernelBits(this.lo), this.hi];
13379
13641
  }
@@ -13381,6 +13643,47 @@ var init_wasi_sigmask = __esm({
13381
13643
  Atomics.and(this.header, SAB_I_SIGNALS, ~sigbit(sig));
13382
13644
  if (this.process) Atomics.and(this.process, SAB_I_SIGNALS, ~sigbit(sig));
13383
13645
  }
13646
+ sigwait(setLo, timeoutNs, publish, took, entered = false) {
13647
+ const set = kernelBits(setLo | 0);
13648
+ const value2 = BigInt.asUintN(64, timeoutNs);
13649
+ const deadline = value2 === FOREVER2 ? Number.POSITIVE_INFINITY : performance.now() + Number((value2 + NS_PER_MS4 - 1n) / NS_PER_MS4);
13650
+ publish(set);
13651
+ try {
13652
+ for (; ; ) {
13653
+ const seen = Atomics.load(this.header, SAB_I_SIGNALS);
13654
+ const sig = this.take(set);
13655
+ if (sig !== 0) {
13656
+ took(sig);
13657
+ return E.SUCCESS;
13658
+ }
13659
+ if (entered || this.deliverUnblocked() || this.interrupted()) return E.INTR;
13660
+ const left = deadline - performance.now();
13661
+ if (left <= 0) return E.AGAIN;
13662
+ Atomics.wait(this.header, SAB_I_SIGNALS, seen, Math.min(left, POLL_MS));
13663
+ }
13664
+ } finally {
13665
+ publish(0);
13666
+ }
13667
+ }
13668
+ take(set) {
13669
+ for (const header of this.process ? [this.header, this.process] : [this.header]) {
13670
+ const ready = Atomics.load(header, SAB_I_SIGNALS) & set;
13671
+ if (ready === 0) continue;
13672
+ const bit = ready & -ready;
13673
+ if ((Atomics.and(header, SAB_I_SIGNALS, ~bit) & bit) !== 0) return 31 - Math.clz32(bit);
13674
+ }
13675
+ return 0;
13676
+ }
13677
+ interrupted() {
13678
+ const killed = this.process ?? this.header;
13679
+ if (Atomics.load(killed, SAB_I_KILLED) !== 0) {
13680
+ this.deliver();
13681
+ return true;
13682
+ }
13683
+ if (Atomics.load(killed, SAB_I_STOP) !== 1) return false;
13684
+ while (Atomics.load(killed, SAB_I_STOP) === 1) Atomics.wait(killed, SAB_I_STOP, 1);
13685
+ return true;
13686
+ }
13384
13687
  pending() {
13385
13688
  const own = Atomics.load(this.header, SAB_I_SIGNALS);
13386
13689
  return libcBits(own | (this.process ? Atomics.load(this.process, SAB_I_SIGNALS) : 0));
@@ -13739,91 +14042,6 @@ var init_wasix_fork = __esm({
13739
14042
  }
13740
14043
  });
13741
14044
 
13742
- // src/process/wasi/wasix-epoll.ts
13743
- function timeoutMs(ns) {
13744
- const value2 = BigInt.asUintN(64, ns);
13745
- if (value2 === FOREVER) return -1;
13746
- const ms = (value2 + NS_PER_MS3 - 1n) / NS_PER_MS3;
13747
- return ms > BigInt(MAX_TIMEOUT_MS) ? -1 : Number(ms);
13748
- }
13749
- function wasixEpollImports(host) {
13750
- const { mem, fds, o } = host;
13751
- const call2 = (req) => o.kernel.call(req);
13752
- const kernelFd = (fd, refusal2) => {
13753
- const e = fds.find(fd);
13754
- if (!e) throw new WasiError("EBADF");
13755
- if (e.type !== "kernel") throw new WasiError(refusal2);
13756
- };
13757
- const writeEvents2 = (ptr, events) => {
13758
- const view = mem.view();
13759
- events.forEach((ev, i) => {
13760
- const at = ptr + i * EVENT_SIZE;
13761
- mem.bytes(at, EVENT_SIZE).fill(0);
13762
- view.setUint32(at, ev.events, true);
13763
- mem.bytes(at + DATA_OFFSET, DATA_SIZE).set(ev.data);
13764
- });
13765
- };
13766
- return {
13767
- epoll_create: (out) => {
13768
- const fd = call2({ op: "epoll-create" });
13769
- fds.adopt(fd, "stream", false);
13770
- mem.view().setUint32(out, fd, true);
13771
- },
13772
- epoll_ctl: (epfd, op, fd, event) => {
13773
- const how = OPS[op];
13774
- if (!how) throw new WasiError("EINVAL");
13775
- kernelFd(epfd, "EINVAL");
13776
- kernelFd(fd, "EPERM");
13777
- if (how !== "del" && event === 0) throw new WasiError("EINVAL");
13778
- const events = event === 0 ? 0 : mem.view().getUint32(event, true);
13779
- const data = event === 0 ? [] : [...mem.bytes(event + DATA_OFFSET, DATA_SIZE)];
13780
- call2({ op: "epoll-ctl", epfd, how, fd, events, data });
13781
- },
13782
- epoll_wait: (epfd, ptr, maxevents, timeout, out) => {
13783
- mem.view().setUint32(out, 0, true);
13784
- if ((maxevents | 0) <= 0) throw new WasiError("EINVAL");
13785
- kernelFd(epfd, "EINVAL");
13786
- const max = Math.min(maxevents | 0, MAX_EVENTS);
13787
- const ms = host.entered ? 0 : timeoutMs(timeout);
13788
- const events = call2({ op: "epoll-wait", epfd, max, timeoutMs: ms });
13789
- if (host.entered && events.length === 0 && timeoutMs(timeout) !== 0) return E.INTR;
13790
- writeEvents2(ptr, events);
13791
- mem.view().setUint32(out, events.length, true);
13792
- return E.SUCCESS;
13793
- },
13794
- fd_event: (initial, flags, out) => {
13795
- const value2 = BigInt.asUintN(64, initial);
13796
- if (value2 > EVENTFD_MAX) throw new WasiError("EINVAL");
13797
- const fd = call2({
13798
- op: "eventfd-open",
13799
- initial: value2.toString(),
13800
- semaphore: (flags & EVENTFD_SEMAPHORE) !== 0
13801
- });
13802
- fds.adopt(fd, "stream", (flags & EVENTFD_NONBLOCK) !== 0);
13803
- mem.view().setUint32(out, fd, true);
13804
- }
13805
- };
13806
- }
13807
- var EVENT_SIZE, DATA_OFFSET, DATA_SIZE, MAX_EVENTS, FOREVER, MAX_TIMEOUT_MS, NS_PER_MS3, EVENTFD_SEMAPHORE, EVENTFD_NONBLOCK, EVENTFD_MAX, OPS;
13808
- var init_wasix_epoll = __esm({
13809
- "src/process/wasi/wasix-epoll.ts"() {
13810
- "use strict";
13811
- init_wasi_abi();
13812
- init_wasi_files();
13813
- EVENT_SIZE = 32;
13814
- DATA_OFFSET = 8;
13815
- DATA_SIZE = 24;
13816
- MAX_EVENTS = 4096;
13817
- FOREVER = 0xffffffffffffffffn;
13818
- MAX_TIMEOUT_MS = 2147483647;
13819
- NS_PER_MS3 = 1000000n;
13820
- EVENTFD_SEMAPHORE = 1;
13821
- EVENTFD_NONBLOCK = 4;
13822
- EVENTFD_MAX = 0xfffffffffffffffen;
13823
- OPS = ["add", "set", "del", "mod"];
13824
- }
13825
- });
13826
-
13827
14045
  // src/process/wasi/wasix-ffi.ts
13828
14046
  function read(view, at, type) {
13829
14047
  if (type === "i32") return view.getInt32(at, true);
@@ -14730,7 +14948,7 @@ function posixSignal(sig) {
14730
14948
  function nsToMs(ns) {
14731
14949
  return Math.ceil(Number(ns) / 1e6);
14732
14950
  }
14733
- var FDFLAGSEXT_CLOEXEC, SPAWN_OP_SIZE, SPAWN_OPS, RIGHTS_FD_WRITE, ICANON2, ECHO2, FUTEX_SLICE_MS, EINTR_LIBC, MAIN_HANDLE, WasixHost;
14951
+ var FDFLAGSEXT_CLOEXEC, SPAWN_OP_SIZE, SPAWN_OPS, RIGHTS_FD_WRITE, ICANON2, ECHO2, FUTEX_SLICE_MS, EINTR_LIBC, STRICT_EPOLL_LIBC, MAIN_HANDLE, WasixHost;
14734
14952
  var init_wasix_host = __esm({
14735
14953
  "src/process/wasi/wasix-host.ts"() {
14736
14954
  "use strict";
@@ -14754,6 +14972,7 @@ var init_wasix_host = __esm({
14754
14972
  ECHO2 = 8;
14755
14973
  FUTEX_SLICE_MS = 50;
14756
14974
  EINTR_LIBC = 22;
14975
+ STRICT_EPOLL_LIBC = 29;
14757
14976
  MAIN_HANDLE = 2147483647;
14758
14977
  WasixHost = class _WasixHost {
14759
14978
  process;
@@ -14772,6 +14991,7 @@ var init_wasix_host = __esm({
14772
14991
  driver,
14773
14992
  () => (this.threads?.tid ?? MAIN_TID) !== MAIN_TID
14774
14993
  );
14994
+ if (module) host.strictEpoll = (libcVersion(module) ?? 0) >= STRICT_EPOLL_LIBC;
14775
14995
  if (module && !WebAssembly.Module.imports(module).some((i) => i.name === "fd_fdflags_set")) {
14776
14996
  host.fds.implicitCloexec = true;
14777
14997
  host.interruptWakes = (libcVersion(module) ?? 0) < EINTR_LIBC;
@@ -15232,6 +15452,7 @@ __export(wasi_runtime_exports, {
15232
15452
  });
15233
15453
  function wireSignals(host, gate) {
15234
15454
  host.interrupted = () => gate.interrupt();
15455
+ host.raisedOnEntry = () => gate.raisedOnEntry();
15235
15456
  host.quietly = (fn) => gate.quiet(fn);
15236
15457
  }
15237
15458
  function catchUpFirst(host, sync) {
@@ -15257,6 +15478,7 @@ function delivering(ns, table, host, driver, before) {
15257
15478
  if (driver.idle) {
15258
15479
  before?.();
15259
15480
  host.entered = host.interrupted?.() === true;
15481
+ host.enteredSignals = host.entered ? host.raisedOnEntry?.() ?? -1 : 0;
15260
15482
  }
15261
15483
  return fn(...args);
15262
15484
  };
@@ -15271,7 +15493,7 @@ function sigmaskOf(module, sab, gate, threads, process) {
15271
15493
  }
15272
15494
  if (threads) threads.blocked = () => loadBlocked(header);
15273
15495
  const shared = process && new Int32Array(process, 0, SAB_HEADER_I32);
15274
- return new WasiSigmask(header, () => gate.deliver(), shared);
15496
+ return new WasiSigmask(header, () => gate.deliver(), shared, threads?.tid ?? MAIN_TID);
15275
15497
  }
15276
15498
  function enosys(module, name2, foreign) {
15277
15499
  const type = foreign?.[module]?.[name2];
@@ -15625,7 +15847,8 @@ async function runWasiProcess(init, port3) {
15625
15847
  ),
15626
15848
  procTree(call2, id.pid)
15627
15849
  ),
15628
- ...descriptors(init, fork, threads)
15850
+ ...descriptors(init, fork, threads),
15851
+ ...threads ? { credGen: threads.ids } : {}
15629
15852
  });
15630
15853
  host.sigmask = sigmaskOf(module, init.sab, gate, threads);
15631
15854
  if (threads) {