@ai-ecoverse/slicc-kernel 1.143.5 → 1.144.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.
Files changed (43) hide show
  1. package/README.md +15 -7
  2. package/dist/driver-worker.js +5 -1
  3. package/dist/driver-worker.js.map +2 -2
  4. package/dist/index.js +5 -1
  5. package/dist/index.js.map +2 -2
  6. package/dist/kernel-worker.js +7830 -7524
  7. package/dist/kernel-worker.js.map +4 -4
  8. package/dist/meta.js +1 -1
  9. package/dist/meta.js.map +2 -2
  10. package/dist/node-driver-worker.js +5 -1
  11. package/dist/node-driver-worker.js.map +2 -2
  12. package/dist/node-process-worker.js +212 -35
  13. package/dist/node-process-worker.js.map +3 -3
  14. package/dist/node.js +24174 -23864
  15. package/dist/node.js.map +4 -4
  16. package/dist/process-worker.js +212 -35
  17. package/dist/process-worker.js.map +3 -3
  18. package/dist/types/client/attach.d.ts +3 -0
  19. package/dist/types/client/protocol.d.ts +3 -0
  20. package/dist/types/client/serve-client.d.ts +1 -1
  21. package/dist/types/cron/crontab.d.ts +13 -1
  22. package/dist/types/cron/service.d.ts +2 -0
  23. package/dist/types/fs/changes.d.ts +4 -0
  24. package/dist/types/fs/dac.d.ts +2 -0
  25. package/dist/types/fs/meta.d.ts +4 -0
  26. package/dist/types/fs/opfs.d.ts +10 -0
  27. package/dist/types/fs/remote.d.ts +4 -0
  28. package/dist/types/fs/types.d.ts +4 -0
  29. package/dist/types/kernel/clipboard.d.ts +3 -2
  30. package/dist/types/kernel/host.d.ts +5 -0
  31. package/dist/types/kernel/proc-info.d.ts +1 -0
  32. package/dist/types/kernel/process.d.ts +1 -1
  33. package/dist/types/kernel/rename-log.d.ts +14 -0
  34. package/dist/types/kernel/sealed.d.ts +8 -3
  35. package/dist/types/kernel/vfs-file.d.ts +1 -0
  36. package/dist/types/launcher.d.ts +12 -1
  37. package/dist/types/process/wasi/wasi-fds.d.ts +4 -1
  38. package/dist/types/process/wasi/wasi-files.d.ts +2 -0
  39. package/dist/types/realm/live-vfs-fs.d.ts +8 -0
  40. package/dist/types/realm/sync-fs-token-registry.d.ts +5 -0
  41. package/dist/types/realm/sync-fs-wire.d.ts +7 -2
  42. package/dist/types/sudo.d.ts +2 -1
  43. package/package.json +7 -7
@@ -287,7 +287,7 @@ function normal(path) {
287
287
  }
288
288
  return `/${parts.join("/")}`;
289
289
  }
290
- var GEN, RING, RING_SIZE, SLOT, SHARED_TTL_MS, DIRTY, FOREIGN, CHANGES_BYTES, ChangeView;
290
+ var GEN, RING, RING_SIZE, SLOT, SHARED_TTL_MS, RENAME_WAIT_MS, DIRTY, FOREIGN, RENAMES, CHANGES_BYTES, ChangeView;
291
291
  var init_changes = __esm({
292
292
  "src/fs/changes.ts"() {
293
293
  "use strict";
@@ -296,9 +296,11 @@ var init_changes = __esm({
296
296
  RING_SIZE = 4096;
297
297
  SLOT = 2;
298
298
  SHARED_TTL_MS = 100;
299
+ RENAME_WAIT_MS = 100;
299
300
  DIRTY = RING + RING_SIZE * SLOT;
300
301
  FOREIGN = DIRTY + 1;
301
- CHANGES_BYTES = (FOREIGN + 1) * 4;
302
+ RENAMES = FOREIGN + 1;
303
+ CHANGES_BYTES = (RENAMES + 1) * 4;
302
304
  ChangeView = class {
303
305
  view;
304
306
  constructor(sab) {
@@ -313,6 +315,13 @@ var init_changes = __esm({
313
315
  foreign() {
314
316
  return this.view.length > FOREIGN && Atomics.load(this.view, FOREIGN) === 1;
315
317
  }
318
+ renames() {
319
+ return this.view.length > RENAMES ? Atomics.load(this.view, RENAMES) : 0;
320
+ }
321
+ awaitRename(seen, ms) {
322
+ if (this.view.length > RENAMES) Atomics.wait(this.view, RENAMES, seen, ms);
323
+ return this.renames();
324
+ }
316
325
  changedSince(seen, path) {
317
326
  const now = Atomics.load(this.view, GEN);
318
327
  const distance = now - seen >>> 0;
@@ -730,7 +739,8 @@ var init_sync_fs_wire = __esm({
730
739
  "truncate",
731
740
  "chown",
732
741
  "lchown",
733
- "access"
742
+ "access",
743
+ "renames"
734
744
  ];
735
745
  HOLD_READ = 4;
736
746
  HOLD_WRITE = 8;
@@ -747,7 +757,8 @@ var init_sync_fs_wire = __esm({
747
757
  "readlink",
748
758
  "statfs",
749
759
  "kept",
750
- "access"
760
+ "access",
761
+ "renames"
751
762
  ]);
752
763
  }
753
764
  });
@@ -966,6 +977,7 @@ function cachingBridge(bridge, now = () => performance.now(), shared) {
966
977
  const entry = (p) => [p, p.slice(0, p.lastIndexOf("/")) || "/"];
967
978
  return {
968
979
  ...bridge.changes ? { changes: bridge.changes } : {},
980
+ ...bridge.renames ? { renames: bridge.renames.bind(bridge) } : {},
969
981
  readFile: (p) => bridge.readFile(p),
970
982
  readdir: (p) => bridge.readdir(p),
971
983
  readdirStat: (p) => {
@@ -1082,6 +1094,7 @@ var init_wasi_files = __esm({
1082
1094
  seen = 0;
1083
1095
  maxFile;
1084
1096
  handle;
1097
+ moved;
1085
1098
  constructor(fs, path, empty, maxFile, size, version, watch) {
1086
1099
  this.fs = fs;
1087
1100
  this.where = path;
@@ -1090,7 +1103,11 @@ var init_wasi_files = __esm({
1090
1103
  this.watch = watch;
1091
1104
  this.seen = watch?.seen ?? watch?.view.now() ?? 0;
1092
1105
  if (size !== void 0 && pread && pwrite && truncate) {
1093
- const io = { pread: pread.bind(fs), pwrite: pwrite.bind(fs), truncate: truncate.bind(fs) };
1106
+ const io = {
1107
+ pread: (_, ...rest2) => this.retried(() => pread.call(fs, this.where, ...rest2)),
1108
+ pwrite: (_, ...rest2) => this.retried(() => pwrite.call(fs, this.where, ...rest2)),
1109
+ truncate: (_, size2) => this.retried(() => truncate.call(fs, this.where, size2))
1110
+ };
1094
1111
  this.ranged = new RangedFile(io, path, size, version, watch);
1095
1112
  if (empty) this.truncate(0);
1096
1113
  } else if (empty) {
@@ -1102,6 +1119,14 @@ var init_wasi_files = __esm({
1102
1119
  get path() {
1103
1120
  return this.where;
1104
1121
  }
1122
+ retried(op) {
1123
+ try {
1124
+ return op();
1125
+ } catch (err) {
1126
+ if (err.code !== "ENOENT" || !this.moved?.(true)) throw err;
1127
+ return op();
1128
+ }
1129
+ }
1105
1130
  set path(path) {
1106
1131
  this.where = path;
1107
1132
  if (this.ranged) this.ranged.path = path;
@@ -1125,7 +1150,7 @@ var init_wasi_files = __esm({
1125
1150
  }
1126
1151
  if (!this.data) {
1127
1152
  this.seen = view?.now() ?? 0;
1128
- this.data = this.fs.readFile(this.path);
1153
+ this.data = this.retried(() => this.fs.readFile(this.path));
1129
1154
  this.length = this.data.length;
1130
1155
  }
1131
1156
  return this.data;
@@ -1166,8 +1191,9 @@ var init_wasi_files = __esm({
1166
1191
  append(bytes) {
1167
1192
  const { append } = this.fs;
1168
1193
  if (!append || this.orphaned) return void 0;
1194
+ this.moved?.(false);
1169
1195
  this.flush();
1170
- const end = append.call(this.fs, this.path, bytes);
1196
+ const end = this.retried(() => append.call(this.fs, this.path, bytes));
1171
1197
  if (!this.ranged) {
1172
1198
  this.data = void 0;
1173
1199
  this.length = 0;
@@ -1215,11 +1241,17 @@ var init_wasi_files = __esm({
1215
1241
  }
1216
1242
  flush() {
1217
1243
  if (this.orphaned || !this.dirty) return;
1244
+ this.moved?.(false);
1218
1245
  if (this.ranged) this.ranged.flush();
1219
1246
  else if (!this.data) return;
1220
- else if (this.whole || !this.fs.pwrite)
1221
- this.fs.writeFile(this.path, this.data.slice(0, this.length), true);
1222
- else this.fs.pwrite(this.path, this.from, this.data.slice(this.from, this.to), true);
1247
+ else if (this.whole || !this.fs.pwrite) {
1248
+ const whole = this.data.slice(0, this.length);
1249
+ this.retried(() => this.fs.writeFile(this.path, whole, true));
1250
+ } else {
1251
+ const { pwrite } = this.fs;
1252
+ const run = this.data.slice(this.from, this.to);
1253
+ this.retried(() => pwrite.call(this.fs, this.path, this.from, run, true));
1254
+ }
1223
1255
  this.dirty = false;
1224
1256
  this.whole = false;
1225
1257
  this.from = Infinity;
@@ -3061,6 +3093,7 @@ var SYNTHETIC_DIRS, O_NONBLOCK, O_WRONLY2, O_RDWR2, O_APPEND2, SEALED_PATH, CLIP
3061
3093
  var init_wasi_fds = __esm({
3062
3094
  "src/process/wasi/wasi-fds.ts"() {
3063
3095
  "use strict";
3096
+ init_changes();
3064
3097
  init_ranged();
3065
3098
  init_fd_table();
3066
3099
  init_sync_fs_wire();
@@ -3081,9 +3114,29 @@ var init_wasi_fds = __esm({
3081
3114
  ids = /* @__PURE__ */ new Map();
3082
3115
  kernel;
3083
3116
  fs;
3117
+ renamesSeen;
3084
3118
  constructor(kernel, fs) {
3085
3119
  this.kernel = kernel;
3086
3120
  this.fs = fs;
3121
+ this.renamesSeen = fs.changes?.renames() ?? 0;
3122
+ }
3123
+ ownRename(seq) {
3124
+ if (seq !== void 0 && seq === (this.renamesSeen + 1 | 0)) this.renamesSeen = seq;
3125
+ }
3126
+ followRenames(missing2 = false) {
3127
+ const view = this.fs.changes;
3128
+ let now = view?.renames() ?? 0;
3129
+ if (missing2 && view && now === this.renamesSeen) now = view.awaitRename(now, RENAME_WAIT_MS);
3130
+ if (now === this.renamesSeen || !this.fs.renames) return false;
3131
+ const held2 = [...this.buffers].filter(([, b]) => !b.isOrphan()).map(([p]) => p);
3132
+ if (held2.length === 0) {
3133
+ this.renamesSeen = now;
3134
+ return false;
3135
+ }
3136
+ const { now: seen, renames } = this.fs.renames(this.renamesSeen, held2);
3137
+ this.renamesSeen = seen;
3138
+ for (const [from, to] of renames) this.renamed(from, to, void 0, true);
3139
+ return renames.length > 0;
3087
3140
  }
3088
3141
  setup(cwd, inherited, root = false) {
3089
3142
  for (const fd of [0, 1, 2]) this.table.set(fd, this.stdioEntry(fd));
@@ -3283,6 +3336,7 @@ var init_wasi_fds = __esm({
3283
3336
  get(fd) {
3284
3337
  const e = this.find(fd);
3285
3338
  if (!e) throw new WasiError("EBADF");
3339
+ if (e.type === "file") this.followRenames();
3286
3340
  return e;
3287
3341
  }
3288
3342
  preopen(fd) {
@@ -3603,9 +3657,9 @@ var init_wasi_fds = __esm({
3603
3657
  buffer.orphan();
3604
3658
  this.forget(buffer);
3605
3659
  }
3606
- renamed(from, to, replacedLinked) {
3660
+ renamed(from, to, replacedLinked, foreign = false) {
3607
3661
  if (from === to) return;
3608
- if (this.shared) this.kernel.call({ op: "fd-path-renamed", from, to });
3662
+ if (this.shared && !foreign) this.kernel.call({ op: "fd-path-renamed", from, to });
3609
3663
  for (const e of this.table.values()) {
3610
3664
  if (e.type === "kernel" && e.path !== void 0 && within(e.path, from)) {
3611
3665
  e.path = to + e.path.slice(from.length);
@@ -3613,6 +3667,7 @@ var init_wasi_fds = __esm({
3613
3667
  }
3614
3668
  const moved = [];
3615
3669
  for (const [p, buffer] of this.buffers) {
3670
+ if (foreign && buffer.isOrphan()) continue;
3616
3671
  if (within(p, from)) moved.push([p, buffer]);
3617
3672
  else if (within(p, to)) {
3618
3673
  this.detach(buffer, replacedLinked);
@@ -3754,6 +3809,7 @@ var init_wasi_fds = __esm({
3754
3809
  }
3755
3810
  file(path, existing, oflags, rights, fdflags, mode, created = false) {
3756
3811
  const { readable: readable3, writable: writable2 } = openAccess(existing, oflags, rights);
3812
+ this.followRenames();
3757
3813
  let buffer = created ? void 0 : this.buffers.get(path);
3758
3814
  if (buffer?.handle !== void 0 && this.fs.kept?.(buffer.handle)) {
3759
3815
  this.buffers.delete(path);
@@ -3801,6 +3857,7 @@ var init_wasi_fds = __esm({
3801
3857
  st
3802
3858
  );
3803
3859
  const buffer = new FileBuffer(io, path, empty, st.maxFile, ranged, st.version, watch);
3860
+ buffer.moved = (missing2) => this.followRenames(missing2);
3804
3861
  buffer.handle = handle;
3805
3862
  this.buffers.set(path, buffer);
3806
3863
  const id = this.identity(st);
@@ -5607,8 +5664,9 @@ var init_wasi_host = __esm({
5607
5664
  const to = at(fd2, p2, l2);
5608
5665
  fds.flushPath(from);
5609
5666
  const replaced = fds.holdsUnder(to) ? linkedElsewhere(o.fs, to) : void 0;
5610
- o.fs.rename(from, to);
5667
+ const seq = o.fs.rename(from, to);
5611
5668
  fds.renamed(from, to, replaced);
5669
+ fds.ownRename(typeof seq === "number" ? seq : void 0);
5612
5670
  },
5613
5671
  path_symlink: (tp, tl, dirfd, p, l) => {
5614
5672
  const path = at(dirfd, p, l);
@@ -6726,7 +6784,7 @@ var KERNEL_VERSION, OS_RELEASE;
6726
6784
  var init_version = __esm({
6727
6785
  "src/version.ts"() {
6728
6786
  "use strict";
6729
- KERNEL_VERSION = true ? "1.143.5" : "0.0.0-dev";
6787
+ KERNEL_VERSION = true ? "1.144.0" : "0.0.0-dev";
6730
6788
  OS_RELEASE = "6.0.0-slicc";
6731
6789
  }
6732
6790
  });
@@ -8076,7 +8134,9 @@ function createSyncFsSabBridge(transport, opts = {}) {
8076
8134
  run({ op: "rm", path }, path);
8077
8135
  },
8078
8136
  rename: (from, to) => {
8079
- run({ op: "rename", path: from, arg2: to }, from);
8137
+ const r = run({ op: "rename", path: from, arg2: to }, from);
8138
+ const seq = r.ok && r.kind === "json" ? r.json.seq : void 0;
8139
+ return typeof seq === "number" ? seq : void 0;
8080
8140
  },
8081
8141
  link: (from, to, follow3) => {
8082
8142
  run({ op: "link", path: from, arg2: to, ...follow3 ? { mode: 1 } : {} }, from);
@@ -8157,7 +8217,11 @@ function createSyncFsSabBridge(transport, opts = {}) {
8157
8217
  run({ op: "hold", path, mode, ...handle !== void 0 ? { handle } : {} }, path);
8158
8218
  return void 0;
8159
8219
  },
8160
- statfs: (path = "/") => parseSyncFsUsage(json2({ op: "statfs", path }, path))
8220
+ statfs: (path = "/") => parseSyncFsUsage(json2({ op: "statfs", path }, path)),
8221
+ renames: (since, held2) => json2(
8222
+ { op: "renames", path: "/", offset: since, arg2: JSON.stringify(held2) },
8223
+ "/"
8224
+ )
8161
8225
  };
8162
8226
  }
8163
8227
  var UNCOUNTED_OPS, calls, looks, SPIN_MS, SPIN_STRIDE, SPIN_STRIDES, SPIN_CORES, spinning, SPIN_CAP_MS;
@@ -8354,12 +8418,130 @@ function freshState(stat) {
8354
8418
  const base = { len: 0, loaded: false, dirty: false, openCount: 0 };
8355
8419
  return stat ? { stat, statAt: syncCallCount(), filledAt: performance.now(), seenAt: syncEpoch(), ...base } : base;
8356
8420
  }
8421
+ function inCache(Fs, node) {
8422
+ const table = Fs.nameTable;
8423
+ const parent = node.parent;
8424
+ const hash = Fs.hashName?.(parent.id ?? 0, node.name);
8425
+ if (!table || hash === void 0) return true;
8426
+ let at = table[hash];
8427
+ while (at) {
8428
+ if (at === node) return true;
8429
+ at = at.name_next;
8430
+ }
8431
+ return false;
8432
+ }
8433
+ function heldUnder(held2, from) {
8434
+ let moving = held2;
8435
+ while (moving && moving !== moving.mount.root && liveNodePath(moving) !== from) {
8436
+ moving = moving.parent;
8437
+ }
8438
+ return moving && moving !== moving.mount.root && liveNodePath(moving) === from ? moving : void 0;
8439
+ }
8440
+ function relinked(Fs, moving, to) {
8441
+ const slash = to.lastIndexOf("/");
8442
+ let dir;
8443
+ try {
8444
+ dir = Fs.lookupPath?.(slash <= 0 ? "/" : to.slice(0, slash)).node;
8445
+ } catch {
8446
+ }
8447
+ if (!dir || dir.mount !== moving.mount) return;
8448
+ const name2 = to.slice(slash + 1);
8449
+ try {
8450
+ const existing = Fs.lookupNode?.(dir, name2);
8451
+ if (existing && existing !== moving) Fs.hashRemoveNode?.(existing);
8452
+ } catch {
8453
+ }
8454
+ moving.parent.live.listed = void 0;
8455
+ dir.live.listed = void 0;
8456
+ Fs.hashRemoveNode?.(moving);
8457
+ moving.name = name2;
8458
+ moving.parent = dir;
8459
+ Fs.hashAddNode?.(moving);
8460
+ moving.live.stat = void 0;
8461
+ }
8462
+ function renameFollower(Fs, bridgeOf, call2) {
8463
+ const open = /* @__PURE__ */ new Set();
8464
+ const seen = /* @__PURE__ */ new Map();
8465
+ const follow3 = (node, missing2 = false) => {
8466
+ const bridge = bridgeOf(node);
8467
+ const view = bridge.changes;
8468
+ const since = seen.get(bridge);
8469
+ let now = view?.renames() ?? 0;
8470
+ if (missing2 && view && now === since) now = view.awaitRename(now, RENAME_WAIT_MS);
8471
+ const ask = bridge.renames?.bind(bridge);
8472
+ if (since === void 0 || now === since || !ask) return false;
8473
+ const held2 = [...open].filter((n) => !n.live.orphan && bridgeOf(n) === bridge);
8474
+ if (held2.length === 0) {
8475
+ seen.set(bridge, now);
8476
+ return false;
8477
+ }
8478
+ const reply = call2(
8479
+ () => ask(
8480
+ since,
8481
+ held2.map((n) => liveNodePath(n))
8482
+ )
8483
+ );
8484
+ seen.set(bridge, reply.now);
8485
+ for (const [from, to] of reply.renames) {
8486
+ for (const n of held2) {
8487
+ const moving = heldUnder(n, from);
8488
+ if (moving && inCache(Fs, moving)) relinked(Fs, moving, to);
8489
+ }
8490
+ }
8491
+ return reply.renames.length > 0;
8492
+ };
8493
+ return {
8494
+ open,
8495
+ follow: follow3,
8496
+ track(node, on) {
8497
+ if (!on) {
8498
+ open.delete(node);
8499
+ return;
8500
+ }
8501
+ follow3(node);
8502
+ open.add(node);
8503
+ },
8504
+ watchRenames(bridge) {
8505
+ if (!seen.has(bridge)) seen.set(bridge, bridge.changes?.renames() ?? 0);
8506
+ },
8507
+ ownRename(bridge, seq) {
8508
+ const since = seen.get(bridge);
8509
+ if (seq !== void 0 && since !== void 0 && seq === (since + 1 | 0))
8510
+ seen.set(bridge, seq);
8511
+ }
8512
+ };
8513
+ }
8514
+ function followingOnce(write2, follow3) {
8515
+ try {
8516
+ write2();
8517
+ } catch (err) {
8518
+ if (err.errno !== wasiErrno("ENOENT") || !follow3()) throw err;
8519
+ write2();
8520
+ }
8521
+ }
8522
+ function renameThrough(h, node, from, to) {
8523
+ const seq = h.call(() => h.bridgeOf(node).rename(from, to));
8524
+ h.ownRename(h.bridgeOf(node), typeof seq === "number" ? seq : void 0);
8525
+ }
8526
+ function heldStream(h, stream, change) {
8527
+ const s = stream.node.live;
8528
+ if ((stream.flags & 3) === 0 || s.orphan) return;
8529
+ const before = s.writers ?? 0;
8530
+ s.writers = Math.max(0, before + change);
8531
+ if (before === 0 !== (s.writers === 0)) {
8532
+ try {
8533
+ h.bridgeOf(stream.node).hold?.(liveNodePath(stream.node), s.writers > 0);
8534
+ } catch {
8535
+ }
8536
+ }
8537
+ }
8357
8538
  function createHelpers(Fs, ops) {
8358
8539
  const bridgeOf = (node) => node.mount.opts.bridge;
8359
8540
  const fileIo = (node) => pinnedIo2(bridgeOf(node), node.live.handle);
8360
8541
  const dirty = /* @__PURE__ */ new Set();
8361
8542
  const handled = /* @__PURE__ */ new Set();
8362
8543
  const linked = linkedStates(bridgeOf);
8544
+ const renames = renameFollower(Fs, bridgeOf, (fn) => call2(fn));
8363
8545
  function markDirty(node) {
8364
8546
  node.live.dirty = true;
8365
8547
  dirty.add(node);
@@ -8452,11 +8634,9 @@ function createHelpers(Fs, ops) {
8452
8634
  function flushNode(node) {
8453
8635
  const s = node.live;
8454
8636
  if (!s.dirty || stale(s) || !(s.data || s.ranged)) return;
8455
- if (s.ranged) call2(() => s.ranged?.flush());
8456
- else {
8457
- const bytes = s.data.slice(0, s.len);
8458
- call2(() => fileIo(node).writeFile(liveNodePath(linked.holder(node)), bytes, true));
8459
- }
8637
+ const whole = () => s.data.slice(0, s.len);
8638
+ const write2 = () => s.ranged ? call2(() => s.ranged?.flush()) : call2(() => fileIo(node).writeFile(liveNodePath(linked.holder(node)), whole(), true));
8639
+ followingOnce(write2, () => renames.follow(node, true));
8460
8640
  s.dirty = false;
8461
8641
  s.stat = void 0;
8462
8642
  }
@@ -8504,6 +8684,7 @@ function createHelpers(Fs, ops) {
8504
8684
  bridgeOf,
8505
8685
  handled,
8506
8686
  linked,
8687
+ ...renames,
8507
8688
  call: call2,
8508
8689
  metadataCall,
8509
8690
  makeNode,
@@ -8663,7 +8844,7 @@ function createNodeOps(h) {
8663
8844
  const from = liveNodePath(oldNode);
8664
8845
  const to = childPath(newDir, newName);
8665
8846
  flushNode(oldNode);
8666
- call2(() => bridgeOf(oldNode).rename(from, to));
8847
+ renameThrough(h, oldNode, from, to);
8667
8848
  try {
8668
8849
  const existing = Fs.lookupNode?.(newDir, newName);
8669
8850
  if (existing && existing !== oldNode) Fs.hashRemoveNode?.(existing);
@@ -8758,21 +8939,11 @@ function dropOpen(s) {
8758
8939
  }
8759
8940
  function createStreamOps(h) {
8760
8941
  const { Fs, statOf, ensureLoaded, ensureCapacity, flushNode, bridgeOf, rangedOf } = h;
8761
- const held2 = (stream, change) => {
8762
- const s = stream.node.live;
8763
- if ((stream.flags & 3) === 0 || s.orphan) return;
8764
- const before = s.writers ?? 0;
8765
- s.writers = Math.max(0, before + change);
8766
- if (before === 0 !== (s.writers === 0)) {
8767
- try {
8768
- bridgeOf(stream.node).hold?.(liveNodePath(stream.node), s.writers > 0);
8769
- } catch {
8770
- }
8771
- }
8772
- };
8942
+ const held2 = (stream, change) => heldStream(h, stream, change);
8773
8943
  const opened2 = (node, on, want = 0) => {
8774
8944
  const s = node.live;
8775
8945
  try {
8946
+ h.track(node, on);
8776
8947
  const handle = holdLive(bridgeOf(node), node, on, want);
8777
8948
  s.handle = on ? handle : void 0;
8778
8949
  h.linked.opening(node, on);
@@ -8868,6 +9039,7 @@ function createStreamOps(h) {
8868
9039
  if (!Fs.isFile(node.mode)) return;
8869
9040
  const s = node.live;
8870
9041
  if (!dropOpen(s)) return;
9042
+ h.follow(node);
8871
9043
  if (s.openCount > 0) {
8872
9044
  held2(stream, -1);
8873
9045
  return;
@@ -8881,12 +9053,14 @@ function createStreamOps(h) {
8881
9053
  s.len = 0;
8882
9054
  s.loaded = false;
8883
9055
  held2(stream, -1);
9056
+ h.track(node, false);
8884
9057
  if (s.handle !== void 0) opened2(node, false);
8885
9058
  }
8886
9059
  },
8887
9060
  read(stream, buffer, offset, length, position) {
8888
9061
  const node = stream.node;
8889
9062
  if (Fs.isDir(node.mode)) throw new Fs.ErrnoError(wasiErrno("EISDIR"));
9063
+ h.follow(node);
8890
9064
  const ranged = rangedOf(node);
8891
9065
  if (ranged) {
8892
9066
  const out2 = new Uint8Array(buffer.buffer, buffer.byteOffset + offset, Math.max(0, length));
@@ -8904,6 +9078,7 @@ function createStreamOps(h) {
8904
9078
  const node = stream.node;
8905
9079
  if (Fs.isDir(node.mode)) throw new Fs.ErrnoError(wasiErrno("EISDIR"));
8906
9080
  if (length <= 0) return 0;
9081
+ h.follow(node);
8907
9082
  const s = node.live;
8908
9083
  const end = position + length;
8909
9084
  if (s.maxFile !== void 0 && end > s.maxFile) throw new Fs.ErrnoError(wasiErrno("EFBIG"));
@@ -8935,6 +9110,7 @@ function createStreamOps(h) {
8935
9110
  return pos;
8936
9111
  },
8937
9112
  fsync(stream) {
9113
+ h.follow(stream.node);
8938
9114
  flushNode(stream.node);
8939
9115
  }
8940
9116
  };
@@ -8969,6 +9145,7 @@ function createLiveVfsPlugin(Fs) {
8969
9145
  flushDirty: () => h.flushDirty(),
8970
9146
  mount(mount) {
8971
9147
  const st = h.call(() => mount.opts.bridge.stat(mount.opts.root));
9148
+ h.watchRenames(mount.opts.bridge);
8972
9149
  if (!st.isDirectory) throw new Fs.ErrnoError(wasiErrno("ENOTDIR"));
8973
9150
  const root = h.makeNode(null, "/", st);
8974
9151
  root.mode = modeFromStat(st, mount.opts.bridge.owners === true);
@@ -10562,7 +10739,7 @@ function pidStatus(info) {
10562
10739
  "TracerPid: 0",
10563
10740
  `Uid: ${ids(c.ruid, c.euid, c.suid)}`,
10564
10741
  `Gid: ${ids(c.rgid, c.egid, c.sgid)}`,
10565
- ...info.tag !== void 0 ? [tagLine(info.tag)] : [],
10742
+ ...(info.tags ?? (info.tag !== void 0 ? [info.tag] : [])).map(tagLine),
10566
10743
  "FDSize: 64",
10567
10744
  `VmSize: ${Math.ceil(info.memory / KIB)} kB`,
10568
10745
  `VmRSS: ${Math.ceil(info.memory / KIB)} kB`,