@ai-ecoverse/slicc-kernel 1.129.0 → 1.130.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.
@@ -636,8 +636,8 @@ var Integrity = class {
636
636
  }
637
637
  }
638
638
  async expected(path) {
639
- const answer = await this.lookup(path);
640
- return typeof answer === "string" ? answer.toLowerCase() : void 0;
639
+ const answer2 = await this.lookup(path);
640
+ return typeof answer2 === "string" ? answer2.toLowerCase() : void 0;
641
641
  }
642
642
  say(event) {
643
643
  try {
@@ -890,10 +890,12 @@ var RemoteWatch = class {
890
890
  quiet;
891
891
  crowd;
892
892
  told;
893
+ counted = 0;
893
894
  recount() {
894
895
  const now = this.crowded();
895
- if (now === this.told) return;
896
+ if (now === this.told && this.peers.size === this.counted) return;
896
897
  this.told = now;
898
+ this.counted = this.peers.size;
897
899
  this.crowd?.(now);
898
900
  }
899
901
  constructor(name2, options = {}) {
@@ -983,12 +985,12 @@ var RemoteWatch = class {
983
985
  }
984
986
  greeted(peer) {
985
987
  this.arrived(peer);
986
- const answer = () => {
988
+ const answer2 = () => {
987
989
  this.channel.postMessage({ here: this.tab, to: peer });
988
990
  if (this.mine.length > 0) void this.announce(this.mine);
989
991
  };
990
- if (this.quiet) void this.quiet().then(answer, answer);
991
- else answer();
992
+ if (this.quiet) void this.quiet().then(answer2, answer2);
993
+ else answer2();
992
994
  }
993
995
  announced({ tab, paths, seq: seq2 }) {
994
996
  const from = tab;
@@ -7020,7 +7022,7 @@ function satisfies(version, range2) {
7020
7022
  }
7021
7023
 
7022
7024
  // src/version.ts
7023
- var KERNEL_VERSION = true ? "1.129.0" : "0.0.0-dev";
7025
+ var KERNEL_VERSION = true ? "1.130.1" : "0.0.0-dev";
7024
7026
  var OS_RELEASE = "6.0.0-slicc";
7025
7027
  function procVersion() {
7026
7028
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -9414,6 +9416,9 @@ var FileChanges = class {
9414
9416
  foreign(on) {
9415
9417
  Atomics.store(this.view, FOREIGN, on ? 1 : 0);
9416
9418
  }
9419
+ flush() {
9420
+ Atomics.add(this.view, GEN, RING_SIZE + 1);
9421
+ }
9417
9422
  publish(...paths) {
9418
9423
  for (const path of paths) {
9419
9424
  const g = Atomics.add(this.view, GEN, 1) + 1 | 0;
@@ -16336,11 +16341,11 @@ function carriesUdp(uplink) {
16336
16341
  return uplink.traits.udp === true && typeof uplink.udp === "function";
16337
16342
  }
16338
16343
  function answerOf(result) {
16339
- const answer = Array.isArray(result) ? { addresses: result } : result;
16340
- const addresses = Array.isArray(answer?.addresses) ? answer.addresses.filter((a) => typeof a === "string") : [];
16344
+ const answer2 = Array.isArray(result) ? { addresses: result } : result;
16345
+ const addresses = Array.isArray(answer2?.addresses) ? answer2.addresses.filter((a) => typeof a === "string") : [];
16341
16346
  return {
16342
16347
  addresses,
16343
- ...typeof answer?.ttl === "number" && answer.ttl >= 0 ? { ttl: answer.ttl } : {}
16348
+ ...typeof answer2?.ttl === "number" && answer2.ttl >= 0 ? { ttl: answer2.ttl } : {}
16344
16349
  };
16345
16350
  }
16346
16351
  var NEVER = new Routes(true);
@@ -16528,9 +16533,9 @@ var Resolver = class {
16528
16533
  async lookup(name2, family, id2, abandoned) {
16529
16534
  const uplink = this.uplink;
16530
16535
  const timeout = AbortSignal.any([AbortSignal.timeout(this.timeoutMs), abandoned]);
16531
- let answer;
16536
+ let answer2;
16532
16537
  try {
16533
- answer = answerOf(
16538
+ answer2 = answerOf(
16534
16539
  await Promise.race([
16535
16540
  uplink.resolve(name2, family, timeout),
16536
16541
  new Promise(
@@ -16541,8 +16546,8 @@ var Resolver = class {
16541
16546
  } catch {
16542
16547
  return [];
16543
16548
  }
16544
- const addresses = answer.addresses.filter((a) => this.usable(name2, a, family));
16545
- if (addresses.length > 0) this.remember(id2, addresses, answer.ttl);
16549
+ const addresses = answer2.addresses.filter((a) => this.usable(name2, a, family));
16550
+ if (addresses.length > 0) this.remember(id2, addresses, answer2.ttl);
16546
16551
  return addresses;
16547
16552
  }
16548
16553
  usable(name2, address, family) {
@@ -21198,8 +21203,8 @@ var WasmProcess = class {
21198
21203
  spares(sig) {
21199
21204
  const { caught, ignored } = this.signalMasks();
21200
21205
  const bit = isSignal(sig) ? sigbit(sig) : 0;
21201
- const answer = (ignored & bit) !== 0 ? "ignore" : (caught & bit) !== 0 ? "spare" : "terminate";
21202
- return { ok: true, kind: "json", json: answer };
21206
+ const answer2 = (ignored & bit) !== 0 ? "ignore" : (caught & bit) !== 0 ? "spare" : "terminate";
21207
+ return { ok: true, kind: "json", json: answer2 };
21203
21208
  }
21204
21209
  async killSelf(sig, target, probe) {
21205
21210
  if (!this.options.exitSignal) throw new KernelError("ENOSYS");
@@ -22316,10 +22321,10 @@ var WasmProcess = class {
22316
22321
  cwd: typeof req.cwd === "string" && req.cwd.startsWith("/") ? req.cwd : "/",
22317
22322
  ...typeof req.term === "string" ? { term: req.term } : {}
22318
22323
  };
22319
- const answer = await sudo(call, this.blockingSignal(cancelled));
22320
- if (!("grant" in answer)) return answer;
22324
+ const answer2 = await sudo(call, this.blockingSignal(cancelled));
22325
+ if (!("grant" in answer2)) return answer2;
22321
22326
  if (this.dying) throw new KernelError("EINTR");
22322
- const { file, argv, env, cwd, cred, caller } = answer.grant;
22327
+ const { file, argv, env, cwd, cred, caller } = answer2.grant;
22323
22328
  const stdio = [{ fd: 0 }, { fd: 1 }, { fd: 2 }];
22324
22329
  return {
22325
22330
  pid: await this.children.spawn({ file, argv, env, cwd, pgid: 0 }, stdio, [], {
@@ -22479,6 +22484,153 @@ var WASM_THREAD_SPAWN = "wasm-thread-spawn";
22479
22484
  var WASM_THREAD_INIT = "wasm-thread-init";
22480
22485
  var WASM_THREAD_EXIT = "wasm-thread-exit";
22481
22486
  var WASM_MAX_THREADS = 256;
22487
+ var JS_THREAD_SPAWN = "js-thread-spawn";
22488
+ var JS_THREAD_INIT = "js-thread-init";
22489
+ var JS_THREAD_EXIT = "js-thread-exit";
22490
+ var JS_MAX_THREADS = 256;
22491
+ var JS_DEFAULT_THREADS = 16;
22492
+ var JS_THREAD_NO_MEMORY = 256;
22493
+ var JS_THREAD_CRASHED = 257;
22494
+
22495
+ // src/kernel/js-threads.ts
22496
+ var JS_OOM = /out of memory|Array buffer allocation failed|Cannot allocate Wasm memory|could not allocate memory|ERR_WORKER_OUT_OF_MEMORY/i;
22497
+ var ENDING = { ok: false, errno: "EINTR", message: "the thread is ending" };
22498
+ var MAIN_ONLY = { ok: true, kind: "void" };
22499
+ function track(ops, req, result) {
22500
+ if (req.op === "async-submit" && result.ok && result.kind === "json") {
22501
+ if (typeof result.json === "number") ops.set(result.json, req.token);
22502
+ } else if (req.op === "async-cancel" || req.op === "async-take" && (result.ok || result.errno !== "EAGAIN")) {
22503
+ ops.delete(req.id);
22504
+ }
22505
+ }
22506
+ function cores() {
22507
+ const n = globalThis.navigator?.hardwareConcurrency;
22508
+ return typeof n === "number" && Number.isInteger(n) && n > 0 ? n : 0;
22509
+ }
22510
+ function jsThreadCap(env) {
22511
+ const asked = Number.parseInt(env.SLICC_JS_THREADS ?? "", 10);
22512
+ if (asked >= 1) return Math.min(asked, JS_MAX_THREADS);
22513
+ return Math.min(JS_MAX_THREADS, Math.max(JS_DEFAULT_THREADS, 2 * cores()));
22514
+ }
22515
+ function codeOf4(code) {
22516
+ if (code === JS_THREAD_NO_MEMORY || code === JS_THREAD_CRASHED) return code;
22517
+ return typeof code === "number" && Number.isInteger(code) ? code & 255 : JS_THREAD_CRASHED;
22518
+ }
22519
+ function answer(control, message3) {
22520
+ control.postMessage(message3);
22521
+ }
22522
+ var JsThreads = class {
22523
+ deps;
22524
+ live = /* @__PURE__ */ new Map();
22525
+ headers = /* @__PURE__ */ new Map();
22526
+ frozen = false;
22527
+ last = 0;
22528
+ closed = false;
22529
+ constructor(deps) {
22530
+ this.deps = deps;
22531
+ }
22532
+ get size() {
22533
+ return this.live.size;
22534
+ }
22535
+ spawn(msg) {
22536
+ const { control, port } = msg;
22537
+ if (this.closed || this.live.size >= this.deps.cap) {
22538
+ answer(
22539
+ control,
22540
+ this.closed ? { errno: "ESRCH", message: "the process is ending" } : { errno: "EAGAIN", message: `more than ${this.deps.cap} threads` }
22541
+ );
22542
+ control.close();
22543
+ port.close();
22544
+ return;
22545
+ }
22546
+ const tid = ++this.last;
22547
+ const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
22548
+ const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
22549
+ if (this.frozen) Atomics.store(header3, SAB_I_STOP, 1);
22550
+ const worker = this.deps.createWorker();
22551
+ const clock = this.deps.clocks.thread(tid + 1, sab);
22552
+ let ended = false;
22553
+ const end = (code) => {
22554
+ if (ended) return;
22555
+ ended = true;
22556
+ this.live.delete(tid);
22557
+ this.headers.delete(tid);
22558
+ this.deps.wakes.delete(header3);
22559
+ for (const [id2, token] of ops) {
22560
+ void this.deps.dispatch({ op: "async-cancel", id: id2, token });
22561
+ }
22562
+ ops.clear();
22563
+ worker.removeEventListener("message", onMessage);
22564
+ worker.removeEventListener("error", onError);
22565
+ control.removeEventListener("message", onControl);
22566
+ responder.dispose();
22567
+ lane.dispose();
22568
+ this.deps.clocks.threadEnded(tid + 1);
22569
+ worker.terminate();
22570
+ answer(control, { exited: code });
22571
+ control.close();
22572
+ };
22573
+ const ops = /* @__PURE__ */ new Map();
22574
+ const dispatch2 = async (req, block) => {
22575
+ if (isWasmSyscall(req) && req.op === "proc-exit") {
22576
+ queueMicrotask(() => end(req.status & 255));
22577
+ return ENDING;
22578
+ }
22579
+ if (isWasmSyscall(req) && req.op === "sig-mask") return MAIN_ONLY;
22580
+ const result = await this.deps.dispatch(req, block);
22581
+ if (!ended) track(ops, req, result);
22582
+ return result;
22583
+ };
22584
+ const responder = this.deps.attach(worker, sab, this.deps.clocks.timed(clock, dispatch2));
22585
+ const lane = this.deps.openLane(dispatch2);
22586
+ const onMessage = (event) => {
22587
+ const data = event.data;
22588
+ if (data?.type === JS_THREAD_EXIT) end(codeOf4(data.code));
22589
+ else if (data?.type === JS_THREAD_SPAWN) this.spawn(event.data);
22590
+ else if (data?.type === WASM_PROCESS_ERROR) this.crashed(String(data.message), end);
22591
+ };
22592
+ const onError = (event) => {
22593
+ event.preventDefault();
22594
+ this.crashed(String(event.message ?? "worker error"), end);
22595
+ };
22596
+ const onControl = (event) => {
22597
+ if (event.data?.terminate === true) end(1);
22598
+ };
22599
+ worker.addEventListener("message", onMessage);
22600
+ worker.addEventListener("error", onError);
22601
+ control.addEventListener("message", onControl);
22602
+ control.start();
22603
+ this.live.set(tid, end);
22604
+ this.headers.set(tid, header3);
22605
+ this.deps.wakes.add(header3);
22606
+ const init = {
22607
+ ...this.deps.init(sab, lane.lane),
22608
+ type: JS_THREAD_INIT,
22609
+ thread: { tid, port, data: msg.data }
22610
+ };
22611
+ try {
22612
+ worker.postMessage(init, [lane.lane.port, port, ...msg.transfer ?? []]);
22613
+ } catch {
22614
+ end(JS_THREAD_CRASHED);
22615
+ return;
22616
+ }
22617
+ answer(control, { tid });
22618
+ }
22619
+ crashed(message3, end) {
22620
+ end(JS_OOM.test(message3) ? JS_THREAD_NO_MEMORY : JS_THREAD_CRASHED);
22621
+ }
22622
+ stopped(stopped) {
22623
+ this.frozen = stopped;
22624
+ for (const header3 of this.headers.values()) {
22625
+ Atomics.store(header3, SAB_I_STOP, stopped ? 1 : 0);
22626
+ Atomics.notify(header3, SAB_I_STOP);
22627
+ }
22628
+ }
22629
+ close() {
22630
+ this.closed = true;
22631
+ for (const end of [...this.live.values()]) end(1);
22632
+ }
22633
+ };
22482
22634
 
22483
22635
  // src/kernel/host.ts
22484
22636
  var CRASHED = 70;
@@ -22581,6 +22733,7 @@ function threadSignalsOf(sab) {
22581
22733
  function threadCancel(thread) {
22582
22734
  return unblocked(thread.header) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
22583
22735
  }
22736
+ var asyncFanout = /* @__PURE__ */ new WeakMap();
22584
22737
  function notifiers(header3) {
22585
22738
  return {
22586
22739
  onPending(sig) {
@@ -22588,8 +22741,10 @@ function notifiers(header3) {
22588
22741
  Atomics.notify(header3, SAB_I_SIGNALS);
22589
22742
  },
22590
22743
  onAsync() {
22591
- Atomics.add(header3, SAB_I_ASYNC, 1);
22592
- Atomics.notify(header3, SAB_I_ASYNC);
22744
+ for (const at of [header3, ...asyncFanout.get(header3) ?? []]) {
22745
+ Atomics.add(at, SAB_I_ASYNC, 1);
22746
+ Atomics.notify(at, SAB_I_ASYNC);
22747
+ }
22593
22748
  }
22594
22749
  };
22595
22750
  }
@@ -22820,6 +22975,7 @@ function spawnWasmProcess(opts) {
22820
22975
  dispatch: clocks.timed(void 0, dispatch2)
22821
22976
  });
22822
22977
  const lane = opts.program.abi === "js" ? openLane(token, dispatch2) : void 0;
22978
+ const jsThreads = jsThreadsOf(opts, process, token, dispatch2, clocks, header3);
22823
22979
  const { promise: exited, resolve: settle3 } = Promise.withResolvers();
22824
22980
  let done5 = false;
22825
22981
  let endedBy;
@@ -22833,6 +22989,7 @@ function spawnWasmProcess(opts) {
22833
22989
  worker.removeEventListener("message", onMessage);
22834
22990
  worker.removeEventListener("error", onError);
22835
22991
  for (const tid of [...threads.keys()]) endThread(tid);
22992
+ jsThreads?.close();
22836
22993
  responder.dispose();
22837
22994
  lane?.dispose();
22838
22995
  revokeSyncFsToken(token);
@@ -22856,6 +23013,8 @@ function spawnWasmProcess(opts) {
22856
23013
  finish(...dying.status(data.code));
22857
23014
  } else if (data?.type === WASM_THREAD_SPAWN && data.thread) {
22858
23015
  spawnThread(data.thread);
23016
+ } else if (data?.type === JS_THREAD_SPAWN && jsThreads) {
23017
+ jsThreads.spawn(data);
22859
23018
  }
22860
23019
  };
22861
23020
  const onMessage = (event) => handle(event.data);
@@ -22929,13 +23088,35 @@ function spawnWasmProcess(opts) {
22929
23088
  termsig: () => endedBy,
22930
23089
  onState: (listener) => process.onState(listener),
22931
23090
  memory: () => Atomics.load(header3, SAB_I_MEMORY) * 65536,
23091
+ ...processViews(process, opts, header3),
23092
+ writesBack: () => opts.program.abi === "wasi" && !done5,
23093
+ ...clockViews(clocks)
23094
+ };
23095
+ }
23096
+ function jsThreadsOf(opts, process, token, dispatch2, clocks, header3) {
23097
+ if (opts.program.abi !== "js") return void 0;
23098
+ const wakes = /* @__PURE__ */ new Set();
23099
+ asyncFanout.set(header3, wakes);
23100
+ const threads = new JsThreads({
23101
+ wakes,
23102
+ cap: jsThreadCap(opts.env),
23103
+ createWorker: opts.createWorker,
23104
+ init: (sab, lane) => processInit(opts, sab, process.umask, copyCred(process.cred), lane),
23105
+ openLane: (laneDispatch) => openLane(token, laneDispatch),
23106
+ attach: (worker, sab, threadDispatch) => attachSyncSabResponder(worker, sab, token, { dispatch: threadDispatch }),
23107
+ dispatch: dispatch2,
23108
+ clocks
23109
+ });
23110
+ process.onState((state) => threads.stopped(state === "stopped"));
23111
+ return threads;
23112
+ }
23113
+ function processViews(process, opts, header3) {
23114
+ return {
22932
23115
  ignoredSignals: (fork) => process.inheritable(fork),
22933
23116
  blockedSignals: () => opts.program.abi === "wasi" ? loadBlocked(header3) : [0, 0],
22934
23117
  signalMasks: () => process.signalMasks(),
22935
23118
  umask: () => process.umask,
22936
- cred: () => copyCred(process.cred),
22937
- writesBack: () => opts.program.abi === "wasi" && !done5,
22938
- ...clockViews(clocks)
23119
+ cred: () => copyCred(process.cred)
22939
23120
  };
22940
23121
  }
22941
23122
  function clockViews(clocks) {
@@ -24253,8 +24434,8 @@ var FSA_CAPABILITIES = {
24253
24434
  ranges: true,
24254
24435
  sessions: true
24255
24436
  };
24256
- var codeOf4 = (err) => err?.code;
24257
- var denied = (err) => codeOf4(err) === "EACCES" || err?.name === "NotAllowedError";
24437
+ var codeOf5 = (err) => err?.code;
24438
+ var denied = (err) => codeOf5(err) === "EACCES" || err?.name === "NotAllowedError";
24258
24439
  function attrOf(st) {
24259
24440
  return {
24260
24441
  kind: st.isDirectory ? "directory" : st.isSymbolicLink ? "symlink" : "file",
@@ -24276,7 +24457,7 @@ function kernelFsHandlers(fs) {
24276
24457
  try {
24277
24458
  return await fs.stat(path);
24278
24459
  } catch (err) {
24279
- if (codeOf4(err) === "ENOENT") return void 0;
24460
+ if (codeOf5(err) === "ENOENT") return void 0;
24280
24461
  throw err;
24281
24462
  }
24282
24463
  }
@@ -24469,7 +24650,7 @@ function parseFstab(text) {
24469
24650
  });
24470
24651
  return lines2;
24471
24652
  }
24472
- function codeOf5(err) {
24653
+ function codeOf6(err) {
24473
24654
  const code = err?.code;
24474
24655
  return typeof code === "string" ? code : "EIO";
24475
24656
  }
@@ -24507,18 +24688,18 @@ async function mountLine({ line, spec, invalid }, mount, signal, retries, discar
24507
24688
  break;
24508
24689
  } catch (err) {
24509
24690
  failed3 = err;
24510
- if (FINAL.has(codeOf5(err)) || attempt === retries.length) break;
24691
+ if (FINAL.has(codeOf6(err)) || attempt === retries.length) break;
24511
24692
  await wait(retries[attempt], signal);
24512
24693
  }
24513
24694
  }
24514
- const code = codeOf5(failed3);
24695
+ const code = codeOf6(failed3);
24515
24696
  return { line, target: spec.target, code, error: String(failed3?.message ?? code) };
24516
24697
  }
24517
24698
 
24518
24699
  // src/mount/hostfs.ts
24519
24700
  var HOSTFS_IO = 16 * 1024 * 1024;
24520
- var codeOf6 = (err) => err?.code;
24521
- var unreachable = (err) => codeOf6(err) === "ENOTCONN";
24701
+ var codeOf7 = (err) => err?.code;
24702
+ var unreachable = (err) => codeOf7(err) === "ENOTCONN";
24522
24703
  function rel(path) {
24523
24704
  return path.replace(/^\/+/, "");
24524
24705
  }
@@ -24695,7 +24876,7 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
24695
24876
  try {
24696
24877
  return { opened: await opening2(), restore: void 0 };
24697
24878
  } catch (err) {
24698
- if (!flags2.write || codeOf6(err) !== "EACCES") throw err;
24879
+ if (!flags2.write || codeOf7(err) !== "EACCES") throw err;
24699
24880
  const was = await client.call("stat", { path: rel(path) });
24700
24881
  const mode = was.mode ?? 0;
24701
24882
  if (mode & 128) throw err;
@@ -25915,14 +26096,14 @@ var Sudo = class {
25915
26096
  if (this.pending.has(cred.ruid)) return failed2("EBUSY", "sudo: another request is pending");
25916
26097
  this.pending.add(cred.ruid);
25917
26098
  try {
25918
- const answer = await this.ask(caller, self, target, parsed2.command, path, cwd, signal);
25919
- if (typeof answer !== "string") return answer;
26099
+ const answer2 = await this.ask(caller, self, target, parsed2.command, path, cwd, signal);
26100
+ if (typeof answer2 !== "string") return answer2;
25920
26101
  if (await this.canonical(call.cwd) !== cwd || !await this.reachable(cred, cwd)) {
25921
26102
  return failed2("EACCES", `sudo: ${call.cwd} changed while the request waited`);
25922
26103
  }
25923
26104
  const changed = await this.untrusted(path, cwd, word);
25924
26105
  if (changed) return changed;
25925
- if (answer === "always" && !await this.remember(self, target, cwd, argv)) {
26106
+ if (answer2 === "always" && !await this.remember(self, target, cwd, argv)) {
25926
26107
  return failed2("EIO", "sudo: the rule could not be recorded");
25927
26108
  }
25928
26109
  return grant();
@@ -25977,11 +26158,11 @@ ${lines2}
25977
26158
  );
25978
26159
  try {
25979
26160
  const answered2 = Promise.resolve().then(() => approve(req, { signal: control.signal })).catch(() => "deny");
25980
- const answer = await Promise.race([answered2, aborted2]);
25981
- if (answer === "aborted" || control.signal.aborted) {
26161
+ const answer2 = await Promise.race([answered2, aborted2]);
26162
+ if (answer2 === "aborted" || control.signal.aborted) {
25982
26163
  return control.signal.reason === "expired" ? failed2("ETIMEDOUT", "sudo: the request expired") : failed2("EINTR", "sudo: the request was withdrawn");
25983
26164
  }
25984
- return answer === "once" || answer === "always" ? answer : failed2("EACCES", "sudo: approval denied");
26165
+ return answer2 === "once" || answer2 === "always" ? answer2 : failed2("EACCES", "sudo: approval denied");
25985
26166
  } finally {
25986
26167
  clearTimeout(timer);
25987
26168
  requester.removeEventListener("abort", withdraw);
@@ -26393,9 +26574,7 @@ var Launcher = class {
26393
26574
  this.usersMode = usersMode(options.users);
26394
26575
  this.memories = memoriesOf(options.wasmMemories);
26395
26576
  this.rootFs = options.fs;
26396
- const peers = options.fs.peers?.();
26397
- this.locks = kernelLocks(options.fs.rootName, peers);
26398
- peers?.watch((crowded) => this.changes.foreign(crowded));
26577
+ this.locks = kernelLocks(options.fs.rootName, this.flushingPeers(options.fs));
26399
26578
  this.dac = this.usersMode === "off" ? void 0 : new Dac(this.usersMode, options.onDenial);
26400
26579
  if (this.dac) this.dac.tagOf = (pid) => this.tagOf(pid);
26401
26580
  this.clipboard = new ClipboardBroker(
@@ -26481,7 +26660,10 @@ var Launcher = class {
26481
26660
  this.nodes.keepsOnDisk = true;
26482
26661
  this.openFiles.add(this.nodes);
26483
26662
  options.fs.onPeer?.(() => this.flushOpen());
26484
- options.fs.remoteChanges?.((change) => this.rewritten(change.paths));
26663
+ options.fs.remoteChanges?.((change) => {
26664
+ this.changes.flush();
26665
+ this.rewritten(change.paths);
26666
+ });
26485
26667
  const holders = [this.held, this.openFiles];
26486
26668
  this.unlinked = new UnlinkedKeeper(
26487
26669
  fs,
@@ -26896,7 +27078,7 @@ var Launcher = class {
26896
27078
  try {
26897
27079
  return await this.planOne(req, ctx);
26898
27080
  } catch (err) {
26899
- const code = codeOf7(err);
27081
+ const code = codeOf8(err);
26900
27082
  const searched = bare && req.search !== false && (code === "ENOENT" || code === "ENOEXEC");
26901
27083
  if (!searched || await this.commandAt(req.file, ctx.scope)) throw err;
26902
27084
  const found = await this.onPath(req, ctx);
@@ -26913,7 +27095,7 @@ var Launcher = class {
26913
27095
  try {
26914
27096
  return await this.planOne({ ...req, file }, ctx);
26915
27097
  } catch (err) {
26916
- const code = codeOf7(err);
27098
+ const code = codeOf8(err);
26917
27099
  if (code === "EACCES") denied2 = true;
26918
27100
  else if (code !== "ENOENT" && code !== "ENOTDIR") throw err;
26919
27101
  }
@@ -26923,7 +27105,7 @@ var Launcher = class {
26923
27105
  }
26924
27106
  async planOne(req, { ppid, cred, scope }) {
26925
27107
  const refused3 = (err) => {
26926
- throw codeOf7(err) === "EACCES" ? new SpawnError("EACCES") : err;
27108
+ throw codeOf8(err) === "EACCES" ? new SpawnError("EACCES") : err;
26927
27109
  };
26928
27110
  const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused3);
26929
27111
  const planned = await this.plan(file, req.argv, req.cwd, scope, req.argv0);
@@ -28251,6 +28433,21 @@ var Launcher = class {
28251
28433
  this.writers ??= this.writerStack();
28252
28434
  return this.writers;
28253
28435
  }
28436
+ flushingPeers(fs) {
28437
+ const peers = fs.peers?.();
28438
+ if (!peers) return void 0;
28439
+ peers.watch((crowded) => {
28440
+ this.changes.flush();
28441
+ this.changes.foreign(crowded);
28442
+ });
28443
+ return {
28444
+ ...peers,
28445
+ fresh: () => {
28446
+ this.changes.flush();
28447
+ peers.fresh?.();
28448
+ }
28449
+ };
28450
+ }
28254
28451
  rewritten(paths) {
28255
28452
  for (const nodes of this.openFiles) for (const path of paths) nodes.rewritten(path);
28256
28453
  this.changes.publish(...paths);
@@ -28433,7 +28630,7 @@ var Launcher = class {
28433
28630
  function cronLocks() {
28434
28631
  return globalThis.navigator?.locks;
28435
28632
  }
28436
- function codeOf7(err) {
28633
+ function codeOf8(err) {
28437
28634
  return err?.code;
28438
28635
  }
28439
28636
 
@@ -28473,14 +28670,14 @@ function clipboardAsker(port) {
28473
28670
  await ask("write", stamp, text);
28474
28671
  }
28475
28672
  };
28476
- const answer = ({ id: id2, text, error }) => {
28673
+ const answer2 = ({ id: id2, text, error }) => {
28477
28674
  const waiting = asks.get(id2);
28478
28675
  if (!waiting) return;
28479
28676
  asks.delete(id2);
28480
28677
  if (error) waiting.reject(Object.assign(new Error(error.message), { name: error.name }));
28481
28678
  else waiting.resolve(text);
28482
28679
  };
28483
- return { hook, answer };
28680
+ return { hook, answer: answer2 };
28484
28681
  }
28485
28682
 
28486
28683
  // src/integrity-relay.ts
@@ -28494,14 +28691,14 @@ function integrityAsker(port) {
28494
28691
  port.postMessage({ integrityAsk: { id: id2, path } });
28495
28692
  return waiting.promise;
28496
28693
  };
28497
- const answer = ({ id: id2, hash, error }) => {
28694
+ const answer2 = ({ id: id2, hash, error }) => {
28498
28695
  const waiting = asks.get(id2);
28499
28696
  if (!waiting) return;
28500
28697
  asks.delete(id2);
28501
28698
  if (error !== void 0) waiting.reject(new Error(error));
28502
28699
  else waiting.resolve(hash);
28503
28700
  };
28504
- return { lookup: lookup2, answer };
28701
+ return { lookup: lookup2, answer: answer2 };
28505
28702
  }
28506
28703
 
28507
28704
  // src/kernel/net/remote-transport.ts
@@ -28725,14 +28922,14 @@ function sealedAsker(port) {
28725
28922
  port.postMessage({ sealedAsk: { id: id2, req } });
28726
28923
  return waiting.promise.finally(() => signal.removeEventListener("abort", abort));
28727
28924
  };
28728
- const answer = ({ id: id2, reply, error }) => {
28925
+ const answer2 = ({ id: id2, reply, error }) => {
28729
28926
  const waiting = asks.get(id2);
28730
28927
  if (!waiting) return;
28731
28928
  asks.delete(id2);
28732
28929
  if (reply) waiting.resolve(reply);
28733
28930
  else waiting.reject(new Error(error ?? "no reply"));
28734
28931
  };
28735
- return { hook, answer };
28932
+ return { hook, answer: answer2 };
28736
28933
  }
28737
28934
 
28738
28935
  // src/serve.ts
@@ -28845,8 +29042,8 @@ function sudoApprovals(port) {
28845
29042
  );
28846
29043
  port.postMessage({ sudoAsk: req });
28847
29044
  }),
28848
- answer({ id: id2, answer }) {
28849
- waiting.get(id2)?.(answer);
29045
+ answer({ id: id2, answer: answer2 }) {
29046
+ waiting.get(id2)?.(answer2);
28850
29047
  waiting.delete(id2);
28851
29048
  }
28852
29049
  };
@@ -28940,10 +29137,10 @@ function policyAsker(port) {
28940
29137
  return {
28941
29138
  mountPolicy: (policy) => policy === void 0 ? {} : { processMounts: policy === "ask" ? askPolicy : policy },
28942
29139
  allowed(data) {
28943
- const answer = data.mountAllowed;
28944
- if (!answer) return false;
28945
- policies.get(answer.id)?.(answer.allowed);
28946
- policies.delete(answer.id);
29140
+ const answer2 = data.mountAllowed;
29141
+ if (!answer2) return false;
29142
+ policies.get(answer2.id)?.(answer2.allowed);
29143
+ policies.delete(answer2.id);
28947
29144
  return true;
28948
29145
  }
28949
29146
  };