@ai-ecoverse/slicc-kernel 1.127.1 → 1.128.1

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.
@@ -185,8 +185,8 @@ var IndexedDbMeta = class {
185
185
  const [transaction, store] = this.transaction("readonly");
186
186
  const found = /* @__PURE__ */ new Map();
187
187
  for (const path of missing4) {
188
- const request2 = store.get(path);
189
- request2.onsuccess = () => void found.set(path, request2.result ?? null);
188
+ const request3 = store.get(path);
189
+ request3.onsuccess = () => void found.set(path, request3.result ?? null);
190
190
  }
191
191
  await settle(transaction, () => void 0);
192
192
  if (generation === this.generation)
@@ -202,16 +202,16 @@ var IndexedDbMeta = class {
202
202
  const requests = paths.map((path) => store.get(path));
203
203
  return settle(
204
204
  transaction,
205
- () => requests.map((request2) => request2.result ?? void 0)
205
+ () => requests.map((request3) => request3.result ?? void 0)
206
206
  );
207
207
  }
208
208
  async update(path, change) {
209
209
  this.settleRemoves();
210
210
  const [transaction, store] = this.transaction("readwrite");
211
- const request2 = store.get(path);
211
+ const request3 = store.get(path);
212
212
  let next3;
213
- request2.onsuccess = () => {
214
- next3 = change(request2.result);
213
+ request3.onsuccess = () => {
214
+ next3 = change(request3.result);
215
215
  if (next3) store.put(next3);
216
216
  else store.delete(path);
217
217
  };
@@ -225,9 +225,9 @@ var IndexedDbMeta = class {
225
225
  const [transaction, store] = this.transaction("readwrite");
226
226
  const next3 = /* @__PURE__ */ new Map();
227
227
  for (const { path, change } of changes) {
228
- const request2 = store.get(path);
229
- request2.onsuccess = () => {
230
- const entry = change(request2.result);
228
+ const request3 = store.get(path);
229
+ request3.onsuccess = () => {
230
+ const entry = change(request3.result);
231
231
  next3.set(path, entry ?? null);
232
232
  if (entry) store.put(entry);
233
233
  else store.delete(path);
@@ -301,9 +301,9 @@ var IndexedDbMeta = class {
301
301
  this.removing = /* @__PURE__ */ new Map();
302
302
  const [transaction, store] = this.transaction("readwrite");
303
303
  for (const [path, seen] of batch) {
304
- const request2 = store.get(path);
305
- request2.onsuccess = () => {
306
- if (request2.result && JSON.stringify(request2.result) === seen) store.delete(path);
304
+ const request3 = store.get(path);
305
+ request3.onsuccess = () => {
306
+ if (request3.result && JSON.stringify(request3.result) === seen) store.delete(path);
307
307
  };
308
308
  }
309
309
  const paths = [...batch.keys()];
@@ -312,8 +312,8 @@ var IndexedDbMeta = class {
312
312
  async links(dir) {
313
313
  this.settleRemoves();
314
314
  const [transaction, store] = this.transaction("readonly");
315
- const request2 = store.index("dir").getAll(dir);
316
- return settle(transaction, () => request2.result);
315
+ const request3 = store.index("dir").getAll(dir);
316
+ return settle(transaction, () => request3.result);
317
317
  }
318
318
  async under(path) {
319
319
  this.settleRemoves();
@@ -330,22 +330,25 @@ var IndexedDbMeta = class {
330
330
  async all() {
331
331
  this.settleRemoves();
332
332
  const [transaction, store] = this.transaction("readonly");
333
- const request2 = store.getAll();
334
- return settle(transaction, () => request2.result);
333
+ const request3 = store.getAll();
334
+ return settle(transaction, () => request3.result);
335
335
  }
336
336
  };
337
- function openMeta(name2, factory) {
337
+ function openMetaDb(name2, factory) {
338
338
  return new Promise((resolve2, reject) => {
339
- const request2 = factory.open(name2, META_VERSION);
340
- request2.onupgradeneeded = (event) => {
339
+ const request3 = factory.open(name2, META_VERSION);
340
+ request3.onupgradeneeded = (event) => {
341
341
  if (event.oldVersion < 1) {
342
- request2.result.createObjectStore(META_STORE, { keyPath: "path" }).createIndex("dir", "dir");
342
+ request3.result.createObjectStore(META_STORE, { keyPath: "path" }).createIndex("dir", "dir");
343
343
  }
344
344
  };
345
- request2.onsuccess = () => resolve2(new IndexedDbMeta(request2.result));
346
- request2.onerror = () => reject(request2.error);
345
+ request3.onsuccess = () => resolve2(request3.result);
346
+ request3.onerror = () => reject(request3.error);
347
347
  });
348
348
  }
349
+ async function openMeta(name2, factory) {
350
+ return new IndexedDbMeta(await openMetaDb(name2, factory));
351
+ }
349
352
 
350
353
  // src/fs/types.ts
351
354
  function rangedOps(fs) {
@@ -689,37 +692,37 @@ function missing(err) {
689
692
  return code === "ENOENT" || code === "ENOTDIR";
690
693
  }
691
694
  async function resolved(fs, path, follow2, hops = []) {
692
- let done4 = [];
695
+ let done5 = [];
693
696
  let todo = partsOf(path);
694
697
  for (let links = 0; todo.length > 0; ) {
695
698
  const part = todo.shift();
696
699
  if (part === "..") {
697
- done4.pop();
700
+ done5.pop();
698
701
  continue;
699
702
  }
700
703
  if (todo.length === 0 && !follow2) {
701
- done4.push(part);
704
+ done5.push(part);
702
705
  break;
703
706
  }
704
- const at = `/${[...done4, part].join("/")}`;
707
+ const at = `/${[...done5, part].join("/")}`;
705
708
  const st = await fs.lstat(at).catch((err) => {
706
709
  if (missing(err)) return void 0;
707
710
  throw err;
708
711
  });
709
712
  if (!st) {
710
- return normalizePath([...done4, part, ...todo].join("/"));
713
+ return normalizePath([...done5, part, ...todo].join("/"));
711
714
  }
712
715
  if (!st.isSymbolicLink) {
713
- done4.push(part);
716
+ done5.push(part);
714
717
  continue;
715
718
  }
716
719
  if (++links > MAX_LINKS) throw fsError("ELOOP", path);
717
720
  hops.push(normalizePath([at, ...todo].join("/")));
718
721
  const link2 = await fs.readlink(at);
719
- if (link2.startsWith("/")) done4 = [];
722
+ if (link2.startsWith("/")) done5 = [];
720
723
  todo = [...partsOf(link2), ...todo];
721
724
  }
722
- return `/${done4.join("/")}`;
725
+ return `/${done5.join("/")}`;
723
726
  }
724
727
  async function namesOf(fs, path) {
725
728
  const lexical2 = normalizePath(path);
@@ -795,6 +798,12 @@ var ProtectedFs = class {
795
798
  st && marked(`${dir}/${name2}`, st)
796
799
  ]);
797
800
  },
801
+ ...fs.copyFile ? {
802
+ async copyFile(...args) {
803
+ await check(args[1], false);
804
+ return fs.copyFile?.(...args);
805
+ }
806
+ } : {},
798
807
  ...fs.createExclusive ? {
799
808
  async createExclusive(...args) {
800
809
  await check(args[0], true);
@@ -1028,16 +1037,16 @@ var RemoteWatch = class {
1028
1037
  this.channel.postMessage({ tab: this.tab, paths: this.mine, seq: seq2 });
1029
1038
  if (this.peers.size === 0) return Promise.resolve();
1030
1039
  return new Promise((resolve2) => {
1031
- const done4 = () => {
1040
+ const done5 = () => {
1032
1041
  clearTimeout(timer);
1033
1042
  this.waiting.delete(seq2);
1034
1043
  resolve2();
1035
1044
  };
1036
1045
  const timer = setTimeout(() => {
1037
- done4();
1046
+ done5();
1038
1047
  void this.prune();
1039
1048
  }, ANNOUNCE_WAIT_MS);
1040
- this.waiting.set(seq2, { left: new Set(this.peers), done: done4 });
1049
+ this.waiting.set(seq2, { left: new Set(this.peers), done: done5 });
1041
1050
  });
1042
1051
  }
1043
1052
  emit(change) {
@@ -1195,11 +1204,11 @@ async function openSync(handle) {
1195
1204
  }
1196
1205
  }
1197
1206
  function writeAll(access2, at, bytes) {
1198
- for (let done4 = 0; done4 < bytes.length; ) {
1199
- const n = access2.write(bytes.subarray(done4), { at: at + done4 });
1207
+ for (let done5 = 0; done5 < bytes.length; ) {
1208
+ const n = access2.write(bytes.subarray(done5), { at: at + done5 });
1200
1209
  if (!(n > 0))
1201
1210
  throw Object.assign(new Error("the file system took no more bytes"), { code: "ENOSPC" });
1202
- done4 += n;
1211
+ done5 += n;
1203
1212
  }
1204
1213
  }
1205
1214
  async function positioned(handle, op) {
@@ -1422,7 +1431,7 @@ var OpfsFs = class {
1422
1431
  return await op();
1423
1432
  } finally {
1424
1433
  this.unlocked--;
1425
- if (this.unlocked === 0) for (const done4 of this.idle.splice(0)) done4();
1434
+ if (this.unlocked === 0) for (const done5 of this.idle.splice(0)) done5();
1426
1435
  }
1427
1436
  }
1428
1437
  settle;
@@ -1539,9 +1548,9 @@ var OpfsFs = class {
1539
1548
  opfsOps() {
1540
1549
  return this.calls + this.others;
1541
1550
  }
1542
- io(request2) {
1551
+ io(request3) {
1543
1552
  this.others++;
1544
- return request2;
1553
+ return request3;
1545
1554
  }
1546
1555
  fresh() {
1547
1556
  this.changes++;
@@ -1697,30 +1706,30 @@ var OpfsFs = class {
1697
1706
  }
1698
1707
  throw fsError("ELOOP", path);
1699
1708
  }
1700
- async physical(base, path, used, of) {
1701
- let done4 = [];
1709
+ async physical(base, path, used2, of) {
1710
+ let done5 = [];
1702
1711
  let todo = (path.startsWith("/") ? path : `${base}/${path}`).split("/").filter((p) => p !== "" && p !== ".");
1703
- let hops = used;
1712
+ let hops = used2;
1704
1713
  while (todo.length > 0) {
1705
1714
  const part = todo.shift();
1706
- if (part === "..") done4.pop();
1707
- else if (!todo.includes("..")) done4.push(part);
1715
+ if (part === "..") done5.pop();
1716
+ else if (!todo.includes("..")) done5.push(part);
1708
1717
  else {
1709
- const at = `/${[...done4, part].join("/")}`;
1718
+ const at = `/${[...done5, part].join("/")}`;
1710
1719
  this.crossing(of, [at, ...todo].join("/"));
1711
1720
  const st = await this.lstat(at);
1712
1721
  if (!st.isSymbolicLink && !st.isDirectory) throw fsError("ENOTDIR", at);
1713
- if (!st.isSymbolicLink) done4.push(part);
1722
+ if (!st.isSymbolicLink) done5.push(part);
1714
1723
  else if (this.rejectLinks) throw fsError("ELOOP", of);
1715
1724
  else if (++hops > MAX_LINKS2) throw fsError("ELOOP", path);
1716
1725
  else {
1717
1726
  const link2 = await this.readlink(at);
1718
- if (link2.startsWith("/")) done4 = [];
1727
+ if (link2.startsWith("/")) done5 = [];
1719
1728
  todo = [...link2.split("/").filter((p) => p !== "" && p !== "."), ...todo];
1720
1729
  }
1721
1730
  }
1722
1731
  }
1723
- return { path: `/${done4.join("/")}`, hops };
1732
+ return { path: `/${done5.join("/")}`, hops };
1724
1733
  }
1725
1734
  mode(path, directory, meta) {
1726
1735
  const fallback = directory || EXECUTABLE.test(path) ? 493 : 420;
@@ -2440,10 +2449,11 @@ var OpfsFs = class {
2440
2449
  return intents.length;
2441
2450
  }
2442
2451
  async settledRename(path) {
2443
- if (this.renamingDirs.size === 0 || typeof path !== "string") return;
2452
+ if (this.renamingDirs.size === 0 && this.copying.size === 0 || typeof path !== "string")
2453
+ return;
2444
2454
  const at = normalizePath(path);
2445
2455
  for (let real; ; ) {
2446
- const busy = this.renameAt(at) ?? (real === void 0 ? void 0 : this.renameAt(real));
2456
+ const busy = this.busyAt(at) ?? (real === void 0 ? void 0 : this.busyAt(real));
2447
2457
  if (busy) {
2448
2458
  await busy.done;
2449
2459
  continue;
@@ -2454,6 +2464,62 @@ var OpfsFs = class {
2454
2464
  if (real === at) return;
2455
2465
  }
2456
2466
  }
2467
+ busyAt(at) {
2468
+ return this.renameAt(at) ?? this.copying.get(at);
2469
+ }
2470
+ copying = /* @__PURE__ */ new Map();
2471
+ async copyFile(from, to, options) {
2472
+ const source = await this.locate(from, true);
2473
+ if (source.handle?.kind !== "file") throw fsError("EINVAL", `${from}: not a regular file`);
2474
+ const [entry] = await this.meta.get([source.path]);
2475
+ if (entry?.fifo || entry?.socket) throw fsError("EINVAL", `${from}: not a regular file`);
2476
+ const parent = await this.locate(parentOf3(to), true);
2477
+ if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", to);
2478
+ const destination = resolvePath(parent.path, baseOf(to));
2479
+ if (destination === source.path) throw fsError("EINVAL", `${from}: copied onto itself`);
2480
+ const file = await this.reading(source.path, (handle) => handle.getFile());
2481
+ const { promise, resolve: resolve2 } = Promise.withResolvers();
2482
+ while (this.copying.has(destination)) await this.copying.get(destination)?.done;
2483
+ this.copying.set(destination, { done: promise });
2484
+ try {
2485
+ await this.copyInto(file, destination, to, options);
2486
+ } finally {
2487
+ this.copying.delete(destination);
2488
+ resolve2();
2489
+ }
2490
+ }
2491
+ async copyInto(file, destination, to, options) {
2492
+ let created4 = false;
2493
+ if (options.exclusive) {
2494
+ await this.createExclusive(destination, options.owner);
2495
+ created4 = true;
2496
+ }
2497
+ let target = destination;
2498
+ let writable2;
2499
+ let handle;
2500
+ try {
2501
+ const [made2, existed, at] = await this.fileFor(destination);
2502
+ handle = made2;
2503
+ target = at;
2504
+ if (!existed && !created4) {
2505
+ created4 = true;
2506
+ await this.stampNew(target, options.owner, false);
2507
+ }
2508
+ const [entry] = await this.meta.get([target]);
2509
+ if (entry?.fifo || entry?.socket) throw fsError("ENXIO", to);
2510
+ this.wrote(handle);
2511
+ writable2 = await handle.createWritable();
2512
+ await writable2.write(file);
2513
+ await writable2.close();
2514
+ } catch (err) {
2515
+ await writable2?.abort().catch(() => void 0);
2516
+ if (created4) await this.rm(target, { file: true }).catch(() => void 0);
2517
+ throw translate(err, to, "commit", false);
2518
+ } finally {
2519
+ if (handle) this.wrote(handle);
2520
+ }
2521
+ this.committed(target);
2522
+ }
2457
2523
  renameAt(at) {
2458
2524
  for (const m of this.renamingDirs) {
2459
2525
  if (within2(at, m.from) || within2(at, m.to) || at === parentOf3(m.from) || at === parentOf3(m.to))
@@ -2625,7 +2691,7 @@ var OpfsFs = class {
2625
2691
  }
2626
2692
  async present(paths) {
2627
2693
  const listed = /* @__PURE__ */ new Map();
2628
- const done4 = /* @__PURE__ */ new Map();
2694
+ const done5 = /* @__PURE__ */ new Map();
2629
2695
  const list = (dir) => {
2630
2696
  const known = listed.get(dir);
2631
2697
  if (known !== void 0) return known;
@@ -2644,7 +2710,7 @@ var OpfsFs = class {
2644
2710
  }
2645
2711
  return children3;
2646
2712
  })().then((children3) => {
2647
- done4.set(dir, children3);
2713
+ done5.set(dir, children3);
2648
2714
  return children3;
2649
2715
  });
2650
2716
  listed.set(dir, listing);
@@ -2658,7 +2724,7 @@ var OpfsFs = class {
2658
2724
  await Promise.all(Array.from({ length: Math.min(RECONCILE_LISTINGS, dirs.length) }, lister));
2659
2725
  return async (path) => {
2660
2726
  if (split(path).length === 0) return true;
2661
- const listing = done4.get(parentOf3(path));
2727
+ const listing = done5.get(parentOf3(path));
2662
2728
  if (listing === null) return this.real(path);
2663
2729
  return listing?.has(baseOf(path)) === true;
2664
2730
  };
@@ -2701,6 +2767,7 @@ var READS = [
2701
2767
  "readVersioned"
2702
2768
  ];
2703
2769
  var WRITES = [
2770
+ "copyFile",
2704
2771
  "writeFile",
2705
2772
  "pwrite",
2706
2773
  "truncate",
@@ -2733,6 +2800,85 @@ for (const [names2, op] of [
2733
2800
  }
2734
2801
  }
2735
2802
 
2803
+ // src/fs/roots.ts
2804
+ var ROOTS_DB = "slicc-kernel-roots";
2805
+ var ROOTS_STORE = "roots";
2806
+ function request(req) {
2807
+ return new Promise((resolve2, reject) => {
2808
+ req.onsuccess = () => resolve2(req.result);
2809
+ req.onerror = () => reject(req.error);
2810
+ });
2811
+ }
2812
+ function open(factory) {
2813
+ const req = factory.open(ROOTS_DB, 1);
2814
+ req.onupgradeneeded = () => req.result.createObjectStore(ROOTS_STORE, { keyPath: "id" });
2815
+ return request(req);
2816
+ }
2817
+ async function same(a, b) {
2818
+ try {
2819
+ return await a.isSameEntry(b);
2820
+ } catch {
2821
+ return false;
2822
+ }
2823
+ }
2824
+ var nameOf = (id2) => `${META_DB}:${id2}`;
2825
+ function done(tx) {
2826
+ return new Promise((resolve2, reject) => {
2827
+ tx.oncomplete = () => resolve2();
2828
+ tx.onerror = () => reject(tx.error);
2829
+ tx.onabort = () => reject(tx.error);
2830
+ });
2831
+ }
2832
+ async function used(root) {
2833
+ for await (const _ of root.keys()) return true;
2834
+ return false;
2835
+ }
2836
+ async function seed(factory, name2) {
2837
+ const known = await factory.databases?.().catch(() => void 0);
2838
+ if (known && !known.some((db) => db.name === META_DB)) return;
2839
+ const from = await openMetaDb(META_DB, factory);
2840
+ const to = await openMetaDb(name2, factory);
2841
+ try {
2842
+ const rows = await request(
2843
+ from.transaction(META_STORE, "readonly").objectStore(META_STORE).getAll()
2844
+ );
2845
+ const tx = to.transaction(META_STORE, "readwrite");
2846
+ const store = tx.objectStore(META_STORE);
2847
+ for (const row of rows) store.put(row);
2848
+ await done(tx);
2849
+ console.warn(
2850
+ `slicc-kernel: a root not seen before got its own metadata database ${name2}, a copy of ${rows.length} records of ${META_DB} (#1120)`
2851
+ );
2852
+ } finally {
2853
+ from.close();
2854
+ to.close();
2855
+ }
2856
+ }
2857
+ async function rootId(factory, root, locks = globalThis.navigator?.locks) {
2858
+ const find = async () => {
2859
+ const db = await open(factory);
2860
+ try {
2861
+ const all = await request(
2862
+ db.transaction(ROOTS_STORE, "readonly").objectStore(ROOTS_STORE).getAll()
2863
+ );
2864
+ for (const record of all) if (await same(record.handle, root)) return record.id;
2865
+ const id2 = crypto.randomUUID();
2866
+ if (await used(root)) await seed(factory, nameOf(id2));
2867
+ const tx = db.transaction(ROOTS_STORE, "readwrite");
2868
+ tx.objectStore(ROOTS_STORE).put({ id: id2, handle: root });
2869
+ await done(tx);
2870
+ return id2;
2871
+ } finally {
2872
+ db.close();
2873
+ }
2874
+ };
2875
+ return locks ? locks.request(ROOTS_DB, find) : find();
2876
+ }
2877
+ async function metadataName(top, root, id2) {
2878
+ if (!top || await same(top, root)) return META_DB;
2879
+ return nameOf(await id2(root));
2880
+ }
2881
+
2736
2882
  // src/kernel/net/http1.ts
2737
2883
  var HttpError = class extends Error {
2738
2884
  status;
@@ -3298,8 +3444,8 @@ var CdpFacade = class {
3298
3444
  } catch {
3299
3445
  break;
3300
3446
  }
3301
- const done4 = this.serve(conn).finally(() => served2.delete(done4));
3302
- served2.add(done4);
3447
+ const done5 = this.serve(conn).finally(() => served2.delete(done5));
3448
+ served2.add(done5);
3303
3449
  }
3304
3450
  await Promise.allSettled([...served2]);
3305
3451
  }
@@ -3510,12 +3656,12 @@ var CdpHosts = class {
3510
3656
  available(runtime) {
3511
3657
  return this.pick(runtime) !== void 0;
3512
3658
  }
3513
- async connect(request2) {
3514
- const entry = this.pick(request2.runtime);
3659
+ async connect(request3) {
3660
+ const entry = this.pick(request3.runtime);
3515
3661
  if (!entry) throw new HttpError(503, NO_CDP_HOST);
3516
3662
  let conn;
3517
3663
  try {
3518
- conn = await entry.hook(request2.runtime ? { runtime: request2.runtime } : {});
3664
+ conn = await entry.hook(request3.runtime ? { runtime: request3.runtime } : {});
3519
3665
  } catch (e) {
3520
3666
  throw new HttpError(502, `CDP host: ${e instanceof Error ? e.message : String(e)}`);
3521
3667
  }
@@ -3549,7 +3695,7 @@ function fresh(bytes, start2 = 0, end = bytes.length) {
3549
3695
 
3550
3696
  // src/cdp/port.ts
3551
3697
  function portCdpHook(ask, gone) {
3552
- return (request2) => new Promise((resolve2, reject) => {
3698
+ return (request3) => new Promise((resolve2, reject) => {
3553
3699
  const { port1, port2 } = new MessageChannel();
3554
3700
  let closed = false;
3555
3701
  const conn = {
@@ -3586,7 +3732,7 @@ function portCdpHook(ask, gone) {
3586
3732
  reject(new Error("the CDP host is gone"));
3587
3733
  conn.onclose?.("the CDP host is gone");
3588
3734
  });
3589
- ask(request2, port2);
3735
+ ask(request3, port2);
3590
3736
  });
3591
3737
  }
3592
3738
 
@@ -4896,10 +5042,10 @@ function uplinkLink(conn, onReset) {
4896
5042
  pipe.openRead();
4897
5043
  pipe.openWrite();
4898
5044
  }
4899
- let open = true;
5045
+ let open2 = true;
4900
5046
  const close = () => {
4901
- if (!open) return;
4902
- open = false;
5047
+ if (!open2) return;
5048
+ open2 = false;
4903
5049
  conn.close();
4904
5050
  };
4905
5051
  void inbound(conn, rx).catch((err) => {
@@ -5724,9 +5870,9 @@ function uploadsFor(peer) {
5724
5870
  return { of, answer: (call) => pulls.get(call.nid)?.(call) };
5725
5871
  }
5726
5872
  function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS2 } = {}) {
5727
- const open = /* @__PURE__ */ new Map();
5873
+ const open2 = /* @__PURE__ */ new Map();
5728
5874
  const fail2 = (nid, e) => {
5729
- open.delete(nid);
5875
+ open2.delete(nid);
5730
5876
  const { status, code } = e;
5731
5877
  peer.postMessage({
5732
5878
  net: "error",
@@ -5740,7 +5886,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS2 } = {})
5740
5886
  const start2 = async (call) => {
5741
5887
  const abort = new AbortController();
5742
5888
  const entry = { abort };
5743
- open.set(call.nid, entry);
5889
+ open2.set(call.nid, entry);
5744
5890
  try {
5745
5891
  const response = await transport.fetch({
5746
5892
  url: call.url,
@@ -5749,11 +5895,11 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS2 } = {})
5749
5895
  ...call.streamed ? { bodyStream: uploads.of(call.nid, abort.signal) } : call.body ? { body: call.body } : {},
5750
5896
  signal: abort.signal
5751
5897
  });
5752
- if (!open.has(call.nid)) {
5898
+ if (!open2.has(call.nid)) {
5753
5899
  await response.cancel();
5754
5900
  return;
5755
5901
  }
5756
- open.set(call.nid, { abort, body: response.body[Symbol.asyncIterator](), response });
5902
+ open2.set(call.nid, { abort, body: response.body[Symbol.asyncIterator](), response });
5757
5903
  peer.postMessage({
5758
5904
  net: "head",
5759
5905
  nid: call.nid,
@@ -5781,7 +5927,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS2 } = {})
5781
5927
  };
5782
5928
  const openSocket = async (call) => {
5783
5929
  const abort = new AbortController();
5784
- open.set(call.nid, { abort });
5930
+ open2.set(call.nid, { abort });
5785
5931
  try {
5786
5932
  if (!transport.websocket) throw new Error(NO_WEBSOCKET);
5787
5933
  const socket = await transport.websocket({
@@ -5790,7 +5936,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS2 } = {})
5790
5936
  headers: call.headers,
5791
5937
  signal: abort.signal
5792
5938
  });
5793
- if (!open.delete(call.nid)) {
5939
+ if (!open2.delete(call.nid)) {
5794
5940
  socket.close(1e3, "cancelled");
5795
5941
  return;
5796
5942
  }
@@ -5858,12 +6004,12 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS2 } = {})
5858
6004
  peer.postMessage({ net: "ws-acked", nid: call.nid, n: payloadSize(call.data) });
5859
6005
  };
5860
6006
  const read = async (nid) => {
5861
- const body = open.get(nid)?.body;
6007
+ const body = open2.get(nid)?.body;
5862
6008
  if (!body) return;
5863
6009
  try {
5864
6010
  const next3 = await body.next();
5865
6011
  if (next3.done) {
5866
- open.delete(nid);
6012
+ open2.delete(nid);
5867
6013
  peer.postMessage({ net: "end", nid });
5868
6014
  } else {
5869
6015
  const bytes = fresh(next3.value);
@@ -5876,8 +6022,8 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS2 } = {})
5876
6022
  const drop = (nid) => {
5877
6023
  sockets.get(nid)?.close(1e3, "cancelled");
5878
6024
  refill(nid, 0, true);
5879
- const entry = open.get(nid);
5880
- open.delete(nid);
6025
+ const entry = open2.get(nid);
6026
+ open2.delete(nid);
5881
6027
  entry?.abort.abort();
5882
6028
  void entry?.response?.cancel().catch(() => void 0);
5883
6029
  };
@@ -5896,7 +6042,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS2 } = {})
5896
6042
  else drop(call.nid);
5897
6043
  },
5898
6044
  close() {
5899
- for (const nid of [...open.keys(), ...sockets.keys()]) drop(nid);
6045
+ for (const nid of [...open2.keys(), ...sockets.keys()]) drop(nid);
5900
6046
  }
5901
6047
  };
5902
6048
  }
@@ -6385,12 +6531,12 @@ function signalOf(host) {
6385
6531
  throw fsError("EINVAL", `this kernel names no signal ${name2}`);
6386
6532
  });
6387
6533
  }
6388
- function dialFor(l, req, open) {
6534
+ function dialFor(l, req, open2) {
6389
6535
  const socket = dialSocket(l.net, req.port, req.host);
6390
6536
  const { port1, port2 } = new MessageChannel();
6391
- open.set(
6537
+ open2.set(
6392
6538
  req.id,
6393
- serveSocket(socket, port1, () => open.delete(req.id))
6539
+ serveSocket(socket, port1, () => open2.delete(req.id))
6394
6540
  );
6395
6541
  return { result: port2, transfer: [port2] };
6396
6542
  }
@@ -6469,7 +6615,7 @@ function cdpRegistry(send2, gone) {
6469
6615
  return {
6470
6616
  serve(l, req) {
6471
6617
  const hook = portCdpHook(
6472
- (request2, cdp) => send2({ cdpOpen: { ...request2, registration: req.id }, port: cdp }, [
6618
+ (request3, cdp) => send2({ cdpOpen: { ...request3, registration: req.id }, port: cdp }, [
6473
6619
  cdp
6474
6620
  ]),
6475
6621
  gone
@@ -6492,7 +6638,7 @@ function facadeRegistry(send2, gone) {
6492
6638
  return {
6493
6639
  serve(l, req) {
6494
6640
  const hook = portFacadeHook(
6495
- (request2, facade) => send2({ facadeOpen: { ...request2, registration: req.id }, port: facade }, [
6641
+ (request3, facade) => send2({ facadeOpen: { ...request3, registration: req.id }, port: facade }, [
6496
6642
  facade
6497
6643
  ]),
6498
6644
  gone
@@ -6874,7 +7020,7 @@ function satisfies(version, range2) {
6874
7020
  }
6875
7021
 
6876
7022
  // src/version.ts
6877
- var KERNEL_VERSION = true ? "1.127.1" : "0.0.0-dev";
7023
+ var KERNEL_VERSION = true ? "1.128.1" : "0.0.0-dev";
6878
7024
  var OS_RELEASE = "6.0.0-slicc";
6879
7025
  function procVersion() {
6880
7026
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -7951,7 +8097,7 @@ var UnlinkedKeeper = class {
7951
8097
  throw err;
7952
8098
  }
7953
8099
  sealed();
7954
- const done4 = () => {
8100
+ const done5 = () => {
7955
8101
  for (const release of releases) release();
7956
8102
  };
7957
8103
  const files = /* @__PURE__ */ new Map();
@@ -7966,7 +8112,7 @@ var UnlinkedKeeper = class {
7966
8112
  moved: new Set(hidden.keys()),
7967
8113
  commit: () => {
7968
8114
  for (const file of files.values()) file.release();
7969
- done4();
8115
+ done5();
7970
8116
  },
7971
8117
  rollback: async () => {
7972
8118
  for (const [path, file] of files) {
@@ -7977,7 +8123,7 @@ var UnlinkedKeeper = class {
7977
8123
  await this.tidy(parentOf5(file.hidden));
7978
8124
  });
7979
8125
  }
7980
- done4();
8126
+ done5();
7981
8127
  }
7982
8128
  };
7983
8129
  }
@@ -8063,14 +8209,14 @@ var systemCronClock = {
8063
8209
  sleep(until, signal) {
8064
8210
  if (signal.aborted) return Promise.resolve();
8065
8211
  return new Promise((resolve2) => {
8066
- const done4 = () => {
8212
+ const done5 = () => {
8067
8213
  clearTimeout(timer);
8068
- signal.removeEventListener("abort", done4);
8214
+ signal.removeEventListener("abort", done5);
8069
8215
  resolve2();
8070
8216
  };
8071
- const timer = setTimeout(done4, Math.max(0, until - Date.now()));
8217
+ const timer = setTimeout(done5, Math.max(0, until - Date.now()));
8072
8218
  timer.unref?.();
8073
- signal.addEventListener("abort", done4, { once: true });
8219
+ signal.addEventListener("abort", done5, { once: true });
8074
8220
  });
8075
8221
  }
8076
8222
  };
@@ -8421,12 +8567,12 @@ var Budget = class {
8421
8567
  while (this.free < n) {
8422
8568
  signal.throwIfAborted();
8423
8569
  await new Promise((resolve2) => {
8424
- const done4 = () => {
8425
- signal.removeEventListener("abort", done4);
8570
+ const done5 = () => {
8571
+ signal.removeEventListener("abort", done5);
8426
8572
  resolve2();
8427
8573
  };
8428
- this.waiters.push(done4);
8429
- signal.addEventListener("abort", done4, { once: true });
8574
+ this.waiters.push(done5);
8575
+ signal.addEventListener("abort", done5, { once: true });
8430
8576
  });
8431
8577
  }
8432
8578
  this.free -= n;
@@ -8565,9 +8711,9 @@ async function watchHangup(conn, abort, until) {
8565
8711
  }
8566
8712
  }
8567
8713
  var BODILESS_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
8568
- async function* drain(body, done4) {
8714
+ async function* drain(body, done5) {
8569
8715
  yield* body;
8570
- done4();
8716
+ done5();
8571
8717
  }
8572
8718
  function untilAborted(response, signal) {
8573
8719
  return new Promise((resolve2, reject) => {
@@ -8659,11 +8805,11 @@ var RealmProxy = class {
8659
8805
  this.slots.release(1);
8660
8806
  break;
8661
8807
  }
8662
- const done4 = this.serve(conn).finally(() => {
8808
+ const done5 = this.serve(conn).finally(() => {
8663
8809
  this.slots.release(1);
8664
- served2.delete(done4);
8810
+ served2.delete(done5);
8665
8811
  });
8666
- served2.add(done4);
8812
+ served2.add(done5);
8667
8813
  }
8668
8814
  } catch {
8669
8815
  }
@@ -8913,8 +9059,8 @@ var RealmProxy = class {
8913
9059
  chain2 = chain2.then(() => ctx.sink.write(bytes, stop));
8914
9060
  return chain2;
8915
9061
  };
8916
- const done4 = new AbortController();
8917
- const reading = AbortSignal.any([stop, done4.signal, hangup]);
9062
+ const done5 = new AbortController();
9063
+ const reading = AbortSignal.any([stop, done5.signal, hangup]);
8918
9064
  const stopping = () => socket.close(1001, "the proxy is stopping");
8919
9065
  stop.addEventListener("abort", stopping, { once: true });
8920
9066
  let guestDone = false;
@@ -8931,10 +9077,10 @@ var RealmProxy = class {
8931
9077
  if (guestDone) return;
8932
9078
  closeSent = true;
8933
9079
  await toGuest(closeFrame(wireCode(closed.code), closed.reason));
8934
- AbortSignal.timeout(this.limits.closeWaitMs).addEventListener("abort", () => done4.abort(), {
9080
+ AbortSignal.timeout(this.limits.closeWaitMs).addEventListener("abort", () => done5.abort(), {
8935
9081
  once: true
8936
9082
  });
8937
- })().catch(() => done4.abort());
9083
+ })().catch(() => done5.abort());
8938
9084
  const reader = new WsReader(ctx.incoming, MESSAGE_LIMIT, true);
8939
9085
  try {
8940
9086
  for (; ; ) {
@@ -9498,6 +9644,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
9498
9644
  ...fs.realpath ? { realpath: fs.realpath.bind(fs) } : {},
9499
9645
  ...fs.chown ? { chown: fs.chown.bind(fs) } : {},
9500
9646
  ...fs.createExclusive ? { createExclusive: fs.createExclusive.bind(fs) } : {},
9647
+ ...fs.copyFile ? { copyFile: fs.copyFile.bind(fs) } : {},
9501
9648
  ...fs.ancestry ? { ancestry: fs.ancestry.bind(fs) } : {},
9502
9649
  ...fs.hasOwner ? { hasOwner: fs.hasOwner.bind(fs) } : {},
9503
9650
  chmod: (path, mode) => fs.chmod(path, mode),
@@ -9790,13 +9937,13 @@ var FsWatchers = class {
9790
9937
  next: async (signal) => {
9791
9938
  while (watch.notes.length === 0 && !watch.ended && !signal.aborted) {
9792
9939
  await new Promise((resolve2) => {
9793
- const done4 = () => {
9940
+ const done5 = () => {
9794
9941
  watch.wake = void 0;
9795
- signal.removeEventListener("abort", done4);
9942
+ signal.removeEventListener("abort", done5);
9796
9943
  resolve2();
9797
9944
  };
9798
- watch.wake = done4;
9799
- signal.addEventListener("abort", done4, { once: true });
9945
+ watch.wake = done5;
9946
+ signal.addEventListener("abort", done5, { once: true });
9800
9947
  });
9801
9948
  }
9802
9949
  const notes = watch.notes.splice(0);
@@ -9847,14 +9994,14 @@ var FsWatchers = class {
9847
9994
  }
9848
9995
  wrap(fs) {
9849
9996
  const after = (run2, changed, type) => async (...args) => {
9850
- let done4 = false;
9997
+ let done5 = false;
9851
9998
  try {
9852
9999
  await run2(...args);
9853
- done4 = true;
10000
+ done5 = true;
9854
10001
  } finally {
9855
10002
  const paths = changed(...args);
9856
10003
  this.report(paths);
9857
- if (done4) this.emit(type, paths);
10004
+ if (done5) this.emit(type, paths);
9858
10005
  }
9859
10006
  };
9860
10007
  const reals = this.reals;
@@ -9876,15 +10023,15 @@ var FsWatchers = class {
9876
10023
  const content = (run2, types) => async (...args) => {
9877
10024
  const at = normalizePath(args[0]);
9878
10025
  const fresh2 = this.covers(at) && !await fs.exists(at).catch(() => true);
9879
- let done4 = false;
10026
+ let done5 = false;
9880
10027
  try {
9881
10028
  await run2(...args);
9882
- done4 = true;
10029
+ done5 = true;
9883
10030
  } finally {
9884
10031
  const real = await realOf(at);
9885
10032
  const paths = real === at ? [at] : [at, real];
9886
10033
  this.report(paths);
9887
- if (done4) for (const type of types(fresh2)) this.emit(type, paths);
10034
+ if (done5) for (const type of types(fresh2)) this.emit(type, paths);
9888
10035
  }
9889
10036
  };
9890
10037
  const written2 = (fresh2) => fresh2 ? ["rename", "change"] : ["change"];
@@ -9899,6 +10046,12 @@ var FsWatchers = class {
9899
10046
  const overrides = {
9900
10047
  writeFile: content(fs.writeFile.bind(fs), written2),
9901
10048
  ...fs.createExclusive ? { createExclusive: content(fs.createExclusive.bind(fs), () => ["rename"]) } : {},
10049
+ ...fs.copyFile ? {
10050
+ copyFile: (from, to, options) => content(
10051
+ (_to) => fs.copyFile?.(from, to, options),
10052
+ written2
10053
+ )(to)
10054
+ } : {},
9902
10055
  mkdir: async (path, options) => {
9903
10056
  const created4 = [];
9904
10057
  if (options?.recursive) {
@@ -9909,13 +10062,13 @@ var FsWatchers = class {
9909
10062
  }
9910
10063
  }
9911
10064
  const fresh2 = !options?.recursive || this.typed.size > 0 && !await fs.exists(path);
9912
- let done4 = false;
10065
+ let done5 = false;
9913
10066
  try {
9914
10067
  await fs.mkdir(path, options);
9915
- done4 = true;
10068
+ done5 = true;
9916
10069
  } finally {
9917
10070
  this.report([...created4, path]);
9918
- if (done4) this.emit("rename", fresh2 ? [...created4, path] : created4);
10071
+ if (done5) this.emit("rename", fresh2 ? [...created4, path] : created4);
9919
10072
  }
9920
10073
  },
9921
10074
  rm: reshaping(after(fs.rm.bind(fs), (path) => [path], "rename")),
@@ -10121,8 +10274,8 @@ var ChildTable = class {
10121
10274
  for (; ; ) {
10122
10275
  const candidates = this.candidates(pid, flags2);
10123
10276
  if (candidates.length === 0) throw new KernelError("ECHILD");
10124
- const done4 = candidates.find(([, child]) => child.code !== void 0);
10125
- if (done4) return this.reap(done4[0], done4[1].code);
10277
+ const done5 = candidates.find(([, child]) => child.code !== void 0);
10278
+ if (done5) return this.reap(done5[0], done5[1].code);
10126
10279
  const changed = this.stateReport(candidates, flags2);
10127
10280
  if (changed) return changed;
10128
10281
  if (nohang) return [0, 0];
@@ -10518,7 +10671,7 @@ var FifoTable = class {
10518
10671
  }
10519
10672
  end(key, path, fifo, reads, writes) {
10520
10673
  const { pipe } = fifo;
10521
- let open = true;
10674
+ let open2 = true;
10522
10675
  return new OpenFile({
10523
10676
  fifo: path,
10524
10677
  identity: fifo,
@@ -10541,8 +10694,8 @@ var FifoTable = class {
10541
10694
  }
10542
10695
  } : {},
10543
10696
  close: () => {
10544
- if (!open) return;
10545
- open = false;
10697
+ if (!open2) return;
10698
+ open2 = false;
10546
10699
  this.release(key, fifo, reads, writes);
10547
10700
  },
10548
10701
  poll: () => ({
@@ -10556,6 +10709,33 @@ var FifoTable = class {
10556
10709
  }
10557
10710
  };
10558
10711
 
10712
+ // src/fs/copy.ts
10713
+ async function present2(fs, path) {
10714
+ return fs.lstat(path).then(
10715
+ () => true,
10716
+ (err) => {
10717
+ if (err?.code === "ENOENT") return false;
10718
+ throw err;
10719
+ }
10720
+ );
10721
+ }
10722
+ async function copyByBytes(fs, from, to, options) {
10723
+ if (!(await fs.stat(from)).isFile) throw fsError("EINVAL", `${from}: not a regular file`);
10724
+ const bytes = await fs.readFileBuffer(from);
10725
+ let created4 = false;
10726
+ if (options.exclusive) {
10727
+ if (fs.createExclusive) await fs.createExclusive(to, options.owner);
10728
+ else if (await present2(fs, to)) throw fsError("EEXIST", to);
10729
+ created4 = true;
10730
+ } else created4 = !await present2(fs, to);
10731
+ try {
10732
+ await fs.writeFile(to, bytes, options.owner);
10733
+ } catch (err) {
10734
+ if (created4) await fs.rm(to, { file: true }).catch(() => void 0);
10735
+ throw err;
10736
+ }
10737
+ }
10738
+
10559
10739
  // src/mount/protocol.ts
10560
10740
  var DRIVER_PROTOCOL = [1, 3];
10561
10741
  function driverVersionError(theirs) {
@@ -10789,8 +10969,8 @@ var HeldPaths = class extends Map {
10789
10969
  for (const file of [...this.uses.keys()]) this.letGo(file, true);
10790
10970
  this.keptHandles.clear();
10791
10971
  }
10792
- hold(path, on, open = false, real, handle) {
10793
- if (open) return this.holdOpen(path, on, real, handle);
10972
+ hold(path, on, open2 = false, real, handle) {
10973
+ if (open2) return this.holdOpen(path, on, real, handle);
10794
10974
  this.holdWrite(path, on);
10795
10975
  return void 0;
10796
10976
  }
@@ -10939,12 +11119,12 @@ var MountTable = class {
10939
11119
  }
10940
11120
  list() {
10941
11121
  const mounted = [...this.mounts.values()].map(
10942
- ({ type, source, target, options, state, error, present: present3 }) => ({
11122
+ ({ type, source, target, options, state, error, present: present4 }) => ({
10943
11123
  type,
10944
11124
  source,
10945
11125
  target,
10946
11126
  options: { ...options },
10947
- state: state === "ok" && present3?.() === false ? "nomedium" : state,
11127
+ state: state === "ok" && present4?.() === false ? "nomedium" : state,
10948
11128
  ...error ? { error } : {}
10949
11129
  })
10950
11130
  );
@@ -11081,7 +11261,7 @@ var MountTable = class {
11081
11261
  session(mount, real, rel2) {
11082
11262
  let session = this.sessions.get(real);
11083
11263
  if (!session) {
11084
- const open = () => mount.conn.call({
11264
+ const open2 = () => mount.conn.call({
11085
11265
  op: "open",
11086
11266
  path: rel2,
11087
11267
  write: true,
@@ -11090,7 +11270,7 @@ var MountTable = class {
11090
11270
  exclusive: false
11091
11271
  });
11092
11272
  const before = this.committing.get(real)?.done ?? Promise.resolve();
11093
- const fh = before.then(open, open);
11273
+ const fh = before.then(open2, open2);
11094
11274
  session = { mount, fh, extents: [], truncated: false };
11095
11275
  this.sessions.set(real, session);
11096
11276
  fh.catch(() => this.sessions.delete(real));
@@ -11105,20 +11285,20 @@ var MountTable = class {
11105
11285
  if (!session) return this.committing.get(real)?.done;
11106
11286
  this.sessions.delete(real);
11107
11287
  session.mount.epoch++;
11108
- const done4 = (async () => {
11288
+ const done5 = (async () => {
11109
11289
  try {
11110
11290
  await session.mount.conn.call({ op: "release", fh: await session.fh });
11111
11291
  } finally {
11112
11292
  this.forget(session.mount, real);
11113
11293
  }
11114
11294
  })();
11115
- const entry = { mount: session.mount, done: done4 };
11295
+ const entry = { mount: session.mount, done: done5 };
11116
11296
  this.committing.set(real, entry);
11117
11297
  const settle3 = () => {
11118
11298
  if (this.committing.get(real) === entry) this.committing.delete(real);
11119
11299
  };
11120
- done4.then(settle3, settle3);
11121
- return done4;
11300
+ done5.then(settle3, settle3);
11301
+ return done5;
11122
11302
  }
11123
11303
  async commitUnder(prefix) {
11124
11304
  const at = normalizePath(prefix);
@@ -11292,8 +11472,8 @@ var MountFs = class _MountFs {
11292
11472
  }
11293
11473
  async across(from, to, redirects) {
11294
11474
  const moved2 = [await this.through(from), await this.through(to)];
11295
- const same = moved2[0] === normalizePath(from) && moved2[1] === normalizePath(to);
11296
- if (same || redirects >= MAX_LINKS7) throw errnoError("EXDEV", `${from} -> ${to}`);
11475
+ const same2 = moved2[0] === normalizePath(from) && moved2[1] === normalizePath(to);
11476
+ if (same2 || redirects >= MAX_LINKS7) throw errnoError("EXDEV", `${from} -> ${to}`);
11297
11477
  return moved2;
11298
11478
  }
11299
11479
  async based(paths, redirects, run2, again) {
@@ -11619,6 +11799,23 @@ var MountFs = class _MountFs {
11619
11799
  throw err;
11620
11800
  }
11621
11801
  }
11802
+ async copyFile(from, to, options, redirects = 0) {
11803
+ const source = await realTarget(this, normalizePath(from));
11804
+ const a = this.at(source);
11805
+ const b = this.at(to);
11806
+ const copy = this.base.copyFile?.bind(this.base);
11807
+ if (!a && !b && copy) {
11808
+ return this.based(
11809
+ [source, to],
11810
+ redirects,
11811
+ () => copy(source, to, options),
11812
+ ([f, t], n) => this.copyFile(f, t, options, n)
11813
+ );
11814
+ }
11815
+ if (a?.mount !== b?.mount) throw errnoError("EXDEV", `${from} -> ${to}`);
11816
+ if (a) this.writable(a.mount, normalizePath(to));
11817
+ return copyByBytes(this, source, to, options);
11818
+ }
11622
11819
  async createExclusive(path, owner, redirects = 0) {
11623
11820
  const exclusive = this.base.createExclusive?.bind(this.base);
11624
11821
  if (!this.at(path) && exclusive) {
@@ -12046,6 +12243,7 @@ var SYNC_FS_OPS = [
12046
12243
  "rm",
12047
12244
  "rename",
12048
12245
  "link",
12246
+ "copy",
12049
12247
  "unlink",
12050
12248
  "rmdir",
12051
12249
  "symlink",
@@ -12123,7 +12321,7 @@ async function storageUsage() {
12123
12321
  return { quota: estimate.quota, usage: estimate.usage ?? 0 };
12124
12322
  }
12125
12323
  var PLAIN_DIR_MODE = 493;
12126
- var done = { ok: true, kind: "void" };
12324
+ var done2 = { ok: true, kind: "void" };
12127
12325
  function json2(value2) {
12128
12326
  return { ok: true, kind: "json", json: value2 };
12129
12327
  }
@@ -12168,14 +12366,14 @@ async function chown(entry, path, req) {
12168
12366
  const cred = entry.cred?.();
12169
12367
  if (!cred) {
12170
12368
  await (req.op === "chown" ? entry.fs.stat(real) : entry.fs.lstat(real));
12171
- return done;
12369
+ return done2;
12172
12370
  }
12173
12371
  await chownAs(entry.fs, cred, real, {
12174
12372
  ...req.uid !== void 0 ? { uid: req.uid } : {},
12175
12373
  ...req.gid !== void 0 ? { gid: req.gid } : {},
12176
12374
  follow: req.op === "chown"
12177
12375
  });
12178
- return done;
12376
+ return done2;
12179
12377
  }
12180
12378
  async function runMkdir(entry, path, req) {
12181
12379
  const { fs } = entry;
@@ -12186,7 +12384,7 @@ async function runMkdir(entry, path, req) {
12186
12384
  await (req.exclusive ? mkdirExclusive(entry, path, req.mode) : fs.mkdir(path, mkdirOptions(entry, req.mode)));
12187
12385
  await fixParents?.();
12188
12386
  if (fresh2) await fs.chmod(path, plain2);
12189
- return done;
12387
+ return done2;
12190
12388
  }
12191
12389
  async function shownAs(entry, path, st) {
12192
12390
  const real = st.isFile && st.size === 0 ? entry.fs.realpath?.(path, true) : void 0;
@@ -12203,7 +12401,7 @@ async function run(entry, path, req) {
12203
12401
  return { ok: true, kind: "bytes", bytes: await readSource(entry, path) };
12204
12402
  case "write":
12205
12403
  await fs.writeFile(path, req.body ?? new Uint8Array(0), ownerFor2(entry, 438));
12206
- return done;
12404
+ return done2;
12207
12405
  case "exists":
12208
12406
  return json2(await fs.exists(path));
12209
12407
  case "stat": {
@@ -12224,51 +12422,53 @@ async function run(entry, path, req) {
12224
12422
  return runMkdir(entry, path, req);
12225
12423
  case "rm":
12226
12424
  await fs.rm(path, { recursive: true });
12227
- return done;
12425
+ return done2;
12228
12426
  case "rename": {
12229
12427
  const to = fs.resolvePath(cwd, req.arg2 ?? "");
12230
12428
  await fs.rename(path, to);
12231
12429
  entry.renamed?.(path, to);
12232
- return done;
12430
+ return done2;
12233
12431
  }
12234
12432
  case "link":
12235
12433
  await fs.link(path, fs.resolvePath(cwd, req.arg2 ?? ""), req.mode === 1);
12236
- return done;
12434
+ return done2;
12237
12435
  case "unlink":
12238
12436
  await fs.rm(path, { file: true });
12239
- return done;
12437
+ return done2;
12240
12438
  case "rmdir":
12241
12439
  if (!(await fs.lstat(path)).isDirectory) throw syncError("ENOTDIR", path);
12242
12440
  if ((await fs.readdir(path)).length > 0) throw syncError("ENOTEMPTY", path);
12243
12441
  await fs.rm(path, { recursive: true });
12244
- return done;
12442
+ return done2;
12245
12443
  case "symlink":
12246
12444
  await fs.symlink(req.arg2 ?? "", path, ownerFor2(entry));
12247
- return done;
12445
+ return done2;
12446
+ case "copy":
12447
+ return copyOp(entry, path, req);
12248
12448
  case "mkfifo": {
12249
12449
  const owner = ownerFor2(entry, req.mode ?? 438) ?? { uid: 0, gid: 0 };
12250
12450
  await createExclusive(fs, path, { ...owner, fifo: true });
12251
12451
  entry.fresh?.(path);
12252
- return done;
12452
+ return done2;
12253
12453
  }
12254
12454
  case "create":
12255
12455
  await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
12256
12456
  if (req.opening) entry.created?.add(path);
12257
12457
  entry.fresh?.(path);
12258
- return done;
12458
+ return done2;
12259
12459
  case "readlink":
12260
12460
  return json2(await fs.readlink(path));
12261
12461
  case "chmod": {
12262
12462
  const g = guardOf(entry);
12263
12463
  await fs.chmod(path, g ? await chmodMode(g, path, req.mode ?? 0) : req.mode ?? 0);
12264
- return done;
12464
+ return done2;
12265
12465
  }
12266
12466
  case "utimes":
12267
12467
  await fs.utimes(path, ...await timesOf(entry, path, req));
12268
- return done;
12468
+ return done2;
12269
12469
  case "lutimes":
12270
12470
  await lutimesOf(fs, path, ...await timesOf(entry, path, req));
12271
- return done;
12471
+ return done2;
12272
12472
  case "chown":
12273
12473
  case "lchown":
12274
12474
  return chown(entry, path, req);
@@ -12351,6 +12551,16 @@ async function guard(g, path, req, cwd) {
12351
12551
  const toWalked = await walkSafe(g, to, false);
12352
12552
  return { path: fromWalked, arg2: toWalked };
12353
12553
  }
12554
+ case "copy": {
12555
+ const to = other();
12556
+ await readable(g, op, path);
12557
+ const there = !req.exclusive && await g.fs.lstat(to).then(
12558
+ () => true,
12559
+ () => false
12560
+ );
12561
+ await (there ? writable(g, op, to) : inParent(g, op, to));
12562
+ return { path: await walkSafe(g, path, true), arg2: await walkSafe(g, to, false) };
12563
+ }
12354
12564
  case "link": {
12355
12565
  const to = other();
12356
12566
  const follow2 = req.mode === 1;
@@ -12397,8 +12607,8 @@ async function stillThere(entry, path, req) {
12397
12607
  }
12398
12608
  async function holdOp(entry, path, req) {
12399
12609
  const mode = req.mode ?? 0;
12400
- const [on, open] = [(mode & 1) === 1, (mode & 2) === 2];
12401
- if (on && open) {
12610
+ const [on, open2] = [(mode & 1) === 1, (mode & 2) === 2];
12611
+ if (on && open2) {
12402
12612
  for (; ; ) {
12403
12613
  const r = entry.replacements;
12404
12614
  await r?.settled(path);
@@ -12408,26 +12618,26 @@ async function holdOp(entry, path, req) {
12408
12618
  await entry.source?.open(path, real);
12409
12619
  await stillThere(entry, path, req);
12410
12620
  if (!r || !r.missed(path) && !r.changedSince(path, gen))
12411
- return json2(entry.hold?.(path, on, open, real) ?? null);
12621
+ return json2(entry.hold?.(path, on, open2, real) ?? null);
12412
12622
  }
12413
12623
  }
12414
- entry.hold?.(path, on, open, void 0, req.handle);
12415
- return done;
12624
+ entry.hold?.(path, on, open2, void 0, req.handle);
12625
+ return done2;
12416
12626
  }
12417
12627
  async function followed(g, path) {
12418
12628
  const st = await g.fs.lstat(path).catch(() => void 0);
12419
12629
  if (st?.isSymbolicLink && !trustedLink(permOf(st), g.links)) deny(g, "follow", path);
12420
- return done;
12630
+ return done2;
12421
12631
  }
12422
12632
  async function accessOp(entry, path, req) {
12423
12633
  const g = guardOf(entry);
12424
- if (!g) return done;
12634
+ if (!g) return done2;
12425
12635
  if (req.arg2 === "follow") return followed(g, path);
12426
- const open = req.arg2 === "open";
12427
- const cred = open || req.arg2 === "eaccess" ? g.cred : realIds(g.cred);
12428
- const options = { follow: req.nofollow !== true, ...open ? { directory: false } : {} };
12429
- await need({ ...g, cred }, open ? "open" : "access", path, req.mode ?? 0, options);
12430
- return done;
12636
+ const open2 = req.arg2 === "open";
12637
+ const cred = open2 || req.arg2 === "eaccess" ? g.cred : realIds(g.cred);
12638
+ const options = { follow: req.nofollow !== true, ...open2 ? { directory: false } : {} };
12639
+ await need({ ...g, cred }, open2 ? "open" : "access", path, req.mode ?? 0, options);
12640
+ return done2;
12431
12641
  }
12432
12642
  var CHANGING = /* @__PURE__ */ new Set([
12433
12643
  "mkdir",
@@ -12451,6 +12661,9 @@ async function mayChange(entry, path, req) {
12451
12661
  const { mayChange: mayChange2 } = entry.fs;
12452
12662
  if (!mayChange2) return;
12453
12663
  const { op } = req;
12664
+ if (op === "copy") {
12665
+ return mayChange2.call(entry.fs, entry.fs.resolvePath(entry.cwd, req.arg2 ?? ""), false);
12666
+ }
12454
12667
  if (CONTENT.has(op) && req.handle === void 0) return mayChange2.call(entry.fs, path, true);
12455
12668
  if (!CHANGING.has(op)) return;
12456
12669
  const follow2 = op === "utimes" || op === "chmod" || op === "chown";
@@ -12474,6 +12687,17 @@ async function guarded(entry, path, req) {
12474
12687
  return { refused: refused3 };
12475
12688
  }
12476
12689
  }
12690
+ async function copyOp(entry, path, req) {
12691
+ const { fs, cwd } = entry;
12692
+ const to = fs.resolvePath(cwd, req.arg2 ?? "");
12693
+ const mode = (req.mode ?? 438) & 4095 & ~(entry.umask?.() ?? 18);
12694
+ const owner = ownerFor2(entry, mode);
12695
+ const options = { exclusive: req.exclusive === true, ...owner ? { owner } : {} };
12696
+ await (fs.copyFile ? fs.copyFile(path, to, options) : copyByBytes(fs, path, to, options));
12697
+ if (!owner) await fs.chmod(to, mode);
12698
+ entry.fresh?.(to);
12699
+ return done2;
12700
+ }
12477
12701
  async function createExclusive(fs, path, owner) {
12478
12702
  if (fs.createExclusive) return fs.createExclusive(path, owner);
12479
12703
  if (await fs.lstat(path).then(
@@ -12519,7 +12743,7 @@ async function ranged(fs, path, req) {
12519
12743
  };
12520
12744
  if (req.op === "pwrite") await ops.pwrite(path, offset, req.body ?? new Uint8Array(0), true);
12521
12745
  else await ops.truncate(path, req.length ?? 0);
12522
- return done;
12746
+ return done2;
12523
12747
  }
12524
12748
  var CHOWN_OPS = /* @__PURE__ */ new Set(["chown", "lchown"]);
12525
12749
  var UNLINKED_OPS = /* @__PURE__ */ new Set(["read", "pread", "pwrite", "append", "truncate"]);
@@ -12648,7 +12872,7 @@ var CREATIONS = /* @__PURE__ */ new Set([
12648
12872
  "create",
12649
12873
  "mkfifo"
12650
12874
  ]);
12651
- var NAMING = /* @__PURE__ */ new Set(["link", "rename"]);
12875
+ var NAMING = /* @__PURE__ */ new Set(["link", "rename", "copy"]);
12652
12876
  async function newDevName(entry, path, req) {
12653
12877
  const named = NAMING.has(req.op);
12654
12878
  if (!named && !CREATIONS.has(req.op)) return void 0;
@@ -12960,10 +13184,10 @@ var CpuClock = class {
12960
13184
  }
12961
13185
  times() {
12962
13186
  const now = this.frozen ?? this.now();
12963
- const open = this.since === 0 ? 0 : Math.max(0, now - this.since);
12964
- const busy = this.kind === "sys" ? Math.min(open, SYS_CAP_US) : 0;
13187
+ const open2 = this.since === 0 ? 0 : Math.max(0, now - this.since);
13188
+ const busy = this.kind === "sys" ? Math.min(open2, SYS_CAP_US) : 0;
12965
13189
  const sys = this.sys + busy;
12966
- const idle2 = this.idle + (open - busy) + localIdle(this.sab, now).idle;
13190
+ const idle2 = this.idle + (open2 - busy) + localIdle(this.sab, now).idle;
12967
13191
  const user = Math.max(0, now - this.start - sys - idle2);
12968
13192
  this.last = {
12969
13193
  utime: Math.max(this.last.utime, Math.floor(user / 1e3)),
@@ -13120,19 +13344,19 @@ var Pages = class {
13120
13344
  return Math.max(0, end - at);
13121
13345
  }
13122
13346
  write(at, bytes) {
13123
- for (let done4 = 0; done4 < bytes.length; ) {
13124
- const pos = at + done4;
13347
+ for (let done5 = 0; done5 < bytes.length; ) {
13348
+ const pos = at + done5;
13125
13349
  const page = Math.floor(pos / PAGE);
13126
13350
  const from = pos - page * PAGE;
13127
- const n = Math.min(PAGE - from, bytes.length - done4);
13351
+ const n = Math.min(PAGE - from, bytes.length - done5);
13128
13352
  let target = this.pages.get(page);
13129
13353
  if (!target) {
13130
13354
  target = this.take(0);
13131
13355
  this.pages.set(page, target);
13132
13356
  }
13133
- target.set(bytes.subarray(done4, done4 + n), from);
13357
+ target.set(bytes.subarray(done5, done5 + n), from);
13134
13358
  this.dirty.add(page);
13135
- done4 += n;
13359
+ done5 += n;
13136
13360
  }
13137
13361
  this.length = Math.max(this.length, at + bytes.length);
13138
13362
  }
@@ -13209,10 +13433,10 @@ var Pages = class {
13209
13433
  clean -= PAGE;
13210
13434
  }
13211
13435
  }
13212
- take(used) {
13436
+ take(used2) {
13213
13437
  const page = this.free.pop();
13214
13438
  if (!page) return new Uint8Array(PAGE);
13215
- page.fill(0, used);
13439
+ page.fill(0, used2);
13216
13440
  return page;
13217
13441
  }
13218
13442
  drop(page) {
@@ -13454,9 +13678,9 @@ function pidFile(name2, info, boot) {
13454
13678
  }
13455
13679
  return pidStatus(info);
13456
13680
  }
13457
- function memoryInfo(source, used = 0) {
13681
+ function memoryInfo(source, used2 = 0) {
13458
13682
  const total = source.deviceMemory ? source.deviceMemory * KIB * KIB * KIB : FALLBACK_MEMORY;
13459
- const free = Math.max(0, total - used - (source.usedHeap ?? 0));
13683
+ const free = Math.max(0, total - used2 - (source.usedHeap ?? 0));
13460
13684
  const kb = (bytes) => `${Math.floor(bytes / KIB)} kB`;
13461
13685
  return [
13462
13686
  ["MemTotal", kb(total)],
@@ -13509,10 +13733,10 @@ function memorySource(scope = globalThis) {
13509
13733
  const nav = scope.navigator;
13510
13734
  const perf = scope.performance;
13511
13735
  const deviceMemory = nav?.deviceMemory;
13512
- const used = perf?.memory?.usedJSHeapSize;
13736
+ const used2 = perf?.memory?.usedJSHeapSize;
13513
13737
  return {
13514
13738
  ...typeof deviceMemory === "number" && deviceMemory > 0 ? { deviceMemory } : {},
13515
- ...typeof used === "number" ? { usedHeap: used } : {}
13739
+ ...typeof used2 === "number" ? { usedHeap: used2 } : {}
13516
13740
  };
13517
13741
  }
13518
13742
 
@@ -13681,7 +13905,7 @@ var ProcTree = class {
13681
13905
  };
13682
13906
  var MAX_HOPS3 = 40;
13683
13907
  function* procWalk(path, follow2) {
13684
- let done4 = [];
13908
+ let done5 = [];
13685
13909
  let todo = path.split("/").filter((part) => part !== "");
13686
13910
  let hops = 0;
13687
13911
  let broken;
@@ -13689,20 +13913,20 @@ function* procWalk(path, follow2) {
13689
13913
  const part = todo.shift();
13690
13914
  if (part === ".") continue;
13691
13915
  if (part === "..") {
13692
- done4.pop();
13916
+ done5.pop();
13693
13917
  continue;
13694
13918
  }
13695
- const at = `/${[...done4, part].join("/")}`;
13696
- const whole = normalize(`/${[...done4, part, ...todo].join("/")}`);
13919
+ const at = `/${[...done5, part].join("/")}`;
13920
+ const whole = normalize(`/${[...done5, part, ...todo].join("/")}`);
13697
13921
  if (inProc(at) && inProc(whole)) return broken ?? whole;
13698
13922
  if (!follow2 && todo.length === 0) return void 0;
13699
13923
  const target = yield { at, check: todo.find((next3) => next3 !== ".") === ".." };
13700
13924
  if (typeof target === "string") {
13701
13925
  if (++hops > MAX_HOPS3) return void 0;
13702
- [done4, todo] = throughLink(target, done4, todo);
13926
+ [done5, todo] = throughLink(target, done5, todo);
13703
13927
  } else {
13704
13928
  broken ??= refusalOf(target);
13705
- done4.push(part);
13929
+ done5.push(part);
13706
13930
  }
13707
13931
  }
13708
13932
  return void 0;
@@ -13715,9 +13939,9 @@ function refusalOf(found) {
13715
13939
  if (found === true) return void 0;
13716
13940
  return found === false ? { refused: "ENOTDIR" } : found;
13717
13941
  }
13718
- function throughLink(target, done4, todo) {
13942
+ function throughLink(target, done5, todo) {
13719
13943
  const parts2 = target.split("/").filter((part) => part !== "");
13720
- return [target.startsWith("/") ? [] : done4, [...parts2, ...todo]];
13944
+ return [target.startsWith("/") ? [] : done5, [...parts2, ...todo]];
13721
13945
  }
13722
13946
  async function procAlias(fs, path, follow2) {
13723
13947
  const { readlink, lstat } = fs;
@@ -13914,16 +14138,16 @@ var EpollFile = class _EpollFile {
13914
14138
  changes = new Notifier();
13915
14139
  cursor = 0;
13916
14140
  ctl(fds, how, fd, events, data) {
13917
- const open = fds.get(fd);
13918
- if (open.file === this) throw new KernelError("EINVAL");
14141
+ const open2 = fds.get(fd);
14142
+ if (open2.file === this) throw new KernelError("EINVAL");
13919
14143
  const known = this.regs.get(fd);
13920
- const current = known?.open === open ? known : void 0;
14144
+ const current = known?.open === open2 ? known : void 0;
13921
14145
  if (how === "add" || how === "set" && !current) {
13922
14146
  if (current) throw new KernelError("EEXIST");
13923
- if (UNPOLLABLE.has(kernelFdKind(open.file))) throw new KernelError("EPERM");
13924
- if (open.file instanceof _EpollFile && open.file.reaches(this)) throw new KernelError("ELOOP");
14147
+ if (UNPOLLABLE.has(kernelFdKind(open2.file))) throw new KernelError("EPERM");
14148
+ if (open2.file instanceof _EpollFile && open2.file.reaches(this)) throw new KernelError("ELOOP");
13925
14149
  if (known) this.drop(known);
13926
- this.register(fd, open, events, data);
14150
+ this.register(fd, open2, events, data);
13927
14151
  } else if (!current) {
13928
14152
  throw new KernelError("ENOENT");
13929
14153
  } else if (how === "del") {
@@ -13990,15 +14214,15 @@ var EpollFile = class _EpollFile {
13990
14214
  for (const reg of [...this.regs.values()]) this.drop(reg);
13991
14215
  this.changes.wake();
13992
14216
  }
13993
- register(fd, open, events, data) {
14217
+ register(fd, open2, events, data) {
13994
14218
  const stop = new AbortController();
13995
- const unhook = open.onClose(() => {
14219
+ const unhook = open2.onClose(() => {
13996
14220
  this.drop(reg);
13997
14221
  this.changes.wake();
13998
14222
  });
13999
14223
  const reg = {
14000
14224
  fd,
14001
- open,
14225
+ open: open2,
14002
14226
  events,
14003
14227
  data,
14004
14228
  gen: 1,
@@ -14079,17 +14303,17 @@ function changedAt(wakers, key, signal) {
14079
14303
  return new Promise((resolve2, reject) => {
14080
14304
  const set3 = wakers.get(key) ?? /* @__PURE__ */ new Set();
14081
14305
  wakers.set(key, set3);
14082
- const done4 = () => {
14306
+ const done5 = () => {
14083
14307
  set3.delete(wake);
14084
14308
  if (set3.size === 0 && wakers.get(key) === set3) wakers.delete(key);
14085
14309
  signal.removeEventListener("abort", abort);
14086
14310
  };
14087
14311
  const wake = () => {
14088
- done4();
14312
+ done5();
14089
14313
  resolve2();
14090
14314
  };
14091
14315
  const abort = () => {
14092
- done4();
14316
+ done5();
14093
14317
  reject(new KernelError("EINTR"));
14094
14318
  };
14095
14319
  set3.add(wake);
@@ -14297,7 +14521,7 @@ var HOST_OPS = [
14297
14521
  "async-close"
14298
14522
  ];
14299
14523
  var json3 = (value2) => ({ ok: true, kind: "json", json: value2 });
14300
- var done2 = { ok: true, kind: "void" };
14524
+ var done3 = { ok: true, kind: "void" };
14301
14525
  var KEPT_OPS = /* @__PURE__ */ new Set(["fd-write"]);
14302
14526
  var unknownSettled = false;
14303
14527
  var AsyncOps = class {
@@ -14434,7 +14658,7 @@ async function hostSyscall(req, ctx) {
14434
14658
  if (req.fd !== void 0 && ctx.locks?.shared?.() && ctx.flockOf) {
14435
14659
  return flock({ op: "flock", fd: req.fd, kind: "unlock" }, ctx);
14436
14660
  }
14437
- return done2;
14661
+ return done3;
14438
14662
  case "lk-set":
14439
14663
  case "lk-get":
14440
14664
  case "lk-close":
@@ -14455,12 +14679,12 @@ async function hostSyscall(req, ctx) {
14455
14679
  return json3(ctx.ops.hold());
14456
14680
  case "async-cancel":
14457
14681
  ctx.ops.cancel(req.id);
14458
- return done2;
14682
+ return done3;
14459
14683
  case "async-settle":
14460
14684
  return json3(await ctx.ops.settle(req.ids));
14461
14685
  case "async-close":
14462
14686
  ctx.ops.close();
14463
- return done2;
14687
+ return done3;
14464
14688
  }
14465
14689
  }
14466
14690
  async function wholeLock(req, ctx) {
@@ -14478,7 +14702,7 @@ async function wholeLock(req, ctx) {
14478
14702
  if (!locks.flockFree(key, owner, kind)) throw new KernelError("EAGAIN");
14479
14703
  }
14480
14704
  if (!locks.lock(ctx.pid, req.path, req.exclusive, req.fd)) throw new KernelError("EAGAIN");
14481
- return done2;
14705
+ return done3;
14482
14706
  }
14483
14707
  var FLOCK_KINDS = /* @__PURE__ */ new Set(["shared", "exclusive", "unlock"]);
14484
14708
  async function flock(req, ctx) {
@@ -14493,7 +14717,7 @@ async function flock(req, ctx) {
14493
14717
  await locks.flocks.wait(key, owner, req.kind, ctx.blocking);
14494
14718
  else if (!await locks.flocks.set(key, owner, req.kind)) throw new KernelError("EAGAIN");
14495
14719
  if (shared && granted2) await grantedAcross(ctx, req.fd);
14496
- return shared ? json3(true) : done2;
14720
+ return shared ? json3(true) : done3;
14497
14721
  }
14498
14722
  async function grantedAcross(ctx, fd) {
14499
14723
  ctx.locks?.fresh?.();
@@ -14510,7 +14734,7 @@ async function recordLock2(req, ctx) {
14510
14734
  if (req.op === "lk-close") {
14511
14735
  if (req.fd !== void 0 && locks.shared?.()) await ctx.settle?.(req.fd, false);
14512
14736
  locks.dropFile(await fileKey(target, "close"), owner);
14513
- return done2;
14737
+ return done3;
14514
14738
  }
14515
14739
  const range2 = lockRange(req.start, req.len);
14516
14740
  const key = await fileKey(target, req.kind, req.op === "lk-set" && req.fd !== void 0);
@@ -14529,7 +14753,7 @@ async function recordLock2(req, ctx) {
14529
14753
  else if (!await locks.set(key, owner, req.kind, range2.start, range2.end))
14530
14754
  throw new KernelError("EAGAIN");
14531
14755
  if (granted2 && shared) await grantedAcross(ctx, fd);
14532
- return shared ? json3(true) : done2;
14756
+ return shared ? json3(true) : done3;
14533
14757
  }
14534
14758
 
14535
14759
  // src/kernel/net/loopback-transport.ts
@@ -15081,7 +15305,7 @@ var CA_RENEW_BEFORE = 30 * DAY;
15081
15305
  var LEAF_LIFETIME = 7 * DAY;
15082
15306
  var ECDSA = { name: "ECDSA", namedCurve: "P-256" };
15083
15307
  var SIGN = { name: "ECDSA", hash: "SHA-256" };
15084
- function request(req) {
15308
+ function request2(req) {
15085
15309
  return new Promise((resolve2, reject) => {
15086
15310
  req.onsuccess = () => resolve2(req.result);
15087
15311
  req.onerror = () => reject(req.error);
@@ -15089,7 +15313,7 @@ function request(req) {
15089
15313
  }
15090
15314
  function indexedDbCaStore(dbName = "slicc-realm-ca") {
15091
15315
  let db;
15092
- const open = () => {
15316
+ const open2 = () => {
15093
15317
  db ??= new Promise((resolve2, reject) => {
15094
15318
  const req = indexedDB.open(dbName, 1);
15095
15319
  req.onupgradeneeded = () => req.result.createObjectStore("ca");
@@ -15103,11 +15327,11 @@ function indexedDbCaStore(dbName = "slicc-realm-ca") {
15103
15327
  };
15104
15328
  return {
15105
15329
  async get(owner) {
15106
- const store = (await open()).transaction("ca").objectStore("ca");
15107
- return await request(store.get(owner));
15330
+ const store = (await open2()).transaction("ca").objectStore("ca");
15331
+ return await request2(store.get(owner));
15108
15332
  },
15109
15333
  async swap(owner, expected, record) {
15110
- const tx = (await open()).transaction("ca", "readwrite");
15334
+ const tx = (await open2()).transaction("ca", "readwrite");
15111
15335
  const store = tx.objectStore("ca");
15112
15336
  let stored = record;
15113
15337
  const read = store.get(owner);
@@ -15810,7 +16034,7 @@ var WsHandles = class {
15810
16034
  async connect(handle, req, entry) {
15811
16035
  const { transport, local } = this;
15812
16036
  const port = local?.port(req.url);
15813
- const open = { protocols: req.protocols, headers: req.headers, signal: entry.abort.signal };
16037
+ const open2 = { protocols: req.protocols, headers: req.headers, signal: entry.abort.signal };
15814
16038
  if (port === void 0 && (!transport.traits.websocket || !transport.websocket)) {
15815
16039
  return fail("ENOTSUP", NO_WEBSOCKET2);
15816
16040
  }
@@ -15818,8 +16042,8 @@ var WsHandles = class {
15818
16042
  try {
15819
16043
  socket = port === void 0 ? await transport.websocket({
15820
16044
  url: toHostLoopback(req.url),
15821
- ...open
15822
- }) : await local.websocket({ url: req.url, ...open }, port);
16045
+ ...open2
16046
+ }) : await local.websocket({ url: req.url, ...open2 }, port);
15823
16047
  } catch (e) {
15824
16048
  return fail(errnoOf(e), message(e));
15825
16049
  }
@@ -16022,14 +16246,14 @@ var HttpHandles = class {
16022
16246
  const port = this.local?.port(req.url);
16023
16247
  try {
16024
16248
  const target = port === void 0 ? toHostLoopback(req.url) : req.url;
16025
- const request2 = {
16249
+ const request3 = {
16026
16250
  url: target,
16027
16251
  method: req.method,
16028
16252
  headers: req.headers,
16029
16253
  ...entry.upload ? { bodyStream: entry.upload } : req.body ? { body: req.body } : {},
16030
16254
  signal: entry.abort.signal
16031
16255
  };
16032
- const response = port === void 0 ? await this.transport.fetch(request2, this.owner) : await this.local.fetch(request2, port);
16256
+ const response = port === void 0 ? await this.transport.fetch(request3, this.owner) : await this.local.fetch(request3, port);
16033
16257
  entry.body = response.body[Symbol.asyncIterator]();
16034
16258
  entry.cancel = () => response.cancel();
16035
16259
  if (!this.open.has(handle)) await entry.cancel().catch(() => void 0);
@@ -16181,10 +16405,10 @@ var RemoteUplink = class {
16181
16405
  write: async (bytes) => {
16182
16406
  const copy = bytes.slice();
16183
16407
  const call = { uplink: "write", uid: ++this.nextId, cid, bytes: copy };
16184
- const done4 = await this.ask(call, void 0, [
16408
+ const done5 = await this.ask(call, void 0, [
16185
16409
  copy.buffer
16186
16410
  ]);
16187
- return done4.n;
16411
+ return done5.n;
16188
16412
  },
16189
16413
  closeWrite: () => this.port.postMessage({ uplink: "close-write", cid }),
16190
16414
  close: () => this.port.postMessage({ uplink: "close", cid })
@@ -16791,7 +17015,7 @@ function terminalOf(ctx, fd) {
16791
17015
  return tty;
16792
17016
  }
16793
17017
  var json4 = (value2) => ({ ok: true, kind: "json", json: value2 });
16794
- var done3 = { ok: true, kind: "void" };
17018
+ var done4 = { ok: true, kind: "void" };
16795
17019
  function sizeKey(rows, cols) {
16796
17020
  return `${rows}x${cols}`;
16797
17021
  }
@@ -16814,23 +17038,23 @@ function ptySyscall(req, ctx) {
16814
17038
  return json4(masterOf(ctx, req.fd).index);
16815
17039
  case "pty-lock":
16816
17040
  masterOf(ctx, req.fd).locked = req.lock;
16817
- return done3;
17041
+ return done4;
16818
17042
  case "pty-ctty": {
16819
17043
  const tty = terminalOf(ctx, req.fd);
16820
17044
  const leader = ctx.jobs?.getsid(ctx.pid, 0) === ctx.pid;
16821
- if (leader && ctx.jobs?.controllingTerminal(ctx.pid) === tty) return done3;
17045
+ if (leader && ctx.jobs?.controllingTerminal(ctx.pid) === tty) return done4;
16822
17046
  if (!ctx.jobs?.acquireTerminal(ctx.pid, tty)) throw new KernelError("EPERM");
16823
- return done3;
17047
+ return done4;
16824
17048
  }
16825
17049
  case "pty-list":
16826
17050
  return json4(ctx.ptys?.numbers() ?? []);
16827
17051
  case "pty-packet":
16828
17052
  masterOf(ctx, req.fd).packet = req.on;
16829
- return done3;
17053
+ return done4;
16830
17054
  case "pty-winsz-set": {
16831
17055
  const tty = terminalOf(ctx, req.fd);
16832
17056
  if (ctx.sizesRead?.get(tty) !== sizeKey(req.rows, req.cols)) tty.resize(req.cols, req.rows);
16833
- return done3;
17057
+ return done4;
16834
17058
  }
16835
17059
  }
16836
17060
  }
@@ -16917,8 +17141,8 @@ async function runChild(req, deps) {
16917
17141
  let status;
16918
17142
  try {
16919
17143
  status = await reaped(deps, pid);
16920
- const open = controls2.filter((c) => c.opened);
16921
- await Promise.race([Promise.all(open.map((c) => c.eof)), decided.promise]);
17144
+ const open2 = controls2.filter((c) => c.opened);
17145
+ await Promise.race([Promise.all(open2.map((c) => c.eof)), decided.promise]);
16922
17146
  } finally {
16923
17147
  cancel?.();
16924
17148
  for (const control of controls2) control.shut = true;
@@ -17196,7 +17420,7 @@ function filePath(addr) {
17196
17420
  if (addr.family !== "unix" || addr.path === "" || addr.path.startsWith("\0")) return void 0;
17197
17421
  return normalizePath(addr.path);
17198
17422
  }
17199
- function nameOf(st) {
17423
+ function nameOf2(st) {
17200
17424
  return { key: `${st.dev ?? 0}:${st.ino}`, typed: st.isSocket === true };
17201
17425
  }
17202
17426
  function codeOf3(err) {
@@ -17218,7 +17442,7 @@ function socketNames(deps) {
17218
17442
  const remove = () => fs.rm(path, { file: true }).catch(() => void 0);
17219
17443
  try {
17220
17444
  if (!deps.owners && owner.mode !== void 0) await fs.chmod(path, owner.mode);
17221
- return { ...nameOf(await fs.lstat(path)), remove };
17445
+ return { ...nameOf2(await fs.lstat(path)), remove };
17222
17446
  } catch (err) {
17223
17447
  await remove();
17224
17448
  throw err;
@@ -17227,7 +17451,7 @@ function socketNames(deps) {
17227
17451
  async find(path) {
17228
17452
  const g = deps.guard();
17229
17453
  if (g) await need(g, "connect", path, W_OK, { directory: false });
17230
- return nameOf(await fs.stat(path));
17454
+ return nameOf2(await fs.stat(path));
17231
17455
  }
17232
17456
  };
17233
17457
  }
@@ -18043,17 +18267,17 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
18043
18267
  });
18044
18268
  };
18045
18269
  const settling = (signal) => new Promise((resolve2, reject) => {
18046
- const done4 = () => {
18047
- waiters.delete(done4);
18270
+ const done5 = () => {
18271
+ waiters.delete(done5);
18048
18272
  signal?.removeEventListener("abort", stop);
18049
18273
  resolve2();
18050
18274
  };
18051
18275
  const stop = () => {
18052
- waiters.delete(done4);
18276
+ waiters.delete(done5);
18053
18277
  reject(new KernelError("EINTR"));
18054
18278
  };
18055
18279
  if (signal?.aborted) return stop();
18056
- waiters.add(done4);
18280
+ waiters.add(done5);
18057
18281
  signal?.addEventListener("abort", stop, { once: true });
18058
18282
  });
18059
18283
  const settled = async () => {
@@ -18245,15 +18469,15 @@ async function substituteHead(head, ask) {
18245
18469
  if (!head.endsWith("\r\n\r\n")) return void 0;
18246
18470
  const lines2 = head.slice(0, -4).split("\r\n");
18247
18471
  if (lines2.some((l) => l.includes("\n") || l.includes("\r"))) return void 0;
18248
- const request2 = REQUEST_LINE2.exec(lines2[0]);
18249
- const found = request2 ? scan(lines2) : void 0;
18250
- if (!request2 || !found || found.length !== 1) return void 0;
18472
+ const request3 = REQUEST_LINE2.exec(lines2[0]);
18473
+ const found = request3 ? scan(lines2) : void 0;
18474
+ if (!request3 || !found || found.length !== 1) return void 0;
18251
18475
  const at = found[0];
18252
18476
  if (at.placeholders.length > SESSION_PLACEHOLDERS) return void 0;
18253
18477
  const values = usable(
18254
18478
  await ask(`header:${at.name}`, at.placeholders, {
18255
- method: request2[1],
18256
- path: request2[2]
18479
+ method: request3[1],
18480
+ path: request3[2]
18257
18481
  })
18258
18482
  );
18259
18483
  if (Object.keys(values).length === 0) return void 0;
@@ -18356,7 +18580,7 @@ var Http1Writer = class {
18356
18580
  this.buffer = new Uint8Array(0);
18357
18581
  const s = this.s;
18358
18582
  const session = sessionId();
18359
- const done4 = await substituteHead(
18583
+ const done5 = await substituteHead(
18360
18584
  latin12(all.subarray(0, end)),
18361
18585
  async (position, placeholders, head2) => s.broker.sessionMaterialize({
18362
18586
  stamp: await s.stamp(),
@@ -18372,10 +18596,10 @@ var Http1Writer = class {
18372
18596
  head: head2
18373
18597
  })
18374
18598
  ).catch(() => void 0);
18375
- const head = done4 ? bytesOf(done4.head) : all.subarray(0, end);
18376
- if (done4) {
18599
+ const head = done5 ? bytesOf(done5.head) : all.subarray(0, end);
18600
+ if (done5) {
18377
18601
  this.scope.add(
18378
- Object.entries(done4.values).map(([placeholder, value2]) => ({
18602
+ Object.entries(done5.values).map(([placeholder, value2]) => ({
18379
18603
  name: "sealed",
18380
18604
  value: value2,
18381
18605
  placeholder
@@ -18793,15 +19017,15 @@ function alertOf(session) {
18793
19017
  }
18794
19018
  async function handshake(conn, o, session, inbox) {
18795
19019
  for (; ; ) {
18796
- let done4;
19020
+ let done5;
18797
19021
  try {
18798
- done4 = session.handshake();
19022
+ done5 = session.handshake();
18799
19023
  } catch (err) {
18800
19024
  await send(conn, session).catch(() => void 0);
18801
19025
  throw refused2(o.engine, session, err);
18802
19026
  }
18803
19027
  await send(conn, session);
18804
- if (done4) return;
19028
+ if (done5) return;
18805
19029
  if (!await inbox.more()) {
18806
19030
  throw new KernelError(
18807
19031
  "ECONNRESET",
@@ -19925,7 +20149,7 @@ var VfsNodes = class {
19925
20149
  if (held) throw fsError("EEXIST", path);
19926
20150
  const exclusive = this.fs.createExclusive;
19927
20151
  if (exclusive) return exclusive.call(this.fs, path, owner);
19928
- if (await present2(this.fs, path)) throw fsError("EEXIST", path);
20152
+ if (await present3(this.fs, path)) throw fsError("EEXIST", path);
19929
20153
  await this.fs.writeFile(path, new Uint8Array(0), owner);
19930
20154
  });
19931
20155
  }
@@ -20031,9 +20255,9 @@ var VfsNodes = class {
20031
20255
  }
20032
20256
  open(path, pin, writable2 = false, id2, ino) {
20033
20257
  const found = this.named(path, id2);
20034
- const same = !found || ino === void 0 || found.ino === void 0 || found.ino === ino;
20035
- if (found && !same) this.orphan(found);
20036
- const node = (same ? found : void 0) ?? this.create(path, id2, new VfsNode(this.fs, path, void 0, false, false, pin));
20258
+ const same2 = !found || ino === void 0 || found.ino === void 0 || found.ino === ino;
20259
+ if (found && !same2) this.orphan(found);
20260
+ const node = (same2 ? found : void 0) ?? this.create(path, id2, new VfsNode(this.fs, path, void 0, false, false, pin));
20037
20261
  node.ino ??= ino;
20038
20262
  node.opens++;
20039
20263
  if (writable2) node.writers++;
@@ -20156,7 +20380,7 @@ var VfsNodes = class {
20156
20380
  }
20157
20381
  }
20158
20382
  };
20159
- async function present2(fs, path, follow2 = false) {
20383
+ async function present3(fs, path, follow2 = false) {
20160
20384
  const look = (follow2 ? void 0 : fs.lstat) ?? fs.stat;
20161
20385
  try {
20162
20386
  await (look ? look.call(fs, path) : fs.readFileBuffer(path));
@@ -20216,9 +20440,9 @@ function heldIo(fs, nodes, changed) {
20216
20440
  const held = await node(path);
20217
20441
  if (!held) return fallback();
20218
20442
  const out = await held.serial(async () => {
20219
- const done4 = await op(held);
20443
+ const done5 = await op(held);
20220
20444
  await held.flush();
20221
- return done4;
20445
+ return done5;
20222
20446
  });
20223
20447
  changed(fs.resolvePath("/", path));
20224
20448
  if (held.path !== fs.resolvePath("/", path)) changed(held.path);
@@ -20334,7 +20558,18 @@ function keepingOpen(fs, nodes, changed = () => {
20334
20558
  await nodes.onEntry(key, () => fs.link(from, to, follow2));
20335
20559
  await nodes.linked(at, key);
20336
20560
  },
20337
- mkdir: (path, options) => nodes.onEntry(fs.resolvePath("/", path), () => fs.mkdir(path, options))
20561
+ mkdir: (path, options) => nodes.onEntry(fs.resolvePath("/", path), () => fs.mkdir(path, options)),
20562
+ ...fs.copyFile ? {
20563
+ async copyFile(from, to, options) {
20564
+ const source = await nodes.targetKey(fs.resolvePath("/", from));
20565
+ await nodes.flush(source);
20566
+ await nodes.flushLinked(source);
20567
+ const at = fs.resolvePath("/", to);
20568
+ const key = await nodes.entryKey(at);
20569
+ if (await heldAt(fs, nodes, at)) return copyByBytes(this, from, to, options);
20570
+ await nodes.onEntry(key, () => fs.copyFile?.(from, to, options));
20571
+ }
20572
+ } : {}
20338
20573
  };
20339
20574
  }
20340
20575
  function vfsFile(fs, opts, nodes) {
@@ -21040,30 +21275,30 @@ var WasmProcess = class {
21040
21275
  else await file?.flush?.();
21041
21276
  }
21042
21277
  async flockOf(fd) {
21043
- const open = this.fds.get(fd);
21278
+ const open2 = this.fds.get(fd);
21044
21279
  const { locks } = this.options;
21045
- if (locks && !flockHooked.has(open)) {
21046
- flockHooked.add(open);
21047
- open.onClose(() => locks.flocks.drop(open));
21280
+ if (locks && !flockHooked.has(open2)) {
21281
+ flockHooked.add(open2);
21282
+ open2.onClose(() => locks.flocks.drop(open2));
21048
21283
  }
21049
- return { key: await this.objectKeyOf(open), owner: open };
21284
+ return { key: await this.objectKeyOf(open2), owner: open2 };
21050
21285
  }
21051
- async objectKeyOf(open) {
21052
- const { file } = open;
21286
+ async objectKeyOf(open2) {
21287
+ const { file } = open2;
21053
21288
  const meta = file.heldMeta;
21054
21289
  if (meta && "device" in meta) return `device:${meta.device}`;
21055
21290
  if (meta && "dir" in meta) {
21056
21291
  const st2 = await this.options.fs.stat?.(meta.dir).catch(() => void 0);
21057
21292
  return st2 ? identityKey(st2, meta.dir) : objectKey(file);
21058
21293
  }
21059
- const known = fileKeys.get(open);
21294
+ const known = fileKeys.get(open2);
21060
21295
  if (known !== void 0) return known;
21061
21296
  const vfs = await file.stat?.().catch(() => void 0);
21062
21297
  if (!vfs || vfs.orphan) return objectKey(file);
21063
21298
  const st = await this.options.fs.stat?.(vfs.path).catch(() => void 0);
21064
21299
  if (!st) return objectKey(file);
21065
21300
  const key = identityKey(st, vfs.path);
21066
- fileKeys.set(open, key);
21301
+ fileKeys.set(open2, key);
21067
21302
  return key;
21068
21303
  }
21069
21304
  async dropRecordLocks(fd) {
@@ -21185,17 +21420,17 @@ var WasmProcess = class {
21185
21420
  return fd;
21186
21421
  }
21187
21422
  if (this.writesAt(req) && this.options.readonlyAt?.(path)) throw new KernelError("EROFS");
21188
- const open = { ...req, path };
21423
+ const open2 = { ...req, path };
21189
21424
  const plain2 = this.plainMode(req.mode);
21190
21425
  if (req.exclusive) {
21191
21426
  await nodes.createExclusive(path, this.newOwner(req.mode));
21192
21427
  if (plain2 !== void 0) await fs.chmod?.(path, plain2);
21193
- this.fds.installAt(fd, this.openVfsFile(open, void 0, fs));
21428
+ this.fds.installAt(fd, this.openVfsFile(open2, void 0, fs));
21194
21429
  } else if (req.create) {
21195
21430
  await nodes.onEntry(path, async () => {
21196
21431
  const marks = this.options.owners || plain2 !== void 0;
21197
- const fresh2 = marks && !await present2(fs, path, true);
21198
- this.fds.installAt(fd, this.openVfsFile(open, await nodes.identify(path), fs));
21432
+ const fresh2 = marks && !await present3(fs, path, true);
21433
+ this.fds.installAt(fd, this.openVfsFile(open2, await nodes.identify(path), fs));
21199
21434
  await this.fds.get(fd).file.stat?.();
21200
21435
  if (fresh2 && plain2 !== void 0) await fs.chmod?.(path, plain2);
21201
21436
  else if (fresh2) {
@@ -21209,11 +21444,11 @@ var WasmProcess = class {
21209
21444
  await this.stillOpen(at, req.handle);
21210
21445
  return nodes.identify(at);
21211
21446
  },
21212
- (id2, at) => this.fds.installAt(fd, this.openVfsFile({ ...open, path: at }, id2, fs)),
21447
+ (id2, at) => this.fds.installAt(fd, this.openVfsFile({ ...open2, path: at }, id2, fs)),
21213
21448
  { at: path, gen }
21214
21449
  );
21215
21450
  }
21216
- if (req.existing && !await present2(fs, path, true)) {
21451
+ if (req.existing && !await present3(fs, path, true)) {
21217
21452
  throw new KernelError("ENOENT");
21218
21453
  }
21219
21454
  } catch (err) {
@@ -21324,11 +21559,11 @@ var WasmProcess = class {
21324
21559
  }
21325
21560
  async stampClipboards() {
21326
21561
  if (!this.options.clipboard) return;
21327
- const open = this.fds.numbers().filter((fd) => this.fds.get(fd).file.clipboard);
21328
- if (open.length === 0) return;
21562
+ const open2 = this.fds.numbers().filter((fd) => this.fds.get(fd).file.clipboard);
21563
+ if (open2.length === 0) return;
21329
21564
  const stamp = await this.clipboardStamp().catch(() => void 0);
21330
21565
  if (!stamp) return;
21331
- for (const fd of open) {
21566
+ for (const fd of open2) {
21332
21567
  const channel = this.fds.get(fd).file.clipboard;
21333
21568
  if (channel) channel.stamp = stamp;
21334
21569
  }
@@ -21581,12 +21816,12 @@ var WasmProcess = class {
21581
21816
  async stillOpen(at, handle) {
21582
21817
  if (handle === void 0 || this.keptHandle?.(handle) !== void 0) return;
21583
21818
  if (this.holdsHandle?.(handle) !== false) return;
21584
- if (!await present2(this.options.fs, at, true)) throw new KernelError("ENOENT");
21819
+ if (!await present3(this.options.fs, at, true)) throw new KernelError("ENOENT");
21585
21820
  }
21586
21821
  async keptOr(path, handle) {
21587
21822
  if (handle !== void 0) return this.keptHandle?.(handle) ?? path;
21588
21823
  const kept = this.keptPath?.(path);
21589
- return kept !== void 0 && !await present2(this.options.fs, path, true) ? kept : path;
21824
+ return kept !== void 0 && !await present3(this.options.fs, path, true) ? kept : path;
21590
21825
  }
21591
21826
  async promote(req) {
21592
21827
  if (!this.fds.get(req.fd).file.held) throw new KernelError("EBADF");
@@ -22121,18 +22356,18 @@ function descId(file) {
22121
22356
  }
22122
22357
  function inheritedFds(fds) {
22123
22358
  return fds.numbers().filter((fd) => fd > 2 && !fds.get(fd).file.held).map((fd) => {
22124
- const open = fds.get(fd);
22359
+ const open2 = fds.get(fd);
22125
22360
  const flags2 = fds.statusFlags(fd);
22126
- const kind = open.file instanceof KernelSocket || isDatagram(open.file) ? "socket" : kernelFdKind(open.file);
22127
- const meta = open.file.heldMeta;
22361
+ const kind = open2.file instanceof KernelSocket || isDatagram(open2.file) ? "socket" : kernelFdKind(open2.file);
22362
+ const meta = open2.file.heldMeta;
22128
22363
  return {
22129
22364
  fd,
22130
22365
  kind,
22131
22366
  ...kind === "device" && meta && "device" in meta ? { device: meta } : {},
22132
22367
  ...flags2 !== void 0 ? { flags: flags2 } : {},
22133
22368
  ...fds.closesOnExec(fd) ? { cloexec: true } : {},
22134
- ...kind === "stream" ? { desc: descId(open) } : {},
22135
- ...open.file.fifo ? { fifo: open.file.fifo } : {}
22369
+ ...kind === "stream" ? { desc: descId(open2) } : {},
22370
+ ...open2.file.fifo ? { fifo: open2.file.fifo } : {}
22136
22371
  };
22137
22372
  });
22138
22373
  }
@@ -22298,7 +22533,7 @@ function holdingToken(opts, holds2, caller) {
22298
22533
  noLinks: opts.noLinks,
22299
22534
  cwd: opts.cwd,
22300
22535
  ...opts.statfs ? { statfs: opts.statfs } : {},
22301
- hold: (path, on, open, real, handle) => holds2.hold(path, on, open, real, handle),
22536
+ hold: (path, on, open2, real, handle) => holds2.hold(path, on, open2, real, handle),
22302
22537
  keptFor: (handle) => holds2.keptFor(handle),
22303
22538
  unlinked: (path) => holds2.keptAt(path),
22304
22539
  gate: (path, op) => opts.unlinkGate && holds2.holding(path) ? opts.unlinkGate.run(holds2.keyOf(path), op) : op(),
@@ -22447,11 +22682,11 @@ function spawnWasmProcess(opts) {
22447
22682
  });
22448
22683
  const lane = opts.program.abi === "js" ? openLane(token, dispatch2) : void 0;
22449
22684
  const { promise: exited, resolve: settle3 } = Promise.withResolvers();
22450
- let done4 = false;
22685
+ let done5 = false;
22451
22686
  let endedBy;
22452
22687
  const finish = (code, sig) => {
22453
- if (done4) return;
22454
- done4 = true;
22688
+ if (done5) return;
22689
+ done5 = true;
22455
22690
  started(true);
22456
22691
  clocks.freeze();
22457
22692
  dying.clear();
@@ -22502,7 +22737,7 @@ function spawnWasmProcess(opts) {
22502
22737
  };
22503
22738
  const spawnThread = (thread) => {
22504
22739
  const { program } = opts;
22505
- if (done4 || program.abi === "js") return;
22740
+ if (done5 || program.abi === "js") return;
22506
22741
  if (threads.size >= WASM_MAX_THREADS - 1) {
22507
22742
  opts.onError?.(`more than ${WASM_MAX_THREADS} threads`);
22508
22743
  finish(CRASHED);
@@ -22538,7 +22773,7 @@ function spawnWasmProcess(opts) {
22538
22773
  transferOf(opts, lane?.lane)
22539
22774
  );
22540
22775
  const terminate = (code, sig) => {
22541
- if (opts.program.abi !== "wasi" || done4) finish(code, sig);
22776
+ if (opts.program.abi !== "wasi" || done5) finish(code, sig);
22542
22777
  else dying.start(code, sig, header3, process, () => finish(code, sig));
22543
22778
  };
22544
22779
  const signal = (sig, info) => {
@@ -22560,7 +22795,7 @@ function spawnWasmProcess(opts) {
22560
22795
  signalMasks: () => process.signalMasks(),
22561
22796
  umask: () => process.umask,
22562
22797
  cred: () => copyCred(process.cred),
22563
- writesBack: () => opts.program.abi === "wasi" && !done4,
22798
+ writesBack: () => opts.program.abi === "wasi" && !done5,
22564
22799
  ...clockViews(clocks)
22565
22800
  };
22566
22801
  }
@@ -23228,21 +23463,21 @@ function replayingHops(inner, heldMs = HELD_MS) {
23228
23463
  return { ...inner.traits, manualRedirects: true };
23229
23464
  },
23230
23465
  ...inner.websocket ? { websocket: inner.websocket.bind(inner) } : {},
23231
- async fetch(request2, owner = KERNEL) {
23232
- const key = keyOf3(owner, request2.method, request2.url);
23466
+ async fetch(request3, owner = KERNEL) {
23467
+ const key = keyOf3(owner, request3.method, request3.url);
23233
23468
  const waiting = held.get(key);
23234
- if (waiting && waiting.fingerprint === fingerprint(request2.headers)) {
23469
+ if (waiting && waiting.fingerprint === fingerprint(request3.headers)) {
23235
23470
  held.delete(key);
23236
23471
  clearTimeout(waiting.timer);
23237
23472
  return replay(waiting);
23238
23473
  }
23239
23474
  if (waiting) drop(key);
23240
- const response = await inner.fetch(request2);
23475
+ const response = await inner.fetch(request3);
23241
23476
  if (!response.redirects?.length) return response;
23242
23477
  return replay({
23243
23478
  owner,
23244
- method: request2.method,
23245
- fingerprint: fingerprint(request2.headers),
23479
+ method: request3.method,
23480
+ fingerprint: fingerprint(request3.headers),
23246
23481
  hops: response.redirects,
23247
23482
  final: response
23248
23483
  });
@@ -23768,7 +24003,7 @@ async function dispatch(h, req) {
23768
24003
  }
23769
24004
  }
23770
24005
  function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
23771
- let open = false;
24006
+ let open2 = false;
23772
24007
  const reply = (message3, transfer = []) => port.postMessage(message3, transfer);
23773
24008
  async function hello(message3) {
23774
24009
  const refused3 = driverVersionError(message3.protocol);
@@ -23778,7 +24013,7 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
23778
24013
  }
23779
24014
  try {
23780
24015
  const refined = await handlers.mount?.(message3.mount);
23781
- open = true;
24016
+ open2 = true;
23782
24017
  reply({
23783
24018
  hello: { protocol: DRIVER_PROTOCOL, capabilities: { ...capabilities, ...refined } }
23784
24019
  });
@@ -23799,7 +24034,7 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
23799
24034
  void hello(data.hello);
23800
24035
  return;
23801
24036
  }
23802
- if (!open) return;
24037
+ if (!open2) return;
23803
24038
  dispatch(handlers, data).then(
23804
24039
  (result) => {
23805
24040
  if (result instanceof Uint8Array) {
@@ -23948,10 +24183,10 @@ function kernelFsHandlers(fs) {
23948
24183
  readlink: (path) => fs.readlink(path),
23949
24184
  async setattr(path, change) {
23950
24185
  if (change.size !== void 0) {
23951
- const open = [...handles.values()].find(
24186
+ const open2 = [...handles.values()].find(
23952
24187
  (h) => h.path === path && h.session !== void 0
23953
24188
  )?.session;
23954
- if (open !== void 0) await (await open).truncate(change.size);
24189
+ if (open2 !== void 0) await (await open2).truncate(change.size);
23955
24190
  else await fs.truncate?.(path, change.size);
23956
24191
  }
23957
24192
  if (change.mode !== void 0) await fs.chmod(path, change.mode);
@@ -23968,7 +24203,7 @@ function granted(handle) {
23968
24203
  () => false
23969
24204
  );
23970
24205
  }
23971
- function removableMedium(onLost, open = (handle) => new OpfsFs(handle)) {
24206
+ function removableMedium(onLost, open2 = (handle) => new OpfsFs(handle)) {
23972
24207
  const slot2 = mediumSlot(
23973
24208
  async (err, handle) => denied(err) && !await granted(handle),
23974
24209
  onLost
@@ -23976,7 +24211,7 @@ function removableMedium(onLost, open = (handle) => new OpfsFs(handle)) {
23976
24211
  return {
23977
24212
  handlers: slot2.handlers,
23978
24213
  present: slot2.present,
23979
- insert: (handle) => slot2.insert(handle, kernelFsHandlers(open(handle))),
24214
+ insert: (handle) => slot2.insert(handle, kernelFsHandlers(open2(handle))),
23980
24215
  eject: slot2.eject
23981
24216
  };
23982
24217
  }
@@ -24102,13 +24337,13 @@ function codeOf5(err) {
24102
24337
  function wait(ms, signal) {
24103
24338
  if (signal.aborted) return Promise.resolve();
24104
24339
  return new Promise((resolve2) => {
24105
- const done4 = () => {
24340
+ const done5 = () => {
24106
24341
  clearTimeout(timer);
24107
- signal.removeEventListener("abort", done4);
24342
+ signal.removeEventListener("abort", done5);
24108
24343
  resolve2();
24109
24344
  };
24110
- const timer = setTimeout(done4, ms);
24111
- signal.addEventListener("abort", done4, { once: true });
24345
+ const timer = setTimeout(done5, ms);
24346
+ signal.addEventListener("abort", done5, { once: true });
24112
24347
  });
24113
24348
  }
24114
24349
  async function mountFstab(lines2, mount, signal, retries = FSTAB_RETRIES, discard = () => {
@@ -24269,8 +24504,8 @@ var HostfsClient = class {
24269
24504
  let buffered = "";
24270
24505
  try {
24271
24506
  for (; ; ) {
24272
- const { done: done4, value: value2 } = await reader.read();
24273
- if (done4) return;
24507
+ const { done: done5, value: value2 } = await reader.read();
24508
+ if (done5) return;
24274
24509
  buffered += decoder4.decode(value2, { stream: true });
24275
24510
  let end = buffered.indexOf("\n");
24276
24511
  while (end >= 0) {
@@ -24302,14 +24537,14 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
24302
24537
  return fresh2(remote);
24303
24538
  };
24304
24539
  const call = (op, body = {}) => current().call(op, body);
24305
- const same = (was, mode, seen) => seen?.mode === (mode | 128) && (was.ino !== void 0 && seen.ino !== void 0 ? seen.ino === was.ino : seen.size === was.size && seen.mtime === was.mtime);
24540
+ const same2 = (was, mode, seen) => seen?.mode === (mode | 128) && (was.ino !== void 0 && seen.ino !== void 0 ? seen.ino === was.ino : seen.size === was.size && seen.mtime === was.mtime);
24306
24541
  const settle3 = (client, { was, ...restore }) => client.call("setattr", restore).catch((err) => {
24307
24542
  if (!client.gone || !client.cleanup) throw err;
24308
24543
  void client.cleanup("setattr", restore).catch(() => {
24309
24544
  });
24310
24545
  const timer = setTimeout(async () => {
24311
24546
  const seen = await client.cleanup?.("stat", { path: restore.path }).catch(() => null);
24312
- if (same(was, restore.mode, seen))
24547
+ if (same2(was, restore.mode, seen))
24313
24548
  void client.cleanup?.("setattr", restore).catch(() => {
24314
24549
  });
24315
24550
  }, againMs);
@@ -24433,13 +24668,13 @@ async function resize(h, path, size) {
24433
24668
  }
24434
24669
  function sleep(ms, signal) {
24435
24670
  return new Promise((resolve2) => {
24436
- const done4 = () => {
24671
+ const done5 = () => {
24437
24672
  clearTimeout(timer);
24438
- signal.removeEventListener("abort", done4);
24673
+ signal.removeEventListener("abort", done5);
24439
24674
  resolve2();
24440
24675
  };
24441
- const timer = setTimeout(done4, ms);
24442
- signal.addEventListener("abort", done4);
24676
+ const timer = setTimeout(done5, ms);
24677
+ signal.addEventListener("abort", done5);
24443
24678
  });
24444
24679
  }
24445
24680
  function keepWatching(loop, signal) {
@@ -24523,8 +24758,8 @@ function timed(transport, ms) {
24523
24758
  let expired = false;
24524
24759
  const running = run2();
24525
24760
  inflight.add(running);
24526
- const done4 = () => inflight.delete(running);
24527
- running.then(done4, done4);
24761
+ const done5 = () => inflight.delete(running);
24762
+ running.then(done5, done5);
24528
24763
  const timer = setTimeout(() => {
24529
24764
  expired = true;
24530
24765
  const why = `the host folder did not answer ${name2} within ${ms} ms`;
@@ -24821,17 +25056,17 @@ function memoryMedia() {
24821
25056
  put: async (id2, handle) => void handles.set(id2, handle)
24822
25057
  };
24823
25058
  }
24824
- function settle2(request2, value2) {
25059
+ function settle2(request3, value2) {
24825
25060
  return new Promise((resolve2, reject) => {
24826
- request2.onsuccess = () => resolve2(value2());
24827
- request2.onerror = () => reject(request2.error);
25061
+ request3.onsuccess = () => resolve2(value2());
25062
+ request3.onerror = () => reject(request3.error);
24828
25063
  });
24829
25064
  }
24830
25065
  function openMedia(name2, factory) {
24831
- const request2 = factory.open(name2, 1);
24832
- request2.onupgradeneeded = () => request2.result.createObjectStore(MEDIA_STORE);
24833
- return settle2(request2, () => {
24834
- const db = request2.result;
25066
+ const request3 = factory.open(name2, 1);
25067
+ request3.onupgradeneeded = () => request3.result.createObjectStore(MEDIA_STORE);
25068
+ return settle2(request3, () => {
25069
+ const db = request3.result;
24835
25070
  const store = (mode) => db.transaction(MEDIA_STORE, mode).objectStore(MEDIA_STORE);
24836
25071
  return {
24837
25072
  get: (id2) => {
@@ -24864,14 +25099,14 @@ var ChunkedBytes = class {
24864
25099
  }
24865
25100
  write(offset, bytes, owned4 = false) {
24866
25101
  const whole = owned4 && bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength;
24867
- for (let done4 = 0; done4 < bytes.length; ) {
24868
- const at = offset + done4;
25102
+ for (let done5 = 0; done5 < bytes.length; ) {
25103
+ const at = offset + done5;
24869
25104
  const index = Math.floor(at / CHUNK3);
24870
25105
  const from = at - index * CHUNK3;
24871
- const n = Math.min(CHUNK3 - from, bytes.length - done4);
25106
+ const n = Math.min(CHUNK3 - from, bytes.length - done5);
24872
25107
  if (whole && n === CHUNK3 && bytes.length === CHUNK3) this.chunks[index] = bytes;
24873
- else this.room(index, from + n).set(bytes.subarray(done4, done4 + n), from);
24874
- done4 += n;
25108
+ else this.room(index, from + n).set(bytes.subarray(done5, done5 + n), from);
25109
+ done5 += n;
24875
25110
  }
24876
25111
  this.size = Math.max(this.size, offset + bytes.length);
24877
25112
  }
@@ -25375,9 +25610,9 @@ function parseArgs(args) {
25375
25610
  break;
25376
25611
  }
25377
25612
  if (!arg.startsWith("-") || arg === "-") break;
25378
- const used = flags(parsed2, arg, args[i + 1]);
25379
- if (typeof used === "string") return used;
25380
- i += used;
25613
+ const used2 = flags(parsed2, arg, args[i + 1]);
25614
+ if (typeof used2 === "string") return used2;
25615
+ i += used2;
25381
25616
  }
25382
25617
  parsed2.command = args.slice(i);
25383
25618
  if (parsed2.list ? parsed2.command.length > 0 : parsed2.command.length === 0) return USAGE;
@@ -26407,9 +26642,9 @@ var Launcher = class {
26407
26642
  const known = this.sameFiles.get(`${a}|${b}`);
26408
26643
  if (known?.stamp === stamp) return known.same;
26409
26644
  const [p, q] = await Promise.all([this.base.readFileBuffer(a), this.base.readFileBuffer(b)]);
26410
- const same = p.length === q.length && p.every((byte, i) => byte === q[i]);
26411
- this.sameFiles.set(`${a}|${b}`, { stamp, same });
26412
- return same;
26645
+ const same2 = p.length === q.length && p.every((byte, i) => byte === q[i]);
26646
+ this.sameFiles.set(`${a}|${b}`, { stamp, same: same2 });
26647
+ return same2;
26413
26648
  }
26414
26649
  async wasmOwner(wasm, name2, scope) {
26415
26650
  const leaf = baseName2(wasm);
@@ -26702,10 +26937,10 @@ var Launcher = class {
26702
26937
  const drop = () => {
26703
26938
  if (cache.get(key) === found) cache.delete(key);
26704
26939
  };
26705
- loading2.then((done4) => {
26706
- if (done4.key === key || done4.key === void 0 && !key.includes("\0")) return;
26940
+ loading2.then((done5) => {
26941
+ if (done5.key === key || done5.key === void 0 && !key.includes("\0")) return;
26707
26942
  drop();
26708
- if (done4.key !== void 0 && revocations === this.revocations) cache.set(done4.key, found);
26943
+ if (done5.key !== void 0 && revocations === this.revocations) cache.set(done5.key, found);
26709
26944
  }, drop);
26710
26945
  return found;
26711
26946
  }
@@ -26850,17 +27085,17 @@ var Launcher = class {
26850
27085
  await req.fds.closeAll();
26851
27086
  throw err;
26852
27087
  }
26853
- const done4 = this.heldUrl(program);
27088
+ const done5 = this.heldUrl(program);
26854
27089
  try {
26855
27090
  const handle = await this.admitted(
26856
27091
  program.abi !== "js",
26857
27092
  req.fds,
26858
27093
  (fds, quietOom) => this.start({ ...req, fds, quietOom, cwd, program, argv0: target.argv0, args, env })
26859
27094
  );
26860
- void handle.exited.finally(done4);
27095
+ void handle.exited.finally(done5);
26861
27096
  return handle;
26862
27097
  } catch (err) {
26863
- done4();
27098
+ done5();
26864
27099
  throw err;
26865
27100
  }
26866
27101
  }
@@ -27403,8 +27638,8 @@ var Launcher = class {
27403
27638
  const at = normalizePath(path);
27404
27639
  this.unlinked.closed(at);
27405
27640
  this.writers?.unlinked.closed(at);
27406
- const open = [...this.openFiles].some((nodes) => nodes.writes(at)) || heldUnder(this.held, at);
27407
- if (!open) void this.mounts.commit(at).catch(() => void 0);
27641
+ const open2 = [...this.openFiles].some((nodes) => nodes.writes(at)) || heldUnder(this.held, at);
27642
+ if (!open2) void this.mounts.commit(at).catch(() => void 0);
27408
27643
  }
27409
27644
  signalMasksOf(pid) {
27410
27645
  const masks = this.processes.get(pid)?.signalMasks?.();
@@ -27860,7 +28095,7 @@ var Launcher = class {
27860
28095
  (path) => this.mountRoot(path),
27861
28096
  {
27862
28097
  locks: webLocks(),
27863
- busy: (path) => [...this.openFiles].some((open) => open.holds(path)),
28098
+ busy: (path) => [...this.openFiles].some((open2) => open2.holds(path)),
27864
28099
  owner: this.unlinkOwnerOption,
27865
28100
  ...this.owners ? { dirOwner: { uid: 0, gid: 0, mode: 448 } } : {}
27866
28101
  }
@@ -28027,11 +28262,11 @@ function cronLocks() {
28027
28262
  // src/pin.ts
28028
28263
  function pinScript(url) {
28029
28264
  try {
28030
- const request2 = new XMLHttpRequest();
28031
- request2.open("GET", url.href, false);
28032
- request2.send();
28033
- if (request2.status !== 200) return url.href;
28034
- const source = `${request2.responseText}
28265
+ const request3 = new XMLHttpRequest();
28266
+ request3.open("GET", url.href, false);
28267
+ request3.send();
28268
+ if (request3.status !== 200) return url.href;
28269
+ const source = `${request3.responseText}
28035
28270
  //# sourceURL=${url.href}
28036
28271
  `;
28037
28272
  return URL.createObjectURL(new Blob([source], { type: "text/javascript" }));
@@ -28184,9 +28419,9 @@ var RemoteTransport = class {
28184
28419
  waiter?.reject(new TransportError("the request was cancelled"));
28185
28420
  this.port.postMessage({ net: "cancel", nid });
28186
28421
  }
28187
- async fetch(request2) {
28422
+ async fetch(request3) {
28188
28423
  const nid = ++this.nextId;
28189
- const { signal } = request2;
28424
+ const { signal } = request3;
28190
28425
  signal.throwIfAborted();
28191
28426
  let finished = false;
28192
28427
  const abort = () => {
@@ -28201,16 +28436,16 @@ var RemoteTransport = class {
28201
28436
  finished = true;
28202
28437
  signal.removeEventListener("abort", abort);
28203
28438
  };
28204
- if (request2.bodyStream) this.uploads.set(nid, request2.bodyStream[Symbol.asyncIterator]());
28439
+ if (request3.bodyStream) this.uploads.set(nid, request3.bodyStream[Symbol.asyncIterator]());
28205
28440
  let head;
28206
28441
  try {
28207
28442
  head = await this.ask({
28208
28443
  net: "fetch",
28209
28444
  nid,
28210
- url: request2.url,
28211
- method: request2.method,
28212
- headers: request2.headers,
28213
- ...request2.bodyStream ? { streamed: true } : request2.body ? { body: request2.body } : {}
28445
+ url: request3.url,
28446
+ method: request3.method,
28447
+ headers: request3.headers,
28448
+ ...request3.bodyStream ? { streamed: true } : request3.body ? { body: request3.body } : {}
28214
28449
  });
28215
28450
  } catch (e) {
28216
28451
  finish();
@@ -28253,9 +28488,9 @@ var RemoteTransport = class {
28253
28488
  }
28254
28489
  };
28255
28490
  }
28256
- async websocket(request2) {
28491
+ async websocket(request3) {
28257
28492
  const nid = ++this.nextId;
28258
- const { signal } = request2;
28493
+ const { signal } = request3;
28259
28494
  signal.throwIfAborted();
28260
28495
  const abort = () => this.cancel(nid);
28261
28496
  signal.addEventListener("abort", abort, { once: true });
@@ -28264,9 +28499,9 @@ var RemoteTransport = class {
28264
28499
  opened2 = await this.ask({
28265
28500
  net: "ws-open",
28266
28501
  nid,
28267
- url: request2.url,
28268
- protocols: request2.protocols,
28269
- headers: request2.headers
28502
+ url: request3.url,
28503
+ protocols: request3.protocols,
28504
+ headers: request3.headers
28270
28505
  });
28271
28506
  } finally {
28272
28507
  signal.removeEventListener("abort", abort);
@@ -28336,6 +28571,12 @@ async function inOpfs(deps, root) {
28336
28571
  const opfs = await deps.storage().catch(() => void 0);
28337
28572
  return await opfs?.resolve(root).catch(() => null) != null;
28338
28573
  }
28574
+ async function rootNamed(deps, req, root) {
28575
+ if (req.metadata !== void 0 || !req.root || !deps.rootId) return req;
28576
+ const top = await deps.storage().catch(() => void 0);
28577
+ const name2 = await metadataName(top, root, deps.rootId);
28578
+ return name2 === META_DB ? req : { ...req, metadata: name2 };
28579
+ }
28339
28580
  function workers(deps) {
28340
28581
  return {
28341
28582
  createWorker: deps.createWorker,
@@ -28380,7 +28621,7 @@ function cdpOption(req, port) {
28380
28621
  if (!req.cdp) return {};
28381
28622
  return {
28382
28623
  cdp: portCdpHook(
28383
- (request2, cdp) => port.postMessage({ cdpOpen: request2, port: cdp }, [cdp])
28624
+ (request3, cdp) => port.postMessage({ cdpOpen: request3, port: cdp }, [cdp])
28384
28625
  )
28385
28626
  };
28386
28627
  }
@@ -28390,7 +28631,7 @@ function pageHooks(req, port) {
28390
28631
  function facadesOption(req, port) {
28391
28632
  if (!req.facades) return {};
28392
28633
  const hook = portFacadeHook(
28393
- (request2, facade) => port.postMessage({ facadeOpen: request2, port: facade }, [facade])
28634
+ (request3, facade) => port.postMessage({ facadeOpen: request3, port: facade }, [facade])
28394
28635
  );
28395
28636
  const facades = {};
28396
28637
  for (const [name2, spec] of Object.entries(req.facades)) {
@@ -28592,6 +28833,7 @@ function serveKernel(port, deps) {
28592
28833
  }
28593
28834
  async function init(req) {
28594
28835
  launcher = (req.root ? Promise.resolve(req.root) : deps.storage()).then(async (root) => {
28836
+ req = await rootNamed(deps, req, root);
28595
28837
  const name2 = req.metadata ?? META_DB;
28596
28838
  const { meta, media } = await stores(deps, name2, req.media);
28597
28839
  const net = remotes(port, req);
@@ -28699,6 +28941,7 @@ serveKernel(globalThis, {
28699
28941
  createDriverWorker: () => new Worker(driverWorker, { type: "module" }),
28700
28942
  moduleUrl: blobModuleUrl,
28701
28943
  metadata: (name2) => openMeta(name2, indexedDB),
28702
- media: (name2) => openMedia(name2, indexedDB)
28944
+ media: (name2) => openMedia(name2, indexedDB),
28945
+ rootId: (root) => rootId(indexedDB, root)
28703
28946
  });
28704
28947
  //# sourceMappingURL=kernel-worker.js.map