@ai-ecoverse/slicc-kernel 1.92.0 → 1.93.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.
@@ -655,9 +655,11 @@ function cachingBridge(bridge, now = () => performance.now(), shared) {
655
655
  ...bridge.kept ? { kept: bridge.kept.bind(bridge) } : {},
656
656
  ...bridge.keptStat ? { keptStat: bridge.keptStat.bind(bridge) } : {},
657
657
  ...bridge.pinned ? { pinned: (handle) => pinnedIo(bridge, handle, rewriting) } : {},
658
- ...bridge.create ? { create: (p) => mutating(() => bridge.create?.(p), ...entry(p)) } : {},
658
+ ...bridge.create ? {
659
+ create: (p, mode, opening2) => mutating(() => bridge.create?.(p, mode, opening2), ...entry(p))
660
+ } : {},
659
661
  ...chown ? {
660
- chown: (p, uid, gid, follow2) => rewriting(p, () => chown.call(bridge, p, uid, gid, follow2))
662
+ chown: (p, ...rest2) => rewriting(p, () => chown.call(bridge, p, ...rest2))
661
663
  } : {},
662
664
  ...bridge.pread && bridge.pwrite && bridge.truncate ? {
663
665
  pread: bridge.pread.bind(bridge),
@@ -995,6 +997,100 @@ var init_protocol = __esm({
995
997
  }
996
998
  });
997
999
 
1000
+ // src/realm/sync-sab-wire.ts
1001
+ function loadBlocked(header) {
1002
+ return [Atomics.load(header, SAB_I_BLOCKED), Atomics.load(header, SAB_I_BLOCKED_HI)];
1003
+ }
1004
+ function storeBlocked(header, [low, high]) {
1005
+ Atomics.store(header, SAB_I_BLOCKED_HI, high);
1006
+ Atomics.store(header, SAB_I_BLOCKED, low);
1007
+ }
1008
+ function loadU53(header, lo, hi) {
1009
+ return (Atomics.load(header, lo) >>> 0) + Atomics.load(header, hi) * U32;
1010
+ }
1011
+ function publishMemory(sab, bytes) {
1012
+ if (bytes > 0)
1013
+ Atomics.store(new Int32Array(sab, 0, SAB_HEADER_I32), SAB_I_MEMORY, Math.ceil(bytes / 65536));
1014
+ }
1015
+ function decodeSabResult(status2, payload) {
1016
+ switch (status2) {
1017
+ case SAB_STATUS_BYTES:
1018
+ return { ok: true, kind: "bytes", bytes: payload };
1019
+ case SAB_STATUS_VOID:
1020
+ return { ok: true, kind: "void" };
1021
+ case SAB_STATUS_JSON: {
1022
+ try {
1023
+ return { ok: true, kind: "json", json: JSON.parse(decoder.decode(payload)) };
1024
+ } catch {
1025
+ return { ok: false, errno: "EIO", message: "sync-sab: malformed json payload" };
1026
+ }
1027
+ }
1028
+ case SAB_STATUS_ERRNO: {
1029
+ try {
1030
+ const parsed = JSON.parse(decoder.decode(payload));
1031
+ const errno2 = typeof parsed.errno === "string" && /^E[A-Z]+$|^EAI_[A-Z]+$/.test(parsed.errno) ? parsed.errno : "EIO";
1032
+ return { ok: false, errno: errno2, message: String(parsed.message ?? errno2) };
1033
+ } catch {
1034
+ return { ok: false, errno: "EIO", message: "sync-sab: malformed errno payload" };
1035
+ }
1036
+ }
1037
+ default:
1038
+ return { ok: false, errno: "EIO", message: `sync-sab: unknown status ${status2}` };
1039
+ }
1040
+ }
1041
+ function sabViews(sab) {
1042
+ if (sab.byteLength < SAB_MIN_BYTES) {
1043
+ throw new Error(`sync-sab: buffer too small (${sab.byteLength} < ${SAB_MIN_BYTES})`);
1044
+ }
1045
+ return {
1046
+ header: new Int32Array(sab, 0, SAB_HEADER_I32),
1047
+ window: new Uint8Array(sab, SAB_HEADER_BYTES)
1048
+ };
1049
+ }
1050
+ var SAB_HEADER_I32, SAB_CLOCK_OFFSET, SAB_CLOCK_I64, SAB_HEADER_BYTES, SAB_I_STATE, SAB_I_SEQ, SAB_I_STATUS, SAB_I_TOTAL, SAB_I_CHUNK, SAB_I_OFFSET, SAB_I_REQ, SAB_I_PUB, SAB_I_SIGNALS, SAB_I_TIMERS, SAB_I_MEMORY, SAB_I_TOTAL_HI, SAB_I_OFFSET_HI, SAB_I_KILLED, SAB_I_ASYNC, SAB_I_STOP, SAB_I_BLOCKED, SAB_I_BLOCKED_HI, anyBlocked, U32, SAB_STATE_IDLE, SAB_STATE_PENDING, SAB_STATE_READY, SAB_STATUS_BYTES, SAB_STATUS_JSON, SAB_STATUS_VOID, SAB_STATUS_ERRNO, SAB_DEFAULT_WINDOW_BYTES, SAB_MIN_BYTES, SYNC_SAB_REQ_MSG, SYNC_SAB_NEXT_MSG, encoder, decoder;
1051
+ var init_sync_sab_wire = __esm({
1052
+ "src/realm/sync-sab-wire.ts"() {
1053
+ "use strict";
1054
+ SAB_HEADER_I32 = 18;
1055
+ SAB_CLOCK_OFFSET = SAB_HEADER_I32 * 4;
1056
+ SAB_CLOCK_I64 = 3;
1057
+ SAB_HEADER_BYTES = SAB_CLOCK_OFFSET + SAB_CLOCK_I64 * 8;
1058
+ SAB_I_STATE = 0;
1059
+ SAB_I_SEQ = 1;
1060
+ SAB_I_STATUS = 2;
1061
+ SAB_I_TOTAL = 3;
1062
+ SAB_I_CHUNK = 4;
1063
+ SAB_I_OFFSET = 5;
1064
+ SAB_I_REQ = 6;
1065
+ SAB_I_PUB = 7;
1066
+ SAB_I_SIGNALS = 8;
1067
+ SAB_I_TIMERS = 9;
1068
+ SAB_I_MEMORY = 10;
1069
+ SAB_I_TOTAL_HI = 11;
1070
+ SAB_I_OFFSET_HI = 12;
1071
+ SAB_I_KILLED = 13;
1072
+ SAB_I_ASYNC = 14;
1073
+ SAB_I_STOP = 15;
1074
+ SAB_I_BLOCKED = 16;
1075
+ SAB_I_BLOCKED_HI = 17;
1076
+ anyBlocked = (mask) => mask !== void 0 && (mask[0] !== 0 || mask[1] !== 0);
1077
+ U32 = 2 ** 32;
1078
+ SAB_STATE_IDLE = 0;
1079
+ SAB_STATE_PENDING = 1;
1080
+ SAB_STATE_READY = 2;
1081
+ SAB_STATUS_BYTES = 1;
1082
+ SAB_STATUS_JSON = 2;
1083
+ SAB_STATUS_VOID = 3;
1084
+ SAB_STATUS_ERRNO = 4;
1085
+ SAB_DEFAULT_WINDOW_BYTES = 1024 * 1024;
1086
+ SAB_MIN_BYTES = SAB_HEADER_BYTES + 4096;
1087
+ SYNC_SAB_REQ_MSG = "sync-sab-req";
1088
+ SYNC_SAB_NEXT_MSG = "sync-sab-next";
1089
+ encoder = new TextEncoder();
1090
+ decoder = new TextDecoder();
1091
+ }
1092
+ });
1093
+
998
1094
  // src/process/wasi/wasi-threads.ts
999
1095
  function threadCap(env) {
1000
1096
  const asked = Number.parseInt(env.SLICC_WASM_THREADS ?? "", 10);
@@ -1005,6 +1101,7 @@ var init_wasi_threads = __esm({
1005
1101
  "src/process/wasi/wasi-threads.ts"() {
1006
1102
  "use strict";
1007
1103
  init_protocol();
1104
+ init_sync_sab_wire();
1008
1105
  init_wasi_files();
1009
1106
  LAST_TID = 0;
1010
1107
  RUNNING = 1;
@@ -1040,7 +1137,7 @@ var init_wasi_threads = __esm({
1040
1137
  this.beforeSpawn?.();
1041
1138
  const tid = Atomics.add(this.ids, LAST_TID, 1) + 1;
1042
1139
  const modules = this.modules?.();
1043
- const blocked = this.blocked?.() ?? 0;
1140
+ const blocked = this.blocked?.();
1044
1141
  this.port.postMessage({
1045
1142
  type: WASM_THREAD_SPAWN,
1046
1143
  thread: {
@@ -1049,7 +1146,7 @@ var init_wasi_threads = __esm({
1049
1146
  memory: this.memory,
1050
1147
  ids: this.ids.buffer,
1051
1148
  ...modules ? { modules } : {},
1052
- ...blocked ? { blocked } : {}
1149
+ ...anyBlocked(blocked) ? { blocked } : {}
1053
1150
  }
1054
1151
  });
1055
1152
  return tid;
@@ -1116,6 +1213,21 @@ function physicalPath(fs, path) {
1116
1213
  }
1117
1214
  return `/${walk.done.join("/")}`;
1118
1215
  }
1216
+ async function physicalPathAsync(fs, path) {
1217
+ const walk = start(path);
1218
+ for (let part = next(walk); part !== void 0; part = next(walk)) {
1219
+ const at = `/${[...walk.done, part].join("/")}`;
1220
+ let target;
1221
+ try {
1222
+ target = (await fs.lstat(at)).isSymbolicLink ? await fs.readlink(at) : void 0;
1223
+ } catch {
1224
+ return rest(walk, part);
1225
+ }
1226
+ if (target === void 0) walk.done.push(part);
1227
+ else if (!follow(walk, target)) return lexical(path);
1228
+ }
1229
+ return `/${walk.done.join("/")}`;
1230
+ }
1119
1231
  var MAX_HOPS;
1120
1232
  var init_physical_path = __esm({
1121
1233
  "src/fs/physical-path.ts"() {
@@ -1124,88 +1236,18 @@ var init_physical_path = __esm({
1124
1236
  }
1125
1237
  });
1126
1238
 
1127
- // src/realm/sync-sab-wire.ts
1128
- function loadU53(header, lo, hi) {
1129
- return (Atomics.load(header, lo) >>> 0) + Atomics.load(header, hi) * U32;
1239
+ // src/fs/dev-removal.ts
1240
+ function inDevTree(path) {
1241
+ return path === "/dev" || path.startsWith("/dev/");
1130
1242
  }
1131
- function publishMemory(sab, bytes) {
1132
- if (bytes > 0)
1133
- Atomics.store(new Int32Array(sab, 0, SAB_HEADER_I32), SAB_I_MEMORY, Math.ceil(bytes / 65536));
1243
+ function devRemoval(path, cred) {
1244
+ if (!inDevTree(path)) return void 0;
1245
+ if (cred && cred.euid !== 0) return "EACCES";
1246
+ return path === "/dev" ? "EBUSY" : "EPERM";
1134
1247
  }
1135
- function decodeSabResult(status2, payload) {
1136
- switch (status2) {
1137
- case SAB_STATUS_BYTES:
1138
- return { ok: true, kind: "bytes", bytes: payload };
1139
- case SAB_STATUS_VOID:
1140
- return { ok: true, kind: "void" };
1141
- case SAB_STATUS_JSON: {
1142
- try {
1143
- return { ok: true, kind: "json", json: JSON.parse(decoder.decode(payload)) };
1144
- } catch {
1145
- return { ok: false, errno: "EIO", message: "sync-sab: malformed json payload" };
1146
- }
1147
- }
1148
- case SAB_STATUS_ERRNO: {
1149
- try {
1150
- const parsed = JSON.parse(decoder.decode(payload));
1151
- const errno2 = typeof parsed.errno === "string" && /^E[A-Z]+$|^EAI_[A-Z]+$/.test(parsed.errno) ? parsed.errno : "EIO";
1152
- return { ok: false, errno: errno2, message: String(parsed.message ?? errno2) };
1153
- } catch {
1154
- return { ok: false, errno: "EIO", message: "sync-sab: malformed errno payload" };
1155
- }
1156
- }
1157
- default:
1158
- return { ok: false, errno: "EIO", message: `sync-sab: unknown status ${status2}` };
1159
- }
1160
- }
1161
- function sabViews(sab) {
1162
- if (sab.byteLength < SAB_MIN_BYTES) {
1163
- throw new Error(`sync-sab: buffer too small (${sab.byteLength} < ${SAB_MIN_BYTES})`);
1164
- }
1165
- return {
1166
- header: new Int32Array(sab, 0, SAB_HEADER_I32),
1167
- window: new Uint8Array(sab, SAB_HEADER_BYTES)
1168
- };
1169
- }
1170
- var SAB_HEADER_I32, SAB_CLOCK_OFFSET, SAB_CLOCK_I64, SAB_HEADER_BYTES, SAB_I_STATE, SAB_I_SEQ, SAB_I_STATUS, SAB_I_TOTAL, SAB_I_CHUNK, SAB_I_OFFSET, SAB_I_REQ, SAB_I_PUB, SAB_I_SIGNALS, SAB_I_TIMERS, SAB_I_MEMORY, SAB_I_TOTAL_HI, SAB_I_OFFSET_HI, SAB_I_KILLED, SAB_I_ASYNC, SAB_I_STOP, SAB_I_BLOCKED, U32, SAB_STATE_IDLE, SAB_STATE_PENDING, SAB_STATE_READY, SAB_STATUS_BYTES, SAB_STATUS_JSON, SAB_STATUS_VOID, SAB_STATUS_ERRNO, SAB_DEFAULT_WINDOW_BYTES, SAB_MIN_BYTES, SYNC_SAB_REQ_MSG, SYNC_SAB_NEXT_MSG, encoder, decoder;
1171
- var init_sync_sab_wire = __esm({
1172
- "src/realm/sync-sab-wire.ts"() {
1248
+ var init_dev_removal = __esm({
1249
+ "src/fs/dev-removal.ts"() {
1173
1250
  "use strict";
1174
- SAB_HEADER_I32 = 18;
1175
- SAB_CLOCK_OFFSET = SAB_HEADER_I32 * 4;
1176
- SAB_CLOCK_I64 = 3;
1177
- SAB_HEADER_BYTES = SAB_CLOCK_OFFSET + SAB_CLOCK_I64 * 8;
1178
- SAB_I_STATE = 0;
1179
- SAB_I_SEQ = 1;
1180
- SAB_I_STATUS = 2;
1181
- SAB_I_TOTAL = 3;
1182
- SAB_I_CHUNK = 4;
1183
- SAB_I_OFFSET = 5;
1184
- SAB_I_REQ = 6;
1185
- SAB_I_PUB = 7;
1186
- SAB_I_SIGNALS = 8;
1187
- SAB_I_TIMERS = 9;
1188
- SAB_I_MEMORY = 10;
1189
- SAB_I_TOTAL_HI = 11;
1190
- SAB_I_OFFSET_HI = 12;
1191
- SAB_I_KILLED = 13;
1192
- SAB_I_ASYNC = 14;
1193
- SAB_I_STOP = 15;
1194
- SAB_I_BLOCKED = 16;
1195
- U32 = 2 ** 32;
1196
- SAB_STATE_IDLE = 0;
1197
- SAB_STATE_PENDING = 1;
1198
- SAB_STATE_READY = 2;
1199
- SAB_STATUS_BYTES = 1;
1200
- SAB_STATUS_JSON = 2;
1201
- SAB_STATUS_VOID = 3;
1202
- SAB_STATUS_ERRNO = 4;
1203
- SAB_DEFAULT_WINDOW_BYTES = 1024 * 1024;
1204
- SAB_MIN_BYTES = SAB_HEADER_BYTES + 4096;
1205
- SYNC_SAB_REQ_MSG = "sync-sab-req";
1206
- SYNC_SAB_NEXT_MSG = "sync-sab-next";
1207
- encoder = new TextEncoder();
1208
- decoder = new TextDecoder();
1209
1251
  }
1210
1252
  });
1211
1253
 
@@ -1832,6 +1874,7 @@ var init_wasi_fds = __esm({
1832
1874
  const { buffer } = e.file;
1833
1875
  try {
1834
1876
  buffer.flush();
1877
+ this.reported.delete(buffer);
1835
1878
  } catch (err) {
1836
1879
  this.reported.add(buffer);
1837
1880
  this.drop(buffer);
@@ -1897,6 +1940,7 @@ var init_wasi_fds = __esm({
1897
1940
  for (const buffer of this.buffers.values()) {
1898
1941
  try {
1899
1942
  buffer.flush();
1943
+ this.reported.delete(buffer);
1900
1944
  } catch (err) {
1901
1945
  if (!this.reported.has(buffer)) throw err;
1902
1946
  }
@@ -2119,7 +2163,7 @@ var init_wasi_fds = __esm({
2119
2163
  return true;
2120
2164
  }
2121
2165
  try {
2122
- this.fs.create(path);
2166
+ this.fs.create(path, void 0, true);
2123
2167
  return true;
2124
2168
  } catch (err) {
2125
2169
  if (oflags & OFLAGS.EXCL || err.code !== "EEXIST") throw err;
@@ -2510,6 +2554,7 @@ var WasiExit, IDS, NS_PER_MS, AT_SYMLINK_NOFOLLOW, AT_EACCESS, ROOT_IDS, GONE, S
2510
2554
  var init_wasi_host = __esm({
2511
2555
  "src/process/wasi/wasi-host.ts"() {
2512
2556
  "use strict";
2557
+ init_dev_removal();
2513
2558
  init_physical_path();
2514
2559
  init_cpu_clock();
2515
2560
  init_cred();
@@ -2607,10 +2652,10 @@ var init_wasi_host = __esm({
2607
2652
  return path;
2608
2653
  };
2609
2654
  const modeOf2 = (st) => (st.mode ?? 0) & 4095;
2610
- const chown = (path, uid, gid, follow2) => {
2655
+ const chown = (path, uid, gid, follow2, handle) => {
2611
2656
  const { chown: own } = this.o.fs;
2612
2657
  if (!own) throw new WasiError("ENOSYS");
2613
- own.call(this.o.fs, path, idOf(uid), idOf(gid), follow2);
2658
+ own.call(this.o.fs, path, idOf(uid), idOf(gid), follow2, handle);
2614
2659
  };
2615
2660
  const caller = () => {
2616
2661
  const cred = this.o.kernel.call({ op: "proc-cred" });
@@ -2641,7 +2686,11 @@ var init_wasi_host = __esm({
2641
2686
  return follow2 ? this.o.fs.stat(path) : this.o.fs.lstat(path);
2642
2687
  };
2643
2688
  return wrap({
2644
- fd_chown: (fd, uid, gid) => void chown(pathOf(fd), uid, gid, true),
2689
+ fd_chown: (fd, uid, gid) => {
2690
+ const e = fds.get(fd);
2691
+ const handle = e.type === "file" ? e.file.buffer.handle : void 0;
2692
+ void chown(pathOf(fd), uid, gid, true, handle);
2693
+ },
2645
2694
  path_chown: (dirfd, p, l, uid, gid, flags) => void chown(at(dirfd, p, l), uid, gid, (flags & AT_SYMLINK_NOFOLLOW) === 0),
2646
2695
  fd_owner: (fd, out) => {
2647
2696
  if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
@@ -2653,14 +2702,14 @@ var init_wasi_host = __esm({
2653
2702
  owner(fdOwned(fd), out);
2654
2703
  },
2655
2704
  path_filestat_owner: (dirfd, lookup2, p, l, statOut, out) => {
2656
- if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
2657
2705
  const path = at(dirfd, p, l);
2706
+ if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
2658
2707
  this.writeFilestat(statOut, this.pathFilestat(path, lookup2));
2659
2708
  owner(pathOwned(path, (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0), out);
2660
2709
  },
2661
2710
  path_owner: (dirfd, p, l, flags, out) => {
2662
- if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
2663
2711
  const path = at(dirfd, p, l);
2712
+ if (!this.o.fs.owners) throw new WasiError("ENOTSUP");
2664
2713
  owner(pathOwned(path, (flags & AT_SYMLINK_NOFOLLOW) === 0), out);
2665
2714
  },
2666
2715
  path_access: (dirfd, p, l, amode, flags) => {
@@ -2917,14 +2966,35 @@ var init_wasi_host = __esm({
2917
2966
  const { mem, fds, o } = this;
2918
2967
  const at = (dirfd, p, l) => fds.resolve(dirfd, mem.string(p, l));
2919
2968
  return {
2920
- path_open: (dirfd, _lookup, p, l, oflags, rights, _inheriting, fdflags, out) => {
2921
- const path = at(dirfd, p, l);
2922
- if (deviceOf(path)) this.interrupted?.();
2923
- const fresh = (oflags & OFLAGS.CREAT) !== 0 && !this.synthetic(path) && !o.fs.exists(path);
2924
- mem.view().setUint32(out, fds.open(path, oflags, rights, fdflags), true);
2925
- if (fresh) this.created(path, 438);
2969
+ path_open: (dirfd, lookup2, p, l, oflags, rights, _inheriting, fdflags, out) => {
2970
+ const follow2 = (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0;
2971
+ try {
2972
+ const path = at(dirfd, p, l);
2973
+ if (deviceOf(path)) this.interrupted?.();
2974
+ const fresh = (oflags & OFLAGS.CREAT) !== 0 && !this.synthetic(path) && !o.fs.exists(path);
2975
+ mem.view().setUint32(out, fds.open(path, oflags, rights, fdflags), true);
2976
+ if (fresh) this.created(path, 438);
2977
+ } catch (err) {
2978
+ if (err.code !== "ENOENT") throw err;
2979
+ const raw = mem.string(p, l);
2980
+ const joined2 = raw.startsWith("/") ? raw : `${fds.dir(dirfd).path}/${raw}`;
2981
+ const resolved2 = this.resolveForDev(joined2, follow2);
2982
+ if (!resolved2) throw err;
2983
+ mem.view().setUint32(out, fds.open(resolved2, oflags, rights, fdflags), true);
2984
+ }
2985
+ },
2986
+ path_filestat_get: (dirfd, lookup2, p, l, out) => {
2987
+ try {
2988
+ this.writeFilestat(out, this.pathFilestat(at(dirfd, p, l), lookup2));
2989
+ } catch (err) {
2990
+ if (err.code !== "ENOENT") throw err;
2991
+ const raw = mem.string(p, l);
2992
+ const joined2 = raw.startsWith("/") ? raw : `${fds.dir(dirfd).path}/${raw}`;
2993
+ const resolved2 = this.resolveForDev(joined2, (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0);
2994
+ if (!resolved2) throw err;
2995
+ this.writeFilestat(out, this.pathFilestat(resolved2, lookup2));
2996
+ }
2926
2997
  },
2927
- path_filestat_get: (dirfd, lookup2, p, l, out) => void this.writeFilestat(out, this.pathFilestat(at(dirfd, p, l), lookup2)),
2928
2998
  path_filestat_set_times: (dirfd, lookup2, p, l, atim, mtim, flags) => {
2929
2999
  const path = at(dirfd, p, l);
2930
3000
  fds.flushPath(path);
@@ -2939,6 +3009,7 @@ var init_wasi_host = __esm({
2939
3009
  path_remove_directory: (dirfd, p, l) => void o.fs.rmdir(at(dirfd, p, l)),
2940
3010
  path_unlink_file: (dirfd, p, l) => {
2941
3011
  const path = at(dirfd, p, l);
3012
+ if (inDevTree(path)) return void o.fs.unlink(path);
2942
3013
  const st = o.fs.lstat(path);
2943
3014
  if (st.isDirectory) throw new WasiError("EISDIR");
2944
3015
  const linked = linkedOf(st);
@@ -3170,7 +3241,12 @@ var init_wasi_host = __esm({
3170
3241
  const v = this.mem.view();
3171
3242
  v.setUint8(out, filetype);
3172
3243
  v.setUint16(out + 2, flags, true);
3173
- const rights = seeks ? RIGHTS.ALL : RIGHTS.ALL & ~(RIGHTS.FD_SEEK | RIGHTS.FD_TELL);
3244
+ let rights = seeks ? RIGHTS.ALL : RIGHTS.ALL & ~(RIGHTS.FD_SEEK | RIGHTS.FD_TELL);
3245
+ if (e.type === "kernel") {
3246
+ const access = this.o.kernel.sys.access?.(fd);
3247
+ if (access === "read") rights &= ~RIGHTS.FD_WRITE;
3248
+ else if (access === "write") rights &= ~RIGHTS.FD_READ;
3249
+ }
3174
3250
  v.setBigUint64(out + 8, rights, true);
3175
3251
  v.setBigUint64(out + 16, RIGHTS.ALL, true);
3176
3252
  }
@@ -3236,6 +3312,21 @@ var init_wasi_host = __esm({
3236
3312
  synthetic(path) {
3237
3313
  return deviceOf(path) !== void 0 || path === SEALED_PATH && !!this.o.kernel.sys.openSealed || path === CLIPBOARD_PATH && !!this.o.kernel.sys.openClipboard;
3238
3314
  }
3315
+ resolveForDev(path, follow2 = true) {
3316
+ try {
3317
+ if (!follow2) {
3318
+ const slash = path.lastIndexOf("/");
3319
+ if (slash <= 0) return void 0;
3320
+ const parent = physicalPath(this.o.fs, path.slice(0, slash));
3321
+ const resolved3 = `${parent}/${path.slice(slash + 1)}`;
3322
+ return resolved3 !== path && this.synthetic(resolved3) ? resolved3 : void 0;
3323
+ }
3324
+ const resolved2 = physicalPath(this.o.fs, path);
3325
+ return resolved2 !== path && this.synthetic(resolved2) ? resolved2 : void 0;
3326
+ } catch {
3327
+ return void 0;
3328
+ }
3329
+ }
3239
3330
  pathFilestat(path, lookup2) {
3240
3331
  if (this.synthetic(path)) {
3241
3332
  return this.local({
@@ -3247,7 +3338,19 @@ var init_wasi_host = __esm({
3247
3338
  }
3248
3339
  this.fds.flushPath(path);
3249
3340
  const follow2 = (lookup2 & LOOKUP_SYMLINK_FOLLOW) !== 0;
3250
- return filestatOf(path, follow2 ? this.o.fs.stat(path) : this.o.fs.lstat(path));
3341
+ try {
3342
+ return filestatOf(path, follow2 ? this.o.fs.stat(path) : this.o.fs.lstat(path));
3343
+ } catch (err) {
3344
+ if (err.code !== "ENOENT") throw err;
3345
+ const resolved2 = this.resolveForDev(path, follow2);
3346
+ if (!resolved2) throw err;
3347
+ return this.local({
3348
+ filetype: FILETYPE.CHARACTER_DEVICE,
3349
+ size: 0n,
3350
+ ino: pathInode(resolved2),
3351
+ mtimeNs: 0n
3352
+ });
3353
+ }
3251
3354
  }
3252
3355
  setTimes(path, atim, mtim, flags, follow2 = true) {
3253
3356
  const asked = FSTFLAGS.ATIM | FSTFLAGS.ATIM_NOW | FSTFLAGS.MTIM | FSTFLAGS.MTIM_NOW;
@@ -3510,7 +3613,8 @@ var init_wasix_process = __esm({
3510
3613
  cwd: this.host.cwd,
3511
3614
  ...fds.isShared ? { shared: true } : {},
3512
3615
  setjmps: this.driver.setjmps(),
3513
- ...this.host.signals ? { signals: this.host.signals.snapshot() } : {}
3616
+ ...this.host.signals ? { signals: this.host.signals.snapshot() } : {},
3617
+ ...this.host.sigmask ? { blocked: this.host.sigmask.inherited() } : {}
3514
3618
  };
3515
3619
  return this.call({
3516
3620
  op: "proc-fork",
@@ -3914,7 +4018,7 @@ var KERNEL_VERSION, OS_RELEASE;
3914
4018
  var init_version = __esm({
3915
4019
  "src/version.ts"() {
3916
4020
  "use strict";
3917
- KERNEL_VERSION = true ? "1.92.0" : "0.0.0-dev";
4021
+ KERNEL_VERSION = true ? "1.93.0" : "0.0.0-dev";
3918
4022
  OS_RELEASE = "6.0.0-slicc";
3919
4023
  }
3920
4024
  });
@@ -4151,6 +4255,8 @@ var init_js_kernel = __esm({
4151
4255
 
4152
4256
  // src/process/js/js-children.ts
4153
4257
  function exitedOf(status2) {
4258
+ if ((status2 & 255) === 127)
4259
+ return { status: 128 + (status2 >> 8 & 255), signal: status2 >> 8 & 255, stopped: true };
4154
4260
  const signal = status2 & 127;
4155
4261
  return signal ? { status: 128 + signal, signal } : { status: status2 >> 8 & 255 };
4156
4262
  }
@@ -4187,8 +4293,10 @@ function writable(io, fd) {
4187
4293
  });
4188
4294
  }
4189
4295
  function childOps(kernel, io, defaults, sync) {
4190
- const wait2 = async (pid) => {
4191
- const r = await kernel.blocking({ op: "proc-wait", pid, nohang: false });
4296
+ const wait2 = async (pid, options = {}) => {
4297
+ if (typeof options !== "object" || options === null) throw new JsCallError("EINVAL", "wait");
4298
+ const untraced = options.untraced === true ? { untraced: true } : {};
4299
+ const r = await kernel.blocking({ op: "proc-wait", pid, nohang: false, ...untraced });
4192
4300
  const [, status2] = r.ok && r.kind === "json" ? r.json : [0, 0];
4193
4301
  return exitedOf(status2);
4194
4302
  };
@@ -4202,7 +4310,7 @@ function childOps(kernel, io, defaults, sync) {
4202
4310
  ...stdin !== void 0 ? { stdin: writable(io, stdin) } : {},
4203
4311
  ...stdout !== void 0 ? { stdout: readable(io, stdout) } : {},
4204
4312
  ...stderr !== void 0 ? { stderr: readable(io, stderr) } : {},
4205
- wait: () => wait2(pid),
4313
+ wait: (options) => wait2(pid, options),
4206
4314
  kill: (signal) => kill(pid, signal)
4207
4315
  };
4208
4316
  };
@@ -4468,6 +4576,7 @@ function* lookup(abs) {
4468
4576
  const names = yield { op: "fd-tty-names" };
4469
4577
  if (names.includes(abs)) return { kind: "terminal", name: abs };
4470
4578
  }
4579
+ if (name2 === "pts") return { kind: "dir", mode: DIR | 365 };
4471
4580
  const pts = /^pts\/(\d+)$/.exec(name2)?.[1];
4472
4581
  if (pts !== void 0) {
4473
4582
  const open = yield { op: "pty-list" };
@@ -4499,7 +4608,8 @@ function* fdStat(fd, path) {
4499
4608
  if (info.kind === "file") {
4500
4609
  const file = yield { op: "fd-vfs-stat", fd };
4501
4610
  if (file.orphan) return { ...nodeStat(33152, file.size), isFile: true };
4502
- return yield* pathStat(file.path);
4611
+ const st = yield* pathStat(file.path);
4612
+ return { ...st, size: file.size };
4503
4613
  }
4504
4614
  if (info.terminal) return yield* terminalStat(info.terminal);
4505
4615
  if (CHAR_KINDS.has(info.kind)) return nodeStat(CHAR | 438);
@@ -4552,16 +4662,26 @@ function* devReadlink(abs) {
4552
4662
  if (node.kind === "fd") return yield* fdTarget(node.fd, abs);
4553
4663
  throw new JsCallError("EINVAL", abs);
4554
4664
  }
4665
+ function* devResolveTarget(abs) {
4666
+ const node = yield* lookup(abs);
4667
+ if (node.kind === "fd") return yield* fdTarget(node.fd, abs);
4668
+ if (node.kind === "link" && node.fd !== void 0) return yield* fdTarget(node.fd, abs);
4669
+ return void 0;
4670
+ }
4555
4671
  function* devReaddir(abs) {
4556
4672
  if (abs === "/dev/fd") {
4557
4673
  const fds = yield { op: "fd-list" };
4558
4674
  return fds.map(({ fd }) => String(fd));
4559
4675
  }
4676
+ if (abs === "/dev/pts") {
4677
+ const open = yield { op: "pty-list" };
4678
+ return open.map(String).sort();
4679
+ }
4560
4680
  const node = yield* lookup(abs);
4561
4681
  if (node.kind !== "dir") throw new JsCallError("ENOTDIR", abs);
4562
4682
  const names = yield { op: "fd-tty-names" };
4563
4683
  const ttys = names.filter((n) => /^\/dev\/tty\d+$/.test(n)).map((n) => n.slice(5));
4564
- return [...DEVICES, "clipboard", "sealed", "tty", "fd", ...STDIO3, ...ttys].sort();
4684
+ return [...DEVICES, "clipboard", "sealed", "tty", "fd", "pts", ...STDIO3, ...ttys].sort();
4565
4685
  }
4566
4686
  function* aliasOf(fd, abs, o) {
4567
4687
  const info = yield* fdInfo(fd, abs);
@@ -4570,6 +4690,9 @@ function* aliasOf(fd, abs, o) {
4570
4690
  const at = yield { op: "fd-vfs-stat", fd };
4571
4691
  if (!at.orphan)
4572
4692
  return { fd: yield openRequest(at.path, { ...o, create: false }), file };
4693
+ const wantWrite = o.write === true || o.append === true || o.truncate === true;
4694
+ if (wantWrite && info.access === "read") throw new JsCallError("EBADF", abs);
4695
+ if (!wantWrite && info.access === "write") throw new JsCallError("EBADF", abs);
4573
4696
  }
4574
4697
  const copy2 = yield { op: "fd-dup", fd, min: 3 };
4575
4698
  if (file && o.truncate) {
@@ -4921,11 +5044,18 @@ function plain(status2, text) {
4921
5044
  function local2(url) {
4922
5045
  return isKernelLoopbackHost(new URL(url).hostname);
4923
5046
  }
5047
+ function badPort(url) {
5048
+ const port3 = url.port ? Number(url.port) : 0;
5049
+ return port3 !== 0 && BAD_PORTS.has(port3);
5050
+ }
4924
5051
  function rewrite(hop, status2, location) {
4925
5052
  const next2 = new URL(location, hop.url);
4926
5053
  if (next2.protocol !== "http:" && next2.protocol !== "https:") {
4927
5054
  throw failed(new JsCallError("EPROTONOSUPPORT", next2.protocol));
4928
5055
  }
5056
+ if (badPort(next2)) {
5057
+ throw failed(new JsCallError("EACCES", `bad port: ${next2.href}`));
5058
+ }
4929
5059
  if (local2(next2.href) && !local2(hop.url)) {
4930
5060
  const from = new URL(hop.url).origin;
4931
5061
  throw failed(
@@ -5211,6 +5341,9 @@ function fetchOp(kernel) {
5211
5341
  if (protocol !== "http:" && protocol !== "https:") {
5212
5342
  throw failed(new JsCallError("EPROTONOSUPPORT", protocol));
5213
5343
  }
5344
+ if (badPort(new URL(request.url))) {
5345
+ throw failed(new JsCallError("EACCES", `bad port: ${request.url}`));
5346
+ }
5214
5347
  let known = await traitsAt(request.url);
5215
5348
  if (!known.manualRedirects && request.redirect !== "follow") {
5216
5349
  throw failed(new JsCallError("ENOTSUP", `redirect: ${request.redirect}`));
@@ -5241,7 +5374,7 @@ function fetchOp(kernel) {
5241
5374
  }
5242
5375
  };
5243
5376
  }
5244
- var CHUNK2, MAX_REDIRECTS, NULL_BODY, REDIRECTS, BODY_HEADERS, DECODED, CREDENTIALS, OVER, TOKEN, QUOTABLE, SPACE, BASE64, SLICE;
5377
+ var CHUNK2, MAX_REDIRECTS, NULL_BODY, REDIRECTS, BODY_HEADERS, DECODED, CREDENTIALS, BAD_PORTS, OVER, TOKEN, QUOTABLE, SPACE, BASE64, SLICE;
5245
5378
  var init_js_fetch = __esm({
5246
5379
  "src/process/js/js-fetch.ts"() {
5247
5380
  "use strict";
@@ -5260,6 +5393,89 @@ var init_js_fetch = __esm({
5260
5393
  ]);
5261
5394
  DECODED = /* @__PURE__ */ new Set(["gzip", "x-gzip", "deflate"]);
5262
5395
  CREDENTIALS = /* @__PURE__ */ new Set(["authorization", "proxy-authorization", "cookie", "cookie2"]);
5396
+ BAD_PORTS = /* @__PURE__ */ new Set([
5397
+ 1,
5398
+ 7,
5399
+ 9,
5400
+ 11,
5401
+ 13,
5402
+ 15,
5403
+ 17,
5404
+ 19,
5405
+ 20,
5406
+ 21,
5407
+ 22,
5408
+ 23,
5409
+ 25,
5410
+ 37,
5411
+ 42,
5412
+ 43,
5413
+ 53,
5414
+ 69,
5415
+ 77,
5416
+ 79,
5417
+ 87,
5418
+ 95,
5419
+ 101,
5420
+ 102,
5421
+ 103,
5422
+ 104,
5423
+ 109,
5424
+ 110,
5425
+ 111,
5426
+ 113,
5427
+ 115,
5428
+ 117,
5429
+ 119,
5430
+ 123,
5431
+ 135,
5432
+ 137,
5433
+ 139,
5434
+ 143,
5435
+ 161,
5436
+ 179,
5437
+ 389,
5438
+ 427,
5439
+ 465,
5440
+ 512,
5441
+ 513,
5442
+ 514,
5443
+ 515,
5444
+ 526,
5445
+ 530,
5446
+ 531,
5447
+ 532,
5448
+ 540,
5449
+ 548,
5450
+ 554,
5451
+ 556,
5452
+ 563,
5453
+ 587,
5454
+ 601,
5455
+ 636,
5456
+ 989,
5457
+ 990,
5458
+ 993,
5459
+ 995,
5460
+ 1719,
5461
+ 1720,
5462
+ 1723,
5463
+ 2049,
5464
+ 3659,
5465
+ 4045,
5466
+ 4190,
5467
+ 5060,
5468
+ 5061,
5469
+ 6e3,
5470
+ 6566,
5471
+ 6665,
5472
+ 6666,
5473
+ 6667,
5474
+ 6668,
5475
+ 6669,
5476
+ 6697,
5477
+ 10080
5478
+ ]);
5263
5479
  OVER = /* @__PURE__ */ Symbol("over");
5264
5480
  TOKEN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
5265
5481
  QUOTABLE = /^[\t\x20-\x7e\x80-\xff]*$/;
@@ -5410,6 +5626,45 @@ var init_js_net = __esm({
5410
5626
  }
5411
5627
  });
5412
5628
 
5629
+ // src/fs/owners.ts
5630
+ function inGroup(cred, gid) {
5631
+ return cred.egid === gid || cred.groups.includes(gid);
5632
+ }
5633
+ var ROOT_OWNER;
5634
+ var init_owners = __esm({
5635
+ "src/fs/owners.ts"() {
5636
+ "use strict";
5637
+ init_types();
5638
+ ROOT_OWNER = Object.freeze({ uid: 0, gid: 0 });
5639
+ }
5640
+ });
5641
+
5642
+ // src/fs/walk.ts
5643
+ var init_walk = __esm({
5644
+ "src/fs/walk.ts"() {
5645
+ "use strict";
5646
+ init_types();
5647
+ }
5648
+ });
5649
+
5650
+ // src/fs/access.ts
5651
+ function permits(cred, perm, want, directory = true) {
5652
+ const mode = perm.mode ?? (directory ? 493 : 420);
5653
+ if (cred.euid === 0) return (want & X_OK) === 0 || directory || (mode & 73) !== 0;
5654
+ const shift = cred.euid === perm.uid ? 6 : inGroup(cred, perm.gid) ? 3 : 0;
5655
+ return (mode >> shift & want) === want;
5656
+ }
5657
+ var X_OK;
5658
+ var init_access = __esm({
5659
+ "src/fs/access.ts"() {
5660
+ "use strict";
5661
+ init_owners();
5662
+ init_types();
5663
+ init_walk();
5664
+ X_OK = 1;
5665
+ }
5666
+ });
5667
+
5413
5668
  // src/process/wasi-errno.ts
5414
5669
  function wasiErrno(code2) {
5415
5670
  return WASI_ERRNO[code2] ?? E.IO;
@@ -5618,12 +5873,21 @@ function createSyncFsSabBridge(transport, opts = {}) {
5618
5873
  lutimes: (path, atimeMs, mtimeMs, now) => {
5619
5874
  run({ op: "lutimes", path, atimeMs, mtimeMs, ...now ? { now } : {} }, path);
5620
5875
  },
5621
- create: (path, mode) => {
5622
- run({ op: "create", path, ...mode !== void 0 ? { mode } : {} }, path);
5876
+ create: (path, mode, opening2) => {
5877
+ const flags = { ...mode !== void 0 ? { mode } : {}, ...opening2 ? { opening: opening2 } : {} };
5878
+ run({ op: "create", path, ...flags }, path);
5623
5879
  },
5624
- chown: (path, uid, gid, follow2) => {
5880
+ chown: (path, uid, gid, follow2, handle) => {
5625
5881
  const ids = { ...uid !== void 0 ? { uid } : {}, ...gid !== void 0 ? { gid } : {} };
5626
- changing({ op: follow2 ? "chown" : "lchown", path, ...ids }, path);
5882
+ changing(
5883
+ {
5884
+ op: follow2 ? "chown" : "lchown",
5885
+ path,
5886
+ ...ids,
5887
+ ...handle !== void 0 ? { handle } : {}
5888
+ },
5889
+ path
5890
+ );
5627
5891
  },
5628
5892
  ...opts.owners ? { owners: true } : {},
5629
5893
  ...opts.links ? { links: true } : {},
@@ -5700,15 +5964,36 @@ function refusal(err) {
5700
5964
  function cachedStat(s, dir) {
5701
5965
  return s.stat !== void 0 && (!dir || s.statAt === syncCallCount());
5702
5966
  }
5967
+ function searchParents(Fs, node, bridge, call2) {
5968
+ const cred = Fs.sliccCred;
5969
+ if (!cred) return;
5970
+ let cur = node.parent;
5971
+ while (cur) {
5972
+ const st = cur.live.stat;
5973
+ if (st && st.uid !== void 0 && st.mode !== void 0) {
5974
+ const perm = { uid: st.uid, gid: st.gid ?? 0, mode: st.mode & 4095 };
5975
+ if (!permits(cred, perm, X_OK, true)) {
5976
+ call2(() => bridge.access?.(liveNodePath(cur), X_OK, "eaccess"));
5977
+ cur.live.stat = void 0;
5978
+ return;
5979
+ }
5980
+ } else {
5981
+ call2(() => bridge.access?.(liveNodePath(cur), X_OK, "eaccess"));
5982
+ return;
5983
+ }
5984
+ if (cur === cur.parent) break;
5985
+ cur = cur.parent;
5986
+ }
5987
+ }
5703
5988
  function linkedStates(bridgeOf) {
5704
5989
  const opens = /* @__PURE__ */ new Map();
5705
5990
  const byId = /* @__PURE__ */ new Map();
5706
- const idOf3 = (st) => st?.ino === void 0 || (st.nlink ?? 1) < 2 ? void 0 : `${st.dev}:${st.ino}`;
5991
+ const idOf4 = (st) => st?.ino === void 0 || (st.nlink ?? 1) < 2 ? void 0 : `${st.dev}:${st.ino}`;
5707
5992
  function know(s, id) {
5708
5993
  s.id = id;
5709
5994
  if (!byId.has(id)) byId.set(id, s);
5710
5995
  }
5711
- function opening(node, on) {
5996
+ function opening2(node, on) {
5712
5997
  const s = node.live;
5713
5998
  if (!on) {
5714
5999
  opens.delete(s);
@@ -5717,14 +6002,14 @@ function linkedStates(bridgeOf) {
5717
6002
  return;
5718
6003
  }
5719
6004
  opens.set(s, node);
5720
- const id = idOf3(s.stat);
6005
+ const id = idOf4(s.stat);
5721
6006
  if (id !== void 0) know(s, id);
5722
6007
  }
5723
6008
  function sharedWith(node) {
5724
6009
  const st = node.live.stat;
5725
6010
  if (st?.ino === void 0) return void 0;
5726
6011
  const id = `${st.dev}:${st.ino}`;
5727
- if (!byId.has(id) && idOf3(st) !== void 0) {
6012
+ if (!byId.has(id) && idOf4(st) !== void 0) {
5728
6013
  for (const [s2, other] of opens) {
5729
6014
  if (s2.id !== void 0 || s2.orphan) continue;
5730
6015
  let st2;
@@ -5732,7 +6017,7 @@ function linkedStates(bridgeOf) {
5732
6017
  st2 = bridgeOf(other).lstat(liveNodePath(other));
5733
6018
  } catch {
5734
6019
  }
5735
- const known = idOf3(st2);
6020
+ const known = idOf4(st2);
5736
6021
  if (known !== void 0) know(s2, known);
5737
6022
  }
5738
6023
  }
@@ -5740,7 +6025,7 @@ function linkedStates(bridgeOf) {
5740
6025
  return s && s !== node.live && !stale(s) ? s : void 0;
5741
6026
  }
5742
6027
  const holder = (node) => opens.get(node.live) ?? node;
5743
- return { opening, sharedWith, know, idOf: idOf3, holder };
6028
+ return { opening: opening2, sharedWith, know, idOf: idOf4, holder };
5744
6029
  }
5745
6030
  function createHelpers(Fs, ops) {
5746
6031
  const bridgeOf = (node) => node.mount.opts.bridge;
@@ -5962,7 +6247,9 @@ function createNodeOps(h) {
5962
6247
  const owned = bridgeOf(node).owners === true;
5963
6248
  if (owned && Fs.isLink(node.mode) && statOf(node).uid === void 0)
5964
6249
  node.live.stat = void 0;
6250
+ const cached = owned && cachedStat(node.live, Fs.isDir(node.mode));
5965
6251
  const st = statOf(node);
6252
+ if (cached) searchParents(Fs, node, bridgeOf(node), call2);
5966
6253
  const s = node.live;
5967
6254
  const size = Fs.isDir(node.mode) ? 4096 : s.ranged?.size() ?? (s.loaded ? s.len : st.size);
5968
6255
  const mtime = new Date(st.mtimeMs ?? 0);
@@ -6025,7 +6312,7 @@ function createNodeOps(h) {
6025
6312
  if (masked !== DEFAULT_DIR_PERM) metadataCall(() => bridge.chmod(path, masked));
6026
6313
  } else if (Fs.isFile(mode)) {
6027
6314
  call2(
6028
- () => bridge.create ? bridge.create(path, perm) : bridge.writeFile(path, new Uint8Array(0))
6315
+ () => bridge.create ? bridge.create(path, perm, opening.get(h.Fs) > 0) : bridge.writeFile(path, new Uint8Array(0))
6029
6316
  );
6030
6317
  } else {
6031
6318
  throw new Fs.ErrnoError(wasiErrno("EPERM"));
@@ -6271,10 +6558,24 @@ function createStreamOps(h) {
6271
6558
  }
6272
6559
  };
6273
6560
  }
6561
+ function countOpens(Fs) {
6562
+ const { open } = Fs;
6563
+ if (typeof open !== "function" || opening.has(Fs)) return;
6564
+ opening.set(Fs, 0);
6565
+ Fs.open = function(...args) {
6566
+ opening.set(Fs, (opening.get(Fs) ?? 0) + 1);
6567
+ try {
6568
+ return open.apply(this, args);
6569
+ } finally {
6570
+ opening.set(Fs, (opening.get(Fs) ?? 1) - 1);
6571
+ }
6572
+ };
6573
+ }
6274
6574
  function createLiveVfsPlugin(Fs) {
6275
6575
  const mounts = /* @__PURE__ */ new Set();
6276
6576
  const ops = {};
6277
6577
  const h = createHelpers(Fs, ops);
6578
+ countOpens(Fs);
6278
6579
  const nodeOps = createNodeOps(h);
6279
6580
  const streamOps = createStreamOps(h);
6280
6581
  ops.node = nodeOps;
@@ -6407,12 +6708,12 @@ function liveRoot(Fs, bridge) {
6407
6708
  };
6408
6709
  }
6409
6710
  function crosses(Fs, from, to) {
6410
- const parentOf = (path) => Fs.lookupPath?.(path, { parent: true }).node;
6711
+ const parentOf2 = (path) => Fs.lookupPath?.(path, { parent: true }).node;
6411
6712
  const name2 = from.replace(/\/+$/, "").split("/").pop() ?? "";
6412
6713
  try {
6413
- const fromDir = parentOf(from);
6714
+ const fromDir = parentOf2(from);
6414
6715
  const node = fromDir && Fs.lookupNode?.(fromDir, name2);
6415
- const dir = parentOf(to);
6716
+ const dir = parentOf2(to);
6416
6717
  return !!node && !!dir && !!node.live !== !!dir.live;
6417
6718
  } catch {
6418
6719
  return false;
@@ -6476,6 +6777,25 @@ function guardRenames(Fs) {
6476
6777
  function idOf2(value2) {
6477
6778
  return value2 === -1 || value2 === 4294967295 ? void 0 : value2 >>> 0;
6478
6779
  }
6780
+ function chownHeld(Fs, node, s, uid, gid) {
6781
+ const bridge = node.mount.opts.bridge;
6782
+ const handle = s.handle;
6783
+ try {
6784
+ bridge.chown?.(liveNodePath(node), idOf2(uid), idOf2(gid), false, handle);
6785
+ } catch (err) {
6786
+ throw toErrno(Fs, err);
6787
+ }
6788
+ if (node.parent?.live) node.parent.live.listed = void 0;
6789
+ if (!s.orphan) {
6790
+ s.stat = void 0;
6791
+ return;
6792
+ }
6793
+ try {
6794
+ const st = bridge.keptStat?.(handle);
6795
+ if (st && s.stat) s.stat = { ...s.stat, uid: st.uid, gid: st.gid, mode: st.mode };
6796
+ } catch {
6797
+ }
6798
+ }
6479
6799
  function useLiveChown(Fs) {
6480
6800
  const chown = Fs.chown?.bind(Fs);
6481
6801
  if (!chown) return;
@@ -6494,8 +6814,10 @@ function useLiveChown(Fs) {
6494
6814
  if (!Fs.fchown || !getStreamChecked) return;
6495
6815
  Fs.fchown = (fd, uid, gid) => {
6496
6816
  const stream = getStreamChecked.call(Fs, fd);
6497
- const live = stream.node.live !== void 0;
6498
- const target = live || stream.path === void 0 ? stream.node : stream.path;
6817
+ const node = stream.node;
6818
+ const s = node.live;
6819
+ if (s?.handle !== void 0 && (!s.orphan || s.kept)) return chownHeld(Fs, node, s, uid, gid);
6820
+ const target = s !== void 0 || stream.path === void 0 ? stream.node : stream.path;
6499
6821
  Fs.chown(target, uid, gid);
6500
6822
  };
6501
6823
  }
@@ -6556,10 +6878,11 @@ function readingLinks(Fs) {
6556
6878
  }
6557
6879
  };
6558
6880
  }
6559
- 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;
6881
+ 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, opening;
6560
6882
  var init_live_vfs_fs = __esm({
6561
6883
  "src/realm/live-vfs-fs.ts"() {
6562
6884
  "use strict";
6885
+ init_access();
6563
6886
  init_ranged();
6564
6887
  init_types();
6565
6888
  init_wasi_errno();
@@ -6578,6 +6901,7 @@ var init_live_vfs_fs = __esm({
6578
6901
  O_TRUNC = 512;
6579
6902
  O_PATH = 2097152;
6580
6903
  stale = (s) => !!s.orphan && !s.kept;
6904
+ opening = /* @__PURE__ */ new WeakMap();
6581
6905
  }
6582
6906
  });
6583
6907
 
@@ -7016,14 +7340,17 @@ function wasmMemory(instance, imports) {
7016
7340
  }
7017
7341
  return void 0;
7018
7342
  }
7019
- function fdOfPath(path, cwd) {
7343
+ function absoluteOf(path, cwd) {
7020
7344
  const parts = [];
7021
7345
  for (const part of `${path.startsWith("/") ? "" : cwd}/${path}`.split("/")) {
7022
7346
  if (part === "" || part === ".") continue;
7023
7347
  if (part === "..") parts.pop();
7024
7348
  else parts.push(part);
7025
7349
  }
7026
- const abs = `/${parts.join("/")}`;
7350
+ return `/${parts.join("/")}`;
7351
+ }
7352
+ function fdOfPath(path, cwd) {
7353
+ const abs = absoluteOf(path, cwd);
7027
7354
  const std = ["/dev/stdin", "/dev/stdout", "/dev/stderr"].indexOf(abs);
7028
7355
  if (std >= 0) return std;
7029
7356
  const m = /^\/(?:dev|proc\/self)\/fd\/(\d+)$/.exec(abs);
@@ -7095,6 +7422,18 @@ function useZeroDevices(Fs) {
7095
7422
  mkdev.call(Fs, path, CHAR_DEVICE, dev);
7096
7423
  }
7097
7424
  }
7425
+ function useDevRemoval(Fs) {
7426
+ const fs = Fs;
7427
+ for (const name2 of ["unlink", "rmdir"]) {
7428
+ const remove = fs[name2];
7429
+ if (typeof remove !== "function") continue;
7430
+ fs[name2] = (path) => {
7431
+ const refused2 = devRemoval(absoluteOf(path, Fs.cwd()), fs.sliccCred);
7432
+ if (refused2) throw new Fs.ErrnoError(wasiErrno(refused2));
7433
+ remove.call(Fs, path);
7434
+ };
7435
+ }
7436
+ }
7098
7437
  function linkStdio(Fs) {
7099
7438
  const { unlink, symlink } = Fs;
7100
7439
  if (!unlink || !symlink) return;
@@ -7310,6 +7649,7 @@ var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC,
7310
7649
  var init_process_fds = __esm({
7311
7650
  "src/process/process-fds.ts"() {
7312
7651
  "use strict";
7652
+ init_dev_removal();
7313
7653
  init_loopback_names();
7314
7654
  init_live_vfs_fs();
7315
7655
  init_process_pty();
@@ -7988,7 +8328,7 @@ function procfsBridge(fs, tree) {
7988
8328
  }
7989
8329
  const { chown } = fs;
7990
8330
  if (chown) {
7991
- over.chown = (p, uid, gid, follow2) => readOnly2([[p, follow2 === true]], () => chown.call(fs, p, uid, gid, follow2));
8331
+ over.chown = (p, ...rest2) => readOnly2([[p, rest2[2] === true]], () => chown.call(fs, p, ...rest2));
7992
8332
  }
7993
8333
  return new Proxy(fs, {
7994
8334
  get: (target, key, receiver) => key in over ? over[key] : Reflect.get(target, key, receiver)
@@ -8349,6 +8689,24 @@ function laneOf(lane) {
8349
8689
  }
8350
8690
  function syncOps(kernel, shared) {
8351
8691
  const { infos, handles, resolve } = shared;
8692
+ const tryDevSync = (abs) => {
8693
+ try {
8694
+ const resolved2 = physicalPath(
8695
+ {
8696
+ lstat(p) {
8697
+ return parseSyncFsStat(kernel.json({ op: "lstat", path: p })) ?? {};
8698
+ },
8699
+ readlink(p) {
8700
+ return String(kernel.json({ op: "readlink", path: p }));
8701
+ }
8702
+ },
8703
+ abs
8704
+ );
8705
+ return resolved2 !== abs && inDev(resolved2) ? resolved2 : void 0;
8706
+ } catch {
8707
+ return void 0;
8708
+ }
8709
+ };
8352
8710
  const info = (fd) => {
8353
8711
  const known = infos.get(fd);
8354
8712
  if (known) return known;
@@ -8381,10 +8739,17 @@ function syncOps(kernel, shared) {
8381
8739
  const statOf = (op, path) => {
8382
8740
  const abs = resolve(path);
8383
8741
  if (inDev(abs)) return devSync(kernel, devStat(abs, op === "stat"));
8384
- kernel.call({ op: "fd-path-flush", path: abs });
8385
- const s = parseSyncFsStat(kernel.json({ op, path: abs }));
8386
- if (!s) throw new JsCallError("EIO", op);
8387
- return s;
8742
+ try {
8743
+ kernel.call({ op: "fd-path-flush", path: abs });
8744
+ const s = parseSyncFsStat(kernel.json({ op, path: abs }));
8745
+ if (!s) throw new JsCallError("EIO", op);
8746
+ return s;
8747
+ } catch (err) {
8748
+ if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
8749
+ const devPath = tryDevSync(abs);
8750
+ if (!devPath) throw err;
8751
+ return devSync(kernel, devStat(devPath, op === "stat"));
8752
+ }
8388
8753
  };
8389
8754
  const openDev2 = (abs, options) => {
8390
8755
  const { fd, file, ...access } = devSync(kernel, devOpen(abs, options));
@@ -8404,27 +8769,34 @@ function syncOps(kernel, shared) {
8404
8769
  const open = (path, options = {}) => {
8405
8770
  const abs = resolve(path);
8406
8771
  if (inDev(abs)) return openDev2(abs, options);
8407
- let existing;
8408
- try {
8409
- existing = statOf(isExclusive(options) ? "lstat" : "stat", abs);
8410
- } catch (err) {
8411
- existing = absent(err);
8412
- }
8413
- checkOpen(abs, options, existing);
8414
- const fd = kernel.json(openRequest(abs, options));
8415
8772
  try {
8416
- kernel.call({ op: "fd-vfs-stat", fd });
8773
+ let existing;
8774
+ try {
8775
+ existing = statOf(isExclusive(options) ? "lstat" : "stat", abs);
8776
+ } catch (err) {
8777
+ existing = absent(err);
8778
+ }
8779
+ checkOpen(abs, options, existing);
8780
+ const fd = kernel.json(openRequest(abs, options));
8781
+ try {
8782
+ kernel.call({ op: "fd-vfs-stat", fd });
8783
+ } catch (err) {
8784
+ kernel.raw({ op: "fd-close", fd });
8785
+ throw err;
8786
+ }
8787
+ infos.set(fd, { kind: "file" });
8788
+ const handle = syncFile(kernel, fd, abs, options.append === true, () => {
8789
+ infos.delete(fd);
8790
+ handles.delete(fd);
8791
+ });
8792
+ handles.set(fd, handle.invalidate);
8793
+ return handle.file;
8417
8794
  } catch (err) {
8418
- kernel.raw({ op: "fd-close", fd });
8419
- throw err;
8795
+ if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
8796
+ const devPath = tryDevSync(abs);
8797
+ if (!devPath) throw err;
8798
+ return openDev2(devPath, options);
8420
8799
  }
8421
- infos.set(fd, { kind: "file" });
8422
- const handle = syncFile(kernel, fd, abs, options.append === true, () => {
8423
- infos.delete(fd);
8424
- handles.delete(fd);
8425
- });
8426
- handles.set(fd, handle.invalidate);
8427
- return handle.file;
8428
8800
  };
8429
8801
  return {
8430
8802
  read: read2,
@@ -8436,7 +8808,7 @@ function syncOps(kernel, shared) {
8436
8808
  kernel.call({ op: "fd-close", fd });
8437
8809
  },
8438
8810
  open: procOpenSync(open, kernel, { resolve, pid: shared.pid }),
8439
- fs: procFsSync(syncPathOps(kernel, resolve, statOf, open), kernel, {
8811
+ fs: procFsSync(syncPathOps(kernel, resolve, statOf, open, tryDevSync), kernel, {
8440
8812
  resolve,
8441
8813
  pid: shared.pid
8442
8814
  })
@@ -8506,14 +8878,16 @@ function syncFile(kernel, fd, path, append, forget) {
8506
8878
  }
8507
8879
  };
8508
8880
  }
8509
- function syncPathOps(kernel, resolve, statOf, open) {
8881
+ function syncPathOps(kernel, resolve, statOf, open, tryDev) {
8510
8882
  return {
8511
8883
  stat: (path) => statOf("stat", path),
8512
8884
  lstat: (path) => statOf("lstat", path),
8513
8885
  exists(path) {
8514
8886
  const abs = resolve(path);
8515
8887
  if (inDev(abs)) return devSync(kernel, devExists(abs));
8516
- return kernel.json({ op: "exists", path: abs }) === true;
8888
+ if (kernel.json({ op: "exists", path: abs }) === true) return true;
8889
+ const devPath = tryDev(abs);
8890
+ return devPath ? devSync(kernel, devExists(devPath)) : false;
8517
8891
  },
8518
8892
  readdir(path) {
8519
8893
  const abs = resolve(path);
@@ -8538,15 +8912,29 @@ function syncPathOps(kernel, resolve, statOf, open) {
8538
8912
  return String(kernel.json({ op: "readlink", path: abs }));
8539
8913
  },
8540
8914
  statfs(path) {
8541
- const abs = resolve(path);
8915
+ let abs = resolve(path);
8916
+ if (inDev(abs)) {
8917
+ try {
8918
+ const target = devSync(kernel, devResolveTarget(abs));
8919
+ if (target?.startsWith("/")) abs = target;
8920
+ } catch {
8921
+ }
8922
+ }
8542
8923
  statOf("stat", abs);
8543
8924
  return statFsOf(kernel.json({ op: "statfs", path: abs }));
8544
8925
  },
8545
8926
  readFile(path) {
8546
8927
  const abs = resolve(path);
8547
8928
  if (inDev(abs)) return readWholeSync(open(abs));
8548
- kernel.call({ op: "fd-path-flush", path: abs });
8549
- return kernel.bytes({ op: "read", path: abs });
8929
+ try {
8930
+ kernel.call({ op: "fd-path-flush", path: abs });
8931
+ return kernel.bytes({ op: "read", path: abs });
8932
+ } catch (err) {
8933
+ if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
8934
+ const devPath = tryDev(abs);
8935
+ if (!devPath) throw err;
8936
+ return readWholeSync(open(devPath));
8937
+ }
8550
8938
  },
8551
8939
  writeFile(path, data, options) {
8552
8940
  const mode = options?.mode;
@@ -8568,6 +8956,7 @@ var encoder3, noLane, JsSyncKernel;
8568
8956
  var init_js_sync = __esm({
8569
8957
  "src/process/js/js-sync.ts"() {
8570
8958
  "use strict";
8959
+ init_physical_path();
8571
8960
  init_signals();
8572
8961
  init_sync_fs_wire();
8573
8962
  init_sync_sab_bridge();
@@ -8964,6 +9353,55 @@ function readable2(read2) {
8964
9353
  { highWaterMark: 0 }
8965
9354
  );
8966
9355
  }
9356
+ async function resolveDevAsync(kernel, abs) {
9357
+ try {
9358
+ const resolved2 = await physicalPathAsync(
9359
+ {
9360
+ async lstat(p) {
9361
+ return parseSyncFsStat(await kernel.json({ op: "lstat", path: p })) ?? {};
9362
+ },
9363
+ async readlink(p) {
9364
+ return String(await kernel.json({ op: "readlink", path: p }));
9365
+ }
9366
+ },
9367
+ abs
9368
+ );
9369
+ return resolved2 !== abs && inDev(resolved2) ? resolved2 : void 0;
9370
+ } catch {
9371
+ return void 0;
9372
+ }
9373
+ }
9374
+ async function vfsStat(kernel, abs, op, tryDev) {
9375
+ try {
9376
+ await kernel.call({ op: "fd-path-flush", path: abs });
9377
+ const s = parseSyncFsStat(await kernel.json({ op, path: abs }));
9378
+ if (!s) throw new JsCallError("EIO", op);
9379
+ return s;
9380
+ } catch (err) {
9381
+ if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
9382
+ const devPath = await tryDev(abs);
9383
+ if (!devPath) throw err;
9384
+ return devAsync(kernel, devStat(devPath, op === "stat"));
9385
+ }
9386
+ }
9387
+ async function vfsOpen(kernel, abs, options, statOf, infos, handles) {
9388
+ const existing = await statOf(isExclusive(options) ? "lstat" : "stat", abs).catch(absent);
9389
+ checkOpen(abs, options, existing);
9390
+ const fd = await kernel.json(openRequest(abs, options));
9391
+ try {
9392
+ await kernel.call({ op: "fd-vfs-stat", fd });
9393
+ } catch (err) {
9394
+ await kernel.raw({ op: "fd-close", fd });
9395
+ throw err;
9396
+ }
9397
+ infos.set(fd, { kind: "file" });
9398
+ const handle = fileHandle(kernel, fd, abs, options.append === true, () => {
9399
+ infos.delete(fd);
9400
+ handles.delete(fd);
9401
+ });
9402
+ handles.set(fd, handle.invalidate);
9403
+ return handle.file;
9404
+ }
8967
9405
  function createContext(o) {
8968
9406
  const { kernel } = o;
8969
9407
  const infos = /* @__PURE__ */ new Map();
@@ -8971,6 +9409,7 @@ function createContext(o) {
8971
9409
  const pending = /* @__PURE__ */ new Set();
8972
9410
  const random = o.random ?? ((bytes) => void crypto.getRandomValues(bytes));
8973
9411
  const resolve = (path) => resolvePath(o.cwd, path);
9412
+ const tryDev = (abs) => resolveDevAsync(kernel, abs);
8974
9413
  let exiting;
8975
9414
  const exit = (code2 = 0) => {
8976
9415
  exiting ??= code2;
@@ -9013,32 +9452,25 @@ function createContext(o) {
9013
9452
  const statOf = async (op, path) => {
9014
9453
  const abs = resolve(path);
9015
9454
  if (inDev(abs)) return devAsync(kernel, devStat(abs, op === "stat"));
9016
- await kernel.call({ op: "fd-path-flush", path: abs });
9017
- const s = parseSyncFsStat(await kernel.json({ op, path: abs }));
9018
- if (!s) throw new JsCallError("EIO", op);
9019
- return s;
9455
+ return vfsStat(kernel, abs, op, tryDev);
9020
9456
  };
9457
+ const devIo = { infos, handles, read: read2, write: writeAll };
9021
9458
  const open = async (path, options = {}) => {
9022
9459
  const abs = resolve(path);
9023
- if (inDev(abs)) return openDev(kernel, abs, options, { infos, handles, read: read2, write: writeAll });
9024
- const existing = await statOf(isExclusive(options) ? "lstat" : "stat", abs).catch(absent);
9025
- checkOpen(abs, options, existing);
9026
- const fd = await kernel.json(openRequest(abs, options));
9460
+ if (inDev(abs)) return openDev(kernel, abs, options, devIo);
9027
9461
  try {
9028
- await kernel.call({ op: "fd-vfs-stat", fd });
9462
+ return await vfsOpen(kernel, abs, options, statOf, infos, handles);
9029
9463
  } catch (err) {
9030
- await kernel.raw({ op: "fd-close", fd });
9031
- throw err;
9464
+ if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
9465
+ const devPath = await tryDev(abs);
9466
+ if (!devPath) throw err;
9467
+ return openDev(kernel, devPath, options, devIo);
9032
9468
  }
9033
- infos.set(fd, { kind: "file" });
9034
- const handle = fileHandle(kernel, fd, abs, options.append === true, () => {
9035
- infos.delete(fd);
9036
- handles.delete(fd);
9037
- });
9038
- handles.set(fd, handle.invalidate);
9039
- return handle.file;
9040
9469
  };
9041
- const fs = procFsAsync(pathOps(kernel, resolve, statOf, open), kernel, { resolve, pid: o.pid });
9470
+ const fs = procFsAsync(pathOps(kernel, resolve, statOf, open, tryDev), kernel, {
9471
+ resolve,
9472
+ pid: o.pid
9473
+ });
9042
9474
  const lane = o.lane ?? laneOf(void 0);
9043
9475
  if (o.lane && o.lane !== noLane) kernel.syncLane = o.lane;
9044
9476
  const syncKernel = new JsSyncKernel(lane, kernel, unwind);
@@ -9234,14 +9666,16 @@ async function sendSome(kernel, fd, body, signal) {
9234
9666
  await kernel.blocking({ op: "fd-select", read: [], write: [fd], timeoutMs: -1 }, signal);
9235
9667
  }
9236
9668
  }
9237
- function pathOps(kernel, resolve, statOf, open) {
9669
+ function pathOps(kernel, resolve, statOf, open, tryDev) {
9238
9670
  return {
9239
9671
  stat: (path) => statOf("stat", path),
9240
9672
  lstat: (path) => statOf("lstat", path),
9241
9673
  async exists(path) {
9242
9674
  const abs = resolve(path);
9243
9675
  if (inDev(abs)) return devAsync(kernel, devExists(abs));
9244
- return await kernel.json({ op: "exists", path: abs }) === true;
9676
+ if (await kernel.json({ op: "exists", path: abs }) === true) return true;
9677
+ const devPath = await tryDev(abs);
9678
+ return devPath ? devAsync(kernel, devExists(devPath)) : false;
9245
9679
  },
9246
9680
  async readdir(path) {
9247
9681
  const abs = resolve(path);
@@ -9266,15 +9700,26 @@ function pathOps(kernel, resolve, statOf, open) {
9266
9700
  return String(await kernel.json({ op: "readlink", path: abs }));
9267
9701
  },
9268
9702
  async statfs(path) {
9269
- const abs = resolve(path);
9703
+ let abs = resolve(path);
9704
+ if (inDev(abs)) {
9705
+ const target = await devAsync(kernel, devResolveTarget(abs)).catch(() => void 0);
9706
+ if (target?.startsWith("/")) abs = target;
9707
+ }
9270
9708
  await statOf("stat", abs);
9271
9709
  return statFsOf(await kernel.json({ op: "statfs", path: abs }));
9272
9710
  },
9273
9711
  async readFile(path) {
9274
9712
  const abs = resolve(path);
9275
9713
  if (inDev(abs)) return readWhole(await open(abs));
9276
- await kernel.call({ op: "fd-path-flush", path: abs });
9277
- return kernel.bytes({ op: "read", path: abs });
9714
+ try {
9715
+ await kernel.call({ op: "fd-path-flush", path: abs });
9716
+ return await kernel.bytes({ op: "read", path: abs });
9717
+ } catch (err) {
9718
+ if (!(err instanceof JsCallError) || err.code !== "ENOENT") throw err;
9719
+ const devPath = await tryDev(abs);
9720
+ if (!devPath) throw err;
9721
+ return readWhole(await open(devPath));
9722
+ }
9278
9723
  },
9279
9724
  async writeFile(path, data, options) {
9280
9725
  const mode = options?.mode;
@@ -9296,6 +9741,7 @@ var KERNEL_INFO, JsExit, encoder4;
9296
9741
  var init_js_context = __esm({
9297
9742
  "src/process/js/js-context.ts"() {
9298
9743
  "use strict";
9744
+ init_physical_path();
9299
9745
  init_signals();
9300
9746
  init_sync_fs_wire();
9301
9747
  init_version();
@@ -9466,6 +9912,22 @@ function topLevelDirs(bridge, warn) {
9466
9912
  }
9467
9913
  return dirs;
9468
9914
  }
9915
+ function linuxRmdir(Fs) {
9916
+ const raw = Fs;
9917
+ const { mayDelete, lookupNode } = raw;
9918
+ if (!mayDelete || !lookupNode) return;
9919
+ raw.mayDelete = (dir, name2, isdir) => {
9920
+ const code2 = mayDelete.call(raw, dir, name2, isdir);
9921
+ if (code2 !== 10 || !isdir) return code2;
9922
+ try {
9923
+ const node = lookupNode.call(raw, dir, name2);
9924
+ if (node === node.parent) return 10;
9925
+ } catch {
9926
+ return code2;
9927
+ }
9928
+ return 0;
9929
+ };
9930
+ }
9469
9931
  function mountVfsIntoEmscripten(Fs, deps) {
9470
9932
  const { bridge, warn } = deps;
9471
9933
  const dirs = topLevelDirs(bridge, warn);
@@ -9473,6 +9935,8 @@ function mountVfsIntoEmscripten(Fs, deps) {
9473
9935
  if (dirs) liveRoot(Fs, bridge);
9474
9936
  if (bridge.owners && Fs.lookupPath) useLiveChown(Fs);
9475
9937
  if (bridge.links && Fs.lookupPath) readingLinks(Fs);
9938
+ linuxRmdir(Fs);
9939
+ if (deps.cred) Fs.sliccCred = deps.cred;
9476
9940
  try {
9477
9941
  Fs.chdir(deps.cwd);
9478
9942
  } catch (err) {
@@ -9495,6 +9959,81 @@ var init_emscripten_vfs_hook = __esm({
9495
9959
  }
9496
9960
  });
9497
9961
 
9962
+ // src/process/fd-metadata.ts
9963
+ function idOf3(value2) {
9964
+ return value2 === -1 || value2 === 4294967295 ? void 0 : value2 >>> 0;
9965
+ }
9966
+ function timeOf(value2) {
9967
+ return typeof value2 === "number" && Number.isFinite(value2) ? value2 : null;
9968
+ }
9969
+ function useKernelFdMetadata(Fs, sys, call2) {
9970
+ const { fdChown, fdChmod, fdUtimes } = sys;
9971
+ const meta = Fs;
9972
+ const kernelFd = (stream) => stream?.sliccKernelFile ? stream.sliccKernelFd : void 0;
9973
+ const find = (match) => {
9974
+ for (const s of Fs.streams) {
9975
+ const kfd = s && match(s) ? kernelFd(s) : void 0;
9976
+ if (kfd !== void 0) return kfd;
9977
+ }
9978
+ return void 0;
9979
+ };
9980
+ const ofPath = (path, follow2) => {
9981
+ if (typeof path !== "string") return find((s) => s.node === path);
9982
+ const fd = follow2 ? fdOfPath(path, Fs.cwd()) : void 0;
9983
+ if (fd !== void 0) return kernelFd(Fs.getStream(fd));
9984
+ return find((s) => s.path === path);
9985
+ };
9986
+ const ofFd = (fd) => kernelFd(Fs.getStream(fd));
9987
+ const chownBy = (kfd, uid, gid) => call2(() => fdChown?.call(sys, kfd, idOf3(uid), idOf3(gid)));
9988
+ if (fdChown && meta.chown) {
9989
+ const chown = meta.chown.bind(Fs);
9990
+ meta.chown = (path, uid, gid, dontFollow) => {
9991
+ const kfd = ofPath(path, !dontFollow);
9992
+ if (kfd === void 0) return chown(path, uid, gid, dontFollow);
9993
+ chownBy(kfd, uid, gid);
9994
+ };
9995
+ }
9996
+ if (fdChown && meta.fchown) {
9997
+ const fchown = meta.fchown.bind(Fs);
9998
+ meta.fchown = (fd, uid, gid) => {
9999
+ const kfd = ofFd(fd);
10000
+ if (kfd === void 0) return fchown(fd, uid, gid);
10001
+ chownBy(kfd, uid, gid);
10002
+ };
10003
+ }
10004
+ if (fdChmod && meta.chmod) {
10005
+ const chmod = meta.chmod.bind(Fs);
10006
+ meta.chmod = (path, mode, dontFollow) => {
10007
+ const kfd = ofPath(path, !dontFollow);
10008
+ if (kfd === void 0) return chmod(path, mode, dontFollow);
10009
+ call2(() => fdChmod.call(sys, kfd, mode & 4095));
10010
+ };
10011
+ }
10012
+ if (fdChmod && meta.fchmod) {
10013
+ const fchmod = meta.fchmod.bind(Fs);
10014
+ meta.fchmod = (fd, mode) => {
10015
+ const kfd = ofFd(fd);
10016
+ if (kfd === void 0) return fchmod(fd, mode);
10017
+ call2(() => fdChmod.call(sys, kfd, mode & 4095));
10018
+ };
10019
+ }
10020
+ if (fdUtimes && meta.utime) {
10021
+ const utime = meta.utime.bind(Fs);
10022
+ meta.utime = (path, atime, mtime) => {
10023
+ const kfd = ofPath(path, true);
10024
+ if (kfd === void 0) return utime(path, atime, mtime);
10025
+ const now = meta.sliccTouch === true;
10026
+ call2(() => fdUtimes.call(sys, kfd, timeOf(atime), timeOf(mtime), now));
10027
+ };
10028
+ }
10029
+ }
10030
+ var init_fd_metadata = __esm({
10031
+ "src/process/fd-metadata.ts"() {
10032
+ "use strict";
10033
+ init_process_fds();
10034
+ }
10035
+ });
10036
+
9498
10037
  // src/process/kernel-streams.ts
9499
10038
  function isPtyPath(path) {
9500
10039
  return PTY_PATH.test(path);
@@ -9522,7 +10061,7 @@ function sealedStat(minor = 250) {
9522
10061
  const now = /* @__PURE__ */ new Date();
9523
10062
  return {
9524
10063
  dev: 22,
9525
- ino: 1,
10064
+ ino: minor === 251 ? 2 : 1,
9526
10065
  mode: 8630,
9527
10066
  nlink: 1,
9528
10067
  uid: 0,
@@ -9539,10 +10078,18 @@ function sealedStat(minor = 250) {
9539
10078
  function nonblocking(stream) {
9540
10079
  return (stream.flags & O_NONBLOCK2) !== 0 ? { nonblock: true } : void 0;
9541
10080
  }
9542
- var POLLIN, POLLOUT, POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, TCSETSF, O_NONBLOCK2, SOCKET_MODE, PTY_PATH, TTY_PATH, TTY_NAME, SEALED_PATH2, STRERROR, CLIPBOARD_PATH2, O_CREAT2, O_EXCL, O_NOCTTY, O_TRUNC2, KILLED_BY_SIGPIPE, ProcessExit, SyscallError, KernelStreams;
10081
+ function datesOf(real) {
10082
+ const dates = {};
10083
+ for (const [key, value2] of Object.entries(real ?? {}))
10084
+ if (/^[amc]time$/.test(key) && (typeof value2 === "string" || typeof value2 === "number"))
10085
+ dates[key] = new Date(value2);
10086
+ return dates;
10087
+ }
10088
+ var POLLIN, POLLOUT, POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, TCSETSF, O_NONBLOCK2, SOCKET_MODE, PTY_PATH, TTY_PATH, TTY_NAME, SEALED_PATH2, STRERROR, CLIPBOARD_PATH2, O_CREAT2, O_EXCL, O_NOCTTY, O_TRUNC2, O_DIRECTORY, KILLED_BY_SIGPIPE, ProcessExit, SyscallError, KernelStreams;
9543
10089
  var init_kernel_streams = __esm({
9544
10090
  "src/process/kernel-streams.ts"() {
9545
10091
  "use strict";
10092
+ init_fd_metadata();
9546
10093
  init_wasi_errno();
9547
10094
  POLLIN = 1;
9548
10095
  POLLOUT = 4;
@@ -9571,6 +10118,7 @@ var init_kernel_streams = __esm({
9571
10118
  O_EXCL = 128;
9572
10119
  O_NOCTTY = 256;
9573
10120
  O_TRUNC2 = 512;
10121
+ O_DIRECTORY = 65536;
9574
10122
  KILLED_BY_SIGPIPE = 128 + 13;
9575
10123
  ProcessExit = class extends Error {
9576
10124
  status;
@@ -9791,13 +10339,15 @@ var init_kernel_streams = __esm({
9791
10339
  };
9792
10340
  }
9793
10341
  sizeFromKernel(stream, kfd) {
9794
- const { size } = this.sys;
10342
+ const { size, fdStat: fdStat2 } = this.sys;
9795
10343
  if (!size) return;
9796
10344
  const node = stream.node;
9797
- this.describe(stream, `${stream.path ?? ""}:${++this.described}`, () => ({
9798
- ...node.node_ops?.getattr?.(node),
9799
- size: this.call(() => size.call(this.sys, kfd))
9800
- }));
10345
+ this.describe(stream, `${stream.path ?? ""}:${++this.described}`, () => {
10346
+ const base = node.node_ops?.getattr?.(node);
10347
+ const live = this.call(() => size.call(this.sys, kfd));
10348
+ const real = fdStat2 && this.call(() => fdStat2.call(this.sys, kfd));
10349
+ return { ...base, ...real, ...datesOf(real), size: live };
10350
+ });
9801
10351
  }
9802
10352
  describe(stream, name2, getattr) {
9803
10353
  if (this.descriptions.size === 0) this.useDescriptions();
@@ -9816,6 +10366,9 @@ var init_kernel_streams = __esm({
9816
10366
  };
9817
10367
  }
9818
10368
  }
10369
+ useKernelFdMetadata() {
10370
+ useKernelFdMetadata(this.Fs, this.sys, this.call.bind(this));
10371
+ }
9819
10372
  useControllingTerminal() {
9820
10373
  if (typeof this.Fs.open !== "function") return;
9821
10374
  this.usePtyPaths();
@@ -9896,10 +10449,17 @@ var init_kernel_streams = __esm({
9896
10449
  openClipboard(open, path, flags, mode) {
9897
10450
  const { openClipboard } = this.sys;
9898
10451
  if (path !== CLIPBOARD_PATH2 || !openClipboard) return void 0;
10452
+ if (flags & O_DIRECTORY) throw new this.Fs.ErrnoError(wasiErrno("ENOTDIR"));
9899
10453
  const kfd = this.call(() => openClipboard.call(this.sys, flags & 3));
9900
- const stream = this.vessel(open, kfd, { path, flags, mode }, false);
9901
- this.reportClose(kfd);
9902
- return stream;
10454
+ try {
10455
+ const stream = this.vessel(open, kfd, { path, flags, mode }, false);
10456
+ this.reportClose(kfd);
10457
+ return stream;
10458
+ } catch (e) {
10459
+ this.sys.clipboardAbort?.(kfd);
10460
+ this.sys.close(kfd);
10461
+ throw e;
10462
+ }
9903
10463
  }
9904
10464
  vessel(open, kfd, at, terminal) {
9905
10465
  let stream;
@@ -10149,7 +10709,8 @@ function kernelEntry2(stream, kernel) {
10149
10709
  }
10150
10710
  const device2 = stream.path === void 0 ? void 0 : NAMED_DEVICES[stream.path];
10151
10711
  const kind = stream.sliccKernelFile ? "file" : stream.tty ? "tty" : device2 ?? "stream";
10152
- return { fd: stream.fd, kernel, kind, ...cloexec };
10712
+ const access = kind === "tty" ? O_RDWR4 : (stream.flags ?? O_RDWR4) & O_ACCMODE3;
10713
+ return { fd: stream.fd, kernel, kind, flags: access, ...cloexec };
10153
10714
  }
10154
10715
  function describeInherited(Fs, sys, streams, livePath, actions = []) {
10155
10716
  const table = /* @__PURE__ */ new Map();
@@ -10196,12 +10757,13 @@ function place(Fs, stream, fd) {
10196
10757
  return moved;
10197
10758
  }
10198
10759
  function placeholder(Fs, streams, entry) {
10199
- if (entry.kind === "socket") return streams.socketStream(entry.flags ?? O_RDWR4);
10760
+ const access = entry.flags ?? O_RDWR4;
10761
+ if (entry.kind === "socket") return streams.socketStream(access);
10200
10762
  if (entry.kind === "tty") return Fs.open("/dev/tty", O_RDWR4);
10201
10763
  if (entry.kind === "stream" || entry.kind === "clipboard" || entry.kind === "sealed")
10202
- return Fs.open("/dev/null", O_RDWR4);
10764
+ return Fs.open("/dev/null", access);
10203
10765
  Fs.mkdirTree(PLACEHOLDER_DIR);
10204
- return Fs.open(`${PLACEHOLDER_DIR}/${entry.fd}`, O_RDWR4 | O_CREAT3);
10766
+ return Fs.open(`${PLACEHOLDER_DIR}/${entry.fd}`, access | O_CREAT3);
10205
10767
  }
10206
10768
  function asFifo(stream, streams, identity) {
10207
10769
  const inos = streamInos.get(streams) ?? /* @__PURE__ */ new Map();
@@ -10986,6 +11548,20 @@ function kernelSys(transport) {
10986
11548
  size(fd) {
10987
11549
  return json2(call2({ op: "fd-vfs-stat", fd }, `fd-vfs-stat ${fd}`)).size;
10988
11550
  },
11551
+ fdStat(fd) {
11552
+ const r = json2(call2({ op: "fd-vfs-stat", fd, full: true }, `fd-vfs-stat ${fd}`));
11553
+ return r?.stat;
11554
+ },
11555
+ fdChmod(fd, mode) {
11556
+ call2({ op: "fd-chmod", fd, mode }, `fd-chmod ${fd}`);
11557
+ },
11558
+ fdChown(fd, uid, gid) {
11559
+ const ids = { ...uid !== void 0 ? { uid } : {}, ...gid !== void 0 ? { gid } : {} };
11560
+ call2({ op: "fd-chown", fd, ...ids }, `fd-chown ${fd}`);
11561
+ },
11562
+ fdUtimes(fd, atimeMs, mtimeMs, now) {
11563
+ call2({ op: "fd-utimes", fd, atimeMs, mtimeMs, now }, `fd-utimes ${fd}`);
11564
+ },
10989
11565
  ttyNames() {
10990
11566
  return json2(call2({ op: "fd-tty-names" }, "fd-tty-names"));
10991
11567
  },
@@ -11017,6 +11593,9 @@ function kernelSys(transport) {
11017
11593
  openClipboard(flags) {
11018
11594
  return json2(call2({ op: "fd-open-clipboard", flags }, "fd-open-clipboard"));
11019
11595
  },
11596
+ clipboardAbort(fd) {
11597
+ call2({ op: "fd-clipboard-abort", fd }, "fd-clipboard-abort");
11598
+ },
11020
11599
  ptyNumbers() {
11021
11600
  return json2(call2({ op: "pty-list" }, "pty-list"));
11022
11601
  },
@@ -11055,7 +11634,7 @@ function openDevice(Fs, fd, meta) {
11055
11634
  return openAt(Fs, fd, `/dev/${meta.device}`, accessMode(meta.access));
11056
11635
  }
11057
11636
  function openHeld(Fs, fd, meta) {
11058
- return "dir" in meta ? openAt(Fs, fd, meta.dir, O_RDONLY | O_DIRECTORY) : openDevice(Fs, fd, meta);
11637
+ return "dir" in meta ? openAt(Fs, fd, meta.dir, O_RDONLY | O_DIRECTORY2) : openDevice(Fs, fd, meta);
11059
11638
  }
11060
11639
  function openAt(Fs, fd, path, flags) {
11061
11640
  let stream;
@@ -11167,6 +11746,17 @@ function kernelWrappers(imports, module, deps) {
11167
11746
  function bridgeFlags(init) {
11168
11747
  return { ...init.owners ? { owners: true } : {}, ...init.links ? { links: true } : {} };
11169
11748
  }
11749
+ function credSyncTransport(gated, early, cred) {
11750
+ return {
11751
+ call: (req, timeoutMs, label) => {
11752
+ if (!FS_OPS.has(req.op)) early();
11753
+ const r = gated.call(req, timeoutMs, label);
11754
+ if (cred && req.op === "proc-setcred" && r.ok && r.kind === "json")
11755
+ Object.assign(cred, r.json);
11756
+ return r;
11757
+ }
11758
+ };
11759
+ }
11170
11760
  async function runWasmProcess(init, port3, deps = {}) {
11171
11761
  const signals = new SignalGate(
11172
11762
  createSyncSabTransport(init.sab, port3, {
@@ -11185,12 +11775,7 @@ async function runWasmProcess(init, port3, deps = {}) {
11185
11775
  const gated = signals.transport();
11186
11776
  let early = () => {
11187
11777
  };
11188
- const transport = {
11189
- call: (req, timeoutMs, label) => {
11190
- if (!FS_OPS.has(req.op)) early();
11191
- return gated.call(req, timeoutMs, label);
11192
- }
11193
- };
11778
+ const transport = credSyncTransport(gated, () => early(), init.cred);
11194
11779
  const sys = kernelSys(transport);
11195
11780
  const encoder5 = new TextEncoder();
11196
11781
  const say = (fd) => (text) => sys.write(fd, encoder5.encode(`${text}
@@ -11273,7 +11858,8 @@ async function runWasmProcess(init, port3, deps = {}) {
11273
11858
  const vfs = mountVfsIntoEmscripten(running.FS, {
11274
11859
  bridge: createSyncFsSabBridge(transport, bridgeFlags(init)),
11275
11860
  cwd: init.cwd,
11276
- warn: deps.warn ?? say(2)
11861
+ warn: deps.warn ?? say(2),
11862
+ cred: init.owners ? init.cred : void 0
11277
11863
  });
11278
11864
  early = () => signals.quiet(() => vfs.flushDirty());
11279
11865
  const sigpipe = () => running.sliccSigpipe?.() === 1;
@@ -11292,6 +11878,7 @@ async function runWasmProcess(init, port3, deps = {}) {
11292
11878
  atExit = () => streams.exiting();
11293
11879
  useMounts(running.FS, init.env, true);
11294
11880
  useZeroDevices(running.FS);
11881
+ useDevRemoval(running.FS);
11295
11882
  useProcfs(running.FS, sys, init.pid);
11296
11883
  if (init.fork) restoreForkedStreams(running.FS, streams, init.fork.streams ?? []);
11297
11884
  else {
@@ -11301,6 +11888,7 @@ async function runWasmProcess(init, port3, deps = {}) {
11301
11888
  const pipefs = ownValue(running, "PIPEFS");
11302
11889
  if (pipefs) streams.usePipes(pipefs);
11303
11890
  streams.useControllingTerminal();
11891
+ streams.useKernelFdMetadata();
11304
11892
  useDevFd(running.FS);
11305
11893
  useFileMmap(running.FS, {
11306
11894
  sys,
@@ -11312,9 +11900,9 @@ async function runWasmProcess(init, port3, deps = {}) {
11312
11900
  transport,
11313
11901
  Fs: running.FS,
11314
11902
  env: init.env,
11903
+ pid: init.pid,
11315
11904
  beforeSpawn: () => vfs.flush(),
11316
11905
  afterChild: () => vfs.invalidate(),
11317
- pid: init.pid,
11318
11906
  raise: (sig) => running.sliccRaise?.(sig),
11319
11907
  restartable,
11320
11908
  memory: () => memory,
@@ -11334,6 +11922,9 @@ async function runWasmProcess(init, port3, deps = {}) {
11334
11922
  sigpipe,
11335
11923
  restartable
11336
11924
  });
11925
+ return runWithFlush(running, init, streams, vfs);
11926
+ }
11927
+ function runWithFlush(running, init, streams, vfs) {
11337
11928
  try {
11338
11929
  return streams.exitStatus(runMain(running, init));
11339
11930
  } finally {
@@ -11398,7 +11989,7 @@ function runMain(running, init) {
11398
11989
  return status2;
11399
11990
  }
11400
11991
  }
11401
- var FS_OPS, O_RDONLY, O_WRONLY6, O_RDWR6, O_ACCMODE4, O_DIRECTORY, accessMode, PLACED, GLUE_TRAILER, evaluateGlue, EVAL_BLOCKED;
11992
+ var FS_OPS, O_RDONLY, O_WRONLY6, O_RDWR6, O_ACCMODE4, O_DIRECTORY2, accessMode, PLACED, GLUE_TRAILER, evaluateGlue, EVAL_BLOCKED;
11402
11993
  var init_process_runtime = __esm({
11403
11994
  "src/process/process-runtime.ts"() {
11404
11995
  "use strict";
@@ -11424,7 +12015,7 @@ var init_process_runtime = __esm({
11424
12015
  O_WRONLY6 = 1;
11425
12016
  O_RDWR6 = 2;
11426
12017
  O_ACCMODE4 = 3;
11427
- O_DIRECTORY = 65536;
12018
+ O_DIRECTORY2 = 65536;
11428
12019
  accessMode = (access) => access === "read" ? O_RDONLY : access === "write" ? O_WRONLY6 : O_RDWR6;
11429
12020
  PLACED = /* @__PURE__ */ new Set(["stream", "file", "socket", "clipboard", "sealed"]);
11430
12021
  GLUE_TRAILER = [
@@ -11605,7 +12196,7 @@ var init_wasi_sigmask = __esm({
11605
12196
  };
11606
12197
  WasiSigmask = class {
11607
12198
  lo;
11608
- hi = 0;
12199
+ hi;
11609
12200
  header;
11610
12201
  deliver;
11611
12202
  process;
@@ -11614,9 +12205,10 @@ var init_wasi_sigmask = __esm({
11614
12205
  this.deliver = deliver;
11615
12206
  this.process = process;
11616
12207
  this.lo = libcBits(Atomics.load(header, SAB_I_BLOCKED));
12208
+ this.hi = Atomics.load(header, SAB_I_BLOCKED_HI);
11617
12209
  }
11618
12210
  static unsupported(header) {
11619
- Atomics.store(header, SAB_I_BLOCKED, 0);
12211
+ storeBlocked(header, [0, 0]);
11620
12212
  }
11621
12213
  set(how, setLo, setHi, old) {
11622
12214
  if (how !== SIG_BLOCK && how !== SIG_UNBLOCK && how !== SIG_SETMASK) return E.INVAL;
@@ -11624,7 +12216,7 @@ var init_wasi_sigmask = __esm({
11624
12216
  this.lo = apply(how, this.lo, setLo | 0) & ~LIBC_UNBLOCKABLE;
11625
12217
  this.hi = apply(how, this.hi, setHi | 0);
11626
12218
  const now = kernelBits(this.lo);
11627
- Atomics.store(this.header, SAB_I_BLOCKED, now);
12219
+ storeBlocked(this.header, [now, this.hi]);
11628
12220
  if ((Atomics.load(this.header, SAB_I_SIGNALS) & ~now) !== 0) this.deliver();
11629
12221
  return E.SUCCESS;
11630
12222
  }
@@ -11632,7 +12224,7 @@ var init_wasi_sigmask = __esm({
11632
12224
  const old = [this.lo, this.hi];
11633
12225
  this.lo = setLo & ~LIBC_UNBLOCKABLE;
11634
12226
  this.hi = setHi | 0;
11635
- Atomics.store(this.header, SAB_I_BLOCKED, kernelBits(this.lo));
12227
+ storeBlocked(this.header, [kernelBits(this.lo), this.hi]);
11636
12228
  return old;
11637
12229
  }
11638
12230
  deliverUnblocked() {
@@ -11645,6 +12237,9 @@ var init_wasi_sigmask = __esm({
11645
12237
  this.set(SIG_SETMASK, lo, hi, () => {
11646
12238
  });
11647
12239
  }
12240
+ inherited() {
12241
+ return [kernelBits(this.lo), this.hi];
12242
+ }
11648
12243
  discard(sig) {
11649
12244
  Atomics.and(this.header, SAB_I_SIGNALS, ~sigbit(sig));
11650
12245
  if (this.process) Atomics.and(this.process, SAB_I_SIGNALS, ~sigbit(sig));
@@ -13622,6 +14217,7 @@ __export(wasi_runtime_exports, {
13622
14217
  runWasiProcess: () => runWasiProcess,
13623
14218
  runWasiThread: () => runWasiThread,
13624
14219
  sigmaskOf: () => sigmaskOf,
14220
+ takeThreadDefault: () => takeThreadDefault,
13625
14221
  trapMessage: () => trapMessage,
13626
14222
  unsupportedImport: () => unsupportedImport,
13627
14223
  wireSignals: () => wireSignals
@@ -13665,7 +14261,7 @@ function sigmaskOf(module, sab, gate, threads, process) {
13665
14261
  WasiSigmask.unsupported(header);
13666
14262
  return void 0;
13667
14263
  }
13668
- if (threads) threads.blocked = () => Atomics.load(header, SAB_I_BLOCKED);
14264
+ if (threads) threads.blocked = () => loadBlocked(header);
13669
14265
  const shared = process && new Int32Array(process, 0, SAB_HEADER_I32);
13670
14266
  return new WasiSigmask(header, () => gate.deliver(), shared);
13671
14267
  }
@@ -14059,7 +14655,7 @@ async function runWasiThread(init, port3) {
14059
14655
  masks: () => null,
14060
14656
  raise: (sig) => signals.raise(sig)
14061
14657
  });
14062
- const signals = new WasiSignals(takeDefault(call2, init.pid));
14658
+ const signals = new WasiSignals(takeThreadDefault(call2, init.pid));
14063
14659
  const threads = new WasiThreads(port3, thread.memory, threadCap(init.env), thread.tid, thread.ids);
14064
14660
  threads.received = thread.modules;
14065
14661
  const id = identify(transport, init);
@@ -14113,7 +14709,7 @@ async function runWasiThread(init, port3) {
14113
14709
  throw e;
14114
14710
  }
14115
14711
  }
14116
- var TRAPPED, PREVIEW1, WASIX, SLICC, SIGNAL_CALLBACK, takeDefault, SLICC_FS, SLICC_TTY, RESERVED2, UNDELIVERED, DELIVERED, importsSlicc, importsSigactionHook, noErrno, FALLBACK_MAXIMUM_PAGES, LinkSync, DL_GEN, BACKTRACE_FRAMES;
14712
+ var TRAPPED, PREVIEW1, WASIX, SLICC, SIGNAL_CALLBACK, takeDefault, takeThreadDefault, SLICC_FS, SLICC_TTY, RESERVED2, UNDELIVERED, DELIVERED, importsSlicc, importsSigactionHook, noErrno, FALLBACK_MAXIMUM_PAGES, LinkSync, DL_GEN, BACKTRACE_FRAMES;
14117
14713
  var init_wasi_runtime = __esm({
14118
14714
  "src/process/wasi/wasi-runtime.ts"() {
14119
14715
  "use strict";
@@ -14148,6 +14744,17 @@ var init_wasi_runtime = __esm({
14148
14744
  call2({ op: "proc-kill", pid, sig });
14149
14745
  if (defaultAction(sig) === "terminate") throw new WasiExit(128 + sig);
14150
14746
  };
14747
+ takeThreadDefault = (call2, pid) => (sig) => {
14748
+ if (defaultAction(sig) !== "terminate") {
14749
+ call2({ op: "proc-kill", pid, sig });
14750
+ return;
14751
+ }
14752
+ try {
14753
+ call2({ op: "proc-kill-self", sig });
14754
+ } catch {
14755
+ }
14756
+ throw new WasiExit(128 + sig);
14757
+ };
14151
14758
  SLICC_FS = "slicc_fs";
14152
14759
  SLICC_TTY = "slicc_tty";
14153
14760
  RESERVED2 = RESERVED_NAMESPACES;
@@ -14293,7 +14900,11 @@ function refuseModules() {
14293
14900
  }
14294
14901
  });
14295
14902
  }
14903
+ var locked = /* @__PURE__ */ new WeakSet();
14904
+ var nodeProcess = typeof globalThis.process === "object" && globalThis.process !== null ? globalThis.process : void 0;
14296
14905
  function nodeLockdown(scope2 = globalThis) {
14906
+ if (locked.has(scope2)) return;
14907
+ locked.add(scope2);
14297
14908
  zeroedBuffers(Buffer);
14298
14909
  lockdown(scope2);
14299
14910
  hide(scope2, NODE_GLOBALS);
@@ -14359,14 +14970,22 @@ function processEntry(port3, run = runWasmProcess, wasi = loadWasi, js = loadJs,
14359
14970
  }
14360
14971
 
14361
14972
  // src/node-process-worker.ts
14973
+ init_wasi_runtime();
14362
14974
  var scope = globalThis;
14363
14975
  scope.require ??= createRequire(import.meta.url);
14364
14976
  scope.__filename ??= new URL(import.meta.url).pathname;
14365
14977
  scope.__dirname ??= new URL(".", import.meta.url).pathname;
14366
14978
  var port2 = parentPort;
14367
14979
  var post = { postMessage: (message2) => port2.postMessage(message2) };
14368
- var onMessage = processEntry(post, void 0, void 0, async () => ({
14369
- runJsProcess: (init, at) => runJsProcess(init, at, { lockdown: () => nodeLockdown() })
14370
- }));
14980
+ var strayScope = nodeProcess ? { process: nodeProcess } : {};
14981
+ var onMessage = processEntry(
14982
+ post,
14983
+ void 0,
14984
+ async () => wasi_runtime_exports,
14985
+ async () => ({
14986
+ runJsProcess: (init, at) => runJsProcess(init, at, { lockdown: () => nodeLockdown(), scope: strayScope })
14987
+ }),
14988
+ () => nodeLockdown()
14989
+ );
14371
14990
  port2.on("message", onMessage);
14372
14991
  //# sourceMappingURL=node-process-worker.js.map