@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.
package/dist/node.js CHANGED
@@ -3913,8 +3913,8 @@ var Integrity = class {
3913
3913
  }
3914
3914
  }
3915
3915
  async expected(path) {
3916
- const answer = await this.lookup(path);
3917
- return typeof answer === "string" ? answer.toLowerCase() : void 0;
3916
+ const answer2 = await this.lookup(path);
3917
+ return typeof answer2 === "string" ? answer2.toLowerCase() : void 0;
3918
3918
  }
3919
3919
  say(event) {
3920
3920
  try {
@@ -4154,10 +4154,12 @@ var RemoteWatch = class {
4154
4154
  quiet;
4155
4155
  crowd;
4156
4156
  told;
4157
+ counted = 0;
4157
4158
  recount() {
4158
4159
  const now = this.crowded();
4159
- if (now === this.told) return;
4160
+ if (now === this.told && this.peers.size === this.counted) return;
4160
4161
  this.told = now;
4162
+ this.counted = this.peers.size;
4161
4163
  this.crowd?.(now);
4162
4164
  }
4163
4165
  constructor(name2, options = {}) {
@@ -4247,12 +4249,12 @@ var RemoteWatch = class {
4247
4249
  }
4248
4250
  greeted(peer) {
4249
4251
  this.arrived(peer);
4250
- const answer = () => {
4252
+ const answer2 = () => {
4251
4253
  this.channel.postMessage({ here: this.tab, to: peer });
4252
4254
  if (this.mine.length > 0) void this.announce(this.mine);
4253
4255
  };
4254
- if (this.quiet) void this.quiet().then(answer, answer);
4255
- else answer();
4256
+ if (this.quiet) void this.quiet().then(answer2, answer2);
4257
+ else answer2();
4256
4258
  }
4257
4259
  announced({ tab, paths, seq: seq2 }) {
4258
4260
  const from = tab;
@@ -7392,7 +7394,7 @@ function satisfies(version, range2) {
7392
7394
  }
7393
7395
 
7394
7396
  // src/version.ts
7395
- var KERNEL_VERSION = true ? "1.129.0" : "0.0.0-dev";
7397
+ var KERNEL_VERSION = true ? "1.130.1" : "0.0.0-dev";
7396
7398
  var OS_RELEASE = "6.0.0-slicc";
7397
7399
  function procVersion() {
7398
7400
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -9427,6 +9429,9 @@ var FileChanges = class {
9427
9429
  foreign(on) {
9428
9430
  Atomics.store(this.view, FOREIGN, on ? 1 : 0);
9429
9431
  }
9432
+ flush() {
9433
+ Atomics.add(this.view, GEN, RING_SIZE + 1);
9434
+ }
9430
9435
  publish(...paths) {
9431
9436
  for (const path of paths) {
9432
9437
  const g = Atomics.add(this.view, GEN, 1) + 1 | 0;
@@ -16301,11 +16306,11 @@ function carriesUdp(uplink) {
16301
16306
  return uplink.traits.udp === true && typeof uplink.udp === "function";
16302
16307
  }
16303
16308
  function answerOf(result) {
16304
- const answer = Array.isArray(result) ? { addresses: result } : result;
16305
- const addresses = Array.isArray(answer?.addresses) ? answer.addresses.filter((a) => typeof a === "string") : [];
16309
+ const answer2 = Array.isArray(result) ? { addresses: result } : result;
16310
+ const addresses = Array.isArray(answer2?.addresses) ? answer2.addresses.filter((a) => typeof a === "string") : [];
16306
16311
  return {
16307
16312
  addresses,
16308
- ...typeof answer?.ttl === "number" && answer.ttl >= 0 ? { ttl: answer.ttl } : {}
16313
+ ...typeof answer2?.ttl === "number" && answer2.ttl >= 0 ? { ttl: answer2.ttl } : {}
16309
16314
  };
16310
16315
  }
16311
16316
  var NEVER = new Routes(true);
@@ -16383,9 +16388,9 @@ var Resolver = class {
16383
16388
  async lookup(name2, family, id2, abandoned) {
16384
16389
  const uplink = this.uplink;
16385
16390
  const timeout = AbortSignal.any([AbortSignal.timeout(this.timeoutMs), abandoned]);
16386
- let answer;
16391
+ let answer2;
16387
16392
  try {
16388
- answer = answerOf(
16393
+ answer2 = answerOf(
16389
16394
  await Promise.race([
16390
16395
  uplink.resolve(name2, family, timeout),
16391
16396
  new Promise(
@@ -16396,8 +16401,8 @@ var Resolver = class {
16396
16401
  } catch {
16397
16402
  return [];
16398
16403
  }
16399
- const addresses = answer.addresses.filter((a) => this.usable(name2, a, family));
16400
- if (addresses.length > 0) this.remember(id2, addresses, answer.ttl);
16404
+ const addresses = answer2.addresses.filter((a) => this.usable(name2, a, family));
16405
+ if (addresses.length > 0) this.remember(id2, addresses, answer2.ttl);
16401
16406
  return addresses;
16402
16407
  }
16403
16408
  usable(name2, address, family) {
@@ -21053,8 +21058,8 @@ var WasmProcess = class {
21053
21058
  spares(sig) {
21054
21059
  const { caught, ignored } = this.signalMasks();
21055
21060
  const bit = isSignal(sig) ? sigbit(sig) : 0;
21056
- const answer = (ignored & bit) !== 0 ? "ignore" : (caught & bit) !== 0 ? "spare" : "terminate";
21057
- return { ok: true, kind: "json", json: answer };
21061
+ const answer2 = (ignored & bit) !== 0 ? "ignore" : (caught & bit) !== 0 ? "spare" : "terminate";
21062
+ return { ok: true, kind: "json", json: answer2 };
21058
21063
  }
21059
21064
  async killSelf(sig, target, probe2) {
21060
21065
  if (!this.options.exitSignal) throw new KernelError("ENOSYS");
@@ -22171,10 +22176,10 @@ var WasmProcess = class {
22171
22176
  cwd: typeof req.cwd === "string" && req.cwd.startsWith("/") ? req.cwd : "/",
22172
22177
  ...typeof req.term === "string" ? { term: req.term } : {}
22173
22178
  };
22174
- const answer = await sudo(call, this.blockingSignal(cancelled));
22175
- if (!("grant" in answer)) return answer;
22179
+ const answer2 = await sudo(call, this.blockingSignal(cancelled));
22180
+ if (!("grant" in answer2)) return answer2;
22176
22181
  if (this.dying) throw new KernelError("EINTR");
22177
- const { file, argv, env, cwd, cred, caller } = answer.grant;
22182
+ const { file, argv, env, cwd, cred, caller } = answer2.grant;
22178
22183
  const stdio = [{ fd: 0 }, { fd: 1 }, { fd: 2 }];
22179
22184
  return {
22180
22185
  pid: await this.children.spawn({ file, argv, env, cwd, pgid: 0 }, stdio, [], {
@@ -22334,6 +22339,153 @@ var WASM_THREAD_SPAWN = "wasm-thread-spawn";
22334
22339
  var WASM_THREAD_INIT = "wasm-thread-init";
22335
22340
  var WASM_THREAD_EXIT = "wasm-thread-exit";
22336
22341
  var WASM_MAX_THREADS = 256;
22342
+ var JS_THREAD_SPAWN = "js-thread-spawn";
22343
+ var JS_THREAD_INIT = "js-thread-init";
22344
+ var JS_THREAD_EXIT = "js-thread-exit";
22345
+ var JS_MAX_THREADS = 256;
22346
+ var JS_DEFAULT_THREADS = 16;
22347
+ var JS_THREAD_NO_MEMORY = 256;
22348
+ var JS_THREAD_CRASHED = 257;
22349
+
22350
+ // src/kernel/js-threads.ts
22351
+ var JS_OOM = /out of memory|Array buffer allocation failed|Cannot allocate Wasm memory|could not allocate memory|ERR_WORKER_OUT_OF_MEMORY/i;
22352
+ var ENDING = { ok: false, errno: "EINTR", message: "the thread is ending" };
22353
+ var MAIN_ONLY = { ok: true, kind: "void" };
22354
+ function track(ops, req, result) {
22355
+ if (req.op === "async-submit" && result.ok && result.kind === "json") {
22356
+ if (typeof result.json === "number") ops.set(result.json, req.token);
22357
+ } else if (req.op === "async-cancel" || req.op === "async-take" && (result.ok || result.errno !== "EAGAIN")) {
22358
+ ops.delete(req.id);
22359
+ }
22360
+ }
22361
+ function cores() {
22362
+ const n = globalThis.navigator?.hardwareConcurrency;
22363
+ return typeof n === "number" && Number.isInteger(n) && n > 0 ? n : 0;
22364
+ }
22365
+ function jsThreadCap(env) {
22366
+ const asked = Number.parseInt(env.SLICC_JS_THREADS ?? "", 10);
22367
+ if (asked >= 1) return Math.min(asked, JS_MAX_THREADS);
22368
+ return Math.min(JS_MAX_THREADS, Math.max(JS_DEFAULT_THREADS, 2 * cores()));
22369
+ }
22370
+ function codeOf4(code) {
22371
+ if (code === JS_THREAD_NO_MEMORY || code === JS_THREAD_CRASHED) return code;
22372
+ return typeof code === "number" && Number.isInteger(code) ? code & 255 : JS_THREAD_CRASHED;
22373
+ }
22374
+ function answer(control, message3) {
22375
+ control.postMessage(message3);
22376
+ }
22377
+ var JsThreads = class {
22378
+ deps;
22379
+ live = /* @__PURE__ */ new Map();
22380
+ headers = /* @__PURE__ */ new Map();
22381
+ frozen = false;
22382
+ last = 0;
22383
+ closed = false;
22384
+ constructor(deps) {
22385
+ this.deps = deps;
22386
+ }
22387
+ get size() {
22388
+ return this.live.size;
22389
+ }
22390
+ spawn(msg) {
22391
+ const { control, port } = msg;
22392
+ if (this.closed || this.live.size >= this.deps.cap) {
22393
+ answer(
22394
+ control,
22395
+ this.closed ? { errno: "ESRCH", message: "the process is ending" } : { errno: "EAGAIN", message: `more than ${this.deps.cap} threads` }
22396
+ );
22397
+ control.close();
22398
+ port.close();
22399
+ return;
22400
+ }
22401
+ const tid = ++this.last;
22402
+ const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
22403
+ const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
22404
+ if (this.frozen) Atomics.store(header4, SAB_I_STOP, 1);
22405
+ const worker = this.deps.createWorker();
22406
+ const clock = this.deps.clocks.thread(tid + 1, sab);
22407
+ let ended = false;
22408
+ const end = (code) => {
22409
+ if (ended) return;
22410
+ ended = true;
22411
+ this.live.delete(tid);
22412
+ this.headers.delete(tid);
22413
+ this.deps.wakes.delete(header4);
22414
+ for (const [id2, token] of ops) {
22415
+ void this.deps.dispatch({ op: "async-cancel", id: id2, token });
22416
+ }
22417
+ ops.clear();
22418
+ worker.removeEventListener("message", onMessage);
22419
+ worker.removeEventListener("error", onError);
22420
+ control.removeEventListener("message", onControl);
22421
+ responder.dispose();
22422
+ lane.dispose();
22423
+ this.deps.clocks.threadEnded(tid + 1);
22424
+ worker.terminate();
22425
+ answer(control, { exited: code });
22426
+ control.close();
22427
+ };
22428
+ const ops = /* @__PURE__ */ new Map();
22429
+ const dispatch2 = async (req, block) => {
22430
+ if (isWasmSyscall(req) && req.op === "proc-exit") {
22431
+ queueMicrotask(() => end(req.status & 255));
22432
+ return ENDING;
22433
+ }
22434
+ if (isWasmSyscall(req) && req.op === "sig-mask") return MAIN_ONLY;
22435
+ const result = await this.deps.dispatch(req, block);
22436
+ if (!ended) track(ops, req, result);
22437
+ return result;
22438
+ };
22439
+ const responder = this.deps.attach(worker, sab, this.deps.clocks.timed(clock, dispatch2));
22440
+ const lane = this.deps.openLane(dispatch2);
22441
+ const onMessage = (event) => {
22442
+ const data = event.data;
22443
+ if (data?.type === JS_THREAD_EXIT) end(codeOf4(data.code));
22444
+ else if (data?.type === JS_THREAD_SPAWN) this.spawn(event.data);
22445
+ else if (data?.type === WASM_PROCESS_ERROR) this.crashed(String(data.message), end);
22446
+ };
22447
+ const onError = (event) => {
22448
+ event.preventDefault();
22449
+ this.crashed(String(event.message ?? "worker error"), end);
22450
+ };
22451
+ const onControl = (event) => {
22452
+ if (event.data?.terminate === true) end(1);
22453
+ };
22454
+ worker.addEventListener("message", onMessage);
22455
+ worker.addEventListener("error", onError);
22456
+ control.addEventListener("message", onControl);
22457
+ control.start();
22458
+ this.live.set(tid, end);
22459
+ this.headers.set(tid, header4);
22460
+ this.deps.wakes.add(header4);
22461
+ const init = {
22462
+ ...this.deps.init(sab, lane.lane),
22463
+ type: JS_THREAD_INIT,
22464
+ thread: { tid, port, data: msg.data }
22465
+ };
22466
+ try {
22467
+ worker.postMessage(init, [lane.lane.port, port, ...msg.transfer ?? []]);
22468
+ } catch {
22469
+ end(JS_THREAD_CRASHED);
22470
+ return;
22471
+ }
22472
+ answer(control, { tid });
22473
+ }
22474
+ crashed(message3, end) {
22475
+ end(JS_OOM.test(message3) ? JS_THREAD_NO_MEMORY : JS_THREAD_CRASHED);
22476
+ }
22477
+ stopped(stopped) {
22478
+ this.frozen = stopped;
22479
+ for (const header4 of this.headers.values()) {
22480
+ Atomics.store(header4, SAB_I_STOP, stopped ? 1 : 0);
22481
+ Atomics.notify(header4, SAB_I_STOP);
22482
+ }
22483
+ }
22484
+ close() {
22485
+ this.closed = true;
22486
+ for (const end of [...this.live.values()]) end(1);
22487
+ }
22488
+ };
22337
22489
 
22338
22490
  // src/kernel/host.ts
22339
22491
  var CRASHED = 70;
@@ -22436,6 +22588,7 @@ function threadSignalsOf(sab) {
22436
22588
  function threadCancel(thread) {
22437
22589
  return unblocked(thread.header) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
22438
22590
  }
22591
+ var asyncFanout = /* @__PURE__ */ new WeakMap();
22439
22592
  function notifiers(header4) {
22440
22593
  return {
22441
22594
  onPending(sig) {
@@ -22443,8 +22596,10 @@ function notifiers(header4) {
22443
22596
  Atomics.notify(header4, SAB_I_SIGNALS);
22444
22597
  },
22445
22598
  onAsync() {
22446
- Atomics.add(header4, SAB_I_ASYNC, 1);
22447
- Atomics.notify(header4, SAB_I_ASYNC);
22599
+ for (const at of [header4, ...asyncFanout.get(header4) ?? []]) {
22600
+ Atomics.add(at, SAB_I_ASYNC, 1);
22601
+ Atomics.notify(at, SAB_I_ASYNC);
22602
+ }
22448
22603
  }
22449
22604
  };
22450
22605
  }
@@ -22675,6 +22830,7 @@ function spawnWasmProcess(opts) {
22675
22830
  dispatch: clocks.timed(void 0, dispatch2)
22676
22831
  });
22677
22832
  const lane = opts.program.abi === "js" ? openLane(token, dispatch2) : void 0;
22833
+ const jsThreads = jsThreadsOf(opts, process2, token, dispatch2, clocks, header4);
22678
22834
  const { promise: exited, resolve: settle } = Promise.withResolvers();
22679
22835
  let done4 = false;
22680
22836
  let endedBy;
@@ -22688,6 +22844,7 @@ function spawnWasmProcess(opts) {
22688
22844
  worker.removeEventListener("message", onMessage);
22689
22845
  worker.removeEventListener("error", onError);
22690
22846
  for (const tid of [...threads.keys()]) endThread(tid);
22847
+ jsThreads?.close();
22691
22848
  responder.dispose();
22692
22849
  lane?.dispose();
22693
22850
  revokeSyncFsToken(token);
@@ -22711,6 +22868,8 @@ function spawnWasmProcess(opts) {
22711
22868
  finish(...dying.status(data.code));
22712
22869
  } else if (data?.type === WASM_THREAD_SPAWN && data.thread) {
22713
22870
  spawnThread(data.thread);
22871
+ } else if (data?.type === JS_THREAD_SPAWN && jsThreads) {
22872
+ jsThreads.spawn(data);
22714
22873
  }
22715
22874
  };
22716
22875
  const onMessage = (event) => handle(event.data);
@@ -22784,13 +22943,35 @@ function spawnWasmProcess(opts) {
22784
22943
  termsig: () => endedBy,
22785
22944
  onState: (listener) => process2.onState(listener),
22786
22945
  memory: () => Atomics.load(header4, SAB_I_MEMORY) * 65536,
22946
+ ...processViews(process2, opts, header4),
22947
+ writesBack: () => opts.program.abi === "wasi" && !done4,
22948
+ ...clockViews(clocks)
22949
+ };
22950
+ }
22951
+ function jsThreadsOf(opts, process2, token, dispatch2, clocks, header4) {
22952
+ if (opts.program.abi !== "js") return void 0;
22953
+ const wakes = /* @__PURE__ */ new Set();
22954
+ asyncFanout.set(header4, wakes);
22955
+ const threads = new JsThreads({
22956
+ wakes,
22957
+ cap: jsThreadCap(opts.env),
22958
+ createWorker: opts.createWorker,
22959
+ init: (sab, lane) => processInit(opts, sab, process2.umask, copyCred(process2.cred), lane),
22960
+ openLane: (laneDispatch) => openLane(token, laneDispatch),
22961
+ attach: (worker, sab, threadDispatch) => attachSyncSabResponder(worker, sab, token, { dispatch: threadDispatch }),
22962
+ dispatch: dispatch2,
22963
+ clocks
22964
+ });
22965
+ process2.onState((state) => threads.stopped(state === "stopped"));
22966
+ return threads;
22967
+ }
22968
+ function processViews(process2, opts, header4) {
22969
+ return {
22787
22970
  ignoredSignals: (fork) => process2.inheritable(fork),
22788
22971
  blockedSignals: () => opts.program.abi === "wasi" ? loadBlocked(header4) : [0, 0],
22789
22972
  signalMasks: () => process2.signalMasks(),
22790
22973
  umask: () => process2.umask,
22791
- cred: () => copyCred(process2.cred),
22792
- writesBack: () => opts.program.abi === "wasi" && !done4,
22793
- ...clockViews(clocks)
22974
+ cred: () => copyCred(process2.cred)
22794
22975
  };
22795
22976
  }
22796
22977
  function clockViews(clocks) {
@@ -24108,8 +24289,8 @@ var FSA_CAPABILITIES = {
24108
24289
  ranges: true,
24109
24290
  sessions: true
24110
24291
  };
24111
- var codeOf4 = (err) => err?.code;
24112
- var denied = (err) => codeOf4(err) === "EACCES" || err?.name === "NotAllowedError";
24292
+ var codeOf5 = (err) => err?.code;
24293
+ var denied = (err) => codeOf5(err) === "EACCES" || err?.name === "NotAllowedError";
24113
24294
  function attrOf(st) {
24114
24295
  return {
24115
24296
  kind: st.isDirectory ? "directory" : st.isSymbolicLink ? "symlink" : "file",
@@ -24131,7 +24312,7 @@ function kernelFsHandlers(fs) {
24131
24312
  try {
24132
24313
  return await fs.stat(path);
24133
24314
  } catch (err) {
24134
- if (codeOf4(err) === "ENOENT") return void 0;
24315
+ if (codeOf5(err) === "ENOENT") return void 0;
24135
24316
  throw err;
24136
24317
  }
24137
24318
  }
@@ -24324,7 +24505,7 @@ function parseFstab(text) {
24324
24505
  });
24325
24506
  return lines2;
24326
24507
  }
24327
- function codeOf5(err) {
24508
+ function codeOf6(err) {
24328
24509
  const code = err?.code;
24329
24510
  return typeof code === "string" ? code : "EIO";
24330
24511
  }
@@ -24362,18 +24543,18 @@ async function mountLine({ line, spec, invalid }, mount, signal, retries, discar
24362
24543
  break;
24363
24544
  } catch (err) {
24364
24545
  failed3 = err;
24365
- if (FINAL.has(codeOf5(err)) || attempt === retries.length) break;
24546
+ if (FINAL.has(codeOf6(err)) || attempt === retries.length) break;
24366
24547
  await wait(retries[attempt], signal);
24367
24548
  }
24368
24549
  }
24369
- const code = codeOf5(failed3);
24550
+ const code = codeOf6(failed3);
24370
24551
  return { line, target: spec.target, code, error: String(failed3?.message ?? code) };
24371
24552
  }
24372
24553
 
24373
24554
  // src/mount/hostfs.ts
24374
24555
  var HOSTFS_IO = 16 * 1024 * 1024;
24375
- var codeOf6 = (err) => err?.code;
24376
- var unreachable = (err) => codeOf6(err) === "ENOTCONN";
24556
+ var codeOf7 = (err) => err?.code;
24557
+ var unreachable = (err) => codeOf7(err) === "ENOTCONN";
24377
24558
  function rel(path) {
24378
24559
  return path.replace(/^\/+/, "");
24379
24560
  }
@@ -24550,7 +24731,7 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
24550
24731
  try {
24551
24732
  return { opened: await opening2(), restore: void 0 };
24552
24733
  } catch (err) {
24553
- if (!flags2.write || codeOf6(err) !== "EACCES") throw err;
24734
+ if (!flags2.write || codeOf7(err) !== "EACCES") throw err;
24554
24735
  const was = await client.call("stat", { path: rel(path) });
24555
24736
  const mode = was.mode ?? 0;
24556
24737
  if (mode & 128) throw err;
@@ -24975,7 +25156,7 @@ var PortTransport = class {
24975
25156
  }
24976
25157
  };
24977
25158
  var errorOf = (err) => ({
24978
- code: typeof codeOf6(err) === "string" ? codeOf6(err) : "EIO",
25159
+ code: typeof codeOf7(err) === "string" ? codeOf7(err) : "EIO",
24979
25160
  message: err?.message ?? String(err)
24980
25161
  });
24981
25162
  function serveHostfsPort(port, transport) {
@@ -24989,14 +25170,14 @@ function serveHostfsPort(port, transport) {
24989
25170
  };
24990
25171
  const send2 = (reply, transfer = []) => port.postMessage(reply, transfer);
24991
25172
  const pending = /* @__PURE__ */ new Set();
24992
- const track = (work) => {
25173
+ const track2 = (work) => {
24993
25174
  pending.add(work);
24994
25175
  const done4 = () => pending.delete(work);
24995
25176
  work.then(done4, done4);
24996
25177
  return work;
24997
25178
  };
24998
- const answer = async (name2, body) => {
24999
- const result = await track(transport.call(name2, body));
25179
+ const answer2 = async (name2, body) => {
25180
+ const result = await track2(transport.call(name2, body));
25000
25181
  const opened2 = result?.fh;
25001
25182
  if (name2 === "open" && typeof opened2 === "number") handles.add(opened2);
25002
25183
  if (name2 === "release") handles.delete(body?.fh);
@@ -25010,7 +25191,7 @@ function serveHostfsPort(port, transport) {
25010
25191
  if (op === "ping") return send2({ id: id2, pong: true });
25011
25192
  if (op === "bye") return stop();
25012
25193
  if (op === "cleanup")
25013
- return void Promise.allSettled([...pending]).then(() => answer(data.name, data.body)).catch(() => {
25194
+ return void Promise.allSettled([...pending]).then(() => answer2(data.name, data.body)).catch(() => {
25014
25195
  });
25015
25196
  if (op === "unwatch") return watches.get(id2)?.abort();
25016
25197
  if (op === "watch") {
@@ -25032,7 +25213,7 @@ function serveHostfsPort(port, transport) {
25032
25213
  }
25033
25214
  try {
25034
25215
  if (op === "read") {
25035
- const read = await track(
25216
+ const read = await track2(
25036
25217
  transport.read(
25037
25218
  data.fh,
25038
25219
  data.offset,
@@ -25044,13 +25225,13 @@ function serveHostfsPort(port, transport) {
25044
25225
  return send2({ id: id2, bytes }, [bytes.buffer]);
25045
25226
  }
25046
25227
  if (op === "write") {
25047
- await track(
25228
+ await track2(
25048
25229
  transport.write(data.fh, data.offset, data.bytes)
25049
25230
  );
25050
25231
  return send2({ id: id2 });
25051
25232
  }
25052
25233
  if (op !== "call") throw fsError2("EINVAL", `unknown hostfs port op ${op}`);
25053
- send2({ id: id2, result: await answer(data.name, data.body) });
25234
+ send2({ id: id2, result: await answer2(data.name, data.body) });
25054
25235
  } catch (err) {
25055
25236
  send2({ id: id2, error: errorOf(err) });
25056
25237
  }
@@ -25842,14 +26023,14 @@ var Sudo = class {
25842
26023
  if (this.pending.has(cred.ruid)) return failed2("EBUSY", "sudo: another request is pending");
25843
26024
  this.pending.add(cred.ruid);
25844
26025
  try {
25845
- const answer = await this.ask(caller, self, target, parsed2.command, path, cwd, signal);
25846
- if (typeof answer !== "string") return answer;
26026
+ const answer2 = await this.ask(caller, self, target, parsed2.command, path, cwd, signal);
26027
+ if (typeof answer2 !== "string") return answer2;
25847
26028
  if (await this.canonical(call.cwd) !== cwd || !await this.reachable(cred, cwd)) {
25848
26029
  return failed2("EACCES", `sudo: ${call.cwd} changed while the request waited`);
25849
26030
  }
25850
26031
  const changed = await this.untrusted(path, cwd, word);
25851
26032
  if (changed) return changed;
25852
- if (answer === "always" && !await this.remember(self, target, cwd, argv)) {
26033
+ if (answer2 === "always" && !await this.remember(self, target, cwd, argv)) {
25853
26034
  return failed2("EIO", "sudo: the rule could not be recorded");
25854
26035
  }
25855
26036
  return grant();
@@ -25904,11 +26085,11 @@ ${lines2}
25904
26085
  );
25905
26086
  try {
25906
26087
  const answered = Promise.resolve().then(() => approve(req, { signal: control.signal })).catch(() => "deny");
25907
- const answer = await Promise.race([answered, aborted2]);
25908
- if (answer === "aborted" || control.signal.aborted) {
26088
+ const answer2 = await Promise.race([answered, aborted2]);
26089
+ if (answer2 === "aborted" || control.signal.aborted) {
25909
26090
  return control.signal.reason === "expired" ? failed2("ETIMEDOUT", "sudo: the request expired") : failed2("EINTR", "sudo: the request was withdrawn");
25910
26091
  }
25911
- return answer === "once" || answer === "always" ? answer : failed2("EACCES", "sudo: approval denied");
26092
+ return answer2 === "once" || answer2 === "always" ? answer2 : failed2("EACCES", "sudo: approval denied");
25912
26093
  } finally {
25913
26094
  clearTimeout(timer);
25914
26095
  requester.removeEventListener("abort", withdraw);
@@ -26316,9 +26497,7 @@ var Launcher = class {
26316
26497
  this.usersMode = usersMode(options.users);
26317
26498
  this.memories = memoriesOf(options.wasmMemories);
26318
26499
  this.rootFs = options.fs;
26319
- const peers = options.fs.peers?.();
26320
- this.locks = kernelLocks(options.fs.rootName, peers);
26321
- peers?.watch((crowded) => this.changes.foreign(crowded));
26500
+ this.locks = kernelLocks(options.fs.rootName, this.flushingPeers(options.fs));
26322
26501
  this.dac = this.usersMode === "off" ? void 0 : new Dac(this.usersMode, options.onDenial);
26323
26502
  if (this.dac) this.dac.tagOf = (pid) => this.tagOf(pid);
26324
26503
  this.clipboard = new ClipboardBroker(
@@ -26404,7 +26583,10 @@ var Launcher = class {
26404
26583
  this.nodes.keepsOnDisk = true;
26405
26584
  this.openFiles.add(this.nodes);
26406
26585
  options.fs.onPeer?.(() => this.flushOpen());
26407
- options.fs.remoteChanges?.((change) => this.rewritten(change.paths));
26586
+ options.fs.remoteChanges?.((change) => {
26587
+ this.changes.flush();
26588
+ this.rewritten(change.paths);
26589
+ });
26408
26590
  const holders = [this.held, this.openFiles];
26409
26591
  this.unlinked = new UnlinkedKeeper(
26410
26592
  fs,
@@ -26819,7 +27001,7 @@ var Launcher = class {
26819
27001
  try {
26820
27002
  return await this.planOne(req, ctx);
26821
27003
  } catch (err) {
26822
- const code = codeOf7(err);
27004
+ const code = codeOf8(err);
26823
27005
  const searched = bare && req.search !== false && (code === "ENOENT" || code === "ENOEXEC");
26824
27006
  if (!searched || await this.commandAt(req.file, ctx.scope)) throw err;
26825
27007
  const found = await this.onPath(req, ctx);
@@ -26836,7 +27018,7 @@ var Launcher = class {
26836
27018
  try {
26837
27019
  return await this.planOne({ ...req, file }, ctx);
26838
27020
  } catch (err) {
26839
- const code = codeOf7(err);
27021
+ const code = codeOf8(err);
26840
27022
  if (code === "EACCES") denied2 = true;
26841
27023
  else if (code !== "ENOENT" && code !== "ENOTDIR") throw err;
26842
27024
  }
@@ -26846,7 +27028,7 @@ var Launcher = class {
26846
27028
  }
26847
27029
  async planOne(req, { ppid, cred, scope }) {
26848
27030
  const refused3 = (err) => {
26849
- throw codeOf7(err) === "EACCES" ? new SpawnError("EACCES") : err;
27031
+ throw codeOf8(err) === "EACCES" ? new SpawnError("EACCES") : err;
26850
27032
  };
26851
27033
  const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused3);
26852
27034
  const planned = await this.plan(file, req.argv, req.cwd, scope, req.argv0);
@@ -28174,6 +28356,21 @@ var Launcher = class {
28174
28356
  this.writers ??= this.writerStack();
28175
28357
  return this.writers;
28176
28358
  }
28359
+ flushingPeers(fs) {
28360
+ const peers = fs.peers?.();
28361
+ if (!peers) return void 0;
28362
+ peers.watch((crowded) => {
28363
+ this.changes.flush();
28364
+ this.changes.foreign(crowded);
28365
+ });
28366
+ return {
28367
+ ...peers,
28368
+ fresh: () => {
28369
+ this.changes.flush();
28370
+ peers.fresh?.();
28371
+ }
28372
+ };
28373
+ }
28177
28374
  rewritten(paths) {
28178
28375
  for (const nodes of this.openFiles) for (const path of paths) nodes.rewritten(path);
28179
28376
  this.changes.publish(...paths);
@@ -28356,7 +28553,7 @@ var Launcher = class {
28356
28553
  function cronLocks() {
28357
28554
  return globalThis.navigator?.locks;
28358
28555
  }
28359
- function codeOf7(err) {
28556
+ function codeOf8(err) {
28360
28557
  return err?.code;
28361
28558
  }
28362
28559
 
@@ -28769,7 +28966,7 @@ import { connect as tls } from "node:tls";
28769
28966
  var PROBE_MS = 3e3;
28770
28967
  var PASSED = /* @__PURE__ */ new Set(["ECONNREFUSED", "EHOSTUNREACH", "ENETUNREACH", "ETIMEDOUT", "ECONNRESET"]);
28771
28968
  var NO_NAME = /* @__PURE__ */ new Set(["ENOTFOUND", "EAI_AGAIN", "EAI_NONAME", "EAI_FAIL", "ENODATA"]);
28772
- function codeOf8(e) {
28969
+ function codeOf9(e) {
28773
28970
  const code = e?.code;
28774
28971
  return typeof code === "string" ? code : void 0;
28775
28972
  }
@@ -28798,7 +28995,7 @@ function probe(secure2, host, port, ms, signal) {
28798
28995
  signal?.addEventListener("abort", stop, { once: true });
28799
28996
  socket.once(secure2 ? "secureConnect" : "connect", () => done4("EPROTO"));
28800
28997
  socket.once("error", (e) => {
28801
- const code = codeOf8(e) ?? "";
28998
+ const code = codeOf9(e) ?? "";
28802
28999
  done4(PASSED.has(code) ? code : "EPROTO");
28803
29000
  });
28804
29001
  });
@@ -28813,7 +29010,7 @@ async function diagnose(url, ms = PROBE_MS, signal) {
28813
29010
  await abortable(lookup3(host), signal);
28814
29011
  } catch (e) {
28815
29012
  if (signal?.aborted) throw signal.reason;
28816
- return NO_NAME.has(codeOf8(e) ?? "") ? "EAI_NONAME" : void 0;
29013
+ return NO_NAME.has(codeOf9(e) ?? "") ? "EAI_NONAME" : void 0;
28817
29014
  }
28818
29015
  const code = await probe(secure2, host, port, ms, signal);
28819
29016
  signal?.throwIfAborted();
@@ -28832,7 +29029,7 @@ function diagnosing(transport, check = byDefault) {
28832
29029
  try {
28833
29030
  return await open(request);
28834
29031
  } catch (e) {
28835
- if (request.signal.aborted || !(e instanceof Error) || codeOf8(e)) throw e;
29032
+ if (request.signal.aborted || !(e instanceof Error) || codeOf9(e)) throw e;
28836
29033
  const code = await abortable(
28837
29034
  check(request.url, request.signal).catch(() => void 0),
28838
29035
  request.signal