@ai-ecoverse/slicc-kernel 1.27.0 → 1.29.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.
package/dist/node.js CHANGED
@@ -465,6 +465,170 @@ var FdTable = class _FdTable {
465
465
  }
466
466
  };
467
467
 
468
+ // src/process/wasi/wasi-abi.ts
469
+ var E = {
470
+ SUCCESS: 0,
471
+ "2BIG": 1,
472
+ ACCES: 2,
473
+ ADDRINUSE: 3,
474
+ ADDRNOTAVAIL: 4,
475
+ AFNOSUPPORT: 5,
476
+ AGAIN: 6,
477
+ ALREADY: 7,
478
+ BADF: 8,
479
+ BADMSG: 9,
480
+ BUSY: 10,
481
+ CANCELED: 11,
482
+ CHILD: 12,
483
+ CONNABORTED: 13,
484
+ CONNREFUSED: 14,
485
+ CONNRESET: 15,
486
+ DEADLK: 16,
487
+ DESTADDRREQ: 17,
488
+ DOM: 18,
489
+ DQUOT: 19,
490
+ EXIST: 20,
491
+ FAULT: 21,
492
+ FBIG: 22,
493
+ HOSTUNREACH: 23,
494
+ IDRM: 24,
495
+ ILSEQ: 25,
496
+ INPROGRESS: 26,
497
+ INTR: 27,
498
+ INVAL: 28,
499
+ IO: 29,
500
+ ISCONN: 30,
501
+ ISDIR: 31,
502
+ LOOP: 32,
503
+ MFILE: 33,
504
+ MLINK: 34,
505
+ MSGSIZE: 35,
506
+ MULTIHOP: 36,
507
+ NAMETOOLONG: 37,
508
+ NETDOWN: 38,
509
+ NETRESET: 39,
510
+ NETUNREACH: 40,
511
+ NFILE: 41,
512
+ NOBUFS: 42,
513
+ NODEV: 43,
514
+ NOENT: 44,
515
+ NOEXEC: 45,
516
+ NOLCK: 46,
517
+ NOLINK: 47,
518
+ NOMEM: 48,
519
+ NOMSG: 49,
520
+ NOPROTOOPT: 50,
521
+ NOSPC: 51,
522
+ NOSYS: 52,
523
+ NOTCONN: 53,
524
+ NOTDIR: 54,
525
+ NOTEMPTY: 55,
526
+ NOTRECOVERABLE: 56,
527
+ NOTSOCK: 57,
528
+ NOTSUP: 58,
529
+ NOTTY: 59,
530
+ NXIO: 60,
531
+ OVERFLOW: 61,
532
+ OWNERDEAD: 62,
533
+ PERM: 63,
534
+ PIPE: 64,
535
+ PROTO: 65,
536
+ PROTONOSUPPORT: 66,
537
+ PROTOTYPE: 67,
538
+ RANGE: 68,
539
+ ROFS: 69,
540
+ SPIPE: 70,
541
+ SRCH: 71,
542
+ STALE: 72,
543
+ TIMEDOUT: 73,
544
+ TXTBSY: 74,
545
+ XDEV: 75,
546
+ NOTCAPABLE: 76
547
+ };
548
+ var RIGHTS = {
549
+ FD_DATASYNC: 1n << 0n,
550
+ FD_READ: 1n << 1n,
551
+ FD_SEEK: 1n << 2n,
552
+ FD_FDSTAT_SET_FLAGS: 1n << 3n,
553
+ FD_SYNC: 1n << 4n,
554
+ FD_TELL: 1n << 5n,
555
+ FD_WRITE: 1n << 6n,
556
+ ALL: (1n << 30n) - 1n
557
+ };
558
+ var WASI_SIGNAL_TO_POSIX = Object.fromEntries(
559
+ Array.from({ length: 30 }, (_, i) => [i + 1, i + 1 < 16 ? i + 1 : i + 2])
560
+ );
561
+
562
+ // src/process/wasi-errno.ts
563
+ var WASI_ERRNO = {
564
+ ...Object.fromEntries(Object.entries(E).map(([name2, errno]) => [`E${name2}`, errno])),
565
+ EWOULDBLOCK: E.AGAIN,
566
+ ENOTSUP: 138,
567
+ EOPNOTSUPP: 138,
568
+ ENOMEDIUM: 148
569
+ };
570
+ function wasiErrno(code) {
571
+ return WASI_ERRNO[code] ?? E.IO;
572
+ }
573
+
574
+ // src/kernel/net/uplink-socket.ts
575
+ var CHUNK = 64 * 1024;
576
+ function hostPort(text) {
577
+ const match = /^\[?([^\]]*?)\]?:(\d{1,5})$/.exec(text);
578
+ const port = Number(match?.[2]);
579
+ const host = match?.[1];
580
+ if (!host || port > 65535) return void 0;
581
+ return { host, port };
582
+ }
583
+ async function inbound(conn, rx) {
584
+ for (; ; ) {
585
+ while (!rx.writeReady) await rx.changed();
586
+ if (rx.readersGone) return;
587
+ const bytes = await conn.read();
588
+ if (!bytes) return;
589
+ await rx.write(bytes);
590
+ }
591
+ }
592
+ async function outbound(conn, tx) {
593
+ for (; ; ) {
594
+ const bytes = await tx.read(CHUNK);
595
+ if (bytes.length === 0) {
596
+ conn.closeWrite();
597
+ return;
598
+ }
599
+ for (let at = 0; at < bytes.length; ) {
600
+ const n = await conn.write(bytes.subarray(at));
601
+ if (!(n > 0)) throw new Error("the uplink wrote nothing");
602
+ at += n;
603
+ }
604
+ }
605
+ }
606
+ async function released(rx, tx) {
607
+ while (!(rx.readersGone && tx.writersGone)) await Promise.race([rx.changed(), tx.changed()]);
608
+ }
609
+ function uplinkLink(conn, onReset) {
610
+ const rx = new KernelPipe();
611
+ const tx = new KernelPipe();
612
+ for (const pipe of [rx, tx]) {
613
+ pipe.openRead();
614
+ pipe.openWrite();
615
+ }
616
+ let open = true;
617
+ const close = () => {
618
+ if (!open) return;
619
+ open = false;
620
+ conn.close();
621
+ };
622
+ void inbound(conn, rx).catch(() => {
623
+ onReset();
624
+ close();
625
+ tx.closeRead();
626
+ }).finally(() => rx.closeWrite());
627
+ void outbound(conn, tx).catch(close).finally(() => tx.closeRead());
628
+ void released(rx, tx).then(close);
629
+ return { rx, tx };
630
+ }
631
+
468
632
  // src/kernel/socket.ts
469
633
  var SOMAXCONN = 4096;
470
634
  var EPHEMERAL_FIRST = 32768;
@@ -482,6 +646,21 @@ var AF_INET = 2;
482
646
  var SHUT_RD = 0;
483
647
  var SHUT_WR = 1;
484
648
  var SHUT_RDWR = 2;
649
+ var DIAL_TIMEOUT_MS = 3e4;
650
+ var DIAL_ERRORS = [
651
+ "ECONNREFUSED",
652
+ "ENETUNREACH",
653
+ "EHOSTUNREACH",
654
+ "ETIMEDOUT",
655
+ "ECONNRESET"
656
+ ];
657
+ function dialError(e, timedOut, closed) {
658
+ if (timedOut) return new KernelError("ETIMEDOUT");
659
+ if (closed) return new KernelError("ECONNABORTED");
660
+ const code = e?.code;
661
+ const known = DIAL_ERRORS.find((errno) => errno === code);
662
+ return new KernelError(known ?? "EHOSTUNREACH");
663
+ }
485
664
  function isLoopback(host) {
486
665
  return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host);
487
666
  }
@@ -530,6 +709,9 @@ var KernelSocket = class _KernelSocket {
530
709
  net;
531
710
  domain;
532
711
  state = "open";
712
+ dialing;
713
+ failed;
714
+ reset = false;
533
715
  local;
534
716
  peer;
535
717
  link;
@@ -537,7 +719,7 @@ var KernelSocket = class _KernelSocket {
537
719
  writeShut = false;
538
720
  queue = [];
539
721
  backlog = 0;
540
- bound = false;
722
+ boundAt;
541
723
  changes = new Changes();
542
724
  options = /* @__PURE__ */ new Map();
543
725
  constructor(net, domain) {
@@ -559,12 +741,16 @@ var KernelSocket = class _KernelSocket {
559
741
  async read(max, signal) {
560
742
  const { rx } = this.connection();
561
743
  if (this.readShut || max <= 0) return new Uint8Array(0);
562
- return pipeCall(() => rx.read(max, signal));
744
+ const bytes = await pipeCall(() => rx.read(max, signal));
745
+ if (bytes.length === 0 && this.reset) throw new KernelError("ECONNRESET");
746
+ return bytes;
563
747
  }
564
748
  async peek(max, signal) {
565
749
  const { rx } = this.connection();
566
750
  if (this.readShut || max <= 0) return new Uint8Array(0);
567
- return pipeCall(() => rx.peek(max, signal));
751
+ const bytes = await pipeCall(() => rx.peek(max, signal));
752
+ if (bytes.length === 0 && this.reset) throw new KernelError("ECONNRESET");
753
+ return bytes;
568
754
  }
569
755
  async write(bytes, signal) {
570
756
  const { tx } = this.connection();
@@ -575,6 +761,8 @@ var KernelSocket = class _KernelSocket {
575
761
  if (this.state === "listening") {
576
762
  return { readable: this.queue.length > 0, writable: false, hangup: false };
577
763
  }
764
+ if (this.state === "connecting") return { readable: false, writable: false, hangup: false };
765
+ if (this.failed) return { readable: true, writable: true, hangup: true };
578
766
  if (this.state !== "connected" || !this.link) {
579
767
  return { readable: false, writable: false, hangup: true };
580
768
  }
@@ -596,7 +784,7 @@ var KernelSocket = class _KernelSocket {
596
784
  if (this.state !== "open" || this.local) throw new KernelError("EINVAL");
597
785
  if (addr.family !== this.domain) throw new KernelError("EAFNOSUPPORT");
598
786
  this.local = this.net.bind(this, addr);
599
- this.bound = true;
787
+ this.boundAt = this.local;
600
788
  }
601
789
  listen(backlog) {
602
790
  if (this.state === "connected") throw new KernelError("EISCONN");
@@ -623,15 +811,19 @@ var KernelSocket = class _KernelSocket {
623
811
  this.changes.wake();
624
812
  return true;
625
813
  }
626
- connect(addr) {
814
+ connect(addr, viaUplink = true) {
627
815
  if (this.state === "connected") throw new KernelError("EISCONN");
816
+ if (this.state === "connecting") throw new KernelError("EALREADY");
628
817
  if (this.state !== "open") throw new KernelError("EINVAL");
629
818
  if (addr.family !== this.domain) throw new KernelError("EAFNOSUPPORT");
819
+ this.failed = void 0;
820
+ const route = viaUplink && addr.family === "inet" ? this.net.uplinkFor(addr.host) : void 0;
821
+ if (route) return this.dial(addr, route);
630
822
  const target = this.net.target(addr);
631
823
  if (!this.local) {
632
824
  if (addr.family === "inet") {
633
825
  this.local = this.net.bind(this, { family: "inet", host: "127.0.0.1", port: 0 });
634
- this.bound = true;
826
+ this.boundAt = this.local;
635
827
  } else this.local = { family: "unix", path: "" };
636
828
  }
637
829
  const server = new _KernelSocket(this.net, this.domain);
@@ -644,6 +836,52 @@ var KernelSocket = class _KernelSocket {
644
836
  server.close();
645
837
  throw new KernelError("ECONNREFUSED");
646
838
  }
839
+ return void 0;
840
+ }
841
+ dial(addr, route) {
842
+ this.state = "connecting";
843
+ const abort = new AbortController();
844
+ this.dialing = abort;
845
+ let timedOut = false;
846
+ const timer = setTimeout(() => {
847
+ timedOut = true;
848
+ abort.abort(new KernelError("ETIMEDOUT"));
849
+ }, route.timeoutMs ?? DIAL_TIMEOUT_MS);
850
+ const abandoned = new Promise((_, reject) => {
851
+ abort.signal.addEventListener("abort", () => reject(abort.signal.reason), { once: true });
852
+ });
853
+ const { host, port } = addr;
854
+ const dialled = new Promise(
855
+ (resolve) => resolve(route.uplink.dial({ network: "tcp", host, port, signal: abort.signal }))
856
+ );
857
+ dialled.then(
858
+ (conn) => abort.signal.aborted && conn.close(),
859
+ () => void 0
860
+ );
861
+ return Promise.race([dialled, abandoned]).then(
862
+ (conn) => {
863
+ if (abort.signal.aborted) throw dialError(abort.signal.reason, timedOut, true);
864
+ this.local = { family: "inet", host: "0.0.0.0", port: 0, ...hostPort(conn.localAddr) };
865
+ this.peer = { ...addr, ...hostPort(conn.remoteAddr) };
866
+ this.dialing = void 0;
867
+ this.attach(
868
+ uplinkLink(conn, () => {
869
+ this.reset = true;
870
+ this.changes.wake();
871
+ })
872
+ );
873
+ },
874
+ (e) => {
875
+ const error = dialError(e, timedOut, abort.signal.aborted);
876
+ if (this.dialing === abort) {
877
+ this.dialing = void 0;
878
+ this.failed = error.code;
879
+ this.state = "open";
880
+ this.changes.wake();
881
+ }
882
+ throw error;
883
+ }
884
+ ).finally(() => clearTimeout(timer));
647
885
  }
648
886
  unlink() {
649
887
  const link2 = this.link;
@@ -673,8 +911,11 @@ var KernelSocket = class _KernelSocket {
673
911
  switch (name2) {
674
912
  case SO_TYPE:
675
913
  return SOCK_STREAM;
676
- case SO_ERROR:
677
- return 0;
914
+ case SO_ERROR: {
915
+ const failed = this.failed;
916
+ this.failed = void 0;
917
+ return failed ? wasiErrno(failed) : 0;
918
+ }
678
919
  case SO_ACCEPTCONN:
679
920
  return this.state === "listening" ? 1 : 0;
680
921
  case SO_DOMAIN:
@@ -692,6 +933,8 @@ var KernelSocket = class _KernelSocket {
692
933
  close() {
693
934
  const was = this.state;
694
935
  this.state = "closed";
936
+ this.dialing?.abort(new KernelError("ECONNABORTED"));
937
+ this.dialing = void 0;
695
938
  if (was === "listening") {
696
939
  for (const pending of this.queue.splice(0)) pending.close();
697
940
  }
@@ -701,8 +944,8 @@ var KernelSocket = class _KernelSocket {
701
944
  this.readShut = true;
702
945
  this.writeShut = true;
703
946
  }
704
- if (this.bound && this.local) this.net.release(this.local, this);
705
- this.bound = false;
947
+ if (this.boundAt) this.net.release(this.boundAt, this);
948
+ this.boundAt = void 0;
706
949
  this.changes.wake();
707
950
  }
708
951
  static pair(net, domain) {
@@ -725,6 +968,15 @@ var LoopbackNet = class {
725
968
  activators = /* @__PURE__ */ new Map();
726
969
  internal = /* @__PURE__ */ new Set();
727
970
  nextEphemeral = EPHEMERAL_FIRST;
971
+ route;
972
+ useUplink(route) {
973
+ this.route = route;
974
+ }
975
+ uplinkFor(host) {
976
+ const route = this.route;
977
+ if (!route) return void 0;
978
+ return route.routes.classify(host) === "uplink" ? route : void 0;
979
+ }
728
980
  kernelOnly(port, reserve = false) {
729
981
  if (reserve) this.internal.add(port);
730
982
  return this.internal.has(port);
@@ -743,7 +995,7 @@ var LoopbackNet = class {
743
995
  }
744
996
  connect(addr) {
745
997
  const socket = this.socket(addr.family);
746
- socket.connect(addr);
998
+ void socket.connect(addr, false);
747
999
  return socket;
748
1000
  }
749
1001
  bind(socket, addr) {
@@ -784,7 +1036,7 @@ var LoopbackNet = class {
784
1036
  };
785
1037
 
786
1038
  // src/kernel/dial.ts
787
- var CHUNK = 64 * 1024;
1039
+ var CHUNK2 = 64 * 1024;
788
1040
  var LOOPBACK_NAMES = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
789
1041
  function dialSocket(net, port, host = "127.0.0.1") {
790
1042
  if (!Number.isInteger(port) || port < 1 || port > 65535) throw new KernelError("EINVAL");
@@ -849,7 +1101,7 @@ function serveSocket(socket, port, onClose) {
849
1101
  for (; ; ) {
850
1102
  await turn();
851
1103
  if (closed) return;
852
- const chunk2 = await socket.read(CHUNK);
1104
+ const chunk2 = await socket.read(CHUNK2);
853
1105
  if (chunk2.length === 0) break;
854
1106
  credit--;
855
1107
  send(chunk2, [chunk2.buffer]);
@@ -1084,7 +1336,7 @@ function serveTransport(peer, transport) {
1084
1336
  }
1085
1337
 
1086
1338
  // src/client/protocol.ts
1087
- var PROTOCOL = [1, 6];
1339
+ var PROTOCOL = [1, 7];
1088
1340
  var FS_METHODS = [
1089
1341
  "readFile",
1090
1342
  "writeFile",
@@ -2807,6 +3059,7 @@ function commandOf(pkg, name2, raw, packageAbi, shared) {
2807
3059
  glue,
2808
3060
  wasm,
2809
3061
  argv0,
3062
+ ...raw.argv0Path === true ? { argv0Path: true } : {},
2810
3063
  ...args ? { args } : {},
2811
3064
  ...withEnv,
2812
3065
  ...imports ? { imports } : {}
@@ -5786,6 +6039,7 @@ function answerOf(result) {
5786
6039
  ...typeof answer?.ttl === "number" && answer.ttl >= 0 ? { ttl: answer.ttl } : {}
5787
6040
  };
5788
6041
  }
6042
+ var NEVER = new Routes(true);
5789
6043
 
5790
6044
  // src/kernel/net/resolver.ts
5791
6045
  var RESOLVE_TTL_MAX = 60;
@@ -6431,10 +6685,15 @@ async function socketSyscall(req, proc) {
6431
6685
  return ok();
6432
6686
  case "sock-accept":
6433
6687
  return ok(await accept(proc, req.fd, req.nonblock));
6434
- case "sock-connect":
6435
- socketAt(fds, req.fd).connect(req.addr);
6436
- if (req.nonblock) throw new KernelError("EINPROGRESS");
6688
+ case "sock-connect": {
6689
+ const dialing = socketAt(fds, req.fd).connect(req.addr);
6690
+ if (req.nonblock) {
6691
+ dialing?.catch(() => void 0);
6692
+ throw new KernelError("EINPROGRESS");
6693
+ }
6694
+ if (dialing !== void 0) await interruptible(dialing, proc.blocking());
6437
6695
  return ok();
6696
+ }
6438
6697
  case "sock-shutdown":
6439
6698
  socketAt(fds, req.fd).shutdown(req.how);
6440
6699
  return ok();
@@ -6456,6 +6715,13 @@ async function socketSyscall(req, proc) {
6456
6715
  }
6457
6716
  }
6458
6717
  }
6718
+ function interruptible(dialing, signal) {
6719
+ return new Promise((resolve, reject) => {
6720
+ const abort = () => reject(new KernelError("EINTR"));
6721
+ signal.addEventListener("abort", abort, { once: true });
6722
+ dialing.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
6723
+ });
6724
+ }
6459
6725
  function unnamed(domain) {
6460
6726
  return domain === "inet" ? { family: "inet", host: "0.0.0.0", port: 0 } : { family: "unix", path: "" };
6461
6727
  }
@@ -8885,7 +9151,7 @@ function memoryMedia() {
8885
9151
  }
8886
9152
 
8887
9153
  // src/mount/chunked.ts
8888
- var CHUNK2 = 1024 * 1024;
9154
+ var CHUNK3 = 1024 * 1024;
8889
9155
  var ChunkedBytes = class {
8890
9156
  chunks = [];
8891
9157
  size = 0;
@@ -8894,9 +9160,9 @@ var ChunkedBytes = class {
8894
9160
  if (end <= offset) return new Uint8Array(0);
8895
9161
  const out = new Uint8Array(end - offset);
8896
9162
  for (let at = offset; at < end; ) {
8897
- const index = Math.floor(at / CHUNK2);
8898
- const from = at - index * CHUNK2;
8899
- const n = Math.min(CHUNK2 - from, end - at);
9163
+ const index = Math.floor(at / CHUNK3);
9164
+ const from = at - index * CHUNK3;
9165
+ const n = Math.min(CHUNK3 - from, end - at);
8900
9166
  const chunk2 = this.chunks[index];
8901
9167
  if (chunk2) out.set(chunk2.subarray(from, Math.min(from + n, chunk2.length)), at - offset);
8902
9168
  at += n;
@@ -8907,10 +9173,10 @@ var ChunkedBytes = class {
8907
9173
  const whole = owned && bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength;
8908
9174
  for (let done4 = 0; done4 < bytes.length; ) {
8909
9175
  const at = offset + done4;
8910
- const index = Math.floor(at / CHUNK2);
8911
- const from = at - index * CHUNK2;
8912
- const n = Math.min(CHUNK2 - from, bytes.length - done4);
8913
- if (whole && n === CHUNK2 && bytes.length === CHUNK2) this.chunks[index] = bytes;
9176
+ const index = Math.floor(at / CHUNK3);
9177
+ const from = at - index * CHUNK3;
9178
+ const n = Math.min(CHUNK3 - from, bytes.length - done4);
9179
+ if (whole && n === CHUNK3 && bytes.length === CHUNK3) this.chunks[index] = bytes;
8914
9180
  else this.room(index, from + n).set(bytes.subarray(done4, done4 + n), from);
8915
9181
  done4 += n;
8916
9182
  }
@@ -8918,10 +9184,10 @@ var ChunkedBytes = class {
8918
9184
  }
8919
9185
  truncate(size) {
8920
9186
  if (size < this.size) {
8921
- const keep = Math.ceil(size / CHUNK2);
9187
+ const keep = Math.ceil(size / CHUNK3);
8922
9188
  this.chunks.length = Math.min(this.chunks.length, keep);
8923
9189
  const tail = this.chunks[keep - 1];
8924
- const from = size - (keep - 1) * CHUNK2;
9190
+ const from = size - (keep - 1) * CHUNK3;
8925
9191
  if (tail && from < tail.length) tail.fill(0, from);
8926
9192
  }
8927
9193
  this.size = size;
@@ -8929,7 +9195,7 @@ var ChunkedBytes = class {
8929
9195
  room(index, need) {
8930
9196
  const chunk2 = this.chunks[index];
8931
9197
  if (chunk2 && chunk2.length >= need) return chunk2;
8932
- const grown = new Uint8Array(Math.min(CHUNK2, Math.max(need, (chunk2?.length ?? 0) * 2)));
9198
+ const grown = new Uint8Array(Math.min(CHUNK3, Math.max(need, (chunk2?.length ?? 0) * 2)));
8933
9199
  if (chunk2) grown.set(chunk2);
8934
9200
  this.chunks[index] = grown;
8935
9201
  return grown;
@@ -9389,6 +9655,7 @@ var Launcher = class {
9389
9655
  this.routes = new Routes(options.uplink?.traits.ipv6 === true);
9390
9656
  if (options.uplink?.routes) this.routes.set(options.uplink.routes);
9391
9657
  this.resolver = new Resolver({ uplink: options.uplink, routes: this.routes });
9658
+ if (options.uplink) this.net.useUplink({ uplink: options.uplink, routes: this.routes });
9392
9659
  enableNetwork(this.net, {
9393
9660
  transport: this.transport,
9394
9661
  engine: kernelTlsEngine(packageTlsEngine(options.fs, this.modulesDir)),
@@ -9419,9 +9686,14 @@ var Launcher = class {
9419
9686
  const command = (await this.commands()).get(name2);
9420
9687
  return command && !command.script ? targetOf(command) : void 0;
9421
9688
  }
9422
- const glue = await followLinks(this.base, this.fs.resolvePath(cwd, file));
9689
+ const path = this.fs.resolvePath(cwd, file);
9690
+ const glue = await followLinks(this.base, path);
9423
9691
  const linked = COMMAND2.exec(glue)?.[1];
9424
- if (linked !== void 0) return this.resolve(`/bin/${linked}`, argv0, cwd);
9692
+ if (linked !== void 0) {
9693
+ const target = await this.resolve(`/bin/${linked}`, argv0, cwd);
9694
+ const byPath = !COMMAND2.test(path) && (await this.commands()).get(linked)?.argv0Path === true;
9695
+ return target && byPath ? { ...target, argv0: path } : target;
9696
+ }
9425
9697
  const head = await this.head(glue);
9426
9698
  if (!head) return void 0;
9427
9699
  if (isWasm(head)) {
@@ -9950,7 +10222,7 @@ function valid(name2) {
9950
10222
  throw new TypeError(`invalid name: ${name2}`);
9951
10223
  }
9952
10224
  }
9953
- var CHUNK3 = 1024 * 1024;
10225
+ var CHUNK4 = 1024 * 1024;
9954
10226
  function bytesOf(data) {
9955
10227
  if (typeof data === "string") return new TextEncoder().encode(data);
9956
10228
  if (data instanceof Blob) return data.arrayBuffer().then((buffer) => new Uint8Array(buffer));
@@ -9974,19 +10246,19 @@ var Chunks = class {
9974
10246
  }
9975
10247
  grow(end) {
9976
10248
  if (end <= this.size) return;
9977
- const last = Math.floor((end - 1) / CHUNK3);
9978
- for (let i = 0; i < last; i++) this.pad(i, CHUNK3);
9979
- this.pad(last, end - last * CHUNK3);
10249
+ const last = Math.floor((end - 1) / CHUNK4);
10250
+ for (let i = 0; i < last; i++) this.pad(i, CHUNK4);
10251
+ this.pad(last, end - last * CHUNK4);
9980
10252
  this.size = end;
9981
10253
  }
9982
10254
  async write(at, bytes) {
9983
10255
  if (bytes.length === 0) return;
9984
- const first = Math.floor(at / CHUNK3);
9985
- for (let i = 0; i < first; i++) this.pad(i, CHUNK3);
10256
+ const first = Math.floor(at / CHUNK4);
10257
+ for (let i = 0; i < first; i++) this.pad(i, CHUNK4);
9986
10258
  for (let done4 = 0; done4 < bytes.length; ) {
9987
- const index = Math.floor((at + done4) / CHUNK3);
9988
- const from = at + done4 - index * CHUNK3;
9989
- const n = Math.min(CHUNK3 - from, bytes.length - done4);
10259
+ const index = Math.floor((at + done4) / CHUNK4);
10260
+ const from = at + done4 - index * CHUNK4;
10261
+ const n = Math.min(CHUNK4 - from, bytes.length - done4);
9990
10262
  const view = bytes.subarray(done4, done4 + n);
9991
10263
  const part = view.buffer instanceof ArrayBuffer ? view : view.slice();
9992
10264
  const old = this.blobs[index];
@@ -10006,10 +10278,10 @@ var Chunks = class {
10006
10278
  this.grow(size);
10007
10279
  return;
10008
10280
  }
10009
- const keep = Math.ceil(size / CHUNK3);
10281
+ const keep = Math.ceil(size / CHUNK4);
10010
10282
  this.blobs.length = keep;
10011
10283
  if (keep > 0)
10012
- this.blobs[keep - 1] = this.blobs[keep - 1].slice(0, size - (keep - 1) * CHUNK3);
10284
+ this.blobs[keep - 1] = this.blobs[keep - 1].slice(0, size - (keep - 1) * CHUNK4);
10013
10285
  this.size = size;
10014
10286
  }
10015
10287
  };