@ai-ecoverse/slicc-kernel 1.128.2 → 1.130.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -544,14 +544,14 @@ var Integrity = class {
544
544
  if (!this.root.version) return void 0;
545
545
  return `${real}\0${await this.root.version(real)}`;
546
546
  }
547
- async read(path, caller, plain2, asked) {
548
- return (await this.readKeyed(path, caller, plain2, asked)).bytes;
547
+ async read(path, caller, plain3, asked) {
548
+ return (await this.readKeyed(path, caller, plain3, asked)).bytes;
549
549
  }
550
- async readKeyed(path, caller, plain2, asked) {
550
+ async readKeyed(path, caller, plain3, asked) {
551
551
  const found = await this.real(path, asked);
552
- if (found === void 0) return { bytes: await plain2() };
552
+ if (found === void 0) return { bytes: await plain3() };
553
553
  const { real, name: name2 } = found;
554
- const read = name2 !== real ? { bytes: await plain2(), version: void 0 } : this.root.readVersioned ? await this.root.readVersioned(real) : { bytes: await this.root.readFileBuffer(real), version: void 0 };
554
+ const read = name2 !== real ? { bytes: await plain3(), version: void 0 } : this.root.readVersioned ? await this.root.readVersioned(real) : { bytes: await this.root.readFileBuffer(real), version: void 0 };
555
555
  const { bytes } = read;
556
556
  const keyed = read.version === void 0 ? { bytes } : { bytes, key: `${real}\0${read.version}` };
557
557
  await this.verify(name2, bytes, caller, EXEC_OPS);
@@ -560,9 +560,9 @@ var Integrity = class {
560
560
  get readsChecked() {
561
561
  return this.sources.length > 0;
562
562
  }
563
- async readSource(path, caller, plain2) {
563
+ async readSource(path, caller, plain3) {
564
564
  const found = await this.source(path);
565
- return found === void 0 ? plain2() : this.checked(found, caller, plain2);
565
+ return found === void 0 ? plain3() : this.checked(found, caller, plain3);
566
566
  }
567
567
  async openSource(path, caller, real) {
568
568
  const found = await this.source(path, real);
@@ -572,10 +572,10 @@ var Integrity = class {
572
572
  }
573
573
  await this.checked(found, caller, () => this.root.readFileBuffer(found.real));
574
574
  }
575
- async checked(found, caller, plain2) {
575
+ async checked(found, caller, plain3) {
576
576
  const { real, name: name2 } = found;
577
577
  if (name2 !== real || !this.root.readVersioned) {
578
- const bytes2 = await plain2();
578
+ const bytes2 = await plain3();
579
579
  await this.verify(name2, bytes2, caller, READ_OPS);
580
580
  return bytes2;
581
581
  }
@@ -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 {
@@ -983,12 +983,12 @@ var RemoteWatch = class {
983
983
  }
984
984
  greeted(peer) {
985
985
  this.arrived(peer);
986
- const answer = () => {
986
+ const answer2 = () => {
987
987
  this.channel.postMessage({ here: this.tab, to: peer });
988
988
  if (this.mine.length > 0) void this.announce(this.mine);
989
989
  };
990
- if (this.quiet) void this.quiet().then(answer, answer);
991
- else answer();
990
+ if (this.quiet) void this.quiet().then(answer2, answer2);
991
+ else answer2();
992
992
  }
993
993
  announced({ tab, paths, seq: seq2 }) {
994
994
  const from = tab;
@@ -3232,11 +3232,11 @@ function frame(opcode, payload) {
3232
3232
  return out;
3233
3233
  }
3234
3234
  function clientFrame(opcode, payload) {
3235
- const plain2 = frame(opcode, payload);
3236
- const head = plain2.length - payload.length;
3235
+ const plain3 = frame(opcode, payload);
3236
+ const head = plain3.length - payload.length;
3237
3237
  const mask = crypto.getRandomValues(new Uint8Array(4));
3238
- const out = new Uint8Array(plain2.length + 4);
3239
- out.set(plain2.subarray(0, head));
3238
+ const out = new Uint8Array(plain3.length + 4);
3239
+ out.set(plain3.subarray(0, head));
3240
3240
  out[1] = out[1] | 128;
3241
3241
  out.set(mask, head);
3242
3242
  for (let i = 0; i < payload.length; i++) {
@@ -7020,7 +7020,7 @@ function satisfies(version, range2) {
7020
7020
  }
7021
7021
 
7022
7022
  // src/version.ts
7023
- var KERNEL_VERSION = true ? "1.128.2" : "0.0.0-dev";
7023
+ var KERNEL_VERSION = true ? "1.130.0" : "0.0.0-dev";
7024
7024
  var OS_RELEASE = "6.0.0-slicc";
7025
7025
  function procVersion() {
7026
7026
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -12378,13 +12378,13 @@ async function chown(entry, path, req) {
12378
12378
  }
12379
12379
  async function runMkdir(entry, path, req) {
12380
12380
  const { fs } = entry;
12381
- const plain2 = plainDirMode(entry, req.mode);
12381
+ const plain3 = plainDirMode(entry, req.mode);
12382
12382
  const parentsMode = !req.exclusive ? plainParentsMode(entry) : void 0;
12383
12383
  const fixParents = parentsMode !== void 0 ? await missingParents(fs, path, parentsMode) : void 0;
12384
- const fresh2 = plain2 !== void 0 && !await fs.exists(path);
12384
+ const fresh2 = plain3 !== void 0 && !await fs.exists(path);
12385
12385
  await (req.exclusive ? mkdirExclusive(entry, path, req.mode) : fs.mkdir(path, mkdirOptions(entry, req.mode)));
12386
12386
  await fixParents?.();
12387
- if (fresh2) await fs.chmod(path, plain2);
12387
+ if (fresh2) await fs.chmod(path, plain3);
12388
12388
  return done2;
12389
12389
  }
12390
12390
  async function shownAs(entry, path, st) {
@@ -12392,8 +12392,8 @@ async function shownAs(entry, path, st) {
12392
12392
  return callerStat(guardOf(entry), await real?.catch(() => path) ?? path, st);
12393
12393
  }
12394
12394
  function readSource(entry, path) {
12395
- const plain2 = () => entry.fs.readFileBuffer(path);
12396
- return entry.source ? entry.source.read(path, plain2) : plain2();
12395
+ const plain3 = () => entry.fs.readFileBuffer(path);
12396
+ return entry.source ? entry.source.read(path, plain3) : plain3();
12397
12397
  }
12398
12398
  async function run(entry, path, req) {
12399
12399
  const { fs, cwd } = entry;
@@ -16336,11 +16336,11 @@ function carriesUdp(uplink) {
16336
16336
  return uplink.traits.udp === true && typeof uplink.udp === "function";
16337
16337
  }
16338
16338
  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") : [];
16339
+ const answer2 = Array.isArray(result) ? { addresses: result } : result;
16340
+ const addresses = Array.isArray(answer2?.addresses) ? answer2.addresses.filter((a) => typeof a === "string") : [];
16341
16341
  return {
16342
16342
  addresses,
16343
- ...typeof answer?.ttl === "number" && answer.ttl >= 0 ? { ttl: answer.ttl } : {}
16343
+ ...typeof answer2?.ttl === "number" && answer2.ttl >= 0 ? { ttl: answer2.ttl } : {}
16344
16344
  };
16345
16345
  }
16346
16346
  var NEVER = new Routes(true);
@@ -16528,9 +16528,9 @@ var Resolver = class {
16528
16528
  async lookup(name2, family, id2, abandoned) {
16529
16529
  const uplink = this.uplink;
16530
16530
  const timeout = AbortSignal.any([AbortSignal.timeout(this.timeoutMs), abandoned]);
16531
- let answer;
16531
+ let answer2;
16532
16532
  try {
16533
- answer = answerOf(
16533
+ answer2 = answerOf(
16534
16534
  await Promise.race([
16535
16535
  uplink.resolve(name2, family, timeout),
16536
16536
  new Promise(
@@ -16541,8 +16541,8 @@ var Resolver = class {
16541
16541
  } catch {
16542
16542
  return [];
16543
16543
  }
16544
- const addresses = answer.addresses.filter((a) => this.usable(name2, a, family));
16545
- if (addresses.length > 0) this.remember(id2, addresses, answer.ttl);
16544
+ const addresses = answer2.addresses.filter((a) => this.usable(name2, a, family));
16545
+ if (addresses.length > 0) this.remember(id2, addresses, answer2.ttl);
16546
16546
  return addresses;
16547
16547
  }
16548
16548
  usable(name2, address, family) {
@@ -18490,6 +18490,95 @@ async function substituteHead(head, ask) {
18490
18490
  `, values };
18491
18491
  }
18492
18492
 
18493
+ // src/kernel/net/sealed-smtp.ts
18494
+ var SMTP_LINE_MAX = 4096;
18495
+ var GREETING = ["EHLO ", "HELO "];
18496
+ function sniffSmtp(start2) {
18497
+ const upper = start2.toUpperCase();
18498
+ for (const word of GREETING) {
18499
+ if (upper.startsWith(word)) return "yes";
18500
+ if (word.startsWith(upper)) return "more";
18501
+ }
18502
+ return "no";
18503
+ }
18504
+ function decoded(b64) {
18505
+ if (!/^[A-Za-z0-9+/]+={0,2}$/.test(b64)) return void 0;
18506
+ try {
18507
+ return atob(b64);
18508
+ } catch {
18509
+ return void 0;
18510
+ }
18511
+ }
18512
+ async function swapped2(text, position, ask) {
18513
+ const placeholders = placeholdersIn(text);
18514
+ if (placeholders.length === 0 || placeholders.length > SESSION_PLACEHOLDERS) return void 0;
18515
+ const values = usable(await ask(position, placeholders));
18516
+ if (Object.keys(values).length === 0) return void 0;
18517
+ return { text: replaced(text, values), values };
18518
+ }
18519
+ async function plain2(b64, ask) {
18520
+ const text = decoded(b64);
18521
+ const fields = text?.split("\0");
18522
+ if (fields?.length !== 3) return { line: b64 };
18523
+ const [authz, user, pass2] = fields;
18524
+ if (placeholdersIn(authz + user).length > 0) return { line: b64 };
18525
+ const done5 = await swapped2(pass2, "auth-plain", ask);
18526
+ if (!done5) return { line: b64 };
18527
+ return { line: btoa(`${authz}\0${user}\0${done5.text}`), values: done5.values };
18528
+ }
18529
+ async function login(b64, ask) {
18530
+ const text = decoded(b64);
18531
+ const done5 = text === void 0 ? void 0 : await swapped2(text, "auth-login", ask);
18532
+ return done5 ? { line: btoa(done5.text), values: done5.values } : { line: b64 };
18533
+ }
18534
+ var SmtpClient = class {
18535
+ state = "command";
18536
+ ask;
18537
+ constructor(ask) {
18538
+ this.ask = ask;
18539
+ }
18540
+ get done() {
18541
+ return this.state === "done";
18542
+ }
18543
+ async line(text) {
18544
+ const state = this.state;
18545
+ if (state === "done") return { line: text };
18546
+ if (state === "plain" || state === "password") {
18547
+ this.state = "done";
18548
+ if (text === "*") return { line: text };
18549
+ return state === "plain" ? plain2(text, this.ask) : login(text, this.ask);
18550
+ }
18551
+ if (state === "user") {
18552
+ this.state = text === "*" ? "done" : "password";
18553
+ return { line: text };
18554
+ }
18555
+ return this.command(text);
18556
+ }
18557
+ async command(text) {
18558
+ const m = /^AUTH[ \t]+(PLAIN|LOGIN)(?:[ \t]+(\S+))?$/i.exec(text);
18559
+ if (!m) {
18560
+ if (/^(MAIL|RCPT|DATA|BDAT|AUTH)\b/i.test(text)) this.state = "done";
18561
+ return { line: text };
18562
+ }
18563
+ const mech = m[1].toUpperCase();
18564
+ const arg = m[2];
18565
+ if (mech === "LOGIN") {
18566
+ this.state = arg === void 0 ? "user" : "password";
18567
+ return { line: text };
18568
+ }
18569
+ if (arg === void 0) {
18570
+ this.state = "plain";
18571
+ return { line: text };
18572
+ }
18573
+ this.state = "done";
18574
+ const out = await plain2(arg, this.ask);
18575
+ return {
18576
+ line: `${text.slice(0, text.length - arg.length)}${out.line}`,
18577
+ ...out.values ? { values: out.values } : {}
18578
+ };
18579
+ }
18580
+ };
18581
+
18493
18582
  // src/kernel/net/sealed-conn.ts
18494
18583
  var HEAD_IDLE_MS = 2e3;
18495
18584
  function substitutes(s) {
@@ -18521,12 +18610,25 @@ function headEnd2(bytes) {
18521
18610
  }
18522
18611
  return -1;
18523
18612
  }
18524
- var Http1Writer = class {
18613
+ function modeOf(start2) {
18614
+ const http = sniffHttp1(start2);
18615
+ const smtp = sniffSmtp(start2);
18616
+ if (http === "yes") return "http1";
18617
+ if (smtp === "yes") return "smtp";
18618
+ return http === "no" && smtp === "no" ? "pass" : void 0;
18619
+ }
18620
+ function crlf(bytes) {
18621
+ for (let i = 0; i + 1 < bytes.length; i++) if (bytes[i] === 13 && bytes[i + 1] === 10) return i;
18622
+ return -1;
18623
+ }
18624
+ var SessionWriter = class {
18525
18625
  buffer = new Uint8Array(0);
18526
- passing = false;
18626
+ mode = "sniff";
18527
18627
  timer;
18528
18628
  chain = Promise.resolve();
18529
18629
  failed;
18630
+ session = sessionId();
18631
+ smtp;
18530
18632
  conn;
18531
18633
  s;
18532
18634
  scope;
@@ -18534,6 +18636,9 @@ var Http1Writer = class {
18534
18636
  this.conn = conn;
18535
18637
  this.s = s;
18536
18638
  this.scope = scope;
18639
+ this.smtp = new SmtpClient(
18640
+ (position, placeholders) => this.ask("smtp", position, placeholders)
18641
+ );
18537
18642
  }
18538
18643
  write(bytes) {
18539
18644
  const run2 = this.chain.then(() => this.take(bytes));
@@ -18543,30 +18648,78 @@ var Http1Writer = class {
18543
18648
  );
18544
18649
  return run2;
18545
18650
  }
18651
+ async ask(protocol, position, placeholders, head) {
18652
+ const s = this.s;
18653
+ const values = await s.broker.sessionMaterialize({
18654
+ stamp: await s.stamp(),
18655
+ session: this.session,
18656
+ host: s.host,
18657
+ port: s.port,
18658
+ protocol,
18659
+ position,
18660
+ verified: s.verified,
18661
+ handshakeAt: s.handshakeAt,
18662
+ exit: s.exit,
18663
+ placeholders,
18664
+ ...head ? { head } : {}
18665
+ });
18666
+ return values;
18667
+ }
18668
+ remember(values) {
18669
+ this.scope.add(
18670
+ Object.entries(values).map(([placeholder, value2]) => ({ name: "sealed", value: value2, placeholder }))
18671
+ );
18672
+ }
18546
18673
  async take(bytes) {
18547
18674
  if (this.failed !== void 0) throw this.failed;
18548
- if (this.passing) return this.conn.write(bytes);
18675
+ if (this.mode === "pass") return this.conn.write(bytes);
18549
18676
  clearTimeout(this.timer);
18550
18677
  const joined4 = new Uint8Array(this.buffer.length + bytes.length);
18551
18678
  joined4.set(this.buffer);
18552
18679
  joined4.set(bytes, this.buffer.length);
18553
18680
  this.buffer.fill(0);
18554
18681
  this.buffer = joined4;
18555
- const sniff = sniffHttp1(latin12(joined4.subarray(0, 8)));
18556
- const end = sniff === "yes" ? headEnd2(joined4) : -1;
18557
- if (sniff === "no" || end > HEAD_MAX || end < 0 && joined4.length > HEAD_MAX)
18558
- await this.release();
18559
- else if (end >= 0) await this.substitute(end);
18560
- else this.timer = setTimeout(() => this.idle(), HEAD_IDLE_MS);
18682
+ if (this.mode === "sniff") this.mode = modeOf(latin12(joined4.subarray(0, 8))) ?? "sniff";
18683
+ if (this.mode === "pass") await this.release();
18684
+ else if (this.mode === "http1") await this.http1();
18685
+ else if (this.mode === "smtp") await this.lines();
18686
+ if (this.mode !== "pass" && this.buffer.length > 0)
18687
+ this.timer = setTimeout(() => this.idle(), HEAD_IDLE_MS);
18561
18688
  return bytes.length;
18562
18689
  }
18690
+ async http1() {
18691
+ const end = headEnd2(this.buffer);
18692
+ if (end > HEAD_MAX || end < 0 && this.buffer.length > HEAD_MAX) await this.release();
18693
+ else if (end >= 0) await this.substitute(end);
18694
+ }
18695
+ async lines() {
18696
+ for (; ; ) {
18697
+ const at = crlf(this.buffer);
18698
+ if (at < 0) break;
18699
+ if (at > SMTP_LINE_MAX) return this.release();
18700
+ const all = this.buffer;
18701
+ this.buffer = all.slice(at + 2);
18702
+ const out = await this.smtp.line(latin12(all.subarray(0, at))).catch(() => ({ line: latin12(all.subarray(0, at)) }));
18703
+ all.fill(0);
18704
+ if ("values" in out && out.values) this.remember(out.values);
18705
+ const line = bytesOf(`${out.line}\r
18706
+ `);
18707
+ try {
18708
+ await writeAll4(this.conn, line);
18709
+ } finally {
18710
+ line.fill(0);
18711
+ }
18712
+ if (this.smtp.done) return this.release();
18713
+ }
18714
+ if (this.buffer.length > SMTP_LINE_MAX) await this.release();
18715
+ }
18563
18716
  idle() {
18564
18717
  this.chain = this.chain.then(() => this.release()).catch((err) => {
18565
18718
  this.failed ??= err;
18566
18719
  });
18567
18720
  }
18568
18721
  async release() {
18569
- this.passing = true;
18722
+ this.mode = "pass";
18570
18723
  const out = this.buffer;
18571
18724
  this.buffer = new Uint8Array(0);
18572
18725
  try {
@@ -18576,37 +18729,15 @@ var Http1Writer = class {
18576
18729
  }
18577
18730
  }
18578
18731
  async substitute(end) {
18579
- this.passing = true;
18732
+ this.mode = "pass";
18580
18733
  const all = this.buffer;
18581
18734
  this.buffer = new Uint8Array(0);
18582
- const s = this.s;
18583
- const session = sessionId();
18584
18735
  const done5 = await substituteHead(
18585
18736
  latin12(all.subarray(0, end)),
18586
- async (position, placeholders, head2) => s.broker.sessionMaterialize({
18587
- stamp: await s.stamp(),
18588
- session,
18589
- host: s.host,
18590
- port: s.port,
18591
- protocol: "http1",
18592
- position,
18593
- verified: s.verified,
18594
- handshakeAt: s.handshakeAt,
18595
- exit: s.exit,
18596
- placeholders,
18597
- head: head2
18598
- })
18737
+ (position, placeholders, head2) => this.ask("http1", position, placeholders, head2)
18599
18738
  ).catch(() => void 0);
18600
18739
  const head = done5 ? bytesOf(done5.head) : all.subarray(0, end);
18601
- if (done5) {
18602
- this.scope.add(
18603
- Object.entries(done5.values).map(([placeholder, value2]) => ({
18604
- name: "sealed",
18605
- value: value2,
18606
- placeholder
18607
- }))
18608
- );
18609
- }
18740
+ if (done5) this.remember(done5.values);
18610
18741
  try {
18611
18742
  await writeAll4(this.conn, head);
18612
18743
  await writeAll4(this.conn, all.subarray(end));
@@ -18617,14 +18748,14 @@ var Http1Writer = class {
18617
18748
  }
18618
18749
  flushed() {
18619
18750
  clearTimeout(this.timer);
18620
- this.chain = this.chain.then(() => this.passing ? void 0 : this.release());
18751
+ this.chain = this.chain.then(() => this.mode === "pass" ? void 0 : this.release());
18621
18752
  return this.chain;
18622
18753
  }
18623
18754
  drop() {
18624
18755
  clearTimeout(this.timer);
18625
18756
  this.buffer.fill(0);
18626
18757
  this.buffer = new Uint8Array(0);
18627
- this.passing = true;
18758
+ this.mode = "pass";
18628
18759
  }
18629
18760
  };
18630
18761
  var IDLE2 = /* @__PURE__ */ Symbol("idle");
@@ -18635,11 +18766,9 @@ var ScrubReader = class {
18635
18766
  held = false;
18636
18767
  ended = false;
18637
18768
  conn;
18638
- s;
18639
18769
  scope;
18640
- constructor(conn, s, scope) {
18770
+ constructor(conn, scope) {
18641
18771
  this.conn = conn;
18642
- this.s = s;
18643
18772
  this.scope = scope;
18644
18773
  }
18645
18774
  current() {
@@ -18698,8 +18827,8 @@ function idle() {
18698
18827
  }
18699
18828
  function sealedConn(conn, s) {
18700
18829
  const scope = s.broker.sessions.scope(s.pid, s.host);
18701
- const writer = substitutes(s) ? new Http1Writer(conn, s, scope) : void 0;
18702
- const reader = new ScrubReader(conn, s, scope);
18830
+ const writer = substitutes(s) ? new SessionWriter(conn, s, scope) : void 0;
18831
+ const reader = new ScrubReader(conn, scope);
18703
18832
  return {
18704
18833
  localAddr: conn.localAddr,
18705
18834
  remoteAddr: conn.remoteAddr,
@@ -19825,6 +19954,12 @@ function tlsOverTransport(req, proc) {
19825
19954
  return { fd: proc.fds.install(new OpenFile(mine), 3), alpnProtocol: "http/1.1", servername };
19826
19955
  }
19827
19956
 
19957
+ // src/kernel/test-hooks.ts
19958
+ var SYSCALL_HOOK = /* @__PURE__ */ Symbol.for("slicc-kernel.test.syscall");
19959
+ function testSyscallHook() {
19960
+ return globalThis[SYSCALL_HOOK];
19961
+ }
19962
+
19828
19963
  // src/kernel/vfs-file.ts
19829
19964
  var O_ACCMODE = 3;
19830
19965
  var O_WRONLY = 1;
@@ -21039,7 +21174,8 @@ var WasmProcess = class {
21039
21174
  cwd,
21040
21175
  ...moved2,
21041
21176
  ...group,
21042
- ...exec ? { exec } : {}
21177
+ ...exec ? { exec } : {},
21178
+ search: req.search
21043
21179
  };
21044
21180
  const pid = await this.children.spawn(spawned, stdio, inherit2);
21045
21181
  if (deathSignal !== void 0) this.onDeath(pgid === 0 || session ? -pid : pid, deathSignal);
@@ -21062,8 +21198,8 @@ var WasmProcess = class {
21062
21198
  spares(sig) {
21063
21199
  const { caught, ignored } = this.signalMasks();
21064
21200
  const bit = isSignal(sig) ? sigbit(sig) : 0;
21065
- const answer = (ignored & bit) !== 0 ? "ignore" : (caught & bit) !== 0 ? "spare" : "terminate";
21066
- return { ok: true, kind: "json", json: answer };
21201
+ const answer2 = (ignored & bit) !== 0 ? "ignore" : (caught & bit) !== 0 ? "spare" : "terminate";
21202
+ return { ok: true, kind: "json", json: answer2 };
21067
21203
  }
21068
21204
  async killSelf(sig, target, probe) {
21069
21205
  if (!this.options.exitSignal) throw new KernelError("ENOSYS");
@@ -21125,6 +21261,8 @@ var WasmProcess = class {
21125
21261
  return void 0;
21126
21262
  }
21127
21263
  async syscall(req, cancelled, block) {
21264
+ const hook = testSyscallHook();
21265
+ if (hook) await hook({ pid: this.pid, op: req.op });
21128
21266
  this.options.onSyscall?.(req);
21129
21267
  this.calls += 1;
21130
21268
  const started = performance.now();
@@ -21422,18 +21560,18 @@ var WasmProcess = class {
21422
21560
  }
21423
21561
  if (this.writesAt(req) && this.options.readonlyAt?.(path)) throw new KernelError("EROFS");
21424
21562
  const open2 = { ...req, path };
21425
- const plain2 = this.plainMode(req.mode);
21563
+ const plain3 = this.plainMode(req.mode);
21426
21564
  if (req.exclusive) {
21427
21565
  await nodes.createExclusive(path, this.newOwner(req.mode));
21428
- if (plain2 !== void 0) await fs.chmod?.(path, plain2);
21566
+ if (plain3 !== void 0) await fs.chmod?.(path, plain3);
21429
21567
  this.fds.installAt(fd, this.openVfsFile(open2, void 0, fs));
21430
21568
  } else if (req.create) {
21431
21569
  await nodes.onEntry(path, async () => {
21432
- const marks = this.options.owners || plain2 !== void 0;
21570
+ const marks = this.options.owners || plain3 !== void 0;
21433
21571
  const fresh2 = marks && !await present3(fs, path, true);
21434
21572
  this.fds.installAt(fd, this.openVfsFile(open2, await nodes.identify(path), fs));
21435
21573
  await this.fds.get(fd).file.stat?.();
21436
- if (fresh2 && plain2 !== void 0) await fs.chmod?.(path, plain2);
21574
+ if (fresh2 && plain3 !== void 0) await fs.chmod?.(path, plain3);
21437
21575
  else if (fresh2) {
21438
21576
  await fs.chown?.(path, { ...this.newOwner(req.mode), kind: "new" });
21439
21577
  }
@@ -22178,10 +22316,10 @@ var WasmProcess = class {
22178
22316
  cwd: typeof req.cwd === "string" && req.cwd.startsWith("/") ? req.cwd : "/",
22179
22317
  ...typeof req.term === "string" ? { term: req.term } : {}
22180
22318
  };
22181
- const answer = await sudo(call, this.blockingSignal(cancelled));
22182
- if (!("grant" in answer)) return answer;
22319
+ const answer2 = await sudo(call, this.blockingSignal(cancelled));
22320
+ if (!("grant" in answer2)) return answer2;
22183
22321
  if (this.dying) throw new KernelError("EINTR");
22184
- const { file, argv, env, cwd, cred, caller } = answer.grant;
22322
+ const { file, argv, env, cwd, cred, caller } = answer2.grant;
22185
22323
  const stdio = [{ fd: 0 }, { fd: 1 }, { fd: 2 }];
22186
22324
  return {
22187
22325
  pid: await this.children.spawn({ file, argv, env, cwd, pgid: 0 }, stdio, [], {
@@ -22341,6 +22479,153 @@ var WASM_THREAD_SPAWN = "wasm-thread-spawn";
22341
22479
  var WASM_THREAD_INIT = "wasm-thread-init";
22342
22480
  var WASM_THREAD_EXIT = "wasm-thread-exit";
22343
22481
  var WASM_MAX_THREADS = 256;
22482
+ var JS_THREAD_SPAWN = "js-thread-spawn";
22483
+ var JS_THREAD_INIT = "js-thread-init";
22484
+ var JS_THREAD_EXIT = "js-thread-exit";
22485
+ var JS_MAX_THREADS = 256;
22486
+ var JS_DEFAULT_THREADS = 16;
22487
+ var JS_THREAD_NO_MEMORY = 256;
22488
+ var JS_THREAD_CRASHED = 257;
22489
+
22490
+ // src/kernel/js-threads.ts
22491
+ var JS_OOM = /out of memory|Array buffer allocation failed|Cannot allocate Wasm memory|could not allocate memory|ERR_WORKER_OUT_OF_MEMORY/i;
22492
+ var ENDING = { ok: false, errno: "EINTR", message: "the thread is ending" };
22493
+ var MAIN_ONLY = { ok: true, kind: "void" };
22494
+ function track(ops, req, result) {
22495
+ if (req.op === "async-submit" && result.ok && result.kind === "json") {
22496
+ if (typeof result.json === "number") ops.set(result.json, req.token);
22497
+ } else if (req.op === "async-cancel" || req.op === "async-take" && (result.ok || result.errno !== "EAGAIN")) {
22498
+ ops.delete(req.id);
22499
+ }
22500
+ }
22501
+ function cores() {
22502
+ const n = globalThis.navigator?.hardwareConcurrency;
22503
+ return typeof n === "number" && Number.isInteger(n) && n > 0 ? n : 0;
22504
+ }
22505
+ function jsThreadCap(env) {
22506
+ const asked = Number.parseInt(env.SLICC_JS_THREADS ?? "", 10);
22507
+ if (asked >= 1) return Math.min(asked, JS_MAX_THREADS);
22508
+ return Math.min(JS_MAX_THREADS, Math.max(JS_DEFAULT_THREADS, 2 * cores()));
22509
+ }
22510
+ function codeOf4(code) {
22511
+ if (code === JS_THREAD_NO_MEMORY || code === JS_THREAD_CRASHED) return code;
22512
+ return typeof code === "number" && Number.isInteger(code) ? code & 255 : JS_THREAD_CRASHED;
22513
+ }
22514
+ function answer(control, message3) {
22515
+ control.postMessage(message3);
22516
+ }
22517
+ var JsThreads = class {
22518
+ deps;
22519
+ live = /* @__PURE__ */ new Map();
22520
+ headers = /* @__PURE__ */ new Map();
22521
+ frozen = false;
22522
+ last = 0;
22523
+ closed = false;
22524
+ constructor(deps) {
22525
+ this.deps = deps;
22526
+ }
22527
+ get size() {
22528
+ return this.live.size;
22529
+ }
22530
+ spawn(msg) {
22531
+ const { control, port } = msg;
22532
+ if (this.closed || this.live.size >= this.deps.cap) {
22533
+ answer(
22534
+ control,
22535
+ this.closed ? { errno: "ESRCH", message: "the process is ending" } : { errno: "EAGAIN", message: `more than ${this.deps.cap} threads` }
22536
+ );
22537
+ control.close();
22538
+ port.close();
22539
+ return;
22540
+ }
22541
+ const tid = ++this.last;
22542
+ const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
22543
+ const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
22544
+ if (this.frozen) Atomics.store(header3, SAB_I_STOP, 1);
22545
+ const worker = this.deps.createWorker();
22546
+ const clock = this.deps.clocks.thread(tid + 1, sab);
22547
+ let ended = false;
22548
+ const end = (code) => {
22549
+ if (ended) return;
22550
+ ended = true;
22551
+ this.live.delete(tid);
22552
+ this.headers.delete(tid);
22553
+ this.deps.wakes.delete(header3);
22554
+ for (const [id2, token] of ops) {
22555
+ void this.deps.dispatch({ op: "async-cancel", id: id2, token });
22556
+ }
22557
+ ops.clear();
22558
+ worker.removeEventListener("message", onMessage);
22559
+ worker.removeEventListener("error", onError);
22560
+ control.removeEventListener("message", onControl);
22561
+ responder.dispose();
22562
+ lane.dispose();
22563
+ this.deps.clocks.threadEnded(tid + 1);
22564
+ worker.terminate();
22565
+ answer(control, { exited: code });
22566
+ control.close();
22567
+ };
22568
+ const ops = /* @__PURE__ */ new Map();
22569
+ const dispatch2 = async (req, block) => {
22570
+ if (isWasmSyscall(req) && req.op === "proc-exit") {
22571
+ queueMicrotask(() => end(req.status & 255));
22572
+ return ENDING;
22573
+ }
22574
+ if (isWasmSyscall(req) && req.op === "sig-mask") return MAIN_ONLY;
22575
+ const result = await this.deps.dispatch(req, block);
22576
+ if (!ended) track(ops, req, result);
22577
+ return result;
22578
+ };
22579
+ const responder = this.deps.attach(worker, sab, this.deps.clocks.timed(clock, dispatch2));
22580
+ const lane = this.deps.openLane(dispatch2);
22581
+ const onMessage = (event) => {
22582
+ const data = event.data;
22583
+ if (data?.type === JS_THREAD_EXIT) end(codeOf4(data.code));
22584
+ else if (data?.type === JS_THREAD_SPAWN) this.spawn(event.data);
22585
+ else if (data?.type === WASM_PROCESS_ERROR) this.crashed(String(data.message), end);
22586
+ };
22587
+ const onError = (event) => {
22588
+ event.preventDefault();
22589
+ this.crashed(String(event.message ?? "worker error"), end);
22590
+ };
22591
+ const onControl = (event) => {
22592
+ if (event.data?.terminate === true) end(1);
22593
+ };
22594
+ worker.addEventListener("message", onMessage);
22595
+ worker.addEventListener("error", onError);
22596
+ control.addEventListener("message", onControl);
22597
+ control.start();
22598
+ this.live.set(tid, end);
22599
+ this.headers.set(tid, header3);
22600
+ this.deps.wakes.add(header3);
22601
+ const init = {
22602
+ ...this.deps.init(sab, lane.lane),
22603
+ type: JS_THREAD_INIT,
22604
+ thread: { tid, port, data: msg.data }
22605
+ };
22606
+ try {
22607
+ worker.postMessage(init, [lane.lane.port, port, ...msg.transfer ?? []]);
22608
+ } catch {
22609
+ end(JS_THREAD_CRASHED);
22610
+ return;
22611
+ }
22612
+ answer(control, { tid });
22613
+ }
22614
+ crashed(message3, end) {
22615
+ end(JS_OOM.test(message3) ? JS_THREAD_NO_MEMORY : JS_THREAD_CRASHED);
22616
+ }
22617
+ stopped(stopped) {
22618
+ this.frozen = stopped;
22619
+ for (const header3 of this.headers.values()) {
22620
+ Atomics.store(header3, SAB_I_STOP, stopped ? 1 : 0);
22621
+ Atomics.notify(header3, SAB_I_STOP);
22622
+ }
22623
+ }
22624
+ close() {
22625
+ this.closed = true;
22626
+ for (const end of [...this.live.values()]) end(1);
22627
+ }
22628
+ };
22344
22629
 
22345
22630
  // src/kernel/host.ts
22346
22631
  var CRASHED = 70;
@@ -22443,6 +22728,7 @@ function threadSignalsOf(sab) {
22443
22728
  function threadCancel(thread) {
22444
22729
  return unblocked(thread.header) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
22445
22730
  }
22731
+ var asyncFanout = /* @__PURE__ */ new WeakMap();
22446
22732
  function notifiers(header3) {
22447
22733
  return {
22448
22734
  onPending(sig) {
@@ -22450,8 +22736,10 @@ function notifiers(header3) {
22450
22736
  Atomics.notify(header3, SAB_I_SIGNALS);
22451
22737
  },
22452
22738
  onAsync() {
22453
- Atomics.add(header3, SAB_I_ASYNC, 1);
22454
- Atomics.notify(header3, SAB_I_ASYNC);
22739
+ for (const at of [header3, ...asyncFanout.get(header3) ?? []]) {
22740
+ Atomics.add(at, SAB_I_ASYNC, 1);
22741
+ Atomics.notify(at, SAB_I_ASYNC);
22742
+ }
22455
22743
  }
22456
22744
  };
22457
22745
  }
@@ -22682,6 +22970,7 @@ function spawnWasmProcess(opts) {
22682
22970
  dispatch: clocks.timed(void 0, dispatch2)
22683
22971
  });
22684
22972
  const lane = opts.program.abi === "js" ? openLane(token, dispatch2) : void 0;
22973
+ const jsThreads = jsThreadsOf(opts, process, token, dispatch2, clocks, header3);
22685
22974
  const { promise: exited, resolve: settle3 } = Promise.withResolvers();
22686
22975
  let done5 = false;
22687
22976
  let endedBy;
@@ -22695,6 +22984,7 @@ function spawnWasmProcess(opts) {
22695
22984
  worker.removeEventListener("message", onMessage);
22696
22985
  worker.removeEventListener("error", onError);
22697
22986
  for (const tid of [...threads.keys()]) endThread(tid);
22987
+ jsThreads?.close();
22698
22988
  responder.dispose();
22699
22989
  lane?.dispose();
22700
22990
  revokeSyncFsToken(token);
@@ -22718,6 +23008,8 @@ function spawnWasmProcess(opts) {
22718
23008
  finish(...dying.status(data.code));
22719
23009
  } else if (data?.type === WASM_THREAD_SPAWN && data.thread) {
22720
23010
  spawnThread(data.thread);
23011
+ } else if (data?.type === JS_THREAD_SPAWN && jsThreads) {
23012
+ jsThreads.spawn(data);
22721
23013
  }
22722
23014
  };
22723
23015
  const onMessage = (event) => handle(event.data);
@@ -22791,13 +23083,35 @@ function spawnWasmProcess(opts) {
22791
23083
  termsig: () => endedBy,
22792
23084
  onState: (listener) => process.onState(listener),
22793
23085
  memory: () => Atomics.load(header3, SAB_I_MEMORY) * 65536,
23086
+ ...processViews(process, opts, header3),
23087
+ writesBack: () => opts.program.abi === "wasi" && !done5,
23088
+ ...clockViews(clocks)
23089
+ };
23090
+ }
23091
+ function jsThreadsOf(opts, process, token, dispatch2, clocks, header3) {
23092
+ if (opts.program.abi !== "js") return void 0;
23093
+ const wakes = /* @__PURE__ */ new Set();
23094
+ asyncFanout.set(header3, wakes);
23095
+ const threads = new JsThreads({
23096
+ wakes,
23097
+ cap: jsThreadCap(opts.env),
23098
+ createWorker: opts.createWorker,
23099
+ init: (sab, lane) => processInit(opts, sab, process.umask, copyCred(process.cred), lane),
23100
+ openLane: (laneDispatch) => openLane(token, laneDispatch),
23101
+ attach: (worker, sab, threadDispatch) => attachSyncSabResponder(worker, sab, token, { dispatch: threadDispatch }),
23102
+ dispatch: dispatch2,
23103
+ clocks
23104
+ });
23105
+ process.onState((state) => threads.stopped(state === "stopped"));
23106
+ return threads;
23107
+ }
23108
+ function processViews(process, opts, header3) {
23109
+ return {
22794
23110
  ignoredSignals: (fork) => process.inheritable(fork),
22795
23111
  blockedSignals: () => opts.program.abi === "wasi" ? loadBlocked(header3) : [0, 0],
22796
23112
  signalMasks: () => process.signalMasks(),
22797
23113
  umask: () => process.umask,
22798
- cred: () => copyCred(process.cred),
22799
- writesBack: () => opts.program.abi === "wasi" && !done5,
22800
- ...clockViews(clocks)
23114
+ cred: () => copyCred(process.cred)
22801
23115
  };
22802
23116
  }
22803
23117
  function clockViews(clocks) {
@@ -23576,15 +23890,15 @@ function isRecord(value2) {
23576
23890
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
23577
23891
  }
23578
23892
  function serialized(reply) {
23579
- let plain2;
23893
+ let plain3;
23580
23894
  try {
23581
23895
  const text = JSON.stringify(reply);
23582
- plain2 = text === void 0 ? void 0 : JSON.parse(text);
23896
+ plain3 = text === void 0 ? void 0 : JSON.parse(text);
23583
23897
  } catch (err) {
23584
23898
  return JSON.stringify(errorReply("EIO", lineOf2(err)));
23585
23899
  }
23586
- if (!isRecord(plain2)) return JSON.stringify(errorReply("EIO", "the vault gave no reply"));
23587
- const { v: _, ...rest2 } = plain2;
23900
+ if (!isRecord(plain3)) return JSON.stringify(errorReply("EIO", "the vault gave no reply"));
23901
+ const { v: _, ...rest2 } = plain3;
23588
23902
  return JSON.stringify({ v: 1, ...rest2 });
23589
23903
  }
23590
23904
  function lineOf2(err) {
@@ -24115,8 +24429,8 @@ var FSA_CAPABILITIES = {
24115
24429
  ranges: true,
24116
24430
  sessions: true
24117
24431
  };
24118
- var codeOf4 = (err) => err?.code;
24119
- var denied = (err) => codeOf4(err) === "EACCES" || err?.name === "NotAllowedError";
24432
+ var codeOf5 = (err) => err?.code;
24433
+ var denied = (err) => codeOf5(err) === "EACCES" || err?.name === "NotAllowedError";
24120
24434
  function attrOf(st) {
24121
24435
  return {
24122
24436
  kind: st.isDirectory ? "directory" : st.isSymbolicLink ? "symlink" : "file",
@@ -24138,7 +24452,7 @@ function kernelFsHandlers(fs) {
24138
24452
  try {
24139
24453
  return await fs.stat(path);
24140
24454
  } catch (err) {
24141
- if (codeOf4(err) === "ENOENT") return void 0;
24455
+ if (codeOf5(err) === "ENOENT") return void 0;
24142
24456
  throw err;
24143
24457
  }
24144
24458
  }
@@ -24331,7 +24645,7 @@ function parseFstab(text) {
24331
24645
  });
24332
24646
  return lines2;
24333
24647
  }
24334
- function codeOf5(err) {
24648
+ function codeOf6(err) {
24335
24649
  const code = err?.code;
24336
24650
  return typeof code === "string" ? code : "EIO";
24337
24651
  }
@@ -24369,18 +24683,18 @@ async function mountLine({ line, spec, invalid }, mount, signal, retries, discar
24369
24683
  break;
24370
24684
  } catch (err) {
24371
24685
  failed3 = err;
24372
- if (FINAL.has(codeOf5(err)) || attempt === retries.length) break;
24686
+ if (FINAL.has(codeOf6(err)) || attempt === retries.length) break;
24373
24687
  await wait(retries[attempt], signal);
24374
24688
  }
24375
24689
  }
24376
- const code = codeOf5(failed3);
24690
+ const code = codeOf6(failed3);
24377
24691
  return { line, target: spec.target, code, error: String(failed3?.message ?? code) };
24378
24692
  }
24379
24693
 
24380
24694
  // src/mount/hostfs.ts
24381
24695
  var HOSTFS_IO = 16 * 1024 * 1024;
24382
- var codeOf6 = (err) => err?.code;
24383
- var unreachable = (err) => codeOf6(err) === "ENOTCONN";
24696
+ var codeOf7 = (err) => err?.code;
24697
+ var unreachable = (err) => codeOf7(err) === "ENOTCONN";
24384
24698
  function rel(path) {
24385
24699
  return path.replace(/^\/+/, "");
24386
24700
  }
@@ -24557,7 +24871,7 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
24557
24871
  try {
24558
24872
  return { opened: await opening2(), restore: void 0 };
24559
24873
  } catch (err) {
24560
- if (!flags2.write || codeOf6(err) !== "EACCES") throw err;
24874
+ if (!flags2.write || codeOf7(err) !== "EACCES") throw err;
24561
24875
  const was = await client.call("stat", { path: rel(path) });
24562
24876
  const mode = was.mode ?? 0;
24563
24877
  if (mode & 128) throw err;
@@ -25546,13 +25860,13 @@ function splitWords(text) {
25546
25860
  while (piece.lastIndex < text.length) {
25547
25861
  const m = piece.exec(text);
25548
25862
  if (!m) return void 0;
25549
- const [, single, double, escaped, plain2, space] = m;
25863
+ const [, single, double, escaped, plain3, space] = m;
25550
25864
  if (space !== void 0) {
25551
25865
  if (word !== void 0) words2.push(word);
25552
25866
  word = void 0;
25553
25867
  continue;
25554
25868
  }
25555
- word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ?? plain2));
25869
+ word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ?? plain3));
25556
25870
  }
25557
25871
  if (word !== void 0) words2.push(word);
25558
25872
  return words2;
@@ -25777,14 +26091,14 @@ var Sudo = class {
25777
26091
  if (this.pending.has(cred.ruid)) return failed2("EBUSY", "sudo: another request is pending");
25778
26092
  this.pending.add(cred.ruid);
25779
26093
  try {
25780
- const answer = await this.ask(caller, self, target, parsed2.command, path, cwd, signal);
25781
- if (typeof answer !== "string") return answer;
26094
+ const answer2 = await this.ask(caller, self, target, parsed2.command, path, cwd, signal);
26095
+ if (typeof answer2 !== "string") return answer2;
25782
26096
  if (await this.canonical(call.cwd) !== cwd || !await this.reachable(cred, cwd)) {
25783
26097
  return failed2("EACCES", `sudo: ${call.cwd} changed while the request waited`);
25784
26098
  }
25785
26099
  const changed = await this.untrusted(path, cwd, word);
25786
26100
  if (changed) return changed;
25787
- if (answer === "always" && !await this.remember(self, target, cwd, argv)) {
26101
+ if (answer2 === "always" && !await this.remember(self, target, cwd, argv)) {
25788
26102
  return failed2("EIO", "sudo: the rule could not be recorded");
25789
26103
  }
25790
26104
  return grant();
@@ -25839,11 +26153,11 @@ ${lines2}
25839
26153
  );
25840
26154
  try {
25841
26155
  const answered2 = Promise.resolve().then(() => approve(req, { signal: control.signal })).catch(() => "deny");
25842
- const answer = await Promise.race([answered2, aborted2]);
25843
- if (answer === "aborted" || control.signal.aborted) {
26156
+ const answer2 = await Promise.race([answered2, aborted2]);
26157
+ if (answer2 === "aborted" || control.signal.aborted) {
25844
26158
  return control.signal.reason === "expired" ? failed2("ETIMEDOUT", "sudo: the request expired") : failed2("EINTR", "sudo: the request was withdrawn");
25845
26159
  }
25846
- return answer === "once" || answer === "always" ? answer : failed2("EACCES", "sudo: approval denied");
26160
+ return answer2 === "once" || answer2 === "always" ? answer2 : failed2("EACCES", "sudo: approval denied");
25847
26161
  } finally {
25848
26162
  clearTimeout(timer);
25849
26163
  requester.removeEventListener("abort", withdraw);
@@ -26745,16 +27059,52 @@ var Launcher = class {
26745
27059
  for (const bin of planned?.bins ?? []) await need(g, "exec", bin, R_OK | X_OK);
26746
27060
  if (planned?.target.copy) await need(g, "exec", planned.target.copy, R_OK | X_OK);
26747
27061
  }
26748
- async checkedPlan(req, { ppid, cred, scope }, fds) {
26749
- const refused3 = async (err) => {
27062
+ async checkedPlan(req, ctx, fds) {
27063
+ try {
27064
+ return await this.planOrSearch(req, ctx);
27065
+ } catch (err) {
26750
27066
  await fds.closeAll();
26751
- throw err.code === "EACCES" ? new SpawnError("EACCES") : err;
27067
+ throw err;
27068
+ }
27069
+ }
27070
+ async planOrSearch(req, ctx) {
27071
+ const bare = !req.file.includes("/") && !COMMAND2.test(req.file);
27072
+ try {
27073
+ return await this.planOne(req, ctx);
27074
+ } catch (err) {
27075
+ const code = codeOf8(err);
27076
+ const searched = bare && req.search !== false && (code === "ENOENT" || code === "ENOEXEC");
27077
+ if (!searched || await this.commandAt(req.file, ctx.scope)) throw err;
27078
+ const found = await this.onPath(req, ctx);
27079
+ if (found) return found;
27080
+ throw err;
27081
+ }
27082
+ }
27083
+ async onPath(req, ctx) {
27084
+ const path = req.env.PATH;
27085
+ if (typeof path !== "string") return void 0;
27086
+ let denied2 = false;
27087
+ for (const dir of path.split(":")) {
27088
+ const file = dir === "" ? `./${req.file}` : `${dir.replace(/\/+$/, "")}/${req.file}`;
27089
+ try {
27090
+ return await this.planOne({ ...req, file }, ctx);
27091
+ } catch (err) {
27092
+ const code = codeOf8(err);
27093
+ if (code === "EACCES") denied2 = true;
27094
+ else if (code !== "ENOENT" && code !== "ENOTDIR") throw err;
27095
+ }
27096
+ }
27097
+ if (denied2) throw new SpawnError("EACCES");
27098
+ return void 0;
27099
+ }
27100
+ async planOne(req, { ppid, cred, scope }) {
27101
+ const refused3 = (err) => {
27102
+ throw codeOf8(err) === "EACCES" ? new SpawnError("EACCES") : err;
26752
27103
  };
26753
27104
  const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused3);
26754
27105
  const planned = await this.plan(file, req.argv, req.cwd, scope, req.argv0);
26755
27106
  await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused3);
26756
27107
  if (planned) return planned;
26757
- await fds.closeAll();
26758
27108
  throw new SpawnError(await this.unrunnable(file, req.cwd, scope));
26759
27109
  }
26760
27110
  async enterable(g, cwd) {
@@ -26921,12 +27271,12 @@ var Launcher = class {
26921
27271
  return `${path}:${st.size}:${st.mtime.getTime()}`;
26922
27272
  }
26923
27273
  verified(path, caller, fs = this.base) {
26924
- const plain2 = () => fs.readFileBuffer(path);
26925
- return this.integrity ? this.integrity.read(path, caller, plain2) : plain2();
27274
+ const plain3 = () => fs.readFileBuffer(path);
27275
+ return this.integrity ? this.integrity.read(path, caller, plain3) : plain3();
26926
27276
  }
26927
27277
  keyed(path, caller, asked) {
26928
- const plain2 = async () => this.base.readFileBuffer(path);
26929
- return this.integrity ? this.integrity.readKeyed(path, caller, plain2, asked) : plain2().then((bytes) => ({ bytes }));
27278
+ const plain3 = async () => this.base.readFileBuffer(path);
27279
+ return this.integrity ? this.integrity.readKeyed(path, caller, plain3, asked) : plain3().then((bytes) => ({ bytes }));
26930
27280
  }
26931
27281
  cached(cache, key, load) {
26932
27282
  const hit = cache.get(key);
@@ -27123,7 +27473,7 @@ var Launcher = class {
27123
27473
  });
27124
27474
  return {
27125
27475
  source: {
27126
- read: (path, plain2) => integrity.readSource(path, caller(), plain2),
27476
+ read: (path, plain3) => integrity.readSource(path, caller(), plain3),
27127
27477
  open: (path, real) => integrity.openSource(path, caller(), real)
27128
27478
  }
27129
27479
  };
@@ -28030,9 +28380,9 @@ var Launcher = class {
28030
28380
  }
28031
28381
  );
28032
28382
  }
28033
- environment(cwd, extra, account, login = false) {
28383
+ environment(cwd, extra, account, login2 = false) {
28034
28384
  const env = {
28035
- ...login ? networkEnv(this.hostname) : this.env,
28385
+ ...login2 ? networkEnv(this.hostname) : this.env,
28036
28386
  ...userEnv(account, this.pnpmHome),
28037
28387
  PWD: cwd,
28038
28388
  ...extra
@@ -28259,6 +28609,9 @@ var Launcher = class {
28259
28609
  function cronLocks() {
28260
28610
  return globalThis.navigator?.locks;
28261
28611
  }
28612
+ function codeOf8(err) {
28613
+ return err?.code;
28614
+ }
28262
28615
 
28263
28616
  // src/pin.ts
28264
28617
  function pinScript(url) {
@@ -28296,14 +28649,14 @@ function clipboardAsker(port) {
28296
28649
  await ask("write", stamp, text);
28297
28650
  }
28298
28651
  };
28299
- const answer = ({ id: id2, text, error }) => {
28652
+ const answer2 = ({ id: id2, text, error }) => {
28300
28653
  const waiting = asks.get(id2);
28301
28654
  if (!waiting) return;
28302
28655
  asks.delete(id2);
28303
28656
  if (error) waiting.reject(Object.assign(new Error(error.message), { name: error.name }));
28304
28657
  else waiting.resolve(text);
28305
28658
  };
28306
- return { hook, answer };
28659
+ return { hook, answer: answer2 };
28307
28660
  }
28308
28661
 
28309
28662
  // src/integrity-relay.ts
@@ -28317,14 +28670,14 @@ function integrityAsker(port) {
28317
28670
  port.postMessage({ integrityAsk: { id: id2, path } });
28318
28671
  return waiting.promise;
28319
28672
  };
28320
- const answer = ({ id: id2, hash, error }) => {
28673
+ const answer2 = ({ id: id2, hash, error }) => {
28321
28674
  const waiting = asks.get(id2);
28322
28675
  if (!waiting) return;
28323
28676
  asks.delete(id2);
28324
28677
  if (error !== void 0) waiting.reject(new Error(error));
28325
28678
  else waiting.resolve(hash);
28326
28679
  };
28327
- return { lookup: lookup2, answer };
28680
+ return { lookup: lookup2, answer: answer2 };
28328
28681
  }
28329
28682
 
28330
28683
  // src/kernel/net/remote-transport.ts
@@ -28548,14 +28901,14 @@ function sealedAsker(port) {
28548
28901
  port.postMessage({ sealedAsk: { id: id2, req } });
28549
28902
  return waiting.promise.finally(() => signal.removeEventListener("abort", abort));
28550
28903
  };
28551
- const answer = ({ id: id2, reply, error }) => {
28904
+ const answer2 = ({ id: id2, reply, error }) => {
28552
28905
  const waiting = asks.get(id2);
28553
28906
  if (!waiting) return;
28554
28907
  asks.delete(id2);
28555
28908
  if (reply) waiting.resolve(reply);
28556
28909
  else waiting.reject(new Error(error ?? "no reply"));
28557
28910
  };
28558
- return { hook, answer };
28911
+ return { hook, answer: answer2 };
28559
28912
  }
28560
28913
 
28561
28914
  // src/serve.ts
@@ -28668,8 +29021,8 @@ function sudoApprovals(port) {
28668
29021
  );
28669
29022
  port.postMessage({ sudoAsk: req });
28670
29023
  }),
28671
- answer({ id: id2, answer }) {
28672
- waiting.get(id2)?.(answer);
29024
+ answer({ id: id2, answer: answer2 }) {
29025
+ waiting.get(id2)?.(answer2);
28673
29026
  waiting.delete(id2);
28674
29027
  }
28675
29028
  };
@@ -28763,10 +29116,10 @@ function policyAsker(port) {
28763
29116
  return {
28764
29117
  mountPolicy: (policy) => policy === void 0 ? {} : { processMounts: policy === "ask" ? askPolicy : policy },
28765
29118
  allowed(data) {
28766
- const answer = data.mountAllowed;
28767
- if (!answer) return false;
28768
- policies.get(answer.id)?.(answer.allowed);
28769
- policies.delete(answer.id);
29119
+ const answer2 = data.mountAllowed;
29120
+ if (!answer2) return false;
29121
+ policies.get(answer2.id)?.(answer2.allowed);
29122
+ policies.delete(answer2.id);
28770
29123
  return true;
28771
29124
  }
28772
29125
  };