@ai-ecoverse/slicc-kernel 1.67.1 → 1.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1310,7 +1310,7 @@ function createStreamOps(h) {
1310
1310
  }
1311
1311
  }
1312
1312
  };
1313
- const opened = (node, on, want = 0) => {
1313
+ const opened2 = (node, on, want = 0) => {
1314
1314
  const s = node.live;
1315
1315
  try {
1316
1316
  const handle = bridgeOf(node).hold?.(liveNodePath(node), on, true, s.handle, want);
@@ -1361,7 +1361,7 @@ function createStreamOps(h) {
1361
1361
  const want = permitted(stream, created);
1362
1362
  live.openCount++;
1363
1363
  counted = true;
1364
- if (live.openCount === 1) opened(stream.node, true, want);
1364
+ if (live.openCount === 1) opened2(stream.node, true, want);
1365
1365
  } catch (err) {
1366
1366
  if (counted) live.openCount--;
1367
1367
  if (stream.fd !== void 0) Fs.closeStream?.(stream.fd);
@@ -1392,7 +1392,7 @@ function createStreamOps(h) {
1392
1392
  s.len = 0;
1393
1393
  s.loaded = false;
1394
1394
  held(stream, -1);
1395
- opened(node, false);
1395
+ opened2(node, false);
1396
1396
  }
1397
1397
  },
1398
1398
  read(stream, buffer, offset, length, position) {
@@ -1983,10 +1983,28 @@ function ptyStat(path) {
1983
1983
  ctime: now
1984
1984
  };
1985
1985
  }
1986
+ function sealedStat() {
1987
+ const now = /* @__PURE__ */ new Date();
1988
+ return {
1989
+ dev: 22,
1990
+ ino: 1,
1991
+ mode: 8630,
1992
+ nlink: 1,
1993
+ uid: 0,
1994
+ gid: 0,
1995
+ rdev: 10 << 8 | 250,
1996
+ size: 0,
1997
+ blksize: 4096,
1998
+ blocks: 0,
1999
+ atime: now,
2000
+ mtime: now,
2001
+ ctime: now
2002
+ };
2003
+ }
1986
2004
  function nonblocking(stream) {
1987
2005
  return (stream.flags & O_NONBLOCK) !== 0 ? { nonblock: true } : void 0;
1988
2006
  }
1989
- var POLLIN, POLLOUT, POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, TCSETSF, O_NONBLOCK, SOCKET_MODE, PTY_PATH, TTY_PATH, TTY_NAME, O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC2, KILLED_BY_SIGPIPE, ProcessExit, SyscallError, KernelStreams;
2007
+ var POLLIN, POLLOUT, POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, TCSETSF, O_NONBLOCK, SOCKET_MODE, PTY_PATH, TTY_PATH, TTY_NAME, SEALED_PATH, O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC2, KILLED_BY_SIGPIPE, ProcessExit, SyscallError, KernelStreams;
1990
2008
  var init_kernel_streams = __esm({
1991
2009
  "src/process/kernel-streams.ts"() {
1992
2010
  "use strict";
@@ -2003,6 +2021,7 @@ var init_kernel_streams = __esm({
2003
2021
  PTY_PATH = /^\/dev\/(?:ptmx|pts\/(\d+))$/;
2004
2022
  TTY_PATH = /^\/dev\/tty\d+$/;
2005
2023
  TTY_NAME = /^tty\d+$/;
2024
+ SEALED_PATH = "/dev/sealed";
2006
2025
  O_CREAT = 64;
2007
2026
  O_EXCL = 128;
2008
2027
  O_NOCTTY = 256;
@@ -2076,6 +2095,15 @@ var init_kernel_streams = __esm({
2076
2095
  if (typeof this.Fs.stat !== "function") return;
2077
2096
  stream.stream_ops = { ...stream.stream_ops, getattr: () => this.Fs.stat?.(name2) ?? {} };
2078
2097
  }
2098
+ listSealed() {
2099
+ const { analyzePath, mkdev, makedev } = this.Fs;
2100
+ if (!this.sys.openSealed || !analyzePath || !mkdev || !makedev) return;
2101
+ if (analyzePath.call(this.Fs, SEALED_PATH).exists) return;
2102
+ try {
2103
+ mkdev.call(this.Fs, SEALED_PATH, makedev.call(this.Fs, 10, 250));
2104
+ } catch {
2105
+ }
2106
+ }
2079
2107
  creatingTerminal = false;
2080
2108
  useTerminalNodes() {
2081
2109
  const fs = this.Fs;
@@ -2102,8 +2130,8 @@ var init_kernel_streams = __esm({
2102
2130
  fs.readdir = (path) => {
2103
2131
  const names = readdir.call(fs, path);
2104
2132
  if (path.replace(/\/+$/, "") !== "/dev") return names;
2105
- const missing = ttyNames().map((tty) => tty.slice("/dev/".length)).filter((name2) => TTY_NAME.test(name2) && !names.includes(name2));
2106
- return [...names, ...missing];
2133
+ const missing2 = ttyNames().map((tty) => tty.slice("/dev/".length)).filter((name2) => TTY_NAME.test(name2) && !names.includes(name2));
2134
+ return [...names, ...missing2];
2107
2135
  };
2108
2136
  }
2109
2137
  ttyNode(name2) {
@@ -2168,13 +2196,14 @@ var init_kernel_streams = __esm({
2168
2196
  if (typeof this.Fs.open !== "function") return;
2169
2197
  this.usePtyPaths();
2170
2198
  this.useTerminalNodes();
2199
+ this.listSealed();
2171
2200
  const open = this.Fs.open.bind(this.Fs);
2172
2201
  this.Fs.open = (path, flags, mode) => {
2173
2202
  const device2 = typeof path === "string" ? this.devicePath(path) : void 0;
2174
2203
  if (device2 !== void 0 && TTY_PATH.test(device2) && !this.terminalExists(device2)) {
2175
2204
  throw new this.Fs.ErrnoError(wasiErrno("ENOENT"));
2176
2205
  }
2177
- const pty = this.openPty(open, path, flags, mode);
2206
+ const pty = this.openPty(open, path, flags, mode) ?? this.openSealed(open, path, flags, mode);
2178
2207
  if (pty) return pty;
2179
2208
  this.refuseExclusiveLink(path, flags);
2180
2209
  const stream = this.openRacing(open, path, flags, mode);
@@ -2232,15 +2261,24 @@ var init_kernel_streams = __esm({
2232
2261
  const kfd = this.call(
2233
2262
  () => pts ? openPts(Number(pts[1]), (flags & O_NOCTTY) !== 0) : openPty()
2234
2263
  );
2264
+ return this.vessel(open, kfd, { path, flags, mode }, true);
2265
+ }
2266
+ openSealed(open, path, flags, mode) {
2267
+ const { openSealed } = this.sys;
2268
+ if (path !== SEALED_PATH || !openSealed) return void 0;
2269
+ const kfd = this.call(() => openSealed.call(this.sys));
2270
+ return this.vessel(open, kfd, { path, flags, mode }, false);
2271
+ }
2272
+ vessel(open, kfd, at, terminal) {
2235
2273
  let stream;
2236
2274
  try {
2237
- stream = open("/dev/null", flags & ~(O_CREAT | O_EXCL | O_TRUNC2), mode);
2275
+ stream = open("/dev/null", at.flags & ~(O_CREAT | O_EXCL | O_TRUNC2), at.mode);
2238
2276
  } catch (e) {
2239
2277
  this.sys.close(kfd);
2240
2278
  throw e;
2241
2279
  }
2242
- this.attach(stream, kfd, true);
2243
- this.nameStream(stream, path);
2280
+ this.attach(stream, kfd, terminal);
2281
+ this.nameStream(stream, at.path);
2244
2282
  return stream;
2245
2283
  }
2246
2284
  usePtyPaths() {
@@ -2254,6 +2292,7 @@ var init_kernel_streams = __esm({
2254
2292
  const original = fs[name2];
2255
2293
  if (typeof original !== "function") continue;
2256
2294
  fs[name2] = (path, ...rest2) => {
2295
+ if (path === SEALED_PATH && this.sys.openSealed) return sealedStat();
2257
2296
  const owned = this.ownedTty(path);
2258
2297
  if (owned && isPtyPath(path)) return this.owned(path, ptyStat(path));
2259
2298
  if (!isPtyPath(path)) {
@@ -2870,13 +2909,13 @@ function describeFdDir(Fs) {
2870
2909
  return;
2871
2910
  }
2872
2911
  const ops = dir?.node_ops;
2873
- const lookup = ops?.lookup;
2874
- if (!dir || !lookup || ops.getattr) return;
2912
+ const lookup2 = ops?.lookup;
2913
+ if (!dir || !lookup2 || ops.getattr) return;
2875
2914
  dir.node_ops = {
2876
2915
  ...ops,
2877
2916
  getattr: () => syntheticAttr(DIR_MODE, 1),
2878
2917
  lookup: (parent, name2) => {
2879
- const entry = lookup(parent, name2);
2918
+ const entry = lookup2(parent, name2);
2880
2919
  entry.node_ops = {
2881
2920
  ...entry.node_ops,
2882
2921
  getattr: () => syntheticAttr(LINK_MODE, entry.id ?? 0)
@@ -4166,7 +4205,7 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
4166
4205
  return found;
4167
4206
  };
4168
4207
  const procOps = proc.node_ops;
4169
- const lookup = procOps.lookup?.bind(procOps);
4208
+ const lookup2 = procOps.lookup?.bind(procOps);
4170
4209
  const readdir = procOps.readdir?.bind(procOps);
4171
4210
  const listAll = (node) => {
4172
4211
  const names = new Set(readdir ? readdir(node) : [".", ".."]);
@@ -4189,8 +4228,8 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
4189
4228
  () => systemFile(name2, procList(), Date.now(), memory)
4190
4229
  );
4191
4230
  }
4192
- if (!lookup) throw error();
4193
- return lookup(parent, name2);
4231
+ if (!lookup2) throw error();
4232
+ return lookup2(parent, name2);
4194
4233
  },
4195
4234
  readdir: (node) => listAll(node)
4196
4235
  };
@@ -4403,6 +4442,9 @@ function kernelSys(transport) {
4403
4442
  openPts(n, noctty) {
4404
4443
  return json2(call2({ op: "pty-slave-open", n, noctty }, `pty-slave-open ${n}`));
4405
4444
  },
4445
+ openSealed() {
4446
+ return json2(call2({ op: "fd-open-sealed" }, "fd-open-sealed"));
4447
+ },
4406
4448
  ptyNumbers() {
4407
4449
  return json2(call2({ op: "pty-list" }, "pty-list"));
4408
4450
  },
@@ -5405,6 +5447,34 @@ var init_wasi_files = __esm({
5405
5447
  }
5406
5448
  });
5407
5449
 
5450
+ // src/kernel/pipe.ts
5451
+ var PIPE_CAPACITY;
5452
+ var init_pipe = __esm({
5453
+ "src/kernel/pipe.ts"() {
5454
+ "use strict";
5455
+ PIPE_CAPACITY = 64 * 1024;
5456
+ }
5457
+ });
5458
+
5459
+ // src/kernel/fd-table.ts
5460
+ function deviceAt(path) {
5461
+ return DEVICE_PATHS.get(path);
5462
+ }
5463
+ var DEVICE_PATHS;
5464
+ var init_fd_table = __esm({
5465
+ "src/kernel/fd-table.ts"() {
5466
+ "use strict";
5467
+ init_pipe();
5468
+ DEVICE_PATHS = /* @__PURE__ */ new Map([
5469
+ ["/dev/null", "null"],
5470
+ ["/dev/zero", "zero"],
5471
+ ["/dev/full", "full"],
5472
+ ["/dev/urandom", "urandom"],
5473
+ ["/dev/random", "urandom"]
5474
+ ]);
5475
+ }
5476
+ });
5477
+
5408
5478
  // src/process/wasi/wasi-fds.ts
5409
5479
  function stdioAlias(path) {
5410
5480
  const m = /^\/dev\/(?:(stdin)|(stdout)|(stderr)|fd\/(\d+))$/.exec(path);
@@ -5412,7 +5482,7 @@ function stdioAlias(path) {
5412
5482
  return m[1] ? 0 : m[2] ? 1 : m[3] ? 2 : Number(m[4]);
5413
5483
  }
5414
5484
  function deviceOf(path) {
5415
- return DEVICES2[path];
5485
+ return deviceAt(path);
5416
5486
  }
5417
5487
  function within(path, root) {
5418
5488
  return path === root || path.startsWith(root === "/" ? "/" : `${root}/`);
@@ -5480,10 +5550,11 @@ function promoteRequest(fd, f, handed) {
5480
5550
  ...f.buffer.handle !== void 0 ? { handle: f.buffer.handle } : {}
5481
5551
  };
5482
5552
  }
5483
- var SYNTHETIC_DIRS2, O_NONBLOCK2, O_WRONLY4, O_RDWR4, O_APPEND, DEVICES2, WasiFds, GEN;
5553
+ var SYNTHETIC_DIRS2, O_NONBLOCK2, O_WRONLY4, O_RDWR4, O_APPEND, SEALED_PATH2, WasiFds, GEN;
5484
5554
  var init_wasi_fds = __esm({
5485
5555
  "src/process/wasi/wasi-fds.ts"() {
5486
5556
  "use strict";
5557
+ init_fd_table();
5487
5558
  init_sync_fs_wire();
5488
5559
  init_wasi_abi();
5489
5560
  init_wasi_files();
@@ -5492,13 +5563,7 @@ var init_wasi_fds = __esm({
5492
5563
  O_WRONLY4 = 1;
5493
5564
  O_RDWR4 = 2;
5494
5565
  O_APPEND = 1024;
5495
- DEVICES2 = {
5496
- "/dev/null": "null",
5497
- "/dev/zero": "zero",
5498
- "/dev/full": "full",
5499
- "/dev/urandom": "urandom",
5500
- "/dev/random": "urandom"
5501
- };
5566
+ SEALED_PATH2 = "/dev/sealed";
5502
5567
  WasiFds = class {
5503
5568
  table = /* @__PURE__ */ new Map();
5504
5569
  buffers = /* @__PURE__ */ new Map();
@@ -5963,16 +6028,30 @@ var init_wasi_fds = __esm({
5963
6028
  const joined2 = path.startsWith("/") ? path : `${this.dir(dirfd).path}/${path}`;
5964
6029
  return joined2.split("/").includes("..") ? physical(this.fs, joined2) : normalize(joined2);
5965
6030
  }
6031
+ openKernelDevice(path, oflags, fdflags) {
6032
+ const { openSealed, openTty } = this.kernel.sys;
6033
+ const nonblock = (fdflags & FDFLAGS.NONBLOCK) !== 0;
6034
+ let fd;
6035
+ let kind;
6036
+ if (path === SEALED_PATH2 && openSealed) {
6037
+ if (oflags & OFLAGS.DIRECTORY) throw new WasiError("ENOTDIR");
6038
+ if (oflags & OFLAGS.CREAT && oflags & OFLAGS.EXCL) throw new WasiError("EEXIST");
6039
+ fd = openSealed.call(this.kernel.sys);
6040
+ kind = "sealed";
6041
+ } else if (path === "/dev/tty" || /^\/dev\/tty\d+$/.test(path)) {
6042
+ fd = openTty?.call(this.kernel.sys, path === "/dev/tty" ? void 0 : path);
6043
+ if (fd === void 0) throw new WasiError("ENXIO");
6044
+ kind = "tty";
6045
+ } else return void 0;
6046
+ this.adopt(fd, kind, nonblock);
6047
+ this.bump();
6048
+ return fd;
6049
+ }
5966
6050
  open(path, oflags, rights, fdflags) {
5967
6051
  const device2 = deviceOf(path);
5968
6052
  if (device2) return this.install({ type: "device", device: device2 });
5969
- if (path === "/dev/tty" || /^\/dev\/tty\d+$/.test(path)) {
5970
- const fd = this.kernel.sys.openTty?.(path === "/dev/tty" ? void 0 : path);
5971
- if (fd === void 0) throw new WasiError("ENXIO");
5972
- this.table.set(fd, { ...kernelEntry2(), kind: "tty" });
5973
- this.bump();
5974
- return fd;
5975
- }
6053
+ const kernelDevice = this.openKernelDevice(path, oflags, fdflags);
6054
+ if (kernelDevice !== void 0) return kernelDevice;
5976
6055
  const alias = stdioAlias(path);
5977
6056
  if (alias !== void 0) return this.reopen(alias);
5978
6057
  const exclusive = (oflags & OFLAGS.CREAT) !== 0 && (oflags & OFLAGS.EXCL) !== 0;
@@ -6413,6 +6492,7 @@ function filestatOf(path, s) {
6413
6492
  function kernelFiletype(kind) {
6414
6493
  switch (kind) {
6415
6494
  case "tty":
6495
+ case "sealed":
6416
6496
  return { filetype: FILETYPE.CHARACTER_DEVICE, seeks: false };
6417
6497
  case "device":
6418
6498
  return { filetype: FILETYPE.CHARACTER_DEVICE, seeks: true };
@@ -6453,7 +6533,7 @@ function wrap(table) {
6453
6533
  }
6454
6534
  return out;
6455
6535
  }
6456
- var WasiExit, IDS, NS_PER_MS, AT_SYMLINK_NOFOLLOW2, AT_EACCESS2, ROOT_IDS, GONE, S_IFIFO, DEFAULT_UMASK, MONOTONIC_BASE, MAX_READ, SIGPIPE_EXIT, WasiHost;
6536
+ var WasiExit, IDS, NS_PER_MS, AT_SYMLINK_NOFOLLOW2, AT_EACCESS2, ROOT_IDS, GONE, S_IFIFO, DEFAULT_UMASK, MONOTONIC_BASE, MAX_READ, SIGPIPE_EXIT, SEALED_MODE, WasiHost;
6457
6537
  var init_wasi_host = __esm({
6458
6538
  "src/process/wasi/wasi-host.ts"() {
6459
6539
  "use strict";
@@ -6483,6 +6563,7 @@ var init_wasi_host = __esm({
6483
6563
  MONOTONIC_BASE = BigInt(Math.round(performance.timeOrigin)) * NS_PER_MS;
6484
6564
  MAX_READ = 1024 * 1024;
6485
6565
  SIGPIPE_EXIT = 141;
6566
+ SEALED_MODE = 8630;
6486
6567
  WasiHost = class {
6487
6568
  mem = new WasiMemory();
6488
6569
  fds;
@@ -6568,7 +6649,9 @@ var init_wasi_host = __esm({
6568
6649
  const fdOwned = (fd) => {
6569
6650
  const e = fds.get(fd);
6570
6651
  if (e.type === "device") return ROOT_IDS;
6571
- if (e.type === "kernel" && fds.kind(fd, e) !== "file") return void 0;
6652
+ const kind = e.type === "kernel" ? fds.kind(fd, e) : "file";
6653
+ if (kind === "sealed") return ROOT_IDS;
6654
+ if (kind !== "file") return void 0;
6572
6655
  try {
6573
6656
  return this.o.fs.stat(pathOf(fd));
6574
6657
  } catch (err) {
@@ -6577,7 +6660,7 @@ var init_wasi_host = __esm({
6577
6660
  }
6578
6661
  };
6579
6662
  const pathOwned = (path, follow2) => {
6580
- if (deviceOf(path)) return ROOT_IDS;
6663
+ if (this.synthetic(path)) return ROOT_IDS;
6581
6664
  return follow2 ? this.o.fs.stat(path) : this.o.fs.lstat(path);
6582
6665
  };
6583
6666
  return wrap({
@@ -6592,11 +6675,11 @@ var init_wasi_host = __esm({
6592
6675
  this.writeFilestat(statOut, this.fdFilestat(fd));
6593
6676
  owner(fdOwned(fd), out);
6594
6677
  },
6595
- path_filestat_owner: (dirfd, lookup, p, l, statOut, out) => {
6678
+ path_filestat_owner: (dirfd, lookup2, p, l, statOut, out) => {
6596
6679
  if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
6597
6680
  const path = at(dirfd, p, l);
6598
- this.writeFilestat(statOut, this.pathFilestat(path, lookup));
6599
- owner(pathOwned(path, (lookup & LOOKUP_SYMLINK_FOLLOW) !== 0), out);
6681
+ this.writeFilestat(statOut, this.pathFilestat(path, lookup2));
6682
+ owner(pathOwned(path, (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0), out);
6600
6683
  },
6601
6684
  path_owner: (dirfd, p, l, flags, out) => {
6602
6685
  if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
@@ -6606,7 +6689,7 @@ var init_wasi_host = __esm({
6606
6689
  path_access: (dirfd, p, l, amode, flags) => {
6607
6690
  const path = at(dirfd, p, l);
6608
6691
  const nofollow = (flags & AT_SYMLINK_NOFOLLOW2) !== 0;
6609
- if (deviceOf(path)) {
6692
+ if (this.synthetic(path)) {
6610
6693
  if (this.o.fs.owners && amode & 1) throw new WasiError("EACCES");
6611
6694
  return;
6612
6695
  }
@@ -6623,12 +6706,14 @@ var init_wasi_host = __esm({
6623
6706
  },
6624
6707
  fd_mode: (fd, out) => {
6625
6708
  const e = fds.get(fd);
6626
- const pipe = e.type === "kernel" && fds.kind(fd, e) === "stream";
6627
- const mode = pipe ? S_IFIFO | 384 : modeOf(this.o.fs.stat(pathOf(fd)));
6709
+ const kind = e.type === "kernel" ? fds.kind(fd, e) : void 0;
6710
+ const mode = kind === "stream" ? S_IFIFO | 384 : kind === "sealed" ? SEALED_MODE : modeOf(this.o.fs.stat(pathOf(fd)));
6628
6711
  mem.view().setUint32(out, mode, true);
6629
6712
  },
6630
6713
  path_mode: (dirfd, p, l, flags, out) => {
6631
6714
  const path = at(dirfd, p, l);
6715
+ if (path === SEALED_PATH2 && this.o.kernel.sys.openSealed)
6716
+ return void mem.view().setUint32(out, SEALED_MODE, true);
6632
6717
  const st = flags & AT_SYMLINK_NOFOLLOW2 ? this.o.fs.lstat(path) : this.o.fs.stat(path);
6633
6718
  mem.view().setUint32(out, modeOf(st), true);
6634
6719
  }
@@ -6816,15 +6901,15 @@ var init_wasi_host = __esm({
6816
6901
  path_open: (dirfd, _lookup, p, l, oflags, rights, _inheriting, fdflags, out) => {
6817
6902
  const path = at(dirfd, p, l);
6818
6903
  if (deviceOf(path)) this.interrupted?.();
6819
- const fresh = (oflags & OFLAGS.CREAT) !== 0 && !o.fs.exists(path);
6904
+ const fresh = (oflags & OFLAGS.CREAT) !== 0 && !this.synthetic(path) && !o.fs.exists(path);
6820
6905
  mem.view().setUint32(out, fds.open(path, oflags, rights, fdflags), true);
6821
6906
  if (fresh) this.created(path, 438);
6822
6907
  },
6823
- path_filestat_get: (dirfd, lookup, p, l, out) => void this.writeFilestat(out, this.pathFilestat(at(dirfd, p, l), lookup)),
6824
- path_filestat_set_times: (dirfd, lookup, p, l, atim, mtim, flags) => {
6908
+ path_filestat_get: (dirfd, lookup2, p, l, out) => void this.writeFilestat(out, this.pathFilestat(at(dirfd, p, l), lookup2)),
6909
+ path_filestat_set_times: (dirfd, lookup2, p, l, atim, mtim, flags) => {
6825
6910
  const path = at(dirfd, p, l);
6826
6911
  fds.flushPath(path);
6827
- this.setTimes(path, atim, mtim, flags, (lookup & LOOKUP_SYMLINK_FOLLOW) !== 0);
6912
+ this.setTimes(path, atim, mtim, flags, (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0);
6828
6913
  },
6829
6914
  path_create_directory: (dirfd, p, l) => {
6830
6915
  const path = at(dirfd, p, l);
@@ -6857,10 +6942,10 @@ var init_wasi_host = __esm({
6857
6942
  mem.bytes(buf, n).set(target.subarray(0, n));
6858
6943
  mem.view().setUint32(used, n, true);
6859
6944
  },
6860
- path_link: (fd, lookup, p, l, fd2, p2, l2) => {
6945
+ path_link: (fd, lookup2, p, l, fd2, p2, l2) => {
6861
6946
  const from = at(fd, p, l);
6862
6947
  const to = at(fd2, p2, l2);
6863
- const follow2 = (lookup & LOOKUP_SYMLINK_FOLLOW) !== 0;
6948
+ const follow2 = (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0;
6864
6949
  const source = follow2 ? physicalPath(o.fs, from) : from;
6865
6950
  fds.flushPath(from);
6866
6951
  if (source !== from) fds.flushPath(source);
@@ -7125,8 +7210,11 @@ var init_wasi_host = __esm({
7125
7210
  const out = this.sized(path, s, size);
7126
7211
  return gone ? { ...out, nlink: 0n } : out;
7127
7212
  }
7128
- pathFilestat(path, lookup) {
7129
- if (deviceOf(path)) {
7213
+ synthetic(path) {
7214
+ return deviceOf(path) !== void 0 || path === SEALED_PATH2 && !!this.o.kernel.sys.openSealed;
7215
+ }
7216
+ pathFilestat(path, lookup2) {
7217
+ if (this.synthetic(path)) {
7130
7218
  return this.local({
7131
7219
  filetype: FILETYPE.CHARACTER_DEVICE,
7132
7220
  size: 0n,
@@ -7135,7 +7223,7 @@ var init_wasi_host = __esm({
7135
7223
  });
7136
7224
  }
7137
7225
  this.fds.flushPath(path);
7138
- const follow2 = (lookup & LOOKUP_SYMLINK_FOLLOW) !== 0;
7226
+ const follow2 = (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0;
7139
7227
  return filestatOf(path, follow2 ? this.o.fs.stat(path) : this.o.fs.lstat(path));
7140
7228
  }
7141
7229
  setTimes(path, atim, mtim, flags, follow2 = true) {
@@ -7333,12 +7421,12 @@ var init_wasix_process = __esm({
7333
7421
  fds.promoteFiles();
7334
7422
  const map = fds.inheritable();
7335
7423
  const nulls = /* @__PURE__ */ new Set();
7336
- const opened = [];
7424
+ const opened2 = [];
7337
7425
  let cwd = this.host.cwd;
7338
7426
  try {
7339
- for (const op of ops) cwd = this.applyFdOp(op, { map, nulls, opened }, cwd);
7427
+ for (const op of ops) cwd = this.applyFdOp(op, { map, nulls, opened: opened2 }, cwd);
7340
7428
  } catch (e) {
7341
- for (const kfd of opened) this.host.o.kernel.sys.close(kfd);
7429
+ for (const kfd of opened2) this.host.o.kernel.sys.close(kfd);
7342
7430
  throw e;
7343
7431
  }
7344
7432
  const stdio = [0, 1, 2].map((fd) => {
@@ -7349,10 +7437,10 @@ var init_wasix_process = __esm({
7349
7437
  ...[...map].filter(([fd]) => fd > 2).map(([fd, kernel]) => ({ fd, kernel })),
7350
7438
  ...[...nulls].filter((fd) => fd > 2).map((fd) => ({ fd, device: "null" }))
7351
7439
  ];
7352
- return { stdio, inherit, cwd, opened };
7440
+ return { stdio, inherit, cwd, opened: opened2 };
7353
7441
  }
7354
7442
  applyFdOp(op, slots3, cwd) {
7355
- const { map, nulls, opened } = slots3;
7443
+ const { map, nulls, opened: opened2 } = slots3;
7356
7444
  const { fds } = this.host;
7357
7445
  const point = (fd, kfd) => {
7358
7446
  if (kfd === void 0) {
@@ -7375,7 +7463,7 @@ var init_wasix_process = __esm({
7375
7463
  point(op.fd, void 0);
7376
7464
  } else if (op.cmd === "open") {
7377
7465
  const kfd = this.openFor(op, cwd);
7378
- opened.push(kfd);
7466
+ opened2.push(kfd);
7379
7467
  point(op.fd, kfd);
7380
7468
  } else if (op.cmd === "chdir") return this.physicalFrom(cwd, op.path);
7381
7469
  else return physicalPath(this.host.o.fs, fds.dir(op.fd).path);
@@ -7397,7 +7485,7 @@ var init_wasix_process = __esm({
7397
7485
  });
7398
7486
  }
7399
7487
  spawn(req, exec = false) {
7400
- const { stdio, inherit, cwd, opened } = this.childFds(req.ops ?? []);
7488
+ const { stdio, inherit, cwd, opened: opened2 } = this.childFds(req.ops ?? []);
7401
7489
  try {
7402
7490
  const spawn = {
7403
7491
  op: "proc-spawn",
@@ -7412,7 +7500,7 @@ var init_wasix_process = __esm({
7412
7500
  };
7413
7501
  return restarted2(() => this.call(spawn));
7414
7502
  } finally {
7415
- for (const kfd of opened) this.host.o.kernel.sys.close(kfd);
7503
+ for (const kfd of opened2) this.host.o.kernel.sys.close(kfd);
7416
7504
  this.host.o.fs.invalidate?.();
7417
7505
  }
7418
7506
  }
@@ -9757,8 +9845,8 @@ var init_wasix_host = __esm({
9757
9845
  mem.view().setUint16(out, host.fds.cloexec.has(fd) ? FDFLAGSEXT_CLOEXEC : 0, true);
9758
9846
  },
9759
9847
  fd_fdflags_set: (fd, flags) => void host.fds.setCloexec(fd, (flags & FDFLAGSEXT_CLOEXEC) !== 0),
9760
- path_open2: (dirfd, lookup, p, l, oflags, rights, inheriting, fdflags, fdflagsext, out) => {
9761
- const r = preview1.path_open(dirfd, lookup, p, l, oflags, rights, inheriting, fdflags, out);
9848
+ path_open2: (dirfd, lookup2, p, l, oflags, rights, inheriting, fdflags, fdflagsext, out) => {
9849
+ const r = preview1.path_open(dirfd, lookup2, p, l, oflags, rights, inheriting, fdflags, out);
9762
9850
  if (r === E.SUCCESS && fdflagsext & FDFLAGSEXT_CLOEXEC)
9763
9851
  host.fds.setCloexec(mem.view().getUint32(out, true), true);
9764
9852
  return r;
@@ -10731,6 +10819,11 @@ function untilAborted(work, signal) {
10731
10819
  work.then(done, done);
10732
10820
  });
10733
10821
  }
10822
+ function caughtOf(handlers) {
10823
+ let caught = 0;
10824
+ for (const sig of handlers.keys()) caught |= sigbit(sig);
10825
+ return caught;
10826
+ }
10734
10827
  var JsCallError, JsKernel;
10735
10828
  var init_js_kernel = __esm({
10736
10829
  "src/process/js/js-kernel.ts"() {
@@ -10758,6 +10851,7 @@ var init_js_kernel = __esm({
10758
10851
  reported = { caught: 0, ignored: 0 };
10759
10852
  watching = false;
10760
10853
  faulted = false;
10854
+ syncLane;
10761
10855
  constructor(o) {
10762
10856
  this.header = new Int32Array(o.sab, 0, SAB_HEADER_I32);
10763
10857
  this.transport = o.transport;
@@ -10860,16 +10954,41 @@ var init_js_kernel = __esm({
10860
10954
  if (sig === SIG.KILL || sig === SIG.STOP) {
10861
10955
  return Promise.reject(new JsCallError("EINVAL", "signal"));
10862
10956
  }
10957
+ if (this.syncLane) {
10958
+ try {
10959
+ this.changeNow(this.syncLane, sig, handler);
10960
+ return Promise.resolve();
10961
+ } catch (err) {
10962
+ return Promise.reject(err);
10963
+ }
10964
+ }
10863
10965
  const run = this.changing.then(() => this.change(sig, handler));
10864
10966
  this.changing = run.catch(() => void 0);
10865
10967
  return run;
10866
10968
  }
10867
- async change(sig, handler) {
10969
+ changeNow(lane, sig, handler) {
10970
+ const { handlers, ignored } = this.disposed(sig, handler);
10971
+ const defaults = handler === "default" ? sigbit(sig) : 0;
10972
+ const caught = caughtOf(handlers);
10973
+ if (caught !== this.reported.caught || ignored !== this.reported.ignored || defaults !== 0) {
10974
+ const r = lane({ op: "sig-mask", caught, ignored, ...defaults ? { defaults } : {} });
10975
+ if (!r.ok) throw new JsCallError(r.errno, "sig-mask");
10976
+ this.reported = { caught, ignored };
10977
+ }
10978
+ this.handlers = handlers;
10979
+ this.ignored = ignored;
10980
+ if (handlers.size > 0) void this.watch();
10981
+ }
10982
+ disposed(sig, handler) {
10868
10983
  const handlers = new Map(this.handlers);
10869
10984
  handlers.delete(sig);
10870
10985
  let ignored = this.ignored & ~sigbit(sig);
10871
10986
  if (handler === "ignore") ignored |= sigbit(sig);
10872
10987
  else if (handler !== "default") handlers.set(sig, handler);
10988
+ return { handlers, ignored };
10989
+ }
10990
+ async change(sig, handler) {
10991
+ const { handlers, ignored } = this.disposed(sig, handler);
10873
10992
  await this.report(handlers, ignored, handler === "default" ? sigbit(sig) : 0);
10874
10993
  this.handlers = handlers;
10875
10994
  this.ignored = ignored;
@@ -10879,8 +10998,7 @@ var init_js_kernel = __esm({
10879
10998
  this.call({ op: "proc-kill", pid: this.pid, sig }).catch(this.onError);
10880
10999
  }
10881
11000
  async report(handlers, ignored, defaults) {
10882
- let caught = 0;
10883
- for (const sig of handlers.keys()) caught |= sigbit(sig);
11001
+ const caught = caughtOf(handlers);
10884
11002
  const same = caught === this.reported.caught && ignored === this.reported.ignored;
10885
11003
  if (same && defaults === 0) return;
10886
11004
  this.reported = { caught, ignored };
@@ -11100,6 +11218,344 @@ var init_js_io = __esm({
11100
11218
  }
11101
11219
  });
11102
11220
 
11221
+ // src/process/js/js-dev.ts
11222
+ function inDev(abs) {
11223
+ return abs.startsWith("/dev") && (abs.length === 4 || abs[4] === "/");
11224
+ }
11225
+ function missing(path) {
11226
+ throw new JsCallError("ENOENT", path);
11227
+ }
11228
+ function nodeStat(mode, size = 0, owner) {
11229
+ return {
11230
+ isFile: false,
11231
+ isDirectory: (mode & S_IFMT2) === DIR,
11232
+ isSymbolicLink: (mode & S_IFMT2) === LINK,
11233
+ size,
11234
+ mode,
11235
+ mtimeMs: BORN,
11236
+ atimeMs: BORN,
11237
+ ctimeMs: BORN,
11238
+ nlink: 1,
11239
+ uid: owner?.uid ?? 0,
11240
+ gid: owner?.gid ?? 0
11241
+ };
11242
+ }
11243
+ function* lookup(abs) {
11244
+ if (abs === "/dev") return { kind: "dir", mode: DIR | 493 };
11245
+ const name2 = abs.slice("/dev/".length);
11246
+ if (DEVICES2.includes(name2)) return { kind: "device" };
11247
+ if (name2 === "tty") return { kind: "tty" };
11248
+ const std = STDIO3.indexOf(name2);
11249
+ if (std >= 0) return { kind: "link", target: `${SELF_FD}/${std}`, fd: std };
11250
+ if (name2 === "fd") return { kind: "link", target: SELF_FD };
11251
+ const fd = /^fd\/(\d+)$/.exec(name2)?.[1];
11252
+ if (fd !== void 0) return { kind: "fd", fd: Number(fd) };
11253
+ if (/^tty\d+$/.test(name2)) {
11254
+ const names = yield { op: "fd-tty-names" };
11255
+ if (names.includes(abs)) return { kind: "terminal", name: abs };
11256
+ }
11257
+ const pts = /^pts\/(\d+)$/.exec(name2)?.[1];
11258
+ if (pts !== void 0) {
11259
+ const open = yield { op: "pty-list" };
11260
+ if (open.includes(Number(pts))) return { kind: "terminal", name: abs, pts: Number(pts) };
11261
+ }
11262
+ return missing(abs);
11263
+ }
11264
+ function* fdInfo(fd, path) {
11265
+ try {
11266
+ return yield { op: "fd-info", fd };
11267
+ } catch (err) {
11268
+ if (err instanceof JsCallError && err.code === "EBADF") return missing(path);
11269
+ throw err;
11270
+ }
11271
+ }
11272
+ function* pathStat(path) {
11273
+ const s = parseSyncFsStat(yield { op: "stat", path });
11274
+ if (!s) throw new JsCallError("EIO", "stat");
11275
+ return s;
11276
+ }
11277
+ function* terminalStat(name2) {
11278
+ const owner = yield { op: "fd-tty-owner", name: name2 };
11279
+ if (owner) return nodeStat(CHAR | (owner.mode ?? 400), 0, owner);
11280
+ return nodeStat(CHAR | (name2.startsWith("/dev/pts/") ? 400 : 438));
11281
+ }
11282
+ function* fdStat(fd, path) {
11283
+ const info = yield* fdInfo(fd, path);
11284
+ if (info.meta && "dir" in info.meta) return yield* pathStat(info.meta.dir);
11285
+ if (info.kind === "file") {
11286
+ const file = yield { op: "fd-vfs-stat", fd };
11287
+ if (file.orphan) return { ...nodeStat(33152, file.size), isFile: true };
11288
+ return yield* pathStat(file.path);
11289
+ }
11290
+ if (info.terminal) return yield* terminalStat(info.terminal);
11291
+ if (info.kind === "device" || info.kind === "tty") return nodeStat(CHAR | 438);
11292
+ if (info.kind === "socket") return nodeStat(49663);
11293
+ return nodeStat(4480);
11294
+ }
11295
+ function* fdTarget(fd, path) {
11296
+ const info = yield* fdInfo(fd, path);
11297
+ if (info.meta && "dir" in info.meta) return info.meta.dir;
11298
+ if (info.kind === "file") return (yield { op: "fd-vfs-stat", fd }).path;
11299
+ if (info.terminal) return info.terminal;
11300
+ if (info.meta && "device" in info.meta) return `/dev/${info.meta.device}`;
11301
+ return `${info.kind === "socket" ? "socket" : "pipe"}:[${fd}]`;
11302
+ }
11303
+ function linkStat(target) {
11304
+ return nodeStat(LINK | 511, target.length);
11305
+ }
11306
+ function* devStat(abs, follow2) {
11307
+ const node = yield* lookup(abs);
11308
+ switch (node.kind) {
11309
+ case "dir":
11310
+ return nodeStat(node.mode);
11311
+ case "device":
11312
+ case "tty":
11313
+ return nodeStat(CHAR | 438);
11314
+ case "terminal":
11315
+ return yield* terminalStat(node.name);
11316
+ case "link":
11317
+ if (!follow2) return linkStat(node.target);
11318
+ return node.fd === void 0 ? nodeStat(DIR | 365) : yield* fdStat(node.fd, abs);
11319
+ case "fd":
11320
+ return follow2 ? yield* fdStat(node.fd, abs) : linkStat(yield* fdTarget(node.fd, abs));
11321
+ }
11322
+ }
11323
+ function* devExists(abs) {
11324
+ try {
11325
+ yield* devStat(abs, true);
11326
+ return true;
11327
+ } catch (err) {
11328
+ if (err instanceof JsCallError) return false;
11329
+ throw err;
11330
+ }
11331
+ }
11332
+ function* devReadlink(abs) {
11333
+ const node = yield* lookup(abs);
11334
+ if (node.kind === "link") return node.target;
11335
+ if (node.kind === "fd") return yield* fdTarget(node.fd, abs);
11336
+ throw new JsCallError("EINVAL", abs);
11337
+ }
11338
+ function* devReaddir(abs) {
11339
+ if (abs === "/dev/fd") {
11340
+ const fds = yield { op: "fd-list" };
11341
+ return fds.map(({ fd }) => String(fd));
11342
+ }
11343
+ const node = yield* lookup(abs);
11344
+ if (node.kind !== "dir") throw new JsCallError("ENOTDIR", abs);
11345
+ const names = yield { op: "fd-tty-names" };
11346
+ const ttys = names.filter((n) => /^\/dev\/tty\d+$/.test(n)).map((n) => n.slice(5));
11347
+ return [...DEVICES2, "tty", "fd", ...STDIO3, ...ttys].sort();
11348
+ }
11349
+ function* aliasOf(fd, abs, o) {
11350
+ const info = yield* fdInfo(fd, abs);
11351
+ const file = info.kind === "file";
11352
+ if (file) {
11353
+ const at = yield { op: "fd-vfs-stat", fd };
11354
+ if (!at.orphan)
11355
+ return { fd: yield openRequest(at.path, { ...o, create: false }), file };
11356
+ }
11357
+ const copy2 = yield { op: "fd-dup", fd, min: 3 };
11358
+ if (file && o.truncate) {
11359
+ try {
11360
+ yield { op: "fd-resize", fd: copy2, size: 0 };
11361
+ } catch (err) {
11362
+ yield { op: "fd-close", fd: copy2 };
11363
+ throw err;
11364
+ }
11365
+ }
11366
+ return { fd: copy2, file };
11367
+ }
11368
+ function* opened(abs, o) {
11369
+ const node = yield* lookup(abs);
11370
+ if (isExclusive(o)) throw new JsCallError("EEXIST", abs);
11371
+ switch (node.kind) {
11372
+ case "device":
11373
+ return { fd: yield openRequest(abs, { ...o, create: false }), file: false };
11374
+ case "tty":
11375
+ return { fd: yield { op: "fd-open-tty" }, file: false };
11376
+ case "terminal": {
11377
+ const req = node.pts === void 0 ? { op: "fd-open-tty", name: node.name } : { op: "pty-slave-open", n: node.pts, noctty: true };
11378
+ return { fd: yield req, file: false };
11379
+ }
11380
+ case "fd":
11381
+ return yield* aliasOf(node.fd, abs, o);
11382
+ case "link":
11383
+ if (node.fd !== void 0) return yield* aliasOf(node.fd, abs, o);
11384
+ throw new JsCallError("EISDIR", abs);
11385
+ case "dir":
11386
+ throw new JsCallError("EISDIR", abs);
11387
+ }
11388
+ }
11389
+ function* devOpen(abs, o) {
11390
+ const write2 = o.write === true || o.append === true || o.truncate === true;
11391
+ return { ...yield* opened(abs, o), read: o.read === true || !write2, write: write2 };
11392
+ }
11393
+ async function devAsync(kernel, step) {
11394
+ let next2 = step.next();
11395
+ while (!next2.done) {
11396
+ let answer2;
11397
+ try {
11398
+ answer2 = { value: await kernel.json(next2.value) };
11399
+ } catch (error) {
11400
+ answer2 = { error };
11401
+ }
11402
+ next2 = "value" in answer2 ? step.next(answer2.value) : step.throw(answer2.error);
11403
+ }
11404
+ return next2.value;
11405
+ }
11406
+ function devSync(kernel, step) {
11407
+ let next2 = step.next();
11408
+ while (!next2.done) {
11409
+ let answer2;
11410
+ try {
11411
+ answer2 = { value: kernel.json(next2.value) };
11412
+ } catch (error) {
11413
+ answer2 = { error };
11414
+ }
11415
+ next2 = "value" in answer2 ? step.next(answer2.value) : step.throw(answer2.error);
11416
+ }
11417
+ return next2.value;
11418
+ }
11419
+ function tooLarge(got) {
11420
+ if (got > DEV_READ_MAX) throw new JsCallError("EFBIG", "readFile");
11421
+ }
11422
+ function liveness(path) {
11423
+ let open = true;
11424
+ return {
11425
+ live: () => {
11426
+ if (!open) throw new JsCallError("EBADF", path);
11427
+ },
11428
+ end: () => {
11429
+ open = false;
11430
+ }
11431
+ };
11432
+ }
11433
+ function allowed(may, what) {
11434
+ if (!may) throw new JsCallError("EBADF", what);
11435
+ }
11436
+ function streamFile(fd, path, io, access) {
11437
+ const { live, end } = liveness(path);
11438
+ const file = {
11439
+ fd,
11440
+ path,
11441
+ async size() {
11442
+ live();
11443
+ return 0;
11444
+ },
11445
+ async read(position, length) {
11446
+ index2(position, "read");
11447
+ index2(length, "read");
11448
+ live();
11449
+ allowed(access.read, "read");
11450
+ return length === 0 ? new Uint8Array(0) : io.read(fd, Math.min(length, MAX_IO));
11451
+ },
11452
+ async write(position, data) {
11453
+ index2(position, "write");
11454
+ live();
11455
+ allowed(access.write, "write");
11456
+ await io.write(fd, data);
11457
+ return data.length;
11458
+ },
11459
+ async truncate(size) {
11460
+ live();
11461
+ index2(size, "truncate");
11462
+ throw new JsCallError("EINVAL", "truncate");
11463
+ },
11464
+ sync: async () => live(),
11465
+ async close() {
11466
+ live();
11467
+ end();
11468
+ await io.close(fd);
11469
+ }
11470
+ };
11471
+ return { file, invalidate: end };
11472
+ }
11473
+ function streamSyncFile(fd, path, io, access) {
11474
+ const { live, end } = liveness(path);
11475
+ const file = {
11476
+ fd,
11477
+ path,
11478
+ size() {
11479
+ live();
11480
+ return 0;
11481
+ },
11482
+ read(position, length) {
11483
+ index2(position, "read");
11484
+ index2(length, "read");
11485
+ live();
11486
+ allowed(access.read, "read");
11487
+ return length === 0 ? new Uint8Array(0) : io.read(fd, Math.min(length, MAX_IO));
11488
+ },
11489
+ write(position, data) {
11490
+ index2(position, "write");
11491
+ live();
11492
+ allowed(access.write, "write");
11493
+ io.write(fd, data);
11494
+ return data.length;
11495
+ },
11496
+ truncate(size) {
11497
+ live();
11498
+ index2(size, "truncate");
11499
+ throw new JsCallError("EINVAL", "truncate");
11500
+ },
11501
+ sync: () => live(),
11502
+ close() {
11503
+ live();
11504
+ end();
11505
+ io.close(fd);
11506
+ }
11507
+ };
11508
+ return { file, invalidate: end };
11509
+ }
11510
+ async function readWhole(file) {
11511
+ try {
11512
+ const parts = [];
11513
+ let got = 0;
11514
+ for (; ; ) {
11515
+ const chunk = await file.read(got, MAX_IO);
11516
+ if (chunk.length === 0) return joined(parts, got);
11517
+ got += chunk.length;
11518
+ tooLarge(got);
11519
+ parts.push(chunk);
11520
+ }
11521
+ } finally {
11522
+ await file.close();
11523
+ }
11524
+ }
11525
+ function readWholeSync(file) {
11526
+ try {
11527
+ const parts = [];
11528
+ let got = 0;
11529
+ for (; ; ) {
11530
+ const chunk = file.read(got, MAX_IO);
11531
+ if (chunk.length === 0) return joined(parts, got);
11532
+ got += chunk.length;
11533
+ tooLarge(got);
11534
+ parts.push(chunk);
11535
+ }
11536
+ } finally {
11537
+ file.close();
11538
+ }
11539
+ }
11540
+ var DEV_READ_MAX, DEVICES2, STDIO3, SELF_FD, S_IFMT2, DIR, LINK, CHAR, BORN;
11541
+ var init_js_dev = __esm({
11542
+ "src/process/js/js-dev.ts"() {
11543
+ "use strict";
11544
+ init_sync_fs_wire();
11545
+ init_js_io();
11546
+ init_js_kernel();
11547
+ DEV_READ_MAX = 64 * 1024 * 1024;
11548
+ DEVICES2 = ["null", "zero", "full", "random", "urandom"];
11549
+ STDIO3 = ["stdin", "stdout", "stderr"];
11550
+ SELF_FD = "/proc/self/fd";
11551
+ S_IFMT2 = 61440;
11552
+ DIR = 16384;
11553
+ LINK = 40960;
11554
+ CHAR = 8192;
11555
+ BORN = Date.now();
11556
+ }
11557
+ });
11558
+
11103
11559
  // src/process/js/js-exit.ts
11104
11560
  function json(r) {
11105
11561
  return r.ok && r.kind === "json" ? r.json : void 0;
@@ -11112,10 +11568,10 @@ function restoreMode(lane, { terminal, fd, termios }) {
11112
11568
  lane({ op: "tty-set", fd: at, termios });
11113
11569
  return;
11114
11570
  }
11115
- const opened = json(lane({ op: "fd-open-tty", name: terminal }));
11116
- if (typeof opened !== "number") return;
11117
- lane({ op: "tty-set", fd: opened, termios });
11118
- lane({ op: "fd-close", fd: opened });
11571
+ const opened2 = json(lane({ op: "fd-open-tty", name: terminal }));
11572
+ if (typeof opened2 !== "number") return;
11573
+ lane({ op: "tty-set", fd: opened2, termios });
11574
+ lane({ op: "fd-close", fd: opened2 });
11119
11575
  }
11120
11576
  function writeOut(lane, fd, data) {
11121
11577
  let at = 0;
@@ -11564,7 +12020,7 @@ function netOps(kernel, io) {
11564
12020
  const r = await kernel.blocking({ op: "sock-resolve", name: host, family: 4 }, signal);
11565
12021
  return (r.ok && r.kind === "json" ? r.json : [])[0];
11566
12022
  };
11567
- const opened = async (use) => {
12023
+ const opened2 = async (use) => {
11568
12024
  const fd = await kernel.json({ op: "sock-open", domain: "inet" });
11569
12025
  try {
11570
12026
  return await use(fd);
@@ -11606,7 +12062,7 @@ function netOps(kernel, io) {
11606
12062
  };
11607
12063
  };
11608
12064
  return {
11609
- listen: (options = {}) => opened(async (fd) => {
12065
+ listen: (options = {}) => opened2(async (fd) => {
11610
12066
  const addr = {
11611
12067
  family: "inet",
11612
12068
  host: options.host ?? "127.0.0.1",
@@ -11626,7 +12082,7 @@ function netOps(kernel, io) {
11626
12082
  host: await resolve(host, signal),
11627
12083
  port: port(options.port)
11628
12084
  };
11629
- return opened(async (fd) => {
12085
+ return opened2(async (fd) => {
11630
12086
  const r = await kernel.raw({ op: "sock-connect", fd, addr, nonblock: true });
11631
12087
  if (!r.ok && r.errno !== "EINPROGRESS") throw new JsCallError(r.errno, "connect");
11632
12088
  await kernel.blocking({ op: "fd-select", read: [], write: [fd], timeoutMs: -1 }, signal);
@@ -11660,7 +12116,7 @@ var init_js_net = __esm({
11660
12116
  // src/process/js/js-run.ts
11661
12117
  function stdioOf(how) {
11662
12118
  if (how === void 0) return "pipe";
11663
- if (!STDIO3.has(how)) throw new JsCallError("EINVAL", "run");
12119
+ if (!STDIO4.has(how)) throw new JsCallError("EINVAL", "run");
11664
12120
  return how;
11665
12121
  }
11666
12122
  function limit(value2) {
@@ -11708,13 +12164,13 @@ function runSync(kernel, d, o) {
11708
12164
  });
11709
12165
  return decodeRun(bytes, stdout, stderr);
11710
12166
  }
11711
- var encoder2, STDIO3;
12167
+ var encoder2, STDIO4;
11712
12168
  var init_js_run = __esm({
11713
12169
  "src/process/js/js-run.ts"() {
11714
12170
  "use strict";
11715
12171
  init_js_kernel();
11716
12172
  encoder2 = new TextEncoder();
11717
- STDIO3 = /* @__PURE__ */ new Set(["pipe", "ignore", "inherit"]);
12173
+ STDIO4 = /* @__PURE__ */ new Set(["pipe", "ignore", "inherit"]);
11718
12174
  }
11719
12175
  });
11720
12176
 
@@ -11757,13 +12213,30 @@ function syncOps(kernel, shared) {
11757
12213
  };
11758
12214
  const statOf = (op, path) => {
11759
12215
  const abs = resolve(path);
12216
+ if (inDev(abs)) return devSync(kernel, devStat(abs, op === "stat"));
11760
12217
  kernel.call({ op: "fd-path-flush", path: abs });
11761
12218
  const s = parseSyncFsStat(kernel.json({ op, path: abs }));
11762
12219
  if (!s) throw new JsCallError("EIO", op);
11763
12220
  return s;
11764
12221
  };
12222
+ const openDev2 = (abs, options) => {
12223
+ const { fd, file, ...access } = devSync(kernel, devOpen(abs, options));
12224
+ const forget = () => {
12225
+ infos.delete(fd);
12226
+ handles.delete(fd);
12227
+ };
12228
+ if (file) infos.set(fd, { kind: "file" });
12229
+ const close = (n) => {
12230
+ forget();
12231
+ kernel.call({ op: "fd-close", fd: n });
12232
+ };
12233
+ const handle = file ? syncFile(kernel, fd, abs, options.append === true, forget) : streamSyncFile(fd, abs, { read: (n, max) => read2(n, max), write: write2, close }, access);
12234
+ handles.set(fd, handle.invalidate);
12235
+ return handle.file;
12236
+ };
11765
12237
  const open = (path, options = {}) => {
11766
12238
  const abs = resolve(path);
12239
+ if (inDev(abs)) return openDev2(abs, options);
11767
12240
  let existing;
11768
12241
  try {
11769
12242
  existing = statOf(isExclusive(options) ? "lstat" : "stat", abs);
@@ -11867,17 +12340,30 @@ function syncPathOps(kernel, resolve, statOf, open) {
11867
12340
  return {
11868
12341
  stat: (path) => statOf("stat", path),
11869
12342
  lstat: (path) => statOf("lstat", path),
11870
- exists: (path) => kernel.json({ op: "exists", path: resolve(path) }) === true,
11871
- readdir: (path) => kernel.json({ op: "readdir", path: resolve(path) }),
12343
+ exists(path) {
12344
+ const abs = resolve(path);
12345
+ if (inDev(abs)) return devSync(kernel, devExists(abs));
12346
+ return kernel.json({ op: "exists", path: abs }) === true;
12347
+ },
12348
+ readdir(path) {
12349
+ const abs = resolve(path);
12350
+ if (inDev(abs)) return devSync(kernel, devReaddir(abs));
12351
+ return kernel.json({ op: "readdir", path: abs });
12352
+ },
11872
12353
  mkdir: (path) => void kernel.call({ op: "mkdir", path: resolve(path) }),
11873
12354
  rm: (path) => void kernel.call({ op: "rm", path: resolve(path) }),
11874
12355
  unlink: (path) => void kernel.call({ op: "unlink", path: resolve(path) }),
11875
12356
  rename: (from, to) => void kernel.call({ op: "rename", path: resolve(from), arg2: resolve(to) }),
11876
12357
  link: (from, to) => void kernel.call({ op: "link", path: resolve(from), arg2: resolve(to) }),
11877
12358
  symlink: (target, path) => void kernel.call({ op: "symlink", path: resolve(path), arg2: target }),
11878
- readlink: (path) => String(kernel.json({ op: "readlink", path: resolve(path) })),
12359
+ readlink(path) {
12360
+ const abs = resolve(path);
12361
+ if (inDev(abs)) return devSync(kernel, devReadlink(abs));
12362
+ return String(kernel.json({ op: "readlink", path: abs }));
12363
+ },
11879
12364
  readFile(path) {
11880
12365
  const abs = resolve(path);
12366
+ if (inDev(abs)) return readWholeSync(open(abs));
11881
12367
  kernel.call({ op: "fd-path-flush", path: abs });
11882
12368
  return kernel.bytes({ op: "read", path: abs });
11883
12369
  },
@@ -11898,6 +12384,7 @@ var init_js_sync = __esm({
11898
12384
  init_signals();
11899
12385
  init_sync_fs_wire();
11900
12386
  init_sync_sab_bridge();
12387
+ init_js_dev();
11901
12388
  init_js_io();
11902
12389
  init_js_kernel();
11903
12390
  encoder3 = new TextEncoder();
@@ -12298,6 +12785,7 @@ function createContext(o) {
12298
12785
  const writable2 = (fd) => new WritableStream({ write: (chunk) => write2(fd, chunk) });
12299
12786
  const statOf = async (op, path) => {
12300
12787
  const abs = resolve(path);
12788
+ if (inDev(abs)) return devAsync(kernel, devStat(abs, op === "stat"));
12301
12789
  await kernel.call({ op: "fd-path-flush", path: abs });
12302
12790
  const s = parseSyncFsStat(await kernel.json({ op, path: abs }));
12303
12791
  if (!s) throw new JsCallError("EIO", op);
@@ -12305,6 +12793,7 @@ function createContext(o) {
12305
12793
  };
12306
12794
  const open = async (path, options = {}) => {
12307
12795
  const abs = resolve(path);
12796
+ if (inDev(abs)) return openDev(kernel, abs, options, { infos, handles, read: read2, write: writeAll });
12308
12797
  const existing = await statOf(isExclusive(options) ? "lstat" : "stat", abs).catch(absent);
12309
12798
  checkOpen(abs, options, existing);
12310
12799
  const fd = await kernel.json(openRequest(abs, options));
@@ -12324,6 +12813,7 @@ function createContext(o) {
12324
12813
  };
12325
12814
  const fs = pathOps(kernel, resolve, statOf, open);
12326
12815
  const lane = o.lane ?? laneOf(void 0);
12816
+ if (o.lane) kernel.syncLane = o.lane;
12327
12817
  const syncKernel = new JsSyncKernel(lane, kernel, unwind);
12328
12818
  const terminal = ttyOps(kernel);
12329
12819
  const sync = {
@@ -12404,6 +12894,26 @@ function createContext(o) {
12404
12894
  };
12405
12895
  return { ctx, drain: drain2 };
12406
12896
  }
12897
+ async function openDev(kernel, abs, options, state) {
12898
+ const { fd, file, ...access } = await devAsync(kernel, devOpen(abs, options));
12899
+ const forget = () => {
12900
+ state.infos.delete(fd);
12901
+ state.handles.delete(fd);
12902
+ };
12903
+ if (file) state.infos.set(fd, { kind: "file" });
12904
+ const close = async (n) => {
12905
+ forget();
12906
+ await kernel.call({ op: "fd-close", fd: n });
12907
+ };
12908
+ const handle = file ? fileHandle(kernel, fd, abs, options.append === true, forget) : streamFile(
12909
+ fd,
12910
+ abs,
12911
+ { read: (n, max) => state.read(n, max), write: state.write, close },
12912
+ access
12913
+ );
12914
+ state.handles.set(fd, handle.invalidate);
12915
+ return handle.file;
12916
+ }
12407
12917
  function fileHandle(kernel, fd, path, append, forget) {
12408
12918
  let open = true;
12409
12919
  const live = () => {
@@ -12496,17 +13006,30 @@ function pathOps(kernel, resolve, statOf, open) {
12496
13006
  return {
12497
13007
  stat: (path) => statOf("stat", path),
12498
13008
  lstat: (path) => statOf("lstat", path),
12499
- exists: async (path) => await kernel.json({ op: "exists", path: resolve(path) }) === true,
12500
- readdir: async (path) => await kernel.json({ op: "readdir", path: resolve(path) }),
13009
+ async exists(path) {
13010
+ const abs = resolve(path);
13011
+ if (inDev(abs)) return devAsync(kernel, devExists(abs));
13012
+ return await kernel.json({ op: "exists", path: abs }) === true;
13013
+ },
13014
+ async readdir(path) {
13015
+ const abs = resolve(path);
13016
+ if (inDev(abs)) return devAsync(kernel, devReaddir(abs));
13017
+ return await kernel.json({ op: "readdir", path: abs });
13018
+ },
12501
13019
  mkdir: async (path) => void await kernel.call({ op: "mkdir", path: resolve(path) }),
12502
13020
  rm: async (path) => void await kernel.call({ op: "rm", path: resolve(path) }),
12503
13021
  unlink: async (path) => void await kernel.call({ op: "unlink", path: resolve(path) }),
12504
13022
  rename: async (from, to) => void await kernel.call({ op: "rename", path: resolve(from), arg2: resolve(to) }),
12505
13023
  link: async (from, to) => void await kernel.call({ op: "link", path: resolve(from), arg2: resolve(to) }),
12506
13024
  symlink: async (target, path) => void await kernel.call({ op: "symlink", path: resolve(path), arg2: target }),
12507
- readlink: async (path) => String(await kernel.json({ op: "readlink", path: resolve(path) })),
13025
+ async readlink(path) {
13026
+ const abs = resolve(path);
13027
+ if (inDev(abs)) return devAsync(kernel, devReadlink(abs));
13028
+ return String(await kernel.json({ op: "readlink", path: abs }));
13029
+ },
12508
13030
  async readFile(path) {
12509
13031
  const abs = resolve(path);
13032
+ if (inDev(abs)) return readWhole(await open(abs));
12510
13033
  await kernel.call({ op: "fd-path-flush", path: abs });
12511
13034
  return kernel.bytes({ op: "read", path: abs });
12512
13035
  },
@@ -12527,6 +13050,7 @@ var init_js_context = __esm({
12527
13050
  init_signals();
12528
13051
  init_sync_fs_wire();
12529
13052
  init_js_children();
13053
+ init_js_dev();
12530
13054
  init_js_exit();
12531
13055
  init_js_fetch();
12532
13056
  init_js_io();