@ai-ecoverse/slicc-kernel 1.40.1 → 1.41.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -106,15 +106,15 @@ var IndexedDbMeta = class {
106
106
  async update(path, change) {
107
107
  const [transaction, store] = this.transaction("readwrite");
108
108
  const request2 = store.get(path);
109
- let next;
109
+ let next2;
110
110
  request2.onsuccess = () => {
111
- next = change(request2.result);
112
- if (next) store.put(next);
111
+ next2 = change(request2.result);
112
+ if (next2) store.put(next2);
113
113
  else store.delete(path);
114
114
  };
115
115
  await settle(transaction, () => void 0);
116
116
  this.changed({ paths: [path] });
117
- this.cache.set(path, next ?? null);
117
+ this.cache.set(path, next2 ?? null);
118
118
  }
119
119
  async move(from, to, root) {
120
120
  const [transaction, store] = this.transaction("readwrite");
@@ -341,8 +341,8 @@ var OpfsFs = class {
341
341
  resolvePath(base, path) {
342
342
  return resolvePath(base, path);
343
343
  }
344
- async walk(parts, from, start) {
345
- let dir = start;
344
+ async walk(parts, from, start2) {
345
+ let dir = start2;
346
346
  for (let at = from; at < parts.length; at++) {
347
347
  dir = await dir.getDirectoryHandle(parts[at]);
348
348
  this.dirs.set(`/${parts.slice(0, at + 1).join("/")}`, dir);
@@ -428,7 +428,7 @@ var OpfsFs = class {
428
428
  }
429
429
  return void 0;
430
430
  }
431
- async locate(path, follow) {
431
+ async locate(path, follow2) {
432
432
  let current = path;
433
433
  for (let hops = 0; hops <= MAX_LINKS; hops++) {
434
434
  try {
@@ -437,9 +437,9 @@ var OpfsFs = class {
437
437
  if (!missing(err)) throw err;
438
438
  const link2 = await this.linkAlong(current);
439
439
  if (!link2) throw err;
440
- if (link2.path === current && !follow) return { path: current, link: link2 };
441
- const rest = current.slice(link2.path.length);
442
- current = resolvePath(parentOf2(link2.path), `${link2.link}${rest}`);
440
+ if (link2.path === current && !follow2) return { path: current, link: link2 };
441
+ const rest2 = current.slice(link2.path.length);
442
+ current = resolvePath(parentOf2(link2.path), `${link2.link}${rest2}`);
443
443
  }
444
444
  }
445
445
  throw fsError("ELOOP", path);
@@ -755,9 +755,9 @@ var OpfsFs = class {
755
755
  return timed;
756
756
  }
757
757
  async restamp(path, timed) {
758
- for (const rest of timed) {
759
- const mtimeFor = await this.modified(path + rest);
760
- await this.meta.update(path + rest, (entry) => entry && { ...entry, mtimeFor });
758
+ for (const rest2 of timed) {
759
+ const mtimeFor = await this.modified(path + rest2);
760
+ await this.meta.update(path + rest2, (entry) => entry && { ...entry, mtimeFor });
761
761
  }
762
762
  }
763
763
  async place(handle, dir, name2) {
@@ -805,8 +805,8 @@ var OpfsFs = class {
805
805
  }));
806
806
  this.touch(parent.path);
807
807
  }
808
- async realpath(path, follow) {
809
- return (await this.locate(path, follow)).path;
808
+ async realpath(path, follow2) {
809
+ return (await this.locate(path, follow2)).path;
810
810
  }
811
811
  async readlink(path) {
812
812
  const found = await this.locate(path, false);
@@ -1659,8 +1659,8 @@ var KernelSocket = class _KernelSocket {
1659
1659
  async accept(signal, nonblock = false) {
1660
1660
  for (; ; ) {
1661
1661
  if (this.state !== "listening") throw new KernelError("EINVAL");
1662
- const next = this.queue.shift();
1663
- if (next) return next;
1662
+ const next2 = this.queue.shift();
1663
+ if (next2) return next2;
1664
1664
  if (nonblock) throw new KernelError("EAGAIN");
1665
1665
  await this.changes.wait(signal);
1666
1666
  }
@@ -1841,8 +1841,8 @@ var LoopbackNet = class {
1841
1841
  if (reserve) this.internal.add(port);
1842
1842
  return this.internal.has(port);
1843
1843
  }
1844
- activate(addr, start) {
1845
- this.activators.set(keyOf(addr), start);
1844
+ activate(addr, start2) {
1845
+ this.activators.set(keyOf(addr), start2);
1846
1846
  }
1847
1847
  socket(domain) {
1848
1848
  return new KernelSocket(this, domain);
@@ -2084,12 +2084,12 @@ var MessageQueue = class {
2084
2084
  }
2085
2085
  async *[Symbol.asyncIterator]() {
2086
2086
  for (; ; ) {
2087
- const next = this.items.shift();
2088
- if (next !== void 0) {
2089
- const n = payloadSize(next);
2087
+ const next2 = this.items.shift();
2088
+ if (next2 !== void 0) {
2089
+ const n = payloadSize(next2);
2090
2090
  this.size -= n;
2091
2091
  this.taken?.(n);
2092
- yield next;
2092
+ yield next2;
2093
2093
  continue;
2094
2094
  }
2095
2095
  if (this.ended) return;
@@ -2118,7 +2118,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
2118
2118
  ...typeof code === "string" ? { code } : {}
2119
2119
  });
2120
2120
  };
2121
- const start = async (call) => {
2121
+ const start2 = async (call) => {
2122
2122
  const abort = new AbortController();
2123
2123
  const entry = { abort };
2124
2124
  open.set(call.nid, entry);
@@ -2197,9 +2197,9 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
2197
2197
  try {
2198
2198
  const messages = socket.messages[Symbol.asyncIterator]();
2199
2199
  for (; ; ) {
2200
- const next = await Promise.race([messages.next(), unanswered]);
2201
- if (next === "late" || next.done) break;
2202
- const data = next.value;
2200
+ const next2 = await Promise.race([messages.next(), unanswered]);
2201
+ if (next2 === "late" || next2.done) break;
2202
+ const data = next2.value;
2203
2203
  if (flow.closing) continue;
2204
2204
  if (payloadSize(data) > MESSAGE_LIMIT) {
2205
2205
  oversize = true;
@@ -2240,12 +2240,12 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
2240
2240
  const body = open.get(nid)?.body;
2241
2241
  if (!body) return;
2242
2242
  try {
2243
- const next = await body.next();
2244
- if (next.done) {
2243
+ const next2 = await body.next();
2244
+ if (next2.done) {
2245
2245
  open.delete(nid);
2246
2246
  peer.postMessage({ net: "end", nid });
2247
2247
  } else {
2248
- const bytes = next.value.slice();
2248
+ const bytes = next2.value.slice();
2249
2249
  peer.postMessage({ net: "chunk", nid, bytes }, [bytes.buffer]);
2250
2250
  }
2251
2251
  } catch (e) {
@@ -2262,7 +2262,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
2262
2262
  };
2263
2263
  return {
2264
2264
  answer(call) {
2265
- if (call.net === "fetch") void start(call);
2265
+ if (call.net === "fetch") void start2(call);
2266
2266
  else if (call.net === "read") void read(call.nid);
2267
2267
  else if (call.net === "ws-open") void openSocket(call);
2268
2268
  else if (call.net === "ws-send") void sendOn(call);
@@ -2290,17 +2290,17 @@ async function realpath(fs, path) {
2290
2290
  let parts = fs.resolvePath("/", path).split("/").filter(Boolean);
2291
2291
  let resolved = "";
2292
2292
  for (let hops = 0; parts.length > 0; ) {
2293
- const [name2, ...rest] = parts;
2294
- const next = `${resolved}/${name2}`;
2295
- if (!(await fs.lstat(next)).isSymbolicLink) {
2296
- resolved = next;
2297
- parts = rest;
2293
+ const [name2, ...rest2] = parts;
2294
+ const next2 = `${resolved}/${name2}`;
2295
+ if (!(await fs.lstat(next2)).isSymbolicLink) {
2296
+ resolved = next2;
2297
+ parts = rest2;
2298
2298
  continue;
2299
2299
  }
2300
2300
  if (++hops > MAX_LINKS2) throw fsError("ELOOP", path);
2301
- const target = await fs.readlink(next);
2301
+ const target = await fs.readlink(next2);
2302
2302
  const base = target.startsWith("/") ? "/" : resolved || "/";
2303
- parts = [...fs.resolvePath(base, target).split("/").filter(Boolean), ...rest];
2303
+ parts = [...fs.resolvePath(base, target).split("/").filter(Boolean), ...rest2];
2304
2304
  resolved = "";
2305
2305
  }
2306
2306
  return resolved || "/";
@@ -2652,10 +2652,10 @@ var Incoming = class {
2652
2652
  this.eof = true;
2653
2653
  return false;
2654
2654
  }
2655
- const next = new Uint8Array(this.buf.length + chunk2.length);
2656
- next.set(this.buf);
2657
- next.set(chunk2, this.buf.length);
2658
- this.buf = next;
2655
+ const next2 = new Uint8Array(this.buf.length + chunk2.length);
2656
+ next2.set(this.buf);
2657
+ next2.set(chunk2, this.buf.length);
2658
+ this.buf = next2;
2659
2659
  return true;
2660
2660
  }
2661
2661
  take(n) {
@@ -3629,15 +3629,15 @@ var octets = (bytes) => tlv(4, bytes);
3629
3629
  var bits = (bytes, unused = 0) => tlv(3, Uint8Array.of(unused), bytes);
3630
3630
  var TRUE = tlv(1, Uint8Array.of(255));
3631
3631
  function integer(magnitude) {
3632
- let start = 0;
3633
- while (start < magnitude.length - 1 && magnitude[start] === 0) start++;
3634
- const trimmed = magnitude.subarray(start);
3632
+ let start2 = 0;
3633
+ while (start2 < magnitude.length - 1 && magnitude[start2] === 0) start2++;
3634
+ const trimmed = magnitude.subarray(start2);
3635
3635
  return tlv(2, trimmed[0] & 128 ? concat2([Uint8Array.of(0), trimmed]) : trimmed);
3636
3636
  }
3637
3637
  function oid(dotted) {
3638
- const [a, b, ...rest] = dotted.split(".").map(Number);
3638
+ const [a, b, ...rest2] = dotted.split(".").map(Number);
3639
3639
  const out = [40 * a + b];
3640
- for (const arc of rest) {
3640
+ for (const arc of rest2) {
3641
3641
  const groups = [];
3642
3642
  for (let v = arc; ; v = Math.floor(v / 128)) {
3643
3643
  groups.unshift(v & 127);
@@ -3677,19 +3677,19 @@ function children(der) {
3677
3677
  function header(der, at) {
3678
3678
  const tag = der[at];
3679
3679
  let len = der[at + 1];
3680
- let start = at + 2;
3680
+ let start2 = at + 2;
3681
3681
  if (len & 128) {
3682
3682
  const count = len & 127;
3683
3683
  len = 0;
3684
- for (let i = 0; i < count; i++) len = len * 256 + der[start + i];
3685
- start += count;
3684
+ for (let i = 0; i < count; i++) len = len * 256 + der[start2 + i];
3685
+ start2 += count;
3686
3686
  }
3687
- if (start + len > der.length) throw new Error("truncated DER");
3688
- return [tag, start, start + len];
3687
+ if (start2 + len > der.length) throw new Error("truncated DER");
3688
+ return [tag, start2, start2 + len];
3689
3689
  }
3690
3690
  function contents(element) {
3691
- const [, start, end] = header(element, 0);
3692
- return element.subarray(start, end);
3691
+ const [, start2, end] = header(element, 0);
3692
+ return element.subarray(start2, end);
3693
3693
  }
3694
3694
  function publicKeyBits(spki) {
3695
3695
  const key = children(spki)[1];
@@ -5288,6 +5288,53 @@ function withCommandDirs(fs, names) {
5288
5288
  };
5289
5289
  }
5290
5290
 
5291
+ // src/fs/physical-path.ts
5292
+ var MAX_HOPS = 40;
5293
+ function start(path) {
5294
+ return { done: [], todo: path.split("/").filter((p) => p !== ""), hops: 0 };
5295
+ }
5296
+ function next(walk) {
5297
+ while (walk.todo.length > 0) {
5298
+ const part = walk.todo.shift();
5299
+ if (part === ".") continue;
5300
+ if (part === "..") {
5301
+ walk.done.pop();
5302
+ continue;
5303
+ }
5304
+ return part;
5305
+ }
5306
+ return void 0;
5307
+ }
5308
+ function lexical(path) {
5309
+ const walk = start(path);
5310
+ for (let part = next(walk); part !== void 0; part = next(walk)) walk.done.push(part);
5311
+ return `/${walk.done.join("/")}`;
5312
+ }
5313
+ function rest(walk, part) {
5314
+ return lexical(`/${[...walk.done, part, ...walk.todo].join("/")}`);
5315
+ }
5316
+ function follow(walk, target) {
5317
+ if (++walk.hops > MAX_HOPS) return false;
5318
+ if (target.startsWith("/")) walk.done.length = 0;
5319
+ walk.todo = [...target.split("/").filter((p) => p !== ""), ...walk.todo];
5320
+ return true;
5321
+ }
5322
+ async function physicalPathAsync(fs, path) {
5323
+ const walk = start(path);
5324
+ for (let part = next(walk); part !== void 0; part = next(walk)) {
5325
+ const at = `/${[...walk.done, part].join("/")}`;
5326
+ let target;
5327
+ try {
5328
+ target = (await fs.lstat(at)).isSymbolicLink ? await fs.readlink(at) : void 0;
5329
+ } catch {
5330
+ return rest(walk, part);
5331
+ }
5332
+ if (target === void 0) walk.done.push(part);
5333
+ else if (!follow(walk, target)) return lexical(path);
5334
+ }
5335
+ return `/${walk.done.join("/")}`;
5336
+ }
5337
+
5291
5338
  // src/fs/unlinked.ts
5292
5339
  var UNLINKED_DIR = ".slicc-unlinked";
5293
5340
  function webLocks() {
@@ -5343,9 +5390,9 @@ var UnlinkedKeeper = class {
5343
5390
  void locks?.request(lockName(this.instance), () => new Promise(() => void 0));
5344
5391
  }
5345
5392
  serial(op) {
5346
- const next = this.queue.then(op);
5347
- this.queue = next.catch(() => void 0);
5348
- return next;
5393
+ const next2 = this.queue.then(op);
5394
+ this.queue = next2.catch(() => void 0);
5395
+ return next2;
5349
5396
  }
5350
5397
  wrap(fs = this.fs) {
5351
5398
  const keeper = this;
@@ -5642,10 +5689,10 @@ var ChildTable = class {
5642
5689
  }
5643
5690
  return this.track(req, fds, captured, this.spawner);
5644
5691
  }
5645
- async track(req, fds, captured, start) {
5692
+ async track(req, fds, captured, start2) {
5646
5693
  let handle;
5647
5694
  try {
5648
- handle = await start(req, fds);
5695
+ handle = await start2(req, fds);
5649
5696
  } catch (e) {
5650
5697
  await fds.closeAll();
5651
5698
  throw e;
@@ -5882,8 +5929,7 @@ var HeldSet = class extends Set {
5882
5929
  delete(holds) {
5883
5930
  const removed = super.delete(holds);
5884
5931
  for (const path of /* @__PURE__ */ new Set([...holds.keys(), ...holds.opens.keys()])) this.idle(path);
5885
- for (const kept of holds.unlinked.values()) kept.release();
5886
- holds.unlinked.clear();
5932
+ holds.releaseAll();
5887
5933
  return removed;
5888
5934
  }
5889
5935
  };
@@ -5896,6 +5942,10 @@ var HeldPaths = class extends Map {
5896
5942
  opens = /* @__PURE__ */ new Map();
5897
5943
  unlinked = /* @__PURE__ */ new Map();
5898
5944
  aliases = /* @__PURE__ */ new Map();
5945
+ handles = /* @__PURE__ */ new Map();
5946
+ keptHandles = /* @__PURE__ */ new Map();
5947
+ uses = /* @__PURE__ */ new Map();
5948
+ lastHandle = 0;
5899
5949
  owning;
5900
5950
  onIdle;
5901
5951
  keyOf(path) {
@@ -5911,29 +5961,70 @@ var HeldPaths = class extends Map {
5911
5961
  return this.opens.keys();
5912
5962
  }
5913
5963
  isKept(path) {
5914
- return this.unlinked.has(path);
5964
+ const ids = this.handlesAt(path);
5965
+ return ids.length === 0 ? this.unlinked.has(path) : ids.every((id) => this.keptHandles.has(id));
5966
+ }
5967
+ handlesAt(path) {
5968
+ return [...this.handles].filter(([, key]) => key === path).map(([id]) => id);
5969
+ }
5970
+ keptFor(handle) {
5971
+ return this.keptHandles.get(handle);
5915
5972
  }
5916
5973
  keep(path, file) {
5974
+ const fresh = this.handlesAt(path).filter((id) => !this.keptHandles.has(id));
5975
+ for (const id of fresh) this.keptHandles.set(id, file);
5976
+ this.uses.set(file, Math.max(fresh.length, 1));
5917
5977
  this.unlinked.set(path, file);
5918
5978
  }
5919
- unkeep(path) {
5920
- this.unlinked.delete(path);
5921
- }
5922
- hold(path, on, open = false, real) {
5923
- if (open) {
5924
- const key = real ?? this.keyOf(path);
5925
- if (key !== path) this.aliases.set(path, key);
5926
- const count2 = (this.opens.get(key) ?? 0) + (on ? 1 : -1);
5927
- if (count2 > 0) this.opens.set(key, count2);
5928
- else {
5929
- this.opens.delete(key);
5930
- this.unlinked.get(key)?.release();
5931
- this.unlinked.delete(key);
5932
- for (const [alias, target] of this.aliases) if (target === key) this.aliases.delete(alias);
5933
- this.onIdle?.(key);
5934
- }
5979
+ unkeep(path, file) {
5980
+ for (const [id, kept] of this.keptHandles) if (kept === file) this.keptHandles.delete(id);
5981
+ this.uses.delete(file);
5982
+ if (this.unlinked.get(path) === file) this.unlinked.delete(path);
5983
+ }
5984
+ letGo(file, all = false) {
5985
+ const left = all ? 0 : (this.uses.get(file) ?? 0) - 1;
5986
+ if (left > 0) {
5987
+ this.uses.set(file, left);
5935
5988
  return;
5936
5989
  }
5990
+ if (!this.uses.delete(file)) return;
5991
+ file.release();
5992
+ for (const [path, kept] of this.unlinked) if (kept === file) this.unlinked.delete(path);
5993
+ }
5994
+ releaseAll() {
5995
+ for (const file of [...this.uses.keys()]) this.letGo(file, true);
5996
+ this.keptHandles.clear();
5997
+ }
5998
+ hold(path, on, open = false, real, handle) {
5999
+ if (open) return this.holdOpen(path, on, real, handle);
6000
+ this.holdWrite(path, on);
6001
+ return void 0;
6002
+ }
6003
+ holdOpen(path, on, real, handle) {
6004
+ const known = handle === void 0 ? void 0 : this.handles.get(handle);
6005
+ const key = known ?? real ?? this.keyOf(path);
6006
+ if (key !== path) this.aliases.set(path, key);
6007
+ if (handle !== void 0) {
6008
+ const kept = this.keptHandles.get(handle);
6009
+ this.handles.delete(handle);
6010
+ this.keptHandles.delete(handle);
6011
+ if (kept) this.letGo(kept);
6012
+ }
6013
+ const count = (this.opens.get(key) ?? 0) + (on ? 1 : -1);
6014
+ if (count > 0) this.opens.set(key, count);
6015
+ else {
6016
+ this.opens.delete(key);
6017
+ for (const id of this.handlesAt(key)) this.handles.delete(id);
6018
+ const kept = this.unlinked.get(key);
6019
+ if (kept) this.letGo(kept, true);
6020
+ for (const [alias, target] of this.aliases) if (target === key) this.aliases.delete(alias);
6021
+ this.onIdle?.(key);
6022
+ }
6023
+ if (!on) return void 0;
6024
+ this.handles.set(++this.lastHandle, key);
6025
+ return this.lastHandle;
6026
+ }
6027
+ holdWrite(path, on) {
5937
6028
  const count = (this.get(path) ?? 0) + (on ? 1 : -1);
5938
6029
  if (count > 0) this.set(path, count);
5939
6030
  else {
@@ -5970,6 +6061,9 @@ var HeldPaths = class extends Map {
5970
6061
  this.opens.delete(path);
5971
6062
  this.opens.set(moved2, (this.opens.get(moved2) ?? 0) + count);
5972
6063
  }
6064
+ for (const [id, key] of this.handles) {
6065
+ if (within4(key, from)) this.handles.set(id, to + key.slice(from.length));
6066
+ }
5973
6067
  }
5974
6068
  isRevoked(path) {
5975
6069
  return this.revoked.has(path);
@@ -6644,9 +6738,9 @@ var MountFs = class {
6644
6738
  this.table.forget(found.mount, normalizePath(path));
6645
6739
  await found.mount.conn.call({ op: "symlink", target, path: found.rel });
6646
6740
  }
6647
- async realpath(path, follow) {
6741
+ async realpath(path, follow2) {
6648
6742
  if (this.at(path) || !this.base.realpath) throw errnoError("ENOSYS", path);
6649
- const real = await this.base.realpath(path, follow);
6743
+ const real = await this.base.realpath(path, follow2);
6650
6744
  if (this.at(real)) throw errnoError("ENOSYS", path);
6651
6745
  return real;
6652
6746
  }
@@ -6833,25 +6927,31 @@ async function ranged(fs, path, req) {
6833
6927
  }
6834
6928
  var UNLINKED_OPS = /* @__PURE__ */ new Set(["read", "pread", "pwrite", "truncate"]);
6835
6929
  var OWN_OPS = /* @__PURE__ */ new Set(["rm", "unlink", "rmdir", "rename"]);
6930
+ async function keptOr(entry, path, handle) {
6931
+ if (handle !== void 0) return entry.keptFor?.(handle)?.hidden ?? path;
6932
+ const kept = entry.unlinked?.(path);
6933
+ return kept && !await entry.fs.exists(path) ? kept.hidden : path;
6934
+ }
6836
6935
  async function dispatchSyncFs(req) {
6837
6936
  const entry = resolveSyncFsToken(req.token);
6838
6937
  if (!entry) return { ok: false, errno: "EACCES", message: "sync-fs: unknown or revoked token" };
6839
6938
  const { fs, cwd } = entry;
6840
6939
  try {
6841
6940
  const path = fs.resolvePath(cwd, req.path);
6941
+ if (req.op === "kept") return json2(entry.keptFor?.(req.handle ?? -1) !== void 0);
6842
6942
  if (req.op === "statfs") return json2(await entry.statfs?.(path) ?? await storageUsage());
6843
6943
  if (req.op === "hold") {
6844
6944
  const [on, open] = [((req.mode ?? 0) & 1) === 1, ((req.mode ?? 0) & 2) === 2];
6845
- const real = on && open ? await fs.realpath?.(path, true).catch(() => path) : void 0;
6846
- entry.hold?.(path, on, open, real);
6945
+ if (on && open) {
6946
+ const real = await fs.realpath?.(path, true).catch(() => path);
6947
+ return json2(entry.hold?.(path, on, open, real) ?? null);
6948
+ }
6949
+ entry.hold?.(path, on, open, void 0, req.handle);
6847
6950
  return done;
6848
6951
  }
6849
6952
  if (entry.revoked?.(path)) return { ok: false, errno: "EIO", message: `${path} was unmounted` };
6850
6953
  if (req.op === "write" && req.mode === 1 || UNLINKED_OPS.has(req.op)) {
6851
- const serve = async () => {
6852
- const kept = entry.unlinked?.(path);
6853
- return run(entry, kept && !await fs.exists(path) ? kept.hidden : path, req);
6854
- };
6954
+ const serve = async () => run(entry, await keptOr(entry, path, req.handle), req);
6855
6955
  return await (entry.gate ? entry.gate(path, serve) : serve());
6856
6956
  }
6857
6957
  if (!entry.own || !OWN_OPS.has(req.op)) return await run(entry, path, req);
@@ -7210,9 +7310,9 @@ var HttpHandles = class {
7210
7310
  return this.close(req.handle);
7211
7311
  }
7212
7312
  traits() {
7213
- const { unavailable, crossOrigin = "any", ...rest } = this.transport.traits;
7313
+ const { unavailable, crossOrigin = "any", ...rest2 } = this.transport.traits;
7214
7314
  if (unavailable) return { ok: false, errno: "ENETUNREACH", message: NO_TRANSPORT };
7215
- return { ok: true, kind: "json", json: { ...rest, crossOrigin } };
7315
+ return { ok: true, kind: "json", json: { ...rest2, crossOrigin } };
7216
7316
  }
7217
7317
  add(abort, body, cancel) {
7218
7318
  const handle = ++this.nextHandle;
@@ -7274,9 +7374,9 @@ var HttpHandles = class {
7274
7374
  async take(entry, max) {
7275
7375
  if (entry.left.length === 0 && !entry.done) {
7276
7376
  try {
7277
- const next = await entry.body.next();
7278
- if (next.done) entry.done = true;
7279
- else entry.left = next.value;
7377
+ const next2 = await entry.body.next();
7378
+ if (next2.done) entry.done = true;
7379
+ else entry.left = next2.value;
7280
7380
  } catch (e) {
7281
7381
  entry.done = true;
7282
7382
  const timedOut = e?.code === "ETIMEDOUT";
@@ -7638,12 +7738,12 @@ var KernelTty = class {
7638
7738
  const chunks = [];
7639
7739
  let n = 0;
7640
7740
  while (this.readable.length > 0 && n < max) {
7641
- const next = this.readable[0];
7642
- if (next === null || next === void 0) break;
7643
- const take = next.subarray(0, max - n);
7741
+ const next2 = this.readable[0];
7742
+ if (next2 === null || next2 === void 0) break;
7743
+ const take = next2.subarray(0, max - n);
7644
7744
  chunks.push(take);
7645
7745
  n += take.length;
7646
- if (take.length < next.length) this.readable[0] = next.subarray(take.length);
7746
+ if (take.length < next2.length) this.readable[0] = next2.subarray(take.length);
7647
7747
  else this.readable.shift();
7648
7748
  if (this.canonical) break;
7649
7749
  }
@@ -7740,11 +7840,11 @@ var PtyPair = class {
7740
7840
  const chunks = [];
7741
7841
  let n = 0;
7742
7842
  while (this.queue.length > 0 && n < max - status) {
7743
- const next = this.queue[0];
7744
- const take = next.subarray(0, max - status - n);
7843
+ const next2 = this.queue[0];
7844
+ const take = next2.subarray(0, max - status - n);
7745
7845
  chunks.push(take);
7746
7846
  n += take.length;
7747
- if (take.length < next.length) this.queue[0] = next.subarray(take.length);
7847
+ if (take.length < next2.length) this.queue[0] = next2.subarray(take.length);
7748
7848
  else this.queue.shift();
7749
7849
  }
7750
7850
  const out = new Uint8Array(status + n);
@@ -8050,7 +8150,7 @@ var Pages = class {
8050
8150
  }
8051
8151
  const last = runs[runs.length - 1];
8052
8152
  if (last) last[1] = Math.max(last[1], Math.min(READAHEAD, this.stored - last[0]));
8053
- return runs.map(([start, n]) => [start, Math.min(n, this.stored - start)]);
8153
+ return runs.map(([start2, n]) => [start2, Math.min(n, this.stored - start2)]);
8054
8154
  }
8055
8155
  partial(at, length2) {
8056
8156
  if (length2 === 0) return [];
@@ -8058,16 +8158,16 @@ var Pages = class {
8058
8158
  const edges = /* @__PURE__ */ new Set([Math.floor(at / PAGE), Math.floor((at + length2 - 1) / PAGE)]);
8059
8159
  const runs = [];
8060
8160
  for (const page of edges) {
8061
- const start = page * PAGE;
8062
- const covered = at <= start && at + length2 >= start + PAGE;
8063
- if (covered || this.pages.has(page) || start >= this.stored) continue;
8064
- runs.push([start, Math.min(PAGE, this.stored - start)]);
8161
+ const start2 = page * PAGE;
8162
+ const covered = at <= start2 && at + length2 >= start2 + PAGE;
8163
+ if (covered || this.pages.has(page) || start2 >= this.stored) continue;
8164
+ runs.push([start2, Math.min(PAGE, this.stored - start2)]);
8065
8165
  }
8066
8166
  return runs;
8067
8167
  }
8068
- fill(start, bytes) {
8168
+ fill(start2, bytes) {
8069
8169
  for (let at = 0; at < bytes.length; at += PAGE) {
8070
- const page = (start + at) / PAGE;
8170
+ const page = (start2 + at) / PAGE;
8071
8171
  if (this.pages.has(page)) continue;
8072
8172
  const part = bytes.subarray(at, Math.min(at + PAGE, bytes.length));
8073
8173
  const fresh = this.take(part.length);
@@ -8133,14 +8233,14 @@ var Pages = class {
8133
8233
  while (j < sorted.length && sorted[j] === first + (j - i) && sorted[j] * PAGE % RUN !== 0) {
8134
8234
  j++;
8135
8235
  }
8136
- const start = first * PAGE;
8236
+ const start2 = first * PAGE;
8137
8237
  const end = Math.min(this.length, (first + (j - i)) * PAGE);
8138
- const bytes = new Uint8Array(end - start);
8238
+ const bytes = new Uint8Array(end - start2);
8139
8239
  for (let k = i; k < j; k++) {
8140
8240
  const page = this.pages.get(sorted[k]);
8141
- bytes.set(page.subarray(0, Math.min(PAGE, end - (k - i) * PAGE - start)), (k - i) * PAGE);
8241
+ bytes.set(page.subarray(0, Math.min(PAGE, end - (k - i) * PAGE - start2)), (k - i) * PAGE);
8142
8242
  }
8143
- runs.push({ offset: start, bytes });
8243
+ runs.push({ offset: start2, bytes });
8144
8244
  i = j;
8145
8245
  }
8146
8246
  const written2 = Math.max(this.stored, ...runs.map((r) => r.offset + r.bytes.length));
@@ -8207,8 +8307,8 @@ var AsyncRangedFile = class {
8207
8307
  return this.pages.length;
8208
8308
  }
8209
8309
  async fetch(runs) {
8210
- for (const [start, n] of runs) {
8211
- this.pages.fill(start, await this.io.pread(this.path, start, n, this.version));
8310
+ for (const [start2, n] of runs) {
8311
+ this.pages.fill(start2, await this.io.pread(this.path, start2, n, this.version));
8212
8312
  }
8213
8313
  }
8214
8314
  async read(at, length2) {
@@ -8283,9 +8383,9 @@ var VfsNode = class {
8283
8383
  if (dirty && contents2 !== void 0) this.markDirty();
8284
8384
  }
8285
8385
  serial(op) {
8286
- const next = this.queue.then(op);
8287
- this.queue = next.catch(() => void 0);
8288
- return next;
8386
+ const next2 = this.queue.then(op);
8387
+ this.queue = next2.catch(() => void 0);
8388
+ return next2;
8289
8389
  }
8290
8390
  revoke() {
8291
8391
  this.revoked = true;
@@ -8467,10 +8567,10 @@ var VfsNodes = class {
8467
8567
  targetKey(path) {
8468
8568
  return this.real(path, true, () => realTarget(this.fs, path));
8469
8569
  }
8470
- async real(path, follow, walk) {
8570
+ async real(path, follow2, walk) {
8471
8571
  if (this.fs.realpath) {
8472
8572
  try {
8473
- return await this.fs.realpath(path, follow);
8573
+ return await this.fs.realpath(path, follow2);
8474
8574
  } catch (err) {
8475
8575
  if (errCode(err) === "ELOOP") throw err;
8476
8576
  }
@@ -8598,8 +8698,8 @@ var VfsNodes = class {
8598
8698
  }
8599
8699
  }
8600
8700
  };
8601
- async function present(fs, path, follow = false) {
8602
- const look = (follow ? void 0 : fs.lstat) ?? fs.stat;
8701
+ async function present(fs, path, follow2 = false) {
8702
+ const look = (follow2 ? void 0 : fs.lstat) ?? fs.stat;
8603
8703
  try {
8604
8704
  await (look ? look.call(fs, path) : fs.readFileBuffer(path));
8605
8705
  return true;
@@ -8625,10 +8725,10 @@ async function realDir(fs, dir, budget = { hops: 0 }) {
8625
8725
  at = parentOf6(at);
8626
8726
  continue;
8627
8727
  }
8628
- const next = at === "/" ? `/${part}` : `${at}/${part}`;
8629
- const link2 = await linkOf(fs, next);
8728
+ const next2 = at === "/" ? `/${part}` : `${at}/${part}`;
8729
+ const link2 = await linkOf(fs, next2);
8630
8730
  if (link2 === void 0) {
8631
- at = next;
8731
+ at = next2;
8632
8732
  continue;
8633
8733
  }
8634
8734
  if (budget.hops >= MAX_LINKS5) throw fsError("ELOOP", dir);
@@ -9623,7 +9723,8 @@ function holdingToken(opts, holds) {
9623
9723
  fs: opts.fs,
9624
9724
  cwd: opts.cwd,
9625
9725
  ...opts.statfs ? { statfs: opts.statfs } : {},
9626
- hold: (path, on, open, real) => holds.hold(path, on, open, real),
9726
+ hold: (path, on, open, real, handle) => holds.hold(path, on, open, real, handle),
9727
+ keptFor: (handle) => holds.keptFor(handle),
9627
9728
  unlinked: (path) => holds.keptAt(path),
9628
9729
  gate: (path, op) => opts.unlinkGate && holds.holding(path) ? opts.unlinkGate.run(holds.keyOf(path), op) : op(),
9629
9730
  own: (path, op) => holds.own(path, op),
@@ -10880,9 +10981,9 @@ function tmpfs() {
10880
10981
  let node = root;
10881
10982
  for (const name2 of parts(path)) {
10882
10983
  if (node.kind !== "directory") throw fsError2("ENOTDIR", path);
10883
- const next = node.children.get(name2);
10884
- if (!next) throw fsError2("ENOENT", path);
10885
- node = next;
10984
+ const next2 = node.children.get(name2);
10985
+ if (!next2) throw fsError2("ENOENT", path);
10986
+ node = next2;
10886
10987
  }
10887
10988
  return node;
10888
10989
  }
@@ -11446,8 +11547,8 @@ var Launcher = class {
11446
11547
  const words = shebang(head) ?? (binfmt ? [binfmt] : void 0);
11447
11548
  if (!words) return void 0;
11448
11549
  if (baseName(words[0]) === "env") words.shift();
11449
- const [interp, ...rest] = words;
11450
- const arg = rest.join(" ");
11550
+ const [interp, ...rest2] = words;
11551
+ const arg = rest2.join(" ");
11451
11552
  const passed = [...arg ? [arg] : [], command ? script : file, ...argv.slice(1)];
11452
11553
  const found = interp ? await this.resolve(interp, interp, cwd) : void 0;
11453
11554
  if (!found) {
@@ -11528,7 +11629,8 @@ var Launcher = class {
11528
11629
  }
11529
11630
  async launch(planned, req) {
11530
11631
  const { target, args } = planned;
11531
- const seen = { ...req.env, HOSTNAME: this.hostname, cwd: req.cwd };
11632
+ const cwd = await physicalPathAsync(this.base, req.cwd);
11633
+ const seen = { ...req.env, HOSTNAME: this.hostname, cwd };
11532
11634
  const env = { ...expandDefaults(target.env, seen), ...req.env };
11533
11635
  for (const key of target.unset ?? []) delete env[key];
11534
11636
  env.HOSTNAME = this.hostname;
@@ -11539,7 +11641,7 @@ var Launcher = class {
11539
11641
  await req.fds.closeAll();
11540
11642
  throw err;
11541
11643
  }
11542
- return this.start({ ...req, program, argv0: target.argv0, args, env });
11644
+ return this.start({ ...req, cwd, program, argv0: target.argv0, args, env });
11543
11645
  }
11544
11646
  groupSession(pgid) {
11545
11647
  return this.jobs.sessionOf(pgid);
@@ -11946,7 +12048,8 @@ var Launcher = class {
11946
12048
  async starting(argv, dir) {
11947
12049
  this.catalog = void 0;
11948
12050
  this.binfmts = void 0;
11949
- const cwd = this.fs.resolvePath("/", dir ?? "/");
12051
+ const start2 = dir ?? "/";
12052
+ const cwd = await physicalPathAsync(this.base, start2.startsWith("/") ? start2 : `/${start2}`);
11950
12053
  const [file = ""] = argv;
11951
12054
  await this.base.mkdir(cwd, { recursive: true });
11952
12055
  return { cwd, file, planned: await this.plan(file, argv, cwd) };