@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
@@ -2491,7 +2491,7 @@ var KERNEL_VERSION, OS_RELEASE;
2491
2491
  var init_version = __esm({
2492
2492
  "src/version.ts"() {
2493
2493
  "use strict";
2494
- KERNEL_VERSION = true ? "1.103.3" : "0.0.0-dev";
2494
+ KERNEL_VERSION = true ? "1.106.2" : "0.0.0-dev";
2495
2495
  OS_RELEASE = "6.0.0-slicc";
2496
2496
  }
2497
2497
  });
@@ -4207,7 +4207,7 @@ function orphanContents(stream) {
4207
4207
  if (live.ranged) return live.ranged.read(0, live.ranged.size());
4208
4208
  return live.data?.slice(0, live.len ?? live.data.length) ?? new Uint8Array(0);
4209
4209
  }
4210
- function vfsPromoter(Fs, sys, streams, livePath) {
4210
+ function vfsPromoter(Fs, sys, streams2, livePath) {
4211
4211
  const promoted = /* @__PURE__ */ new Map();
4212
4212
  return (stream) => {
4213
4213
  if (stream.sliccKernelFd !== void 0 || !isVfsFile(Fs, stream)) return;
@@ -4227,11 +4227,11 @@ function vfsPromoter(Fs, sys, streams, livePath) {
4227
4227
  );
4228
4228
  promoted.set(stream.shared, kfd);
4229
4229
  }
4230
- streams.attachFile(stream, kfd);
4230
+ streams2.attachFile(stream, kfd);
4231
4231
  };
4232
4232
  }
4233
- function describeForFork(Fs, sys, streams, livePath) {
4234
- const promote = vfsPromoter(Fs, sys, streams, livePath);
4233
+ function describeForFork(Fs, sys, streams2, livePath) {
4234
+ const promote = vfsPromoter(Fs, sys, streams2, livePath);
4235
4235
  const out = [];
4236
4236
  for (const stream of Fs.streams) {
4237
4237
  if (!stream) continue;
@@ -4255,7 +4255,7 @@ function kernelEntry(stream, kernel) {
4255
4255
  const access = kind === "tty" ? O_RDWR : (stream.flags ?? O_RDWR) & O_ACCMODE4;
4256
4256
  return { fd: stream.fd, kernel, kind, flags: access, ...cloexec };
4257
4257
  }
4258
- function describeInherited(Fs, sys, streams, livePath, actions = []) {
4258
+ function describeInherited(Fs, sys, streams2, livePath, actions = []) {
4259
4259
  const table = /* @__PURE__ */ new Map();
4260
4260
  for (const stream of Fs.streams) {
4261
4261
  if (stream) table.set(stream.fd, { stream, cloexec: closesOnExec(stream) });
@@ -4270,7 +4270,7 @@ function describeInherited(Fs, sys, streams, livePath, actions = []) {
4270
4270
  for (const [fd, { stream, cloexec }] of table) {
4271
4271
  if (fd > 2 && !cloexec) slots3.set(fd, stream);
4272
4272
  }
4273
- const promote = vfsPromoter(Fs, sys, streams, livePath);
4273
+ const promote = vfsPromoter(Fs, sys, streams2, livePath);
4274
4274
  const out = [];
4275
4275
  for (const [fd, stream] of slots3) {
4276
4276
  promote(stream);
@@ -4299,50 +4299,50 @@ function place(Fs, stream, fd) {
4299
4299
  Fs.closeStream(stream.fd);
4300
4300
  return moved;
4301
4301
  }
4302
- function placeholder(Fs, streams, entry) {
4302
+ function placeholder(Fs, streams2, entry) {
4303
4303
  const access = entry.flags ?? O_RDWR;
4304
- if (entry.kind === "socket") return streams.socketStream(access);
4304
+ if (entry.kind === "socket") return streams2.socketStream(access);
4305
4305
  if (entry.kind === "tty") return Fs.open("/dev/tty", O_RDWR);
4306
4306
  if (entry.kind === "stream" || entry.kind === "clipboard" || entry.kind === "sealed")
4307
4307
  return Fs.open("/dev/null", access);
4308
4308
  Fs.mkdirTree(PLACEHOLDER_DIR);
4309
4309
  return Fs.open(`${PLACEHOLDER_DIR}/${entry.fd}`, access | O_CREAT3);
4310
4310
  }
4311
- function asFifo(stream, streams, identity) {
4312
- const inos = streamInos.get(streams) ?? /* @__PURE__ */ new Map();
4313
- streamInos.set(streams, inos);
4311
+ function asFifo(stream, streams2, identity) {
4312
+ const inos = streamInos.get(streams2) ?? /* @__PURE__ */ new Map();
4313
+ streamInos.set(streams2, inos);
4314
4314
  const fixed = inos.get(identity) ?? nextStreamIno++;
4315
4315
  inos.set(identity, fixed);
4316
4316
  const node = stream.node;
4317
- streams.describe(stream, `pipe:[${fixed}]`, () => ({
4317
+ streams2.describe(stream, `pipe:[${fixed}]`, () => ({
4318
4318
  ...node.node_ops?.getattr?.(node),
4319
4319
  mode: FIFO_MODE,
4320
4320
  ino: fixed,
4321
4321
  size: 0
4322
4322
  }));
4323
4323
  }
4324
- function placeKernelStream(Fs, streams, entry) {
4325
- const stream = place(Fs, placeholder(Fs, streams, entry), entry.fd);
4324
+ function placeKernelStream(Fs, streams2, entry) {
4325
+ const stream = place(Fs, placeholder(Fs, streams2, entry), entry.fd);
4326
4326
  if (entry.kind === "file") {
4327
- streams.attachFile(stream, entry.kernel);
4328
- streams.sizeFromKernel(stream, entry.kernel);
4329
- } else if (entry.kind === "socket") streams.attachSocket(stream, entry.kernel);
4330
- else streams.attach(stream, entry.kernel, entry.kind === "tty");
4331
- if (entry.kind === "clipboard") streams.reportClose(entry.kernel);
4332
- if (entry.kind === "sealed" || entry.kind === "clipboard") streams.nameDevice(stream, entry.kind);
4333
- if (entry.kind === "tty") streams.nameTerminal(stream);
4327
+ streams2.attachFile(stream, entry.kernel);
4328
+ streams2.sizeFromKernel(stream, entry.kernel);
4329
+ } else if (entry.kind === "socket") streams2.attachSocket(stream, entry.kernel);
4330
+ else streams2.attach(stream, entry.kernel, entry.kind === "tty");
4331
+ if (entry.kind === "clipboard") streams2.reportClose(entry.kernel);
4332
+ if (entry.kind === "sealed" || entry.kind === "clipboard") streams2.nameDevice(stream, entry.kind);
4333
+ if (entry.kind === "tty") streams2.nameTerminal(stream);
4334
4334
  if (entry.kind === "stream") {
4335
- asFifo(stream, streams, entry.desc !== void 0 ? `d${entry.desc}` : `k${entry.kernel}`);
4335
+ asFifo(stream, streams2, entry.desc !== void 0 ? `d${entry.desc}` : `k${entry.kernel}`);
4336
4336
  }
4337
4337
  setCloseOnExec(stream, entry.cloexec === true);
4338
4338
  return stream;
4339
4339
  }
4340
- function restoreForkedStreams(Fs, streams, table) {
4340
+ function restoreForkedStreams(Fs, streams2, table) {
4341
4341
  for (const stream of Fs.streams) if (stream) Fs.closeStream(stream.fd);
4342
4342
  for (const entry of table) {
4343
4343
  try {
4344
4344
  if ("kernel" in entry) {
4345
- placeKernelStream(Fs, streams, entry);
4345
+ placeKernelStream(Fs, streams2, entry);
4346
4346
  } else {
4347
4347
  const placed = place(
4348
4348
  Fs,
@@ -4410,14 +4410,14 @@ function forkRestarted(deps, state, snapshotAt) {
4410
4410
  let memory = state.memory;
4411
4411
  let seen = snapshotAt;
4412
4412
  return restarted(() => {
4413
- const streams = deps.describeFork();
4413
+ const streams2 = deps.describeFork();
4414
4414
  const now = deps.deliveries?.();
4415
4415
  if (now !== seen) {
4416
4416
  seen = now;
4417
4417
  const live = deps.memory?.();
4418
4418
  if (live) memory = new Uint8Array(live.buffer).slice();
4419
4419
  }
4420
- const forked = { ...state, memory, streams, cwd: deps.Fs.cwd() };
4420
+ const forked = { ...state, memory, streams: streams2, cwd: deps.Fs.cwd() };
4421
4421
  return deps.transport.call(
4422
4422
  { op: "proc-fork", state: forked, restart: true },
4423
4423
  Infinity,
@@ -4729,6 +4729,8 @@ var init_process_signals = __esm({
4729
4729
  unwinding = false;
4730
4730
  quieted = 0;
4731
4731
  delivered = 0;
4732
+ raised = 0;
4733
+ entering = 0;
4732
4734
  raw;
4733
4735
  header;
4734
4736
  hooks;
@@ -4791,9 +4793,18 @@ var init_process_signals = __esm({
4791
4793
  const header = this.header;
4792
4794
  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);
4793
4795
  if (pending === 0) return false;
4794
- this.deliver();
4796
+ if (this.entering === 0) this.raised = this.quieted > 0 ? -1 : 0;
4797
+ this.entering++;
4798
+ try {
4799
+ this.deliver();
4800
+ } finally {
4801
+ this.entering--;
4802
+ }
4795
4803
  return true;
4796
4804
  }
4805
+ raisedOnEntry() {
4806
+ return this.raised;
4807
+ }
4797
4808
  deliver() {
4798
4809
  if (this.quieted > 0) return;
4799
4810
  const killed = Atomics.load(this.header, SAB_I_KILLED);
@@ -4806,6 +4817,7 @@ var init_process_signals = __esm({
4806
4817
  const pending = blocked === 0 ? Atomics.exchange(this.header, SAB_I_SIGNALS, 0) : Atomics.and(this.header, SAB_I_SIGNALS, blocked) & ~blocked;
4807
4818
  if (this.depth <= 1) this.lastDelivered = pending | (timers & 1 ? sigbit(SIG.ALRM) : 0);
4808
4819
  if (pending !== 0 || timers !== 0) this.delivered++;
4820
+ this.raised |= pending | (timers & 1 ? sigbit(SIG.ALRM) : 0) | (timers & ~1 ? -1 : 0);
4809
4821
  for (let which = 0; which < 3; which++) {
4810
4822
  if (timers & 1 << which) this.hooks.timer?.(which);
4811
4823
  }
@@ -4828,7 +4840,7 @@ function resolved(Fs, addr) {
4828
4840
  return { family: "unix", path: normalizePath(path) };
4829
4841
  }
4830
4842
  function createSocketKernel(deps) {
4831
- const { transport, Fs, sys, streams } = deps;
4843
+ const { transport, Fs, sys, streams: streams2 } = deps;
4832
4844
  const call2 = (req) => {
4833
4845
  const r = transport.call(req, Number.POSITIVE_INFINITY, req.op);
4834
4846
  if (!r.ok) throw new SyscallError(r.errno);
@@ -4864,12 +4876,12 @@ function createSocketKernel(deps) {
4864
4876
  const install = (k, nonblock, cloexec = false) => {
4865
4877
  let stream;
4866
4878
  try {
4867
- stream = streams.socketStream(O_RDWR2 | (nonblock ? O_NONBLOCK : 0));
4879
+ stream = streams2.socketStream(O_RDWR2 | (nonblock ? O_NONBLOCK : 0));
4868
4880
  } catch (e) {
4869
4881
  sys.close(k);
4870
4882
  throw e;
4871
4883
  }
4872
- streams.attachSocket(stream, k);
4884
+ streams2.attachSocket(stream, k);
4873
4885
  setCloseOnExec(stream, cloexec);
4874
4886
  return stream.fd;
4875
4887
  };
@@ -5562,9 +5574,9 @@ function kernelSys(transport) {
5562
5574
  }
5563
5575
  };
5564
5576
  }
5565
- function wireKernelFd(Fs, streams, entry) {
5577
+ function wireKernelFd(Fs, streams2, entry) {
5566
5578
  if (entry.device && openDevice(Fs, entry.fd, entry.device)) return;
5567
- placeKernelStream(Fs, streams, {
5579
+ placeKernelStream(Fs, streams2, {
5568
5580
  ...entry,
5569
5581
  kind: entry.device ? "stream" : entry.kind,
5570
5582
  kernel: entry.fd
@@ -5589,7 +5601,7 @@ function openAt(Fs, fd, path, flags) {
5589
5601
  }
5590
5602
  return true;
5591
5603
  }
5592
- function wireKernelStdio(Fs, streams, sys) {
5604
+ function wireKernelStdio(Fs, streams2, sys) {
5593
5605
  for (const fd of [0, 1, 2]) {
5594
5606
  const stream = Fs.getStream(fd);
5595
5607
  if (!stream) continue;
@@ -5600,11 +5612,11 @@ function wireKernelStdio(Fs, streams, sys) {
5600
5612
  const flags = sys?.access ? stream.flags & ~O_ACCMODE5 | accessMode(sys.access(fd)) : stream.flags;
5601
5613
  Fs.closeStream(fd);
5602
5614
  const kernel = { fd, kernel: fd, kind, flags };
5603
- placeKernelStream(Fs, streams, kernel).flags = flags;
5615
+ placeKernelStream(Fs, streams2, kernel).flags = flags;
5604
5616
  continue;
5605
5617
  }
5606
- streams.attach(stream, fd);
5607
- streams.nameTerminal(stream);
5618
+ streams2.attach(stream, fd);
5619
+ streams2.nameTerminal(stream);
5608
5620
  }
5609
5621
  }
5610
5622
  function glueBody(glue) {
@@ -5703,6 +5715,11 @@ function credSyncTransport(gated, early, cred) {
5703
5715
  }
5704
5716
  };
5705
5717
  }
5718
+ function sigpipeSpared(transport) {
5719
+ const req = { op: "proc-kill-self", sig: SIG.PIPE, probe: true };
5720
+ const r = transport.call(req, Number.POSITIVE_INFINITY, "proc-kill-self");
5721
+ return r.ok && !(r.kind === "json" && r.json === "terminate");
5722
+ }
5706
5723
  async function runWasmProcess(init, port2, deps = {}) {
5707
5724
  const signals = new SignalGate(
5708
5725
  createSyncSabTransport(init.sab, port2, {
@@ -5810,10 +5827,10 @@ async function runWasmProcess(init, port2, deps = {}) {
5810
5827
  });
5811
5828
  early = () => signals.quiet(() => vfs.flushDirty());
5812
5829
  closeDropsLocks(running.FS, sys);
5813
- const sigpipe = () => running.sliccSigpipe?.() === 1;
5830
+ const sigpipe = () => running.sliccSigpipe?.() === 1 || sigpipeSpared(gated);
5814
5831
  const restartable = () => signals.restartable();
5815
5832
  const owners = init.owners ? { owners: true } : {};
5816
- const streams = new KernelStreams(running.FS, sys, {
5833
+ const streams2 = new KernelStreams(running.FS, sys, {
5817
5834
  sigpipe,
5818
5835
  restartable,
5819
5836
  ...owners,
@@ -5821,21 +5838,21 @@ async function runWasmProcess(init, port2, deps = {}) {
5821
5838
  });
5822
5839
  trackCloseOnExec(running.FS);
5823
5840
  quietQuit(running.FS, (on) => {
5824
- streams.quitting = on;
5841
+ streams2.quitting = on;
5825
5842
  });
5826
- atExit = () => streams.exiting();
5843
+ atExit = () => streams2.exiting();
5827
5844
  useMounts(running.FS, init.env, true);
5828
5845
  useZeroDevices(running.FS);
5829
5846
  useProcfs(running.FS, sys, init.pid);
5830
- if (init.fork) restoreForkedStreams(running.FS, streams, init.fork.streams ?? []);
5847
+ if (init.fork) restoreForkedStreams(running.FS, streams2, init.fork.streams ?? []);
5831
5848
  else {
5832
- wireKernelStdio(running.FS, streams, sys);
5833
- for (const entry of init.fds ?? []) wireKernelFd(running.FS, streams, entry);
5849
+ wireKernelStdio(running.FS, streams2, sys);
5850
+ for (const entry of init.fds ?? []) wireKernelFd(running.FS, streams2, entry);
5834
5851
  }
5835
5852
  const pipefs = ownValue(running, "PIPEFS");
5836
- if (pipefs) streams.usePipes(pipefs);
5837
- streams.useControllingTerminal();
5838
- streams.useKernelFdMetadata();
5853
+ if (pipefs) streams2.usePipes(pipefs);
5854
+ streams2.useControllingTerminal();
5855
+ streams2.useKernelFdMetadata();
5839
5856
  useDevFd(running.FS);
5840
5857
  useDevRemoval(running.FS);
5841
5858
  useFileMmap(running.FS, {
@@ -5855,9 +5872,9 @@ async function runWasmProcess(init, port2, deps = {}) {
5855
5872
  restartable,
5856
5873
  memory: () => memory,
5857
5874
  deliveries: () => signals.deliveries(),
5858
- describeFork: () => describeForFork(running.FS, sys, streams, livePath),
5859
- inherit: (actions) => describeInherited(running.FS, sys, streams, livePath, actions),
5860
- stdioPromoter: () => vfsPromoter(running.FS, sys, streams, livePath),
5875
+ describeFork: () => describeForFork(running.FS, sys, streams2, livePath),
5876
+ inherit: (actions) => describeInherited(running.FS, sys, streams2, livePath, actions),
5877
+ stdioPromoter: () => vfsPromoter(running.FS, sys, streams2, livePath),
5861
5878
  ...callerOwner(running.FS, init)
5862
5879
  });
5863
5880
  running.sliccKernel.http = createHttpKernel(transport);
@@ -5866,15 +5883,15 @@ async function runWasmProcess(init, port2, deps = {}) {
5866
5883
  transport,
5867
5884
  Fs: running.FS,
5868
5885
  sys,
5869
- streams,
5886
+ streams: streams2,
5870
5887
  sigpipe,
5871
5888
  restartable
5872
5889
  });
5873
- return runWithFlush(running, init, streams, vfs);
5890
+ return runWithFlush(running, init, streams2, vfs);
5874
5891
  }
5875
- function runWithFlush(running, init, streams, vfs) {
5892
+ function runWithFlush(running, init, streams2, vfs) {
5876
5893
  try {
5877
- return streams.exitStatus(runMain(running, init));
5894
+ return streams2.exitStatus(runMain(running, init));
5878
5895
  } finally {
5879
5896
  try {
5880
5897
  vfs.flush();
@@ -6419,7 +6436,7 @@ function pinnedIo2(bridge, handle, rewriting) {
6419
6436
  } : {}
6420
6437
  };
6421
6438
  }
6422
- var WasiError, FileBuffer, LocalFile, MAX_LINKS, MISS_TTL_MS, FS_GEN, RING2, RING_SIZE2, SLOT2, SHARED_IDS_BYTES, StatCache;
6439
+ var WasiError, FileBuffer, LocalFile, MAX_LINKS, MISS_TTL_MS, FS_GEN, CRED_GEN, RING2, RING_SIZE2, SLOT2, SHARED_IDS_BYTES, StatCache;
6423
6440
  var init_wasi_files = __esm({
6424
6441
  "src/process/wasi/wasi-files.ts"() {
6425
6442
  "use strict";
@@ -6641,6 +6658,7 @@ var init_wasi_files = __esm({
6641
6658
  MAX_LINKS = 40;
6642
6659
  MISS_TTL_MS = 20;
6643
6660
  FS_GEN = 4;
6661
+ CRED_GEN = 5;
6644
6662
  RING2 = 8;
6645
6663
  RING_SIZE2 = 64;
6646
6664
  SLOT2 = 3;
@@ -6861,6 +6879,48 @@ var init_slicc_sem = __esm({
6861
6879
  }
6862
6880
  });
6863
6881
 
6882
+ // src/process/wasi/wasi-cred.ts
6883
+ var CredCache;
6884
+ var init_wasi_cred = __esm({
6885
+ "src/process/wasi/wasi-cred.ts"() {
6886
+ "use strict";
6887
+ init_wasi_files();
6888
+ CredCache = class {
6889
+ cred;
6890
+ stamp = 0;
6891
+ fetch;
6892
+ shared;
6893
+ constructor(fetch, shared) {
6894
+ this.fetch = fetch;
6895
+ this.shared = shared;
6896
+ }
6897
+ gen() {
6898
+ return this.shared ? Atomics.load(this.shared, CRED_GEN) : 0;
6899
+ }
6900
+ get() {
6901
+ const gen = this.gen();
6902
+ if (this.cred === void 0 || this.stamp !== gen) {
6903
+ this.cred = this.fetch();
6904
+ this.stamp = gen;
6905
+ }
6906
+ return this.cred;
6907
+ }
6908
+ change(apply2) {
6909
+ const seen = this.gen();
6910
+ const cred = apply2();
6911
+ if (!this.shared) {
6912
+ this.cred = cred;
6913
+ return cred;
6914
+ }
6915
+ const was = Atomics.add(this.shared, CRED_GEN, 1);
6916
+ this.cred = was === seen ? cred : void 0;
6917
+ this.stamp = was + 1;
6918
+ return cred;
6919
+ }
6920
+ };
6921
+ }
6922
+ });
6923
+
6864
6924
  // src/kernel/pipe.ts
6865
6925
  var PIPE_CAPACITY;
6866
6926
  var init_pipe = __esm({
@@ -7949,6 +8009,92 @@ var init_wasi_termios = __esm({
7949
8009
  }
7950
8010
  });
7951
8011
 
8012
+ // src/process/wasi/wasix-epoll.ts
8013
+ function timeoutMs(ns) {
8014
+ const value2 = BigInt.asUintN(64, ns);
8015
+ if (value2 === FOREVER) return -1;
8016
+ const ms = (value2 + NS_PER_MS2 - 1n) / NS_PER_MS2;
8017
+ return ms > BigInt(MAX_TIMEOUT_MS) ? -1 : Number(ms);
8018
+ }
8019
+ function wasixEpollImports(host) {
8020
+ const { mem, fds, o } = host;
8021
+ const call2 = (req) => o.kernel.call(req);
8022
+ const kernelFd = (fd, refusal2) => {
8023
+ const e = fds.find(fd);
8024
+ if (!e) throw new WasiError("EBADF");
8025
+ if (e.type !== "kernel") throw new WasiError(refusal2);
8026
+ };
8027
+ const writeEvents2 = (ptr, events) => {
8028
+ const view = mem.view();
8029
+ events.forEach((ev, i) => {
8030
+ const at = ptr + i * EVENT_SIZE;
8031
+ mem.bytes(at, EVENT_SIZE).fill(0);
8032
+ view.setUint32(at, ev.events, true);
8033
+ mem.bytes(at + DATA_OFFSET, DATA_SIZE).set(ev.data);
8034
+ });
8035
+ };
8036
+ return {
8037
+ epoll_create: (out) => {
8038
+ const fd = call2({ op: "epoll-create" });
8039
+ fds.adopt(fd, "stream", false);
8040
+ mem.view().setUint32(out, fd, true);
8041
+ },
8042
+ epoll_ctl: (epfd, op, fd, event) => {
8043
+ const how = (host.strictEpoll ? WASIX_OPS : DUAL_OPS)[op];
8044
+ if (!how) throw new WasiError("EINVAL");
8045
+ kernelFd(epfd, "EINVAL");
8046
+ kernelFd(fd, "EPERM");
8047
+ if (how !== "del" && event === 0) throw new WasiError("EINVAL");
8048
+ const events = event === 0 ? 0 : mem.view().getUint32(event, true);
8049
+ const data = event === 0 ? [] : [...mem.bytes(event + DATA_OFFSET, DATA_SIZE)];
8050
+ call2({ op: "epoll-ctl", epfd, how, fd, events, data });
8051
+ },
8052
+ epoll_wait: (epfd, ptr, maxevents, timeout, out) => {
8053
+ mem.view().setUint32(out, 0, true);
8054
+ if ((maxevents | 0) <= 0) throw new WasiError("EINVAL");
8055
+ kernelFd(epfd, "EINVAL");
8056
+ const max = Math.min(maxevents | 0, MAX_EVENTS);
8057
+ const ms = host.entered ? 0 : timeoutMs(timeout);
8058
+ const events = call2({ op: "epoll-wait", epfd, max, timeoutMs: ms });
8059
+ if (host.entered && events.length === 0 && timeoutMs(timeout) !== 0) return E.INTR;
8060
+ writeEvents2(ptr, events);
8061
+ mem.view().setUint32(out, events.length, true);
8062
+ return E.SUCCESS;
8063
+ },
8064
+ fd_event: (initial, flags, out) => {
8065
+ const value2 = BigInt.asUintN(64, initial);
8066
+ if (value2 > EVENTFD_MAX) throw new WasiError("EINVAL");
8067
+ const fd = call2({
8068
+ op: "eventfd-open",
8069
+ initial: value2.toString(),
8070
+ semaphore: (flags & EVENTFD_SEMAPHORE) !== 0
8071
+ });
8072
+ fds.adopt(fd, "stream", (flags & EVENTFD_NONBLOCK) !== 0);
8073
+ mem.view().setUint32(out, fd, true);
8074
+ }
8075
+ };
8076
+ }
8077
+ 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;
8078
+ var init_wasix_epoll = __esm({
8079
+ "src/process/wasi/wasix-epoll.ts"() {
8080
+ "use strict";
8081
+ init_wasi_abi();
8082
+ init_wasi_files();
8083
+ EVENT_SIZE = 32;
8084
+ DATA_OFFSET = 8;
8085
+ DATA_SIZE = 24;
8086
+ MAX_EVENTS = 4096;
8087
+ FOREVER = 0xffffffffffffffffn;
8088
+ MAX_TIMEOUT_MS = 2147483647;
8089
+ NS_PER_MS2 = 1000000n;
8090
+ EVENTFD_SEMAPHORE = 1;
8091
+ EVENTFD_NONBLOCK = 4;
8092
+ EVENTFD_MAX = 0xfffffffffffffffen;
8093
+ WASIX_OPS = ["add", "mod", "del"];
8094
+ DUAL_OPS = ["add", "set", "del", "mod"];
8095
+ }
8096
+ });
8097
+
7952
8098
  // src/kernel/net/datagram-wire.ts
7953
8099
  function decodeReceived(raw) {
7954
8100
  const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);
@@ -8335,7 +8481,7 @@ function filestatOf(path, s) {
8335
8481
  size: BigInt(s.size),
8336
8482
  ino: s.ino !== void 0 ? BigInt(s.ino) : pathInode(path),
8337
8483
  ...s.nlink !== void 0 ? { nlink: BigInt(s.nlink) } : {},
8338
- mtimeNs: BigInt(Math.round(s.mtimeMs ?? 0)) * NS_PER_MS2
8484
+ mtimeNs: BigInt(Math.round(s.mtimeMs ?? 0)) * NS_PER_MS3
8339
8485
  };
8340
8486
  }
8341
8487
  function kernelFiletype(kind) {
@@ -8385,7 +8531,7 @@ function wrap(table) {
8385
8531
  }
8386
8532
  return out;
8387
8533
  }
8388
- var WasiExit, IDS, NS_PER_MS2, AT_SYMLINK_NOFOLLOW2, AT_EACCESS2, ROOT_IDS, GONE, S_IFIFO, DEFAULT_UMASK, MONOTONIC_BASE, MAX_READ, SIGPIPE_EXIT, SIG_IGN, SEALED_MODE, WasiHost;
8534
+ var WasiExit, IDS, NS_PER_MS3, AT_SYMLINK_NOFOLLOW2, AT_EACCESS2, ROOT_IDS, GONE, S_IFIFO, DEFAULT_UMASK, MONOTONIC_BASE, MAX_READ, SIGPIPE_EXIT, SIG_IGN, SEALED_MODE, WasiHost;
8389
8535
  var init_wasi_host = __esm({
8390
8536
  "src/process/wasi/wasi-host.ts"() {
8391
8537
  "use strict";
@@ -8393,14 +8539,17 @@ var init_wasi_host = __esm({
8393
8539
  init_physical_path();
8394
8540
  init_cpu_clock();
8395
8541
  init_cred();
8542
+ init_signals();
8396
8543
  init_slicc_lock();
8397
8544
  init_slicc_sem();
8398
8545
  init_wasi_abi();
8546
+ init_wasi_cred();
8399
8547
  init_wasi_fds();
8400
8548
  init_wasi_files();
8401
8549
  init_wasi_memory();
8402
8550
  init_wasi_poll();
8403
8551
  init_wasi_termios();
8552
+ init_wasix_epoll();
8404
8553
  init_wasix_sockets();
8405
8554
  WasiExit = class extends Error {
8406
8555
  code;
@@ -8410,26 +8559,30 @@ var init_wasi_host = __esm({
8410
8559
  }
8411
8560
  };
8412
8561
  IDS = ["ruid", "euid", "suid", "rgid", "egid", "sgid"];
8413
- NS_PER_MS2 = 1000000n;
8562
+ NS_PER_MS3 = 1000000n;
8414
8563
  AT_SYMLINK_NOFOLLOW2 = 1;
8415
8564
  AT_EACCESS2 = 2;
8416
8565
  ROOT_IDS = Object.freeze({ uid: 0, gid: 0 });
8417
8566
  GONE = /* @__PURE__ */ new Set(["ENOENT", "ENOTDIR"]);
8418
8567
  S_IFIFO = 4096;
8419
8568
  DEFAULT_UMASK = 18;
8420
- MONOTONIC_BASE = BigInt(Math.round(performance.timeOrigin)) * NS_PER_MS2;
8569
+ MONOTONIC_BASE = BigInt(Math.round(performance.timeOrigin)) * NS_PER_MS3;
8421
8570
  MAX_READ = 1024 * 1024;
8422
- SIGPIPE_EXIT = 141;
8571
+ SIGPIPE_EXIT = 128 + SIG.PIPE;
8423
8572
  SIG_IGN = 1;
8424
8573
  SEALED_MODE = 8630;
8425
8574
  WasiHost = class {
8426
8575
  mem = new WasiMemory();
8427
8576
  fds;
8577
+ creds;
8428
8578
  started = performance.now();
8429
8579
  cache;
8430
8580
  startCwd;
8431
8581
  interruptWakes = false;
8582
+ strictEpoll = false;
8432
8583
  entered = false;
8584
+ enteredSignals = 0;
8585
+ raisedOnEntry;
8433
8586
  onRaise;
8434
8587
  muted;
8435
8588
  signals;
@@ -8460,6 +8613,10 @@ var init_wasi_host = __esm({
8460
8613
  this.o = { ...o, kernel: { sys, call: call2 } };
8461
8614
  this.startCwd = o.cwd;
8462
8615
  this.fds = new WasiFds(this.o.kernel, o.fs);
8616
+ this.creds = new CredCache(
8617
+ () => this.o.kernel.call({ op: "proc-cred" }),
8618
+ o.credGen ?? o.shared
8619
+ );
8463
8620
  if (o.shared) this.fds.share(o.shared, true);
8464
8621
  else if (o.forked) this.fds.restore(o.forked.fds, o.forked.cloexec);
8465
8622
  else this.fds.setup(o.cwd, o.inherited ?? [], o.preopenRoot === true);
@@ -8499,7 +8656,7 @@ var init_wasi_host = __esm({
8499
8656
  own.call(this.o.fs, path, idOf3(uid), idOf3(gid), follow2, handle);
8500
8657
  };
8501
8658
  const caller = () => {
8502
- const cred = this.o.kernel.call({ op: "proc-cred" });
8659
+ const cred = this.creds.get();
8503
8660
  return [cred.euid, cred.egid];
8504
8661
  };
8505
8662
  const owner = (st, out) => {
@@ -8604,7 +8761,7 @@ var init_wasi_host = __esm({
8604
8761
  }),
8605
8762
  umount2: (tp, tl, flags) => void this.o.kernel.call({ op: "umount", target: path(tp, tl), flags }),
8606
8763
  cred_get: (out) => {
8607
- const cred = this.o.kernel.call({ op: "proc-cred" });
8764
+ const cred = this.creds.get();
8608
8765
  const view = mem.view();
8609
8766
  view.getUint32(out + 20, true);
8610
8767
  IDS.forEach((key, i) => void view.setUint32(out + i * 4, cred[key], true));
@@ -8614,7 +8771,7 @@ var init_wasi_host = __esm({
8614
8771
  IDS.forEach((key, i) => {
8615
8772
  if (ids[i] !== -1) change[key] = ids[i] >>> 0;
8616
8773
  });
8617
- void this.o.kernel.call({ op: "proc-setcred", change });
8774
+ void this.creds.change(() => this.o.kernel.call({ op: "proc-setcred", change }));
8618
8775
  },
8619
8776
  ...semImports(this),
8620
8777
  ...lockImports({
@@ -8638,7 +8795,7 @@ var init_wasi_host = __esm({
8638
8795
  }
8639
8796
  }),
8640
8797
  groups_get: (buf, cap, count) => {
8641
- const { groups } = this.o.kernel.call({ op: "proc-cred" });
8798
+ const { groups } = this.creds.get();
8642
8799
  if (cap !== 0 && cap < groups.length) throw new WasiError("EINVAL");
8643
8800
  const shown = cap === 0 ? [] : groups;
8644
8801
  const view = mem.view();
@@ -8651,7 +8808,9 @@ var init_wasi_host = __esm({
8651
8808
  if (n < 0 || n > MAX_GROUPS) throw new WasiError("EINVAL");
8652
8809
  const view = mem.view();
8653
8810
  const groups = Array.from({ length: n }, (_, i) => view.getUint32(buf + i * 4, true));
8654
- void this.o.kernel.call({ op: "proc-setcred", change: { groups } });
8811
+ void this.creds.change(
8812
+ () => this.o.kernel.call({ op: "proc-setcred", change: { groups } })
8813
+ );
8655
8814
  },
8656
8815
  sigaction_set: (sig, disposition, flags) => {
8657
8816
  if (!this.signals) return E.NOSYS;
@@ -8666,6 +8825,24 @@ var init_wasi_host = __esm({
8666
8825
  view.setUint32(old + 4, oldHi, true);
8667
8826
  }) : E.NOSYS,
8668
8827
  sigmask_poll: (lo, hi, inPtr, outPtr, n, nevents) => this.sigmask ? this.maskedPoll(this.sigmask, [lo, hi], [inPtr, outPtr, n, nevents]) : E.NOSYS,
8828
+ sigmask_epoll_wait: (lo, hi, epfd, events, max, timeout, nevents) => this.sigmask ? this.maskedEpoll(
8829
+ this.sigmask,
8830
+ [lo, hi],
8831
+ nevents,
8832
+ (epoll) => epoll(epfd, events, max, timeout, nevents)
8833
+ ) : E.NOSYS,
8834
+ sigwait: (lo, _hi, timeout, out) => {
8835
+ const mask = this.sigmask;
8836
+ if (!mask) return E.NOSYS;
8837
+ mem.view().setUint32(out, 0, true);
8838
+ return mask.sigwait(
8839
+ lo,
8840
+ timeout,
8841
+ (set) => void this.o.kernel.call({ op: "sig-waiting", tid: mask.tid, set }),
8842
+ (sig) => void mem.view().setUint32(out, sig, true),
8843
+ this.entered
8844
+ );
8845
+ },
8669
8846
  sigpending_get: (out) => {
8670
8847
  if (!this.sigmask) return E.NOSYS;
8671
8848
  mem.view().setBigUint64(out, BigInt(this.sigmask.pending()), true);
@@ -8698,6 +8875,7 @@ var init_wasi_host = __esm({
8698
8875
  try {
8699
8876
  this.mem.view().setUint32(nevents, 0, true);
8700
8877
  if (mask.deliverUnblocked()) return E.INTR;
8878
+ this.settleEntry(mask);
8701
8879
  if (n > 0) return this.poll(inPtr, outPtr, n, nevents);
8702
8880
  return this.entered ? E.INTR : this.suspend();
8703
8881
  } finally {
@@ -8705,6 +8883,23 @@ var init_wasi_host = __esm({
8705
8883
  mask.restore(old);
8706
8884
  }
8707
8885
  }
8886
+ epollWait;
8887
+ settleEntry(mask) {
8888
+ if (this.entered && (this.enteredSignals & ~mask.blockedBits()) === 0) this.entered = false;
8889
+ }
8890
+ maskedEpoll(mask, set, nevents, wait2) {
8891
+ const old = mask.swap(set[0], set[1]);
8892
+ try {
8893
+ this.mem.view().setUint32(nevents, 0, true);
8894
+ if (mask.deliverUnblocked()) return E.INTR;
8895
+ this.settleEntry(mask);
8896
+ this.epollWait ??= wasixEpollImports(this).epoll_wait;
8897
+ return wait2(this.epollWait) ?? E.SUCCESS;
8898
+ } finally {
8899
+ mask.deliverUnblocked();
8900
+ mask.restore(old);
8901
+ }
8902
+ }
8708
8903
  suspend() {
8709
8904
  for (; ; ) {
8710
8905
  try {
@@ -8727,7 +8922,7 @@ var init_wasi_host = __esm({
8727
8922
  return this.cache;
8728
8923
  }
8729
8924
  now(id) {
8730
- if (id === CLOCK.REALTIME) return BigInt(Date.now()) * NS_PER_MS2;
8925
+ if (id === CLOCK.REALTIME) return BigInt(Date.now()) * NS_PER_MS3;
8731
8926
  if (id === CLOCK.MONOTONIC) {
8732
8927
  return MONOTONIC_BASE + BigInt(Math.round(performance.now() * 1e6));
8733
8928
  }
@@ -9061,7 +9256,7 @@ var init_wasi_host = __esm({
9061
9256
  return this.fds.kind(fd, e) === "file" ? this.changed(fd, e, n) : n;
9062
9257
  } catch (err) {
9063
9258
  const broken = err.code === "EPIPE";
9064
- if (broken && this.fds.kind(fd, e) !== "socket") throw new WasiExit(SIGPIPE_EXIT);
9259
+ if (broken && this.fds.kind(fd, e) !== "socket") this.brokenPipe();
9065
9260
  throw err;
9066
9261
  }
9067
9262
  }
@@ -9073,6 +9268,18 @@ var init_wasi_host = __esm({
9073
9268
  }
9074
9269
  return this.file(fd, "write").write(data);
9075
9270
  }
9271
+ brokenPipe() {
9272
+ let action;
9273
+ try {
9274
+ action = this.o.kernel.call({ op: "proc-kill-self", sig: SIG.PIPE, probe: true });
9275
+ } catch {
9276
+ action = "terminate";
9277
+ }
9278
+ if (action !== "terminate") return;
9279
+ const mask = this.sigmask;
9280
+ if (!mask?.blocks(SIG.PIPE)) throw new WasiExit(SIGPIPE_EXIT);
9281
+ this.o.kernel.call({ op: "thread-kill", tid: mask.tid, sig: SIG.PIPE });
9282
+ }
9076
9283
  read(fd, max) {
9077
9284
  const e = this.fds.get(fd);
9078
9285
  if (e.type === "kernel") {
@@ -9256,7 +9463,7 @@ var init_wasi_host = __esm({
9256
9463
  current ??= statOf(path);
9257
9464
  return current[field2] ?? current.mtimeMs ?? now;
9258
9465
  };
9259
- const pick = (set, setNow, value2, field2) => flags & setNow ? now : flags & set ? Number(value2 / NS_PER_MS2) : kept(field2);
9466
+ const pick = (set, setNow, value2, field2) => flags & setNow ? now : flags & set ? Number(value2 / NS_PER_MS3) : kept(field2);
9260
9467
  (follow2 ? this.o.fs.utimes : this.o.fs.lutimes).call(
9261
9468
  this.o.fs,
9262
9469
  path,
@@ -10257,7 +10464,7 @@ var init_wasi_procfs = __esm({
10257
10464
  });
10258
10465
 
10259
10466
  // src/process/wasi/wasi-sigmask.ts
10260
- var UNBLOCKABLE, LIBC_UNBLOCKABLE, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK, kernelBits, libcBits, apply, WasiSigmask;
10467
+ var UNBLOCKABLE, LIBC_UNBLOCKABLE, FOREVER2, NS_PER_MS4, POLL_MS, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK, kernelBits, libcBits, apply, WasiSigmask;
10261
10468
  var init_wasi_sigmask = __esm({
10262
10469
  "src/process/wasi/wasi-sigmask.ts"() {
10263
10470
  "use strict";
@@ -10266,6 +10473,9 @@ var init_wasi_sigmask = __esm({
10266
10473
  init_wasi_abi();
10267
10474
  UNBLOCKABLE = sigbit(SIG.KILL) | sigbit(SIG.STOP);
10268
10475
  LIBC_UNBLOCKABLE = 1 << SIG.KILL - 1 | 1 << SIG.STOP - 1;
10476
+ FOREVER2 = 0xffffffffffffffffn;
10477
+ NS_PER_MS4 = 1000000n;
10478
+ POLL_MS = 50;
10269
10479
  SIG_BLOCK = 0;
10270
10480
  SIG_UNBLOCK = 1;
10271
10481
  SIG_SETMASK = 2;
@@ -10282,10 +10492,12 @@ var init_wasi_sigmask = __esm({
10282
10492
  header;
10283
10493
  deliver;
10284
10494
  process;
10285
- constructor(header, deliver, process) {
10495
+ tid;
10496
+ constructor(header, deliver, process, tid = 1) {
10286
10497
  this.header = header;
10287
10498
  this.deliver = deliver;
10288
10499
  this.process = process;
10500
+ this.tid = tid;
10289
10501
  this.lo = libcBits(Atomics.load(header, SAB_I_BLOCKED));
10290
10502
  this.hi = Atomics.load(header, SAB_I_BLOCKED_HI);
10291
10503
  }
@@ -10319,6 +10531,12 @@ var init_wasi_sigmask = __esm({
10319
10531
  this.set(SIG_SETMASK, lo, hi, () => {
10320
10532
  });
10321
10533
  }
10534
+ blockedBits() {
10535
+ return Atomics.load(this.header, SAB_I_BLOCKED);
10536
+ }
10537
+ blocks(sig) {
10538
+ return (Atomics.load(this.header, SAB_I_BLOCKED) & sigbit(sig)) !== 0;
10539
+ }
10322
10540
  inherited() {
10323
10541
  return [kernelBits(this.lo), this.hi];
10324
10542
  }
@@ -10326,6 +10544,47 @@ var init_wasi_sigmask = __esm({
10326
10544
  Atomics.and(this.header, SAB_I_SIGNALS, ~sigbit(sig));
10327
10545
  if (this.process) Atomics.and(this.process, SAB_I_SIGNALS, ~sigbit(sig));
10328
10546
  }
10547
+ sigwait(setLo, timeoutNs, publish, took, entered = false) {
10548
+ const set = kernelBits(setLo | 0);
10549
+ const value2 = BigInt.asUintN(64, timeoutNs);
10550
+ const deadline = value2 === FOREVER2 ? Number.POSITIVE_INFINITY : performance.now() + Number((value2 + NS_PER_MS4 - 1n) / NS_PER_MS4);
10551
+ publish(set);
10552
+ try {
10553
+ for (; ; ) {
10554
+ const seen = Atomics.load(this.header, SAB_I_SIGNALS);
10555
+ const sig = this.take(set);
10556
+ if (sig !== 0) {
10557
+ took(sig);
10558
+ return E.SUCCESS;
10559
+ }
10560
+ if (entered || this.deliverUnblocked() || this.interrupted()) return E.INTR;
10561
+ const left = deadline - performance.now();
10562
+ if (left <= 0) return E.AGAIN;
10563
+ Atomics.wait(this.header, SAB_I_SIGNALS, seen, Math.min(left, POLL_MS));
10564
+ }
10565
+ } finally {
10566
+ publish(0);
10567
+ }
10568
+ }
10569
+ take(set) {
10570
+ for (const header of this.process ? [this.header, this.process] : [this.header]) {
10571
+ const ready = Atomics.load(header, SAB_I_SIGNALS) & set;
10572
+ if (ready === 0) continue;
10573
+ const bit = ready & -ready;
10574
+ if ((Atomics.and(header, SAB_I_SIGNALS, ~bit) & bit) !== 0) return 31 - Math.clz32(bit);
10575
+ }
10576
+ return 0;
10577
+ }
10578
+ interrupted() {
10579
+ const killed = this.process ?? this.header;
10580
+ if (Atomics.load(killed, SAB_I_KILLED) !== 0) {
10581
+ this.deliver();
10582
+ return true;
10583
+ }
10584
+ if (Atomics.load(killed, SAB_I_STOP) !== 1) return false;
10585
+ while (Atomics.load(killed, SAB_I_STOP) === 1) Atomics.wait(killed, SAB_I_STOP, 1);
10586
+ return true;
10587
+ }
10329
10588
  pending() {
10330
10589
  const own = Atomics.load(this.header, SAB_I_SIGNALS);
10331
10590
  return libcBits(own | (this.process ? Atomics.load(this.process, SAB_I_SIGNALS) : 0));
@@ -10684,91 +10943,6 @@ var init_wasix_fork = __esm({
10684
10943
  }
10685
10944
  });
10686
10945
 
10687
- // src/process/wasi/wasix-epoll.ts
10688
- function timeoutMs(ns) {
10689
- const value2 = BigInt.asUintN(64, ns);
10690
- if (value2 === FOREVER) return -1;
10691
- const ms = (value2 + NS_PER_MS3 - 1n) / NS_PER_MS3;
10692
- return ms > BigInt(MAX_TIMEOUT_MS) ? -1 : Number(ms);
10693
- }
10694
- function wasixEpollImports(host) {
10695
- const { mem, fds, o } = host;
10696
- const call2 = (req) => o.kernel.call(req);
10697
- const kernelFd = (fd, refusal2) => {
10698
- const e = fds.find(fd);
10699
- if (!e) throw new WasiError("EBADF");
10700
- if (e.type !== "kernel") throw new WasiError(refusal2);
10701
- };
10702
- const writeEvents2 = (ptr, events) => {
10703
- const view = mem.view();
10704
- events.forEach((ev, i) => {
10705
- const at = ptr + i * EVENT_SIZE;
10706
- mem.bytes(at, EVENT_SIZE).fill(0);
10707
- view.setUint32(at, ev.events, true);
10708
- mem.bytes(at + DATA_OFFSET, DATA_SIZE).set(ev.data);
10709
- });
10710
- };
10711
- return {
10712
- epoll_create: (out) => {
10713
- const fd = call2({ op: "epoll-create" });
10714
- fds.adopt(fd, "stream", false);
10715
- mem.view().setUint32(out, fd, true);
10716
- },
10717
- epoll_ctl: (epfd, op, fd, event) => {
10718
- const how = OPS[op];
10719
- if (!how) throw new WasiError("EINVAL");
10720
- kernelFd(epfd, "EINVAL");
10721
- kernelFd(fd, "EPERM");
10722
- if (how !== "del" && event === 0) throw new WasiError("EINVAL");
10723
- const events = event === 0 ? 0 : mem.view().getUint32(event, true);
10724
- const data = event === 0 ? [] : [...mem.bytes(event + DATA_OFFSET, DATA_SIZE)];
10725
- call2({ op: "epoll-ctl", epfd, how, fd, events, data });
10726
- },
10727
- epoll_wait: (epfd, ptr, maxevents, timeout, out) => {
10728
- mem.view().setUint32(out, 0, true);
10729
- if ((maxevents | 0) <= 0) throw new WasiError("EINVAL");
10730
- kernelFd(epfd, "EINVAL");
10731
- const max = Math.min(maxevents | 0, MAX_EVENTS);
10732
- const ms = host.entered ? 0 : timeoutMs(timeout);
10733
- const events = call2({ op: "epoll-wait", epfd, max, timeoutMs: ms });
10734
- if (host.entered && events.length === 0 && timeoutMs(timeout) !== 0) return E.INTR;
10735
- writeEvents2(ptr, events);
10736
- mem.view().setUint32(out, events.length, true);
10737
- return E.SUCCESS;
10738
- },
10739
- fd_event: (initial, flags, out) => {
10740
- const value2 = BigInt.asUintN(64, initial);
10741
- if (value2 > EVENTFD_MAX) throw new WasiError("EINVAL");
10742
- const fd = call2({
10743
- op: "eventfd-open",
10744
- initial: value2.toString(),
10745
- semaphore: (flags & EVENTFD_SEMAPHORE) !== 0
10746
- });
10747
- fds.adopt(fd, "stream", (flags & EVENTFD_NONBLOCK) !== 0);
10748
- mem.view().setUint32(out, fd, true);
10749
- }
10750
- };
10751
- }
10752
- var EVENT_SIZE, DATA_OFFSET, DATA_SIZE, MAX_EVENTS, FOREVER, MAX_TIMEOUT_MS, NS_PER_MS3, EVENTFD_SEMAPHORE, EVENTFD_NONBLOCK, EVENTFD_MAX, OPS;
10753
- var init_wasix_epoll = __esm({
10754
- "src/process/wasi/wasix-epoll.ts"() {
10755
- "use strict";
10756
- init_wasi_abi();
10757
- init_wasi_files();
10758
- EVENT_SIZE = 32;
10759
- DATA_OFFSET = 8;
10760
- DATA_SIZE = 24;
10761
- MAX_EVENTS = 4096;
10762
- FOREVER = 0xffffffffffffffffn;
10763
- MAX_TIMEOUT_MS = 2147483647;
10764
- NS_PER_MS3 = 1000000n;
10765
- EVENTFD_SEMAPHORE = 1;
10766
- EVENTFD_NONBLOCK = 4;
10767
- EVENTFD_MAX = 0xfffffffffffffffen;
10768
- OPS = ["add", "set", "del", "mod"];
10769
- }
10770
- });
10771
-
10772
10946
  // src/process/wasi/wasix-ffi.ts
10773
10947
  function read(view, at, type) {
10774
10948
  if (type === "i32") return view.getInt32(at, true);
@@ -11675,7 +11849,7 @@ function posixSignal(sig) {
11675
11849
  function nsToMs(ns) {
11676
11850
  return Math.ceil(Number(ns) / 1e6);
11677
11851
  }
11678
- var FDFLAGSEXT_CLOEXEC, SPAWN_OP_SIZE, SPAWN_OPS, RIGHTS_FD_WRITE, ICANON, ECHO, FUTEX_SLICE_MS, EINTR_LIBC, MAIN_HANDLE, WasixHost;
11852
+ var FDFLAGSEXT_CLOEXEC, SPAWN_OP_SIZE, SPAWN_OPS, RIGHTS_FD_WRITE, ICANON, ECHO, FUTEX_SLICE_MS, EINTR_LIBC, STRICT_EPOLL_LIBC, MAIN_HANDLE, WasixHost;
11679
11853
  var init_wasix_host = __esm({
11680
11854
  "src/process/wasi/wasix-host.ts"() {
11681
11855
  "use strict";
@@ -11699,6 +11873,7 @@ var init_wasix_host = __esm({
11699
11873
  ECHO = 8;
11700
11874
  FUTEX_SLICE_MS = 50;
11701
11875
  EINTR_LIBC = 22;
11876
+ STRICT_EPOLL_LIBC = 29;
11702
11877
  MAIN_HANDLE = 2147483647;
11703
11878
  WasixHost = class _WasixHost {
11704
11879
  process;
@@ -11717,6 +11892,7 @@ var init_wasix_host = __esm({
11717
11892
  driver,
11718
11893
  () => (this.threads?.tid ?? MAIN_TID) !== MAIN_TID
11719
11894
  );
11895
+ if (module) host.strictEpoll = (libcVersion(module) ?? 0) >= STRICT_EPOLL_LIBC;
11720
11896
  if (module && !WebAssembly.Module.imports(module).some((i) => i.name === "fd_fdflags_set")) {
11721
11897
  host.fds.implicitCloexec = true;
11722
11898
  host.interruptWakes = (libcVersion(module) ?? 0) < EINTR_LIBC;
@@ -12177,6 +12353,7 @@ __export(wasi_runtime_exports, {
12177
12353
  });
12178
12354
  function wireSignals(host, gate) {
12179
12355
  host.interrupted = () => gate.interrupt();
12356
+ host.raisedOnEntry = () => gate.raisedOnEntry();
12180
12357
  host.quietly = (fn) => gate.quiet(fn);
12181
12358
  }
12182
12359
  function catchUpFirst(host, sync) {
@@ -12202,6 +12379,7 @@ function delivering(ns, table, host, driver, before) {
12202
12379
  if (driver.idle) {
12203
12380
  before?.();
12204
12381
  host.entered = host.interrupted?.() === true;
12382
+ host.enteredSignals = host.entered ? host.raisedOnEntry?.() ?? -1 : 0;
12205
12383
  }
12206
12384
  return fn(...args);
12207
12385
  };
@@ -12216,7 +12394,7 @@ function sigmaskOf(module, sab, gate, threads, process) {
12216
12394
  }
12217
12395
  if (threads) threads.blocked = () => loadBlocked(header);
12218
12396
  const shared = process && new Int32Array(process, 0, SAB_HEADER_I32);
12219
- return new WasiSigmask(header, () => gate.deliver(), shared);
12397
+ return new WasiSigmask(header, () => gate.deliver(), shared, threads?.tid ?? MAIN_TID);
12220
12398
  }
12221
12399
  function enosys(module, name2, foreign) {
12222
12400
  const type = foreign?.[module]?.[name2];
@@ -12570,7 +12748,8 @@ async function runWasiProcess(init, port2) {
12570
12748
  ),
12571
12749
  procTree(call2, id.pid)
12572
12750
  ),
12573
- ...descriptors(init, fork, threads)
12751
+ ...descriptors(init, fork, threads),
12752
+ ...threads ? { credGen: threads.ids } : {}
12574
12753
  });
12575
12754
  host.sigmask = sigmaskOf(module, init.sab, gate, threads);
12576
12755
  if (threads) {
@@ -13935,6 +14114,9 @@ function rewrite(hop, status2, location) {
13935
14114
  );
13936
14115
  }
13937
14116
  const toGet = (status2 === 301 || status2 === 302) && hop.method === "POST" || status2 === 303 && hop.method !== "GET" && hop.method !== "HEAD";
14117
+ if (hop.stream && !toGet) {
14118
+ throw failed3(new JsCallError("EIO", `a ${status2} redirect would send a streamed body again`));
14119
+ }
13938
14120
  const crossOrigin = next2.origin !== new URL(hop.url).origin;
13939
14121
  const headers = hop.headers.filter(
13940
14122
  ([name2]) => !(toGet && BODY_HEADERS.has(name2.toLowerCase())) && !(crossOrigin && CREDENTIALS.has(name2.toLowerCase()))
@@ -14101,6 +14283,44 @@ async function bodyOf(request, cap, signal) {
14101
14283
  }
14102
14284
  return out;
14103
14285
  }
14286
+ function streams(known, request, init, url) {
14287
+ if (known.streamingBodies !== true || !(init?.body instanceof ReadableStream)) return false;
14288
+ return request.method !== "GET" && request.method !== "HEAD" && !local2(url);
14289
+ }
14290
+ async function pump(kernel, handle, stream, signal) {
14291
+ const reader = stream.getReader();
14292
+ const stop = () => void reader.cancel(signal.reason).catch(() => void 0);
14293
+ signal.addEventListener("abort", stop, { once: true });
14294
+ try {
14295
+ await pumpFrom(kernel, handle, reader, signal);
14296
+ } finally {
14297
+ signal.removeEventListener("abort", stop);
14298
+ }
14299
+ }
14300
+ async function pumpFrom(kernel, handle, reader, signal) {
14301
+ for (; ; ) {
14302
+ let bytes;
14303
+ try {
14304
+ const next2 = await reader.read();
14305
+ if (next2.done) break;
14306
+ bytes = bytesOf(next2.value);
14307
+ } catch (err) {
14308
+ await reader.cancel(err).catch(() => void 0);
14309
+ await kernel.raw({ op: "net-close", handle });
14310
+ return;
14311
+ }
14312
+ if (bytes.length === 0) continue;
14313
+ const taken = await kernel.blocking({ op: "net-write", handle, bytes }, signal).then(
14314
+ () => true,
14315
+ () => false
14316
+ );
14317
+ if (!taken) {
14318
+ await reader.cancel().catch(() => void 0);
14319
+ return;
14320
+ }
14321
+ }
14322
+ await kernel.raw({ op: "net-end", handle });
14323
+ }
14104
14324
  function fetchOp(kernel) {
14105
14325
  const traits = /* @__PURE__ */ new Map();
14106
14326
  const traitsOf = (url) => {
@@ -14120,8 +14340,9 @@ function fetchOp(kernel) {
14120
14340
  url: hop.url,
14121
14341
  method: hop.method,
14122
14342
  headers: hop.headers,
14123
- ...hop.body ? { body: hop.body } : {}
14343
+ ...hop.stream ? { stream: true } : hop.body ? { body: hop.body } : {}
14124
14344
  });
14345
+ if (hop.stream) void pump(kernel, handle, hop.stream, signal);
14125
14346
  try {
14126
14347
  const r = await kernel.blocking({ op: "net-head", handle }, signal);
14127
14348
  signal.throwIfAborted();
@@ -14215,7 +14436,8 @@ function fetchOp(kernel) {
14215
14436
  throw failed3(new JsCallError("ENOTSUP", `redirect: ${request.redirect}`));
14216
14437
  }
14217
14438
  const url = withoutFragment(new URL(request.url));
14218
- const bytes = await bodyOf(request, known.maxRequestBody, signal);
14439
+ const streamed = streams(known, request, init, url);
14440
+ const bytes = streamed ? void 0 : await bodyOf(request, known.maxRequestBody, signal);
14219
14441
  if (bytes === OVER) {
14220
14442
  return withMeta(plain(413, `request body over ${known.maxRequestBody} bytes`), url, false);
14221
14443
  }
@@ -14223,7 +14445,8 @@ function fetchOp(kernel) {
14223
14445
  url,
14224
14446
  method: request.method,
14225
14447
  headers: [...request.headers],
14226
- body: bytes
14448
+ body: bytes,
14449
+ ...streamed && request.body ? { stream: request.body } : {}
14227
14450
  };
14228
14451
  for (let hops = 0; ; hops++) {
14229
14452
  const head = await send(hop, signal);