@ai-ecoverse/slicc-kernel 1.88.1 → 1.89.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.
@@ -1070,6 +1070,7 @@ function createSyncFsSabBridge(transport, opts = {}) {
1070
1070
  changing({ op: follow2 ? "chown" : "lchown", path, ...ids }, path);
1071
1071
  },
1072
1072
  ...opts.owners ? { owners: true } : {},
1073
+ ...opts.links ? { links: true } : {},
1073
1074
  access: (path, mode, kind = "access", nofollow) => {
1074
1075
  run({ op: "access", path, mode, arg2: kind, ...nofollow ? { nofollow } : {} }, path);
1075
1076
  },
@@ -1540,7 +1541,12 @@ function createNodeOps(h) {
1540
1541
  },
1541
1542
  readlink(node) {
1542
1543
  if (!Fs.isLink(node.mode)) throw new Fs.ErrnoError(wasiErrno("EINVAL"));
1543
- return call2(() => bridgeOf(node).readlink(liveNodePath(node)));
1544
+ const bridge = bridgeOf(node);
1545
+ const path = liveNodePath(node);
1546
+ if (bridge.links && Fs.sliccReading !== node) {
1547
+ call2(() => bridge.access?.(path, 0, "follow", true));
1548
+ }
1549
+ return call2(() => bridge.readlink(path));
1544
1550
  }
1545
1551
  };
1546
1552
  }
@@ -1936,6 +1942,19 @@ function useLiveChown(Fs) {
1936
1942
  Fs.chown(target, uid, gid);
1937
1943
  };
1938
1944
  }
1945
+ function readingLinks(Fs) {
1946
+ const readlink = Fs.readlink?.bind(Fs);
1947
+ if (!readlink) return;
1948
+ Fs.readlink = (path) => {
1949
+ const was = Fs.sliccReading;
1950
+ Fs.sliccReading = Fs.lookupPath(path).node;
1951
+ try {
1952
+ return readlink(path);
1953
+ } finally {
1954
+ Fs.sliccReading = was;
1955
+ }
1956
+ };
1957
+ }
1939
1958
  var S_IFDIR, S_IFREG, S_IFLNK, PERM_MASK, DEFAULT_DIR_PERM, UMASK, SEEK_CUR, SEEK_END, EARLY_WHOLE_FILE, O_ACCMODE, O_TRUNC, O_PATH, stale;
1940
1959
  var init_live_vfs_fs = __esm({
1941
1960
  "src/realm/live-vfs-fs.ts"() {
@@ -1987,6 +2006,7 @@ function mountVfsIntoEmscripten(Fs, deps) {
1987
2006
  const { plugin, mounted } = mountLiveVfsDirs(Fs, bridge, dirs ?? [], warn);
1988
2007
  if (dirs) liveRoot(Fs, bridge);
1989
2008
  if (bridge.owners && Fs.lookupPath) useLiveChown(Fs);
2009
+ if (bridge.links && Fs.lookupPath) readingLinks(Fs);
1990
2010
  try {
1991
2011
  Fs.chdir(deps.cwd);
1992
2012
  } catch (err) {
@@ -2154,21 +2174,46 @@ var init_kernel_streams = __esm({
2154
2174
  if (typeof this.Fs.stat !== "function") return;
2155
2175
  stream.stream_ops = { ...stream.stream_ops, getattr: () => this.Fs.stat?.(name2) ?? {} };
2156
2176
  }
2177
+ nameDevice(stream, kind) {
2178
+ this.nameStream(stream, kind === "sealed" ? SEALED_PATH : CLIPBOARD_PATH);
2179
+ }
2157
2180
  listSealed() {
2158
- const { analyzePath, mkdev, makedev } = this.Fs;
2181
+ const fs = this.Fs;
2182
+ const { analyzePath, mkdev, makedev, registerDevice } = fs;
2159
2183
  if (!analyzePath || !mkdev || !makedev) return;
2160
2184
  const nodes = [
2161
2185
  [SEALED_PATH, 250, this.sys.openSealed],
2162
2186
  [CLIPBOARD_PATH, 251, this.sys.openClipboard]
2163
2187
  ];
2164
- for (const [path, minor, present] of nodes) {
2165
- if (!present || analyzePath.call(this.Fs, path).exists) continue;
2188
+ for (const [path, minor, opener] of nodes) {
2189
+ if (!opener) continue;
2190
+ const dev = makedev.call(fs, 10, minor);
2191
+ registerDevice?.call(fs, dev, {
2192
+ open: (stream) => this.openNode(stream, path, opener)
2193
+ });
2194
+ if (analyzePath.call(fs, path).exists) continue;
2166
2195
  try {
2167
- mkdev.call(this.Fs, path, makedev.call(this.Fs, 10, minor));
2196
+ const node = mkdev.call(fs, path, dev);
2197
+ if (typeof node === "object" && node !== null) {
2198
+ const made = node;
2199
+ made.node_ops = { ...made.node_ops, getattr: () => sealedStat(minor) };
2200
+ }
2168
2201
  } catch {
2169
2202
  }
2170
2203
  }
2171
2204
  }
2205
+ openNode(stream, path, opener) {
2206
+ let kfd;
2207
+ try {
2208
+ kfd = this.call(() => opener.call(this.sys, stream.flags & 3));
2209
+ } catch (e) {
2210
+ this.Fs.closeStream(stream.fd);
2211
+ throw e;
2212
+ }
2213
+ this.attach(stream, kfd, false);
2214
+ this.nameStream(stream, path);
2215
+ if (path === CLIPBOARD_PATH) this.reportClose(kfd);
2216
+ }
2172
2217
  reporting = /* @__PURE__ */ new Set();
2173
2218
  reportClose(kfd) {
2174
2219
  this.reporting.add(kfd);
@@ -3223,8 +3268,9 @@ function readonlyRefusal(Fs, memory, call2) {
3223
3268
  follow: follow2
3224
3269
  });
3225
3270
  const bridge = node.live ? node.mount.opts.bridge : void 0;
3226
- const stat = bridge?.stat;
3227
- return stat?.(liveNodePath(node)).readonly ? -wasiErrno("EROFS") : 0;
3271
+ const stats = bridge;
3272
+ const stat = follow2 ? stats?.stat : stats?.lstat;
3273
+ return stat?.call(stats, liveNodePath(node)).readonly ? -wasiErrno("EROFS") : 0;
3228
3274
  } catch {
3229
3275
  return 0;
3230
3276
  }
@@ -3412,7 +3458,8 @@ function kernelEntry(stream, kernel) {
3412
3458
  if (stream.sliccKernelSocket) {
3413
3459
  return { fd: stream.fd, kernel, kind: "socket", flags: stream.flags, ...cloexec };
3414
3460
  }
3415
- const kind = stream.sliccKernelFile ? "file" : stream.tty ? "tty" : "stream";
3461
+ const device2 = stream.path === void 0 ? void 0 : NAMED_DEVICES[stream.path];
3462
+ const kind = stream.sliccKernelFile ? "file" : stream.tty ? "tty" : device2 ?? "stream";
3416
3463
  return { fd: stream.fd, kernel, kind, ...cloexec };
3417
3464
  }
3418
3465
  function describeInherited(Fs, sys, streams, livePath, actions = []) {
@@ -3462,7 +3509,8 @@ function place(Fs, stream, fd) {
3462
3509
  function placeholder(Fs, streams, entry) {
3463
3510
  if (entry.kind === "socket") return streams.socketStream(entry.flags ?? O_RDWR);
3464
3511
  if (entry.kind === "tty") return Fs.open("/dev/tty", O_RDWR);
3465
- if (entry.kind === "stream" || entry.kind === "clipboard") return Fs.open("/dev/null", O_RDWR);
3512
+ if (entry.kind === "stream" || entry.kind === "clipboard" || entry.kind === "sealed")
3513
+ return Fs.open("/dev/null", O_RDWR);
3466
3514
  Fs.mkdirTree(PLACEHOLDER_DIR);
3467
3515
  return Fs.open(`${PLACEHOLDER_DIR}/${entry.fd}`, O_RDWR | O_CREAT3);
3468
3516
  }
@@ -3487,6 +3535,7 @@ function placeKernelStream(Fs, streams, entry) {
3487
3535
  } else if (entry.kind === "socket") streams.attachSocket(stream, entry.kernel);
3488
3536
  else streams.attach(stream, entry.kernel, entry.kind === "tty");
3489
3537
  if (entry.kind === "clipboard") streams.reportClose(entry.kernel);
3538
+ if (entry.kind === "sealed" || entry.kind === "clipboard") streams.nameDevice(stream, entry.kind);
3490
3539
  if (entry.kind === "tty") streams.nameTerminal(stream);
3491
3540
  if (entry.kind === "stream") {
3492
3541
  asFifo(stream, streams, entry.desc !== void 0 ? `d${entry.desc}` : `k${entry.kernel}`);
@@ -3512,7 +3561,7 @@ function restoreForkedStreams(Fs, streams, table) {
3512
3561
  }
3513
3562
  }
3514
3563
  }
3515
- var O_RDWR, O_ACCMODE3, O_CREAT3, O_EXCL2, O_TRUNC3, PLACEHOLDER_DIR, ACCESS, DEVICES, FIFO_MODE, nextStreamIno, streamInos;
3564
+ var O_RDWR, O_ACCMODE3, O_CREAT3, O_EXCL2, O_TRUNC3, PLACEHOLDER_DIR, NAMED_DEVICES, ACCESS, DEVICES, FIFO_MODE, nextStreamIno, streamInos;
3516
3565
  var init_process_fork = __esm({
3517
3566
  "src/process/process-fork.ts"() {
3518
3567
  "use strict";
@@ -3523,6 +3572,10 @@ var init_process_fork = __esm({
3523
3572
  O_EXCL2 = 128;
3524
3573
  O_TRUNC3 = 512;
3525
3574
  PLACEHOLDER_DIR = "/dev/slicc-fd";
3575
+ NAMED_DEVICES = {
3576
+ "/dev/sealed": "sealed",
3577
+ "/dev/clipboard": "clipboard"
3578
+ };
3526
3579
  ACCESS = { 0: "read", 1: "write" };
3527
3580
  DEVICES = {
3528
3581
  "/dev/null": "null",
@@ -4160,7 +4213,7 @@ var KERNEL_VERSION, OS_RELEASE;
4160
4213
  var init_version = __esm({
4161
4214
  "src/version.ts"() {
4162
4215
  "use strict";
4163
- KERNEL_VERSION = true ? "1.88.1" : "0.0.0-dev";
4216
+ KERNEL_VERSION = true ? "1.89.0" : "0.0.0-dev";
4164
4217
  OS_RELEASE = "6.0.0-slicc";
4165
4218
  }
4166
4219
  });
@@ -4440,9 +4493,9 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
4440
4493
  }
4441
4494
  return found;
4442
4495
  };
4443
- const procOps = proc.node_ops;
4444
- const lookup2 = procOps.lookup?.bind(procOps);
4445
- const readdir = procOps.readdir?.bind(procOps);
4496
+ const procOps2 = proc.node_ops;
4497
+ const lookup2 = procOps2.lookup?.bind(procOps2);
4498
+ const readdir = procOps2.readdir?.bind(procOps2);
4446
4499
  const listAll = (node) => {
4447
4500
  const names = new Set(readdir ? readdir(node) : [".", ".."]);
4448
4501
  for (const name2 of [...SYSTEM_FILES, "mounts", "sys"]) names.add(name2);
@@ -4450,7 +4503,7 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
4450
4503
  return [...names];
4451
4504
  };
4452
4505
  proc.node_ops = {
4453
- ...procOps,
4506
+ ...procOps2,
4454
4507
  lookup: (parent, name2) => {
4455
4508
  if (/^[1-9]\d*$/.test(name2)) {
4456
4509
  if (!infoOf(Number(name2)) && !listed(Number(name2))) throw error();
@@ -4838,6 +4891,9 @@ function kernelWrappers(imports, module, deps) {
4838
4891
  reportGrowth(imports, grown, kernelGlue);
4839
4892
  holdWhileStopped(imports, new Int32Array(init.sab, 0, SAB_HEADER_I32), kernelGlue, deps.poll);
4840
4893
  }
4894
+ function bridgeFlags(init) {
4895
+ return { ...init.owners ? { owners: true } : {}, ...init.links ? { links: true } : {} };
4896
+ }
4841
4897
  async function runWasmProcess(init, port2, deps = {}) {
4842
4898
  const signals = new SignalGate(
4843
4899
  createSyncSabTransport(init.sab, port2, {
@@ -4942,7 +4998,7 @@ async function runWasmProcess(init, port2, deps = {}) {
4942
4998
  if (!hasStreams(running)) return runStdioOnly(running, init);
4943
4999
  if (init.owners) linuxDevices(running.FS);
4944
5000
  const vfs = mountVfsIntoEmscripten(running.FS, {
4945
- bridge: createSyncFsSabBridge(transport, init.owners ? { owners: true } : {}),
5001
+ bridge: createSyncFsSabBridge(transport, bridgeFlags(init)),
4946
5002
  cwd: init.cwd,
4947
5003
  warn: deps.warn ?? say(2)
4948
5004
  });
@@ -5097,7 +5153,7 @@ var init_process_runtime = __esm({
5097
5153
  O_ACCMODE4 = 3;
5098
5154
  O_DIRECTORY = 65536;
5099
5155
  accessMode = (access) => access === "read" ? O_RDONLY : access === "write" ? O_WRONLY3 : O_RDWR3;
5100
- PLACED = /* @__PURE__ */ new Set(["stream", "file", "socket", "clipboard"]);
5156
+ PLACED = /* @__PURE__ */ new Set(["stream", "file", "socket", "clipboard", "sealed"]);
5101
5157
  GLUE_TRAILER = [
5102
5158
  "if (typeof ENV !== 'undefined') Object.assign(ENV, Module.sliccEnv);",
5103
5159
  "if (typeof thisProgram !== 'undefined' && Module.thisProgram === '') thisProgram = '';",
@@ -5314,6 +5370,7 @@ function physical(fs, path) {
5314
5370
  const st = fs.lstat(at);
5315
5371
  if (st.isSymbolicLink) {
5316
5372
  if (++hops > MAX_LINKS) throw new WasiError("ELOOP");
5373
+ if (fs.links) fs.access?.(at, 0, "follow", true);
5317
5374
  const target = fs.readlink(at);
5318
5375
  if (target.startsWith("/")) done = [];
5319
5376
  todo = [...target.split("/").filter((p) => p !== "" && p !== "."), ...todo];
@@ -5453,6 +5510,7 @@ function cachingBridge(bridge, now = () => performance.now(), shared) {
5453
5510
  truncate: (p, size) => rewriting(p, () => bridge.truncate?.(p, size))
5454
5511
  } : {},
5455
5512
  ...bridge.owners ? { owners: true } : {},
5513
+ ...bridge.links ? { links: true } : {},
5456
5514
  invalidate,
5457
5515
  touched,
5458
5516
  threaded
@@ -7129,6 +7187,7 @@ var init_wasi_host = __esm({
7129
7187
  view.setUint32(old, oldLo, true);
7130
7188
  view.setUint32(old + 4, oldHi, true);
7131
7189
  }) : E.NOSYS,
7190
+ sigmask_poll: (lo, hi, inPtr, outPtr, n, nevents) => this.sigmask ? this.maskedPoll(this.sigmask, [lo, hi], [inPtr, outPtr, n, nevents]) : E.NOSYS,
7132
7191
  sigpending_get: (out) => {
7133
7192
  if (!this.sigmask) return E.NOSYS;
7134
7193
  mem.view().setBigUint64(out, BigInt(this.sigmask.pending()), true);
@@ -7136,6 +7195,47 @@ var init_wasi_host = __esm({
7136
7195
  }
7137
7196
  });
7138
7197
  }
7198
+ poll(inPtr, outPtr, n, nevents) {
7199
+ try {
7200
+ return pollOneoff(
7201
+ {
7202
+ mem: this.mem,
7203
+ fds: this.fds,
7204
+ kernel: this.o.kernel,
7205
+ now: (id) => this.now(id),
7206
+ interruptWakes: this.interruptWakes
7207
+ },
7208
+ inPtr,
7209
+ outPtr,
7210
+ n,
7211
+ nevents
7212
+ );
7213
+ } finally {
7214
+ this.o.fs.invalidate?.();
7215
+ }
7216
+ }
7217
+ maskedPoll(mask, set, [inPtr, outPtr, n, nevents]) {
7218
+ const old = mask.swap(set[0], set[1]);
7219
+ try {
7220
+ this.mem.view().setUint32(nevents, 0, true);
7221
+ if (mask.deliverUnblocked()) return E.INTR;
7222
+ if (n > 0) return this.poll(inPtr, outPtr, n, nevents);
7223
+ return this.suspend();
7224
+ } finally {
7225
+ mask.deliverUnblocked();
7226
+ mask.restore(old);
7227
+ }
7228
+ }
7229
+ suspend() {
7230
+ for (; ; ) {
7231
+ try {
7232
+ this.o.kernel.call({ op: "fd-select", read: [], write: [], timeoutMs: -1 });
7233
+ } catch (e) {
7234
+ if (e.code === "EINTR") return E.INTR;
7235
+ throw e;
7236
+ }
7237
+ }
7238
+ }
7139
7239
  imports() {
7140
7240
  this.cache ??= wrap({
7141
7241
  ...this.processImports(),
@@ -7143,25 +7243,7 @@ var init_wasi_host = __esm({
7143
7243
  ...this.statImports(),
7144
7244
  ...this.pathImports(),
7145
7245
  ...this.socketImports(),
7146
- poll_oneoff: (inPtr, outPtr, n, nevents) => {
7147
- try {
7148
- return pollOneoff(
7149
- {
7150
- mem: this.mem,
7151
- fds: this.fds,
7152
- kernel: this.o.kernel,
7153
- now: (id) => this.now(id),
7154
- interruptWakes: this.interruptWakes
7155
- },
7156
- inPtr,
7157
- outPtr,
7158
- n,
7159
- nevents
7160
- );
7161
- } finally {
7162
- this.o.fs.invalidate?.();
7163
- }
7164
- }
7246
+ poll_oneoff: (inPtr, outPtr, n, nevents) => this.poll(inPtr, outPtr, n, nevents)
7165
7247
  });
7166
7248
  return this.cache;
7167
7249
  }
@@ -8253,15 +8335,15 @@ function procPath(fs, path, follow2) {
8253
8335
  return result;
8254
8336
  }
8255
8337
  function frozen(bytes) {
8256
- const refuse = () => {
8338
+ const refuse2 = () => {
8257
8339
  throw syncError("EROFS", "/proc");
8258
8340
  };
8259
8341
  return {
8260
8342
  readFile: () => bytes,
8261
8343
  pread: (_p, at, n) => bytes.subarray(at, at + n),
8262
- writeFile: refuse,
8263
- pwrite: refuse,
8264
- truncate: refuse
8344
+ writeFile: refuse2,
8345
+ pwrite: refuse2,
8346
+ truncate: refuse2
8265
8347
  };
8266
8348
  }
8267
8349
  function procfsBridge(fs, tree) {
@@ -8287,7 +8369,7 @@ function procfsBridge(fs, tree) {
8287
8369
  return proc(real);
8288
8370
  }
8289
8371
  };
8290
- const readOnly = (paths, run) => {
8372
+ const readOnly2 = (paths, run) => {
8291
8373
  const physical2 = shadowing();
8292
8374
  for (const [p, follow2] of paths) {
8293
8375
  if (inProc(p) || physical2 && toProc(p, follow2) !== void 0) throw syncError("EROFS", p);
@@ -8367,15 +8449,15 @@ function procfsBridge(fs, tree) {
8367
8449
  return [...listed, ["proc", tree.stat("/proc")]];
8368
8450
  }
8369
8451
  ),
8370
- rename: (from, to) => readOnly(
8452
+ rename: (from, to) => readOnly2(
8371
8453
  [
8372
8454
  [from, false],
8373
8455
  [to, false]
8374
8456
  ],
8375
8457
  () => fs.rename(from, to)
8376
8458
  ),
8377
- symlink: (target, link) => readOnly([[link, false]], () => fs.symlink(target, link)),
8378
- link: (from, to, follow2) => readOnly(
8459
+ symlink: (target, link) => readOnly2([[link, false]], () => fs.symlink(target, link)),
8460
+ link: (from, to, follow2) => readOnly2(
8379
8461
  [
8380
8462
  [from, follow2 === true],
8381
8463
  [to, false]
@@ -8407,12 +8489,12 @@ function procfsBridge(fs, tree) {
8407
8489
  for (const name2 of names) {
8408
8490
  const fn = fs[name2];
8409
8491
  if (!fn) continue;
8410
- over[name2] = (p, ...rest2) => readOnly([[p, follow2]], () => fn.call(fs, p, ...rest2));
8492
+ over[name2] = (p, ...rest2) => readOnly2([[p, follow2]], () => fn.call(fs, p, ...rest2));
8411
8493
  }
8412
8494
  }
8413
8495
  const { chown } = fs;
8414
8496
  if (chown) {
8415
- over.chown = (p, uid, gid, follow2) => readOnly([[p, follow2 === true]], () => chown.call(fs, p, uid, gid, follow2));
8497
+ over.chown = (p, uid, gid, follow2) => readOnly2([[p, follow2 === true]], () => chown.call(fs, p, uid, gid, follow2));
8416
8498
  }
8417
8499
  return new Proxy(fs, {
8418
8500
  get: (target, key, receiver) => key in over ? over[key] : Reflect.get(target, key, receiver)
@@ -8593,6 +8675,23 @@ var init_wasi_sigmask = __esm({
8593
8675
  if ((Atomics.load(this.header, SAB_I_SIGNALS) & ~now) !== 0) this.deliver();
8594
8676
  return E.SUCCESS;
8595
8677
  }
8678
+ swap(setLo, setHi) {
8679
+ const old = [this.lo, this.hi];
8680
+ this.lo = setLo & ~LIBC_UNBLOCKABLE;
8681
+ this.hi = setHi | 0;
8682
+ Atomics.store(this.header, SAB_I_BLOCKED, kernelBits(this.lo));
8683
+ return old;
8684
+ }
8685
+ deliverUnblocked() {
8686
+ const now = Atomics.load(this.header, SAB_I_BLOCKED);
8687
+ if ((Atomics.load(this.header, SAB_I_SIGNALS) & ~now) === 0) return false;
8688
+ this.deliver();
8689
+ return true;
8690
+ }
8691
+ restore([lo, hi]) {
8692
+ this.set(SIG_SETMASK, lo, hi, () => {
8693
+ });
8694
+ }
8596
8695
  discard(sig) {
8597
8696
  Atomics.and(this.header, SAB_I_SIGNALS, ~sigbit(sig));
8598
8697
  if (this.process) Atomics.and(this.process, SAB_I_SIGNALS, ~sigbit(sig));
@@ -10878,7 +10977,7 @@ function descriptors(init, fork, threads) {
10878
10977
  return { inherited: init.fds ?? [], ...init.program.preopenRoot ? { preopenRoot: true } : {} };
10879
10978
  }
10880
10979
  function ownersOf(init) {
10881
- return init.owners ? { owners: true } : {};
10980
+ return { ...init.owners ? { owners: true } : {}, ...init.links ? { links: true } : {} };
10882
10981
  }
10883
10982
  async function runWasiProcess(init, port2) {
10884
10983
  captureBacktraces(init.env);
@@ -12685,6 +12784,153 @@ var init_js_net = __esm({
12685
12784
  }
12686
12785
  });
12687
12786
 
12787
+ // src/process/js/js-proc.ts
12788
+ function* procStep(abs, pid, run) {
12789
+ const listing = yield { op: "proc-list" };
12790
+ const mounts = abs === "/proc/mounts" ? yield { op: "mount-list" } : [];
12791
+ const tree = new ProcTree(
12792
+ { procList: () => listing, mountList: () => mounts },
12793
+ pid,
12794
+ memorySource()
12795
+ );
12796
+ try {
12797
+ return run(tree);
12798
+ } catch (err) {
12799
+ throw new JsCallError(err.code ?? "EIO", abs);
12800
+ }
12801
+ }
12802
+ function readOnly(path) {
12803
+ throw new JsCallError("EROFS", path);
12804
+ }
12805
+ function procWrites(options) {
12806
+ return !!(options?.write || options?.append || options?.create || options?.truncate || options?.exclusive);
12807
+ }
12808
+ function snapshotFile(path, bytes) {
12809
+ let closed = false;
12810
+ const live = () => {
12811
+ if (closed) throw new JsCallError("EBADF", path);
12812
+ };
12813
+ return {
12814
+ fd: -1,
12815
+ path,
12816
+ size: () => {
12817
+ live();
12818
+ return bytes.length;
12819
+ },
12820
+ read: (position, length) => {
12821
+ live();
12822
+ index2(position, "read");
12823
+ index2(length, "read");
12824
+ return bytes.slice(position, position + length);
12825
+ },
12826
+ write: () => {
12827
+ throw new JsCallError("EBADF", path);
12828
+ },
12829
+ truncate: () => {
12830
+ throw new JsCallError("EBADF", path);
12831
+ },
12832
+ sync: () => live(),
12833
+ close: () => {
12834
+ live();
12835
+ closed = true;
12836
+ }
12837
+ };
12838
+ }
12839
+ function promised(file) {
12840
+ const out = { ...file };
12841
+ for (const [name2, value2] of Object.entries(file)) {
12842
+ if (typeof value2 === "function") {
12843
+ out[name2] = (...args) => new Promise((resolve) => resolve(value2(...args)));
12844
+ }
12845
+ }
12846
+ return out;
12847
+ }
12848
+ function procOps(paths, run) {
12849
+ const at = (path) => {
12850
+ const abs = paths.resolve(path);
12851
+ return inProc(abs) ? abs : void 0;
12852
+ };
12853
+ const step = (abs, op) => run(procStep(abs, paths.pid, op));
12854
+ return { at, step };
12855
+ }
12856
+ function withProc(fs, paths, run) {
12857
+ const { at, step } = procOps(paths, run);
12858
+ const out = { ...fs };
12859
+ const pass = fs;
12860
+ const reads = {
12861
+ stat: (tree, abs) => tree.stat(abs, true),
12862
+ lstat: (tree, abs) => tree.stat(abs, false),
12863
+ exists: (tree, abs) => tree.exists(abs),
12864
+ readdir: (tree, abs) => tree.readdir(abs),
12865
+ readlink: (tree, abs) => tree.readlink(abs),
12866
+ readFile: (tree, abs) => tree.read(abs)
12867
+ };
12868
+ for (const [name2, read2] of Object.entries(reads)) {
12869
+ out[name2] = (path, ...rest2) => {
12870
+ const abs = at(path);
12871
+ return abs ? step(abs, (tree) => read2(tree, abs)) : pass[name2]?.(path, ...rest2);
12872
+ };
12873
+ }
12874
+ for (const name2 of WRITES) {
12875
+ out[name2] = (path, ...rest2) => {
12876
+ const abs = at(path);
12877
+ return abs ? run(refuse(abs)) : pass[name2]?.(path, ...rest2);
12878
+ };
12879
+ }
12880
+ for (const name2 of TWO) {
12881
+ out[name2] = (from, to) => {
12882
+ const abs = at(from) ?? at(to);
12883
+ return abs ? run(refuse(abs)) : pass[name2]?.(from, to);
12884
+ };
12885
+ }
12886
+ out.symlink = (target, path) => {
12887
+ const abs = at(path);
12888
+ return abs ? run(refuse(abs)) : pass.symlink?.(target, path);
12889
+ };
12890
+ return out;
12891
+ }
12892
+ function* refuse(abs) {
12893
+ yield* [];
12894
+ return readOnly(abs);
12895
+ }
12896
+ function procOpen(open, paths, run, async = false) {
12897
+ const { at, step } = procOps(paths, run);
12898
+ return (path, options) => {
12899
+ const abs = at(path);
12900
+ if (!abs) return open(path, options);
12901
+ if (procWrites(options)) return run(refuse(abs));
12902
+ return step(abs, (tree) => {
12903
+ const file = snapshotFile(abs, tree.read(abs));
12904
+ return async ? promised(file) : file;
12905
+ });
12906
+ };
12907
+ }
12908
+ function procFsAsync(fs, kernel, paths) {
12909
+ return withProc(fs, paths, (step) => devAsync(kernel, step));
12910
+ }
12911
+ function procFsSync(fs, kernel, paths) {
12912
+ return withProc(fs, paths, (step) => devSync(kernel, step));
12913
+ }
12914
+ function procOpenAsync(open, kernel, paths) {
12915
+ return procOpen(open, paths, (step) => devAsync(kernel, step), true);
12916
+ }
12917
+ function procOpenSync(open, kernel, paths) {
12918
+ return procOpen(open, paths, (step) => devSync(kernel, step));
12919
+ }
12920
+ var WRITES, TWO;
12921
+ var init_js_proc = __esm({
12922
+ "src/process/js/js-proc.ts"() {
12923
+ "use strict";
12924
+ init_procfs();
12925
+ init_wasi_procfs();
12926
+ init_js_dev();
12927
+ init_js_io();
12928
+ init_js_kernel();
12929
+ WRITES = ["mkdir", "rm", "unlink", "chmod", "writeFile"];
12930
+ TWO = ["rename", "link"];
12931
+ }
12932
+ });
12933
+
12688
12934
  // src/process/js/js-run.ts
12689
12935
  function stdioOf(how) {
12690
12936
  if (how === void 0) return "pipe";
@@ -12849,8 +13095,11 @@ function syncOps(kernel, shared) {
12849
13095
  infos.delete(fd);
12850
13096
  kernel.call({ op: "fd-close", fd });
12851
13097
  },
12852
- open,
12853
- fs: syncPathOps(kernel, resolve, statOf, open)
13098
+ open: procOpenSync(open, kernel, { resolve, pid: shared.pid }),
13099
+ fs: procFsSync(syncPathOps(kernel, resolve, statOf, open), kernel, {
13100
+ resolve,
13101
+ pid: shared.pid
13102
+ })
12854
13103
  };
12855
13104
  }
12856
13105
  function syncFile(kernel, fd, path, append, forget) {
@@ -12978,6 +13227,7 @@ var init_js_sync = __esm({
12978
13227
  init_js_dev();
12979
13228
  init_js_io();
12980
13229
  init_js_kernel();
13230
+ init_js_proc();
12981
13231
  encoder3 = new TextEncoder();
12982
13232
  noLane = () => ({ ok: false, errno: "ENOSYS", message: "no sync lane" });
12983
13233
  JsSyncKernel = class {
@@ -13441,7 +13691,7 @@ function createContext(o) {
13441
13691
  handles.set(fd, handle.invalidate);
13442
13692
  return handle.file;
13443
13693
  };
13444
- const fs = pathOps(kernel, resolve, statOf, open);
13694
+ const fs = procFsAsync(pathOps(kernel, resolve, statOf, open), kernel, { resolve, pid: o.pid });
13445
13695
  const lane = o.lane ?? laneOf(void 0);
13446
13696
  if (o.lane && o.lane !== noLane) kernel.syncLane = o.lane;
13447
13697
  const syncKernel = new JsSyncKernel(lane, kernel, unwind);
@@ -13493,7 +13743,7 @@ function createContext(o) {
13493
13743
  return { type, tty: type === "tty", seekable: type === "file" };
13494
13744
  },
13495
13745
  isatty: async (fd) => typeOf(await info(fd)) === "tty",
13496
- open,
13746
+ open: procOpenAsync(open, kernel, { resolve, pid: o.pid }),
13497
13747
  resolve,
13498
13748
  fs,
13499
13749
  signals: {
@@ -13700,6 +13950,7 @@ var init_js_context = __esm({
13700
13950
  init_js_io();
13701
13951
  init_js_kernel();
13702
13952
  init_js_net();
13953
+ init_js_proc();
13703
13954
  init_js_run();
13704
13955
  init_js_sync();
13705
13956
  init_js_tty();