@volter/tabnode 0.3.1 → 0.4.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.
@@ -6635,6 +6635,7 @@ function pidIsLive(pid) {
6635
6635
  return false;
6636
6636
  }
6637
6637
  const owners = /* @__PURE__ */ new Map();
6638
+ const allOwned = /* @__PURE__ */ new Map();
6638
6639
  const heldBy = /* @__PURE__ */ new WeakMap();
6639
6640
  const refHeld = /* @__PURE__ */ new WeakSet();
6640
6641
  const activeHandles = /* @__PURE__ */ new WeakSet();
@@ -6665,6 +6666,15 @@ function ownerOf(handle) {
6665
6666
  }
6666
6667
  function registerHandle(handle) {
6667
6668
  heldBy.set(handle, currentOwner());
6669
+ const token = heldBy.get(handle);
6670
+ if (token != null) {
6671
+ let owned = allOwned.get(token);
6672
+ if (!owned) {
6673
+ owned = /* @__PURE__ */ new Set();
6674
+ allOwned.set(token, owned);
6675
+ }
6676
+ owned.add(handle);
6677
+ }
6668
6678
  refHeld.add(handle);
6669
6679
  activeHandles.add(handle);
6670
6680
  hold(handle);
@@ -6686,6 +6696,12 @@ function handleHasRef(handle) {
6686
6696
  }
6687
6697
  function releaseHandle(handle) {
6688
6698
  drop(handle);
6699
+ const token = heldBy.get(handle);
6700
+ if (token != null) {
6701
+ const owned = allOwned.get(token);
6702
+ owned == null ? void 0 : owned.delete(handle);
6703
+ if ((owned == null ? void 0 : owned.size) === 0) allOwned.delete(token);
6704
+ }
6689
6705
  heldBy.delete(handle);
6690
6706
  refHeld.delete(handle);
6691
6707
  activeHandles.delete(handle);
@@ -6719,8 +6735,9 @@ function __releaseOwnedServers(token, stopTimers = true, stopProcess) {
6719
6735
  }
6720
6736
  }
6721
6737
  function __releaseOwnedHandles(token) {
6722
- const held = owners.get(token);
6738
+ const held = allOwned.get(token);
6723
6739
  if (!held) return;
6740
+ allOwned.delete(token);
6724
6741
  owners.delete(token);
6725
6742
  for (const handle of [...held]) {
6726
6743
  try {
@@ -6732,7 +6749,21 @@ function __releaseOwnedHandles(token) {
6732
6749
  function __adoptHandle(handle, token) {
6733
6750
  if (!handle) return;
6734
6751
  drop(handle);
6752
+ const previous = heldBy.get(handle);
6753
+ if (previous != null) {
6754
+ const owned = allOwned.get(previous);
6755
+ owned == null ? void 0 : owned.delete(handle);
6756
+ if ((owned == null ? void 0 : owned.size) === 0) allOwned.delete(previous);
6757
+ }
6735
6758
  heldBy.set(handle, token);
6759
+ if (token !== null) {
6760
+ let owned = allOwned.get(token);
6761
+ if (!owned) {
6762
+ owned = /* @__PURE__ */ new Set();
6763
+ allOwned.set(token, owned);
6764
+ }
6765
+ owned.add(handle);
6766
+ }
6736
6767
  hold(handle);
6737
6768
  }
6738
6769
  function ownedBytes(view) {
@@ -9077,7 +9108,9 @@ function refuseLinks(syscall, path2) {
9077
9108
  { code: "EPERM", errno: -1, syscall, path: path2 }
9078
9109
  );
9079
9110
  }
9080
- const pathModes = /* @__PURE__ */ new Map();
9111
+ function unsupportedMetadata(syscall) {
9112
+ throw Object.assign(new Error(`ENOTSUP: filesystem does not support ${syscall}`), { code: "ENOTSUP", syscall });
9113
+ }
9081
9114
  function treeHoldsLinks() {
9082
9115
  return vfs$1().holdsLinks === true;
9083
9116
  }
@@ -9141,19 +9174,18 @@ function fileFor(fd2) {
9141
9174
  return file;
9142
9175
  }
9143
9176
  function statArray(stats, bigint, path2) {
9144
- var _a3, _b3;
9177
+ var _a3, _b3, _c3;
9145
9178
  const mtime = stats.mtime instanceof Date ? stats.mtime.getTime() : Number(stats.mtimeMs ?? 0);
9146
9179
  const atime = stats.atime instanceof Date ? stats.atime.getTime() : Number(stats.atimeMs ?? mtime);
9147
9180
  const ctime = stats.ctime instanceof Date ? stats.ctime.getTime() : Number(stats.ctimeMs ?? mtime);
9148
9181
  const birth = stats.birthtime instanceof Date ? stats.birthtime.getTime() : Number(stats.birthtimeMs ?? mtime);
9149
9182
  const seconds = (ms2) => Math.floor(ms2 / 1e3);
9150
9183
  const nanos = (ms2) => Math.floor(ms2 % 1e3 * 1e6);
9151
- const stored = path2 !== void 0 ? pathModes.get(path2) : void 0;
9152
- const permissions = (stored !== void 0 ? stored : Number(stats.mode ?? 0)) & 4095;
9153
- const type2 = ((_a3 = stats.isDirectory) == null ? void 0 : _a3.call(stats)) ? S_IFDIR : ((_b3 = stats.isSymbolicLink) == null ? void 0 : _b3.call(stats)) ? S_IFLNK : S_IFREG;
9184
+ const permissions = Number(stats.mode ?? (((_a3 = stats.isDirectory) == null ? void 0 : _a3.call(stats)) ? 493 : 420)) & 4095;
9185
+ const type2 = ((_b3 = stats.isDirectory) == null ? void 0 : _b3.call(stats)) ? S_IFDIR : ((_c3 = stats.isSymbolicLink) == null ? void 0 : _c3.call(stats)) ? S_IFLNK : S_IFREG;
9154
9186
  const values = [
9155
9187
  Number(stats.dev ?? 0),
9156
- type2 | (permissions || (type2 === S_IFDIR ? 493 : 420)),
9188
+ type2 | permissions,
9157
9189
  Number(stats.nlink ?? 1),
9158
9190
  Number(stats.uid ?? 0),
9159
9191
  Number(stats.gid ?? 0),
@@ -9299,15 +9331,23 @@ class FSEvent {
9299
9331
  __privateAdd(this, _watcher, null);
9300
9332
  __publicField(this, "initialized", false);
9301
9333
  }
9302
- start(path2, _persistent, recursive, _encoding2) {
9334
+ start(path2, persistent, recursive, _encoding2) {
9303
9335
  const name = asPath(path2);
9304
9336
  const tree2 = vfs$1();
9337
+ const cwd = callingCwd();
9338
+ const owner = currentOwner();
9305
9339
  try {
9306
9340
  __privateSet(this, _watcher, tree2.watch(name, { recursive: Boolean(recursive) }, (event, filename) => {
9307
- var _a3;
9308
- (_a3 = this.onchange) == null ? void 0 : _a3.call(this, 0, event === "rename" ? "rename" : "change", filename ?? "");
9341
+ const notify = () => withFilesystem(tree2, () => withCwd(cwd, () => {
9342
+ var _a3;
9343
+ return (_a3 = this.onchange) == null ? void 0 : _a3.call(this, 0, event === "rename" ? "rename" : "change", filename ?? "");
9344
+ }));
9345
+ if (owner === null) notify();
9346
+ else enterRun(owner, notify);
9309
9347
  }));
9310
9348
  this.initialized = true;
9349
+ registerHandle(this);
9350
+ if (persistent === false) unrefHandle(this);
9311
9351
  return 0;
9312
9352
  } catch (error) {
9313
9353
  const code2 = error.code;
@@ -9316,6 +9356,7 @@ class FSEvent {
9316
9356
  }
9317
9357
  close() {
9318
9358
  var _a3;
9359
+ releaseHandle(this);
9319
9360
  this.initialized = false;
9320
9361
  try {
9321
9362
  (_a3 = __privateGet(this, _watcher)) == null ? void 0 : _a3.close();
@@ -9324,14 +9365,16 @@ class FSEvent {
9324
9365
  __privateSet(this, _watcher, null);
9325
9366
  }
9326
9367
  ref() {
9368
+ if (this.initialized) refHandle(this);
9327
9369
  }
9328
9370
  unref() {
9371
+ unrefHandle(this);
9329
9372
  }
9330
9373
  getAsyncId() {
9331
9374
  return 0;
9332
9375
  }
9333
9376
  hasRef() {
9334
- return this.initialized;
9377
+ return this.initialized && handleHasRef(this);
9335
9378
  }
9336
9379
  }
9337
9380
  _watcher = new WeakMap();
@@ -9428,6 +9471,9 @@ const fsBinding = {
9428
9471
  const tree2 = vfs$1();
9429
9472
  const bits = flagBits();
9430
9473
  const exists = tree2.existsSync(name);
9474
+ if (exists && ((flags & 3) !== 0 || (flags & (bits.create | bits.truncate | bits.append)) !== 0)) {
9475
+ tree2.accessSync(name, 2);
9476
+ }
9431
9477
  if ((flags & bits.excl) !== 0 && (flags & bits.create) !== 0 && exists) throw createNodeError$1("EEXIST", "open", name);
9432
9478
  if (!exists) {
9433
9479
  if ((flags & bits.create) === 0) throw createNodeError$1("ENOENT", "open", name);
@@ -9579,10 +9625,10 @@ const fsBinding = {
9579
9625
  return bigint ? BigInt64Array.from(values.map((value) => BigInt(value))) : Float64Array.from(values);
9580
9626
  });
9581
9627
  },
9582
- access(path2, _mode, req) {
9628
+ access(path2, mode, req) {
9583
9629
  return answer(req, () => {
9584
9630
  const name = asPath(path2);
9585
- if (!vfs$1().existsSync(name)) throw createNodeError$1("ENOENT", "access", name);
9631
+ vfs$1().accessSync(name, mode);
9586
9632
  return void 0;
9587
9633
  });
9588
9634
  },
@@ -9687,13 +9733,10 @@ const fsBinding = {
9687
9733
  if (tree2.existsSync(name)) {
9688
9734
  const stats = tree2.statSync(name);
9689
9735
  if (!recursive || !stats.isDirectory()) throw createNodeError$1("EEXIST", "mkdir", name);
9690
- const stored = pathModes.get(name);
9691
- if (stored !== void 0 && (stored & 511) !== wanted) throw createNodeError$1("EEXIST", "mkdir", name);
9692
- pathModes.set(name, wanted);
9693
9736
  return void 0;
9694
9737
  }
9695
9738
  tree2.mkdirSync(name, { recursive });
9696
- pathModes.set(name, wanted);
9739
+ tree2.chmodSync(name, wanted);
9697
9740
  return void 0;
9698
9741
  });
9699
9742
  },
@@ -9765,46 +9808,50 @@ const fsBinding = {
9765
9808
  }
9766
9809
  });
9767
9810
  },
9768
- // ---- the calls a page's filesystem has nothing to do -------------------
9769
- // Ownership and times are a kernel's bookkeeping. Permissions `chmod` sets
9770
- // are kept here, because a program that sets a mode and stats it back must
9771
- // see what it set, and a missing path is ENOENT as Node's is.
9811
+ // Metadata belongs to the filesystem, including a host's permission view.
9812
+ // Never keep a realm-global mode table or bypass that view for descriptors.
9772
9813
  chmod(path2, mode, req) {
9773
9814
  return answer(req, () => {
9774
9815
  const name = asPath(path2);
9775
- if (!vfs$1().existsSync(name)) throw createNodeError$1("ENOENT", "chmod", name);
9776
- pathModes.set(name, mode & 4095);
9816
+ vfs$1().chmodSync(name, mode);
9777
9817
  return void 0;
9778
9818
  });
9779
9819
  },
9780
9820
  fchmod(fd2, mode, req) {
9781
9821
  return answer(req, () => {
9782
9822
  const file = fileFor(fd2);
9783
- pathModes.set(file.path, mode & 4095);
9823
+ file.tree.chmodSync(file.path, mode);
9784
9824
  return void 0;
9785
9825
  });
9786
9826
  },
9787
- chown(path2, _uid, _gid, req) {
9788
- return answer(req, () => {
9789
- const name = asPath(path2);
9790
- if (!vfs$1().existsSync(name)) throw createNodeError$1("ENOENT", "chown", name);
9791
- return void 0;
9792
- });
9827
+ chown(_path, _uid, _gid, req) {
9828
+ return answer(req, () => unsupportedMetadata("chown"));
9793
9829
  },
9794
9830
  fchown(_fd, _uid, _gid, req) {
9795
- return answer(req, () => void 0);
9831
+ return answer(req, () => unsupportedMetadata("fchown"));
9796
9832
  },
9797
9833
  lchown(_path, _uid, _gid, req) {
9798
- return answer(req, () => void 0);
9834
+ return answer(req, () => unsupportedMetadata("lchown"));
9799
9835
  },
9800
- utimes(_path, _atime, _mtime, req) {
9801
- return answer(req, () => void 0);
9836
+ utimes(path2, atime, mtime, req) {
9837
+ return answer(req, () => {
9838
+ vfs$1().utimesSync(asPath(path2), new Date(atime * 1e3), new Date(mtime * 1e3));
9839
+ return void 0;
9840
+ });
9802
9841
  },
9803
- futimes(_fd, _atime, _mtime, req) {
9804
- return answer(req, () => void 0);
9842
+ futimes(fd2, atime, mtime, req) {
9843
+ return answer(req, () => {
9844
+ const file = fileFor(fd2);
9845
+ file.tree.utimesSync(file.path, new Date(atime * 1e3), new Date(mtime * 1e3));
9846
+ return void 0;
9847
+ });
9805
9848
  },
9806
- lutimes(_path, _atime, _mtime, req) {
9807
- return answer(req, () => void 0);
9849
+ lutimes(path2, atime, mtime, req) {
9850
+ return answer(req, () => {
9851
+ if (treeHoldsLinks()) return unsupportedMetadata("lutimes");
9852
+ vfs$1().utimesSync(asPath(path2), new Date(atime * 1e3), new Date(mtime * 1e3));
9853
+ return void 0;
9854
+ });
9808
9855
  },
9809
9856
  fsync(_fd, req) {
9810
9857
  return answer(req, () => void 0);
@@ -26407,6 +26454,17 @@ class VirtualFS {
26407
26454
  /**
26408
26455
  * Get stats for path
26409
26456
  */
26457
+ chmodSync(path2, mode) {
26458
+ const node = this.getNode(path2);
26459
+ if (!node) throw createNodeError("ENOENT", "chmod", path2);
26460
+ node.mode = mode & 4095;
26461
+ }
26462
+ utimesSync(path2, atime, mtime) {
26463
+ const node = this.getNode(path2);
26464
+ if (!node) throw createNodeError("ENOENT", "utimes", path2);
26465
+ node.atime = atime instanceof Date ? atime.getTime() : atime * 1e3;
26466
+ node.mtime = mtime instanceof Date ? mtime.getTime() : mtime * 1e3;
26467
+ }
26410
26468
  statSync(path2) {
26411
26469
  var _a3;
26412
26470
  const node = this.getNode(path2);
@@ -26425,7 +26483,7 @@ class VirtualFS {
26425
26483
  isFIFO: () => false,
26426
26484
  isSocket: () => false,
26427
26485
  size,
26428
- mode: node.type === "directory" ? 493 : 420,
26486
+ mode: node.mode ?? (node.type === "directory" ? 493 : 420),
26429
26487
  mtime: new Date(mtime),
26430
26488
  atime: new Date(atime),
26431
26489
  ctime: new Date(mtime),
@@ -68772,7 +68830,7 @@ function initChildProcess(vfs2) {
68772
68830
  };
68773
68831
  };
68774
68832
  const nodeCommand = uA("node", async (args, ctx) => {
68775
- var _a3, _b3;
68833
+ var _a3, _b3, _c3, _d3;
68776
68834
  if (!tree2) {
68777
68835
  return { stdout: "", stderr: "VFS not initialized\n", exitCode: 1 };
68778
68836
  }
@@ -68859,7 +68917,7 @@ function initChildProcess(vfs2) {
68859
68917
  // open, as a pipe whose writer has not closed.
68860
68918
  stdin: typeof ctx.stdin === "string" ? ctx.stdin : "",
68861
68919
  ...(streams == null ? void 0 : streams.held) || (streams == null ? void 0 : streams.stdinOpen) ? { stdinHeld: true } : {},
68862
- ...(streams == null ? void 0 : streams.held) ? { tty: true } : {},
68920
+ ...(streams == null ? void 0 : streams.held) || (streams == null ? void 0 : streams.terminal) ? { tty: true } : {},
68863
68921
  // The numbers this run was started with, so the guest's `process.pid`
68864
68922
  // is the one its parent's handle carries.
68865
68923
  ...runPid(runToken) ? { pid: runPid(runToken).pid, ppid: runPid(runToken).ppid } : {}
@@ -68901,12 +68959,28 @@ function initChildProcess(vfs2) {
68901
68959
  proc.argv0 = "node";
68902
68960
  proc.execArgv = execArgv;
68903
68961
  if (streams) streams.stdin = proc.stdin;
68904
- if (streams == null ? void 0 : streams.held) {
68962
+ if ((streams == null ? void 0 : streams.held) || (streams == null ? void 0 : streams.terminal)) {
68905
68963
  proc.stdout.isTTY = true;
68906
68964
  proc.stderr.isTTY = true;
68907
68965
  proc.stdin.isTTY = true;
68908
68966
  proc.stdin.setRawMode = () => proc.stdin;
68909
68967
  }
68968
+ const terminal = streams == null ? void 0 : streams.terminal;
68969
+ const resize = (columns, rows) => {
68970
+ for (const stream of [proc.stdout, proc.stderr]) {
68971
+ stream.columns = columns;
68972
+ stream.rows = rows;
68973
+ stream.emit("resize");
68974
+ }
68975
+ };
68976
+ let stopResize;
68977
+ let inputActive = true;
68978
+ let inputIterator;
68979
+ const readableInput = proc.stdin;
68980
+ const inputReading = () => {
68981
+ var _a4, _b4;
68982
+ return readableInput.readableFlowing === true || ((_a4 = readableInput._readableState) == null ? void 0 : _a4.reading) === true || ((_b4 = readableInput._readableState) == null ? void 0 : _b4.needReadable) === true || readableInput.listenerCount("data") > 0 || readableInput.listenerCount("readable") > 0;
68983
+ };
68910
68984
  if (Number.isInteger(channelFd) && channelFd >= 0 && runToken !== null) {
68911
68985
  enterRun(runToken, () => {
68912
68986
  attachChannel(proc, channelFd, channelSerialization);
@@ -68964,6 +69038,39 @@ ${reason.stack || ""}` : String(reason);
68964
69038
  };
68965
69039
  const detachUncaught = __onUncaughtException(proc, onUncaughtException);
68966
69040
  try {
69041
+ if (streams == null ? void 0 : streams.stdinStream) {
69042
+ inputIterator = streams.stdinStream[Symbol.asyncIterator]();
69043
+ const input = inputIterator;
69044
+ void (async () => {
69045
+ var _a4, _b4, _c4, _d4, _e3;
69046
+ const push = (chunk) => {
69047
+ if (runToken === null) proc.stdin.push(chunk);
69048
+ else enterRun(runToken, () => proc.stdin.push(chunk));
69049
+ };
69050
+ try {
69051
+ while (inputActive && !((_a4 = streams.signal) == null ? void 0 : _a4.aborted)) {
69052
+ while (inputActive && !((_b4 = streams.signal) == null ? void 0 : _b4.aborted) && (!inputReading() || readableInput.readableLength >= readableInput.readableHighWaterMark)) {
69053
+ await new Promise((resolve2) => (globalThis.__browserRuntimeNativeSetTimeout ?? setTimeout).call(globalThis, resolve2, 10));
69054
+ }
69055
+ if (!inputActive || ((_c4 = streams.signal) == null ? void 0 : _c4.aborted)) break;
69056
+ const next2 = await input.next();
69057
+ if (next2.done) break;
69058
+ if (!inputActive || ((_d4 = streams.signal) == null ? void 0 : _d4.aborted)) break;
69059
+ push(next2.value);
69060
+ }
69061
+ if (inputActive && !((_e3 = streams.signal) == null ? void 0 : _e3.aborted)) push(null);
69062
+ } catch (error) {
69063
+ if (inputActive) onUncaughtException(error);
69064
+ } finally {
69065
+ streams.stdinOpen = false;
69066
+ }
69067
+ })();
69068
+ }
69069
+ if (terminal) resize(terminal.columns, terminal.rows);
69070
+ stopResize = (_a3 = terminal == null ? void 0 : terminal.onResize) == null ? void 0 : _a3.call(terminal, (columns, rows) => {
69071
+ if (runToken === null) resize(columns, rows);
69072
+ else enterRun(runToken, () => resize(columns, rows));
69073
+ });
68967
69074
  let entrySettling;
68968
69075
  try {
68969
69076
  const runEntry = () => runtime2.runFile(resolvedPath);
@@ -69001,7 +69108,7 @@ ${error.stack || ""}` : String(error);
69001
69108
  }
69002
69109
  }
69003
69110
  const __ownsHandles = () => runToken !== null && (__ownedServerPorts(runToken).length > 0 || __ownedHandleCount(runToken) > 0);
69004
- const __printedThenWorking = () => pendingGuestTimers(proc) > 0 || heldWork().count > 0 || __ownsHandles();
69111
+ const __printedThenWorking = () => (streams == null ? void 0 : streams.stdinOpen) === true && inputReading() || pendingGuestTimers(proc) > 0 || heldWork().count > 0 || __ownsHandles();
69005
69112
  if ((stdout.length > 0 || stderr.length > 0) && !__printedThenWorking()) {
69006
69113
  await new Promise((r10) => (globalThis.__browserRuntimeNativeSetTimeout ?? setTimeout).call(globalThis, r10, 0));
69007
69114
  if (exitCalled) return { stdout, stderr, exitCode };
@@ -69024,16 +69131,16 @@ ${error.stack || ""}` : String(error);
69024
69131
  const startTime = Date.now();
69025
69132
  let lastOutputLen = stdout.length + stderr.length;
69026
69133
  let idleMs = 0;
69027
- const stillWorking = () => pendingGuestTimers(proc) > 0 || __ownsHandles();
69134
+ const stillWorking = () => (streams == null ? void 0 : streams.stdinOpen) === true && inputReading() || pendingGuestTimers(proc) > 0 || __ownsHandles();
69028
69135
  const isLongRunning = !!(streams == null ? void 0 : streams.held);
69029
69136
  while (!exitCalled) {
69030
- if ((_a3 = streams == null ? void 0 : streams.signal) == null ? void 0 : _a3.aborted) break;
69137
+ if ((_b3 = streams == null ? void 0 : streams.signal) == null ? void 0 : _b3.aborted) break;
69031
69138
  const raceResult = await Promise.race([
69032
69139
  exitPromise.then(() => "exit"),
69033
69140
  new Promise((r10) => (globalThis.__browserRuntimeNativeSetTimeout ?? setTimeout).call(globalThis, () => r10("tick"), CHECK_MS))
69034
69141
  ]);
69035
69142
  if (raceResult === "exit" || exitCalled) break;
69036
- if ((_b3 = streams == null ? void 0 : streams.signal) == null ? void 0 : _b3.aborted) break;
69143
+ if ((_c3 = streams == null ? void 0 : streams.signal) == null ? void 0 : _c3.aborted) break;
69037
69144
  const currentLen = stdout.length + stderr.length;
69038
69145
  if (currentLen > lastOutputLen) {
69039
69146
  lastOutputLen = currentLen;
@@ -69058,6 +69165,16 @@ ${error.stack || ""}` : String(error);
69058
69165
  } finally {
69059
69166
  detachRejections();
69060
69167
  detachUncaught();
69168
+ inputActive = false;
69169
+ try {
69170
+ void Promise.resolve((_d3 = inputIterator == null ? void 0 : inputIterator.return) == null ? void 0 : _d3.call(inputIterator)).catch(() => {
69171
+ });
69172
+ } catch {
69173
+ }
69174
+ try {
69175
+ stopResize == null ? void 0 : stopResize();
69176
+ } catch {
69177
+ }
69061
69178
  if (runToken !== null) {
69062
69179
  __releaseOwnedServers(runToken, false);
69063
69180
  __releaseOwnedHandles(runToken);
package/dist/index.d.ts CHANGED
@@ -55,6 +55,12 @@ export interface RunOptions {
55
55
  env?: Record<string, string>;
56
56
  /** What the shell reads on stdin, so a builtin reads what was piped to it. */
57
57
  stdin?: string;
58
+ stdinStream?: AsyncIterable<Uint8Array>;
59
+ terminal?: {
60
+ columns: number;
61
+ rows: number;
62
+ onResize?: (listener: (columns: number, rows: number) => void) => () => void;
63
+ };
58
64
  /** Callback for streaming stdout chunks as they arrive (for long-running commands like vitest watch) */
59
65
  onStdout?: (data: string) => void;
60
66
  /** Callback for streaming stderr chunks as they arrive */