@volter/tabnode 0.3.0 → 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.
- package/dist/assets/{runtime-worker-BcDCBbhG.js → runtime-worker-DoV8lqBn.js} +202 -61
- package/dist/index.d.ts +6 -0
- package/dist/index.mjs +229 -78
- package/dist/node-lib/binding/fs.d.ts +8 -8
- package/dist/server-bridge.d.ts +1 -0
- package/dist/shims/child_process.d.ts +6 -0
- package/dist/virtual-fs.d.ts +3 -0
- package/package.json +1 -1
- package/src/index.ts +6 -1
- package/src/node-lib/binding/fs.ts +66 -48
- package/src/node-lib/binding/handles.ts +27 -1
- package/src/server-bridge.ts +12 -2
- package/src/shims/child_process.ts +58 -4
- package/src/virtual-fs.ts +28 -3
|
@@ -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 =
|
|
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) {
|
|
@@ -7913,11 +7944,11 @@ function answerFilesystem(method, args) {
|
|
|
7913
7944
|
return answer2.apply(hostVfs, plain) ?? null;
|
|
7914
7945
|
}
|
|
7915
7946
|
const inodes = /* @__PURE__ */ new Map();
|
|
7916
|
-
let nextInode = 1;
|
|
7947
|
+
let nextInode$1 = 1;
|
|
7917
7948
|
function inodeOf(path2) {
|
|
7918
7949
|
let inode = inodes.get(path2);
|
|
7919
7950
|
if (inode === void 0) {
|
|
7920
|
-
inode = nextInode++;
|
|
7951
|
+
inode = nextInode$1++;
|
|
7921
7952
|
inodes.set(path2, inode);
|
|
7922
7953
|
}
|
|
7923
7954
|
return inode;
|
|
@@ -9077,7 +9108,9 @@ function refuseLinks(syscall, path2) {
|
|
|
9077
9108
|
{ code: "EPERM", errno: -1, syscall, path: path2 }
|
|
9078
9109
|
);
|
|
9079
9110
|
}
|
|
9080
|
-
|
|
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
|
|
9152
|
-
const
|
|
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 |
|
|
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,
|
|
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
|
-
|
|
9308
|
-
|
|
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,9 +9471,14 @@ 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);
|
|
9480
|
+
const parent = name.slice(0, name.lastIndexOf("/")) || "/";
|
|
9481
|
+
if (!tree2.statSync(parent).isDirectory()) throw createNodeError$1("ENOTDIR", "open", name);
|
|
9434
9482
|
tree2.writeFileSync(name, "");
|
|
9435
9483
|
} else if ((flags & bits.truncate) !== 0) {
|
|
9436
9484
|
tree2.writeFileSync(name, "");
|
|
@@ -9443,6 +9491,7 @@ const fsBinding = {
|
|
|
9443
9491
|
},
|
|
9444
9492
|
close(fd2, req) {
|
|
9445
9493
|
return answer(req, () => {
|
|
9494
|
+
fileFor(fd2);
|
|
9446
9495
|
openFiles.delete(fd2);
|
|
9447
9496
|
return void 0;
|
|
9448
9497
|
});
|
|
@@ -9451,6 +9500,7 @@ const fsBinding = {
|
|
|
9451
9500
|
read(fd2, buffer2, offset2, length, position, req) {
|
|
9452
9501
|
return answer(req, () => {
|
|
9453
9502
|
const file = fileFor(fd2);
|
|
9503
|
+
if ((file.flags & 3) === 1) throw createNodeError$1("EBADF", "read", file.path);
|
|
9454
9504
|
if (file.cached === void 0) file.cached = file.tree.readFileSync(file.path);
|
|
9455
9505
|
const bytes2 = file.cached;
|
|
9456
9506
|
const from = position === null || position === void 0 || position < 0 ? file.position : position;
|
|
@@ -9473,17 +9523,27 @@ const fsBinding = {
|
|
|
9473
9523
|
});
|
|
9474
9524
|
},
|
|
9475
9525
|
/** Node's fast path for `readFile` with an encoding it can decode itself. */
|
|
9476
|
-
readFileUtf8(path2,
|
|
9477
|
-
|
|
9526
|
+
readFileUtf8(path2, flags) {
|
|
9527
|
+
const owned = typeof path2 !== "number";
|
|
9528
|
+
const fd2 = owned ? fsBinding.open(path2, flags, 438) : path2;
|
|
9529
|
+
try {
|
|
9530
|
+
const file = fileFor(fd2);
|
|
9531
|
+
const bytes2 = new Uint8Array(file.tree.statSync(file.path).size);
|
|
9532
|
+
const length = fsBinding.read(fd2, bytes2, 0, bytes2.length, -1);
|
|
9533
|
+
return new TextDecoder().decode(bytes2.subarray(0, length));
|
|
9534
|
+
} finally {
|
|
9535
|
+
if (owned) fsBinding.close(fd2);
|
|
9536
|
+
}
|
|
9478
9537
|
},
|
|
9479
9538
|
// ---- writing ------------------------------------------------------------
|
|
9480
9539
|
writeBuffer(fd2, buffer2, offset2, length, position, req) {
|
|
9481
9540
|
return answer(req, () => {
|
|
9482
9541
|
const file = fileFor(fd2);
|
|
9542
|
+
if ((file.flags & 3) === 0) throw createNodeError$1("EBADF", "write", file.path);
|
|
9483
9543
|
const tree2 = file.tree;
|
|
9484
9544
|
const slice = buffer2.subarray(offset2, offset2 + length);
|
|
9485
9545
|
const existing = file.cached ?? (tree2.existsSync(file.path) ? tree2.readFileSync(file.path) : new Uint8Array(0));
|
|
9486
|
-
const at3 = position === null || position === void 0 || position < 0 ? file.position : position;
|
|
9546
|
+
const at3 = (file.flags & flagBits().append) !== 0 ? existing.length : position === null || position === void 0 || position < 0 ? file.position : position;
|
|
9487
9547
|
const size = Math.max(existing.length, at3 + slice.length);
|
|
9488
9548
|
const next2 = new Uint8Array(size);
|
|
9489
9549
|
next2.set(existing, 0);
|
|
@@ -9513,15 +9573,14 @@ const fsBinding = {
|
|
|
9513
9573
|
const bytes2 = encoding === "utf8" || encoding === void 0 || encoding === "utf-8" ? new TextEncoder().encode(value) : Uint8Array.from(value, (character) => character.charCodeAt(0) & 255);
|
|
9514
9574
|
return fsBinding.writeBuffer(fd2, bytes2, 0, bytes2.length, position ?? null, req);
|
|
9515
9575
|
},
|
|
9516
|
-
writeFileUtf8(path2, data2, flags,
|
|
9517
|
-
const
|
|
9518
|
-
const
|
|
9519
|
-
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9576
|
+
writeFileUtf8(path2, data2, flags, mode) {
|
|
9577
|
+
const owned = typeof path2 !== "number";
|
|
9578
|
+
const fd2 = owned ? fsBinding.open(path2, flags, mode) : path2;
|
|
9579
|
+
try {
|
|
9580
|
+
fsBinding.writeString(fd2, data2, null, "utf8");
|
|
9581
|
+
} finally {
|
|
9582
|
+
if (owned) fsBinding.close(fd2);
|
|
9523
9583
|
}
|
|
9524
|
-
tree2.writeFileSync(name, data2);
|
|
9525
9584
|
return void 0;
|
|
9526
9585
|
},
|
|
9527
9586
|
// ---- metadata -----------------------------------------------------------
|
|
@@ -9566,10 +9625,10 @@ const fsBinding = {
|
|
|
9566
9625
|
return bigint ? BigInt64Array.from(values.map((value) => BigInt(value))) : Float64Array.from(values);
|
|
9567
9626
|
});
|
|
9568
9627
|
},
|
|
9569
|
-
access(path2,
|
|
9628
|
+
access(path2, mode, req) {
|
|
9570
9629
|
return answer(req, () => {
|
|
9571
9630
|
const name = asPath(path2);
|
|
9572
|
-
|
|
9631
|
+
vfs$1().accessSync(name, mode);
|
|
9573
9632
|
return void 0;
|
|
9574
9633
|
});
|
|
9575
9634
|
},
|
|
@@ -9674,13 +9733,10 @@ const fsBinding = {
|
|
|
9674
9733
|
if (tree2.existsSync(name)) {
|
|
9675
9734
|
const stats = tree2.statSync(name);
|
|
9676
9735
|
if (!recursive || !stats.isDirectory()) throw createNodeError$1("EEXIST", "mkdir", name);
|
|
9677
|
-
const stored = pathModes.get(name);
|
|
9678
|
-
if (stored !== void 0 && (stored & 511) !== wanted) throw createNodeError$1("EEXIST", "mkdir", name);
|
|
9679
|
-
pathModes.set(name, wanted);
|
|
9680
9736
|
return void 0;
|
|
9681
9737
|
}
|
|
9682
9738
|
tree2.mkdirSync(name, { recursive });
|
|
9683
|
-
|
|
9739
|
+
tree2.chmodSync(name, wanted);
|
|
9684
9740
|
return void 0;
|
|
9685
9741
|
});
|
|
9686
9742
|
},
|
|
@@ -9752,46 +9808,50 @@ const fsBinding = {
|
|
|
9752
9808
|
}
|
|
9753
9809
|
});
|
|
9754
9810
|
},
|
|
9755
|
-
//
|
|
9756
|
-
//
|
|
9757
|
-
// are kept here, because a program that sets a mode and stats it back must
|
|
9758
|
-
// 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.
|
|
9759
9813
|
chmod(path2, mode, req) {
|
|
9760
9814
|
return answer(req, () => {
|
|
9761
9815
|
const name = asPath(path2);
|
|
9762
|
-
|
|
9763
|
-
pathModes.set(name, mode & 4095);
|
|
9816
|
+
vfs$1().chmodSync(name, mode);
|
|
9764
9817
|
return void 0;
|
|
9765
9818
|
});
|
|
9766
9819
|
},
|
|
9767
9820
|
fchmod(fd2, mode, req) {
|
|
9768
9821
|
return answer(req, () => {
|
|
9769
9822
|
const file = fileFor(fd2);
|
|
9770
|
-
|
|
9823
|
+
file.tree.chmodSync(file.path, mode);
|
|
9771
9824
|
return void 0;
|
|
9772
9825
|
});
|
|
9773
9826
|
},
|
|
9774
|
-
chown(
|
|
9775
|
-
return answer(req, () =>
|
|
9776
|
-
const name = asPath(path2);
|
|
9777
|
-
if (!vfs$1().existsSync(name)) throw createNodeError$1("ENOENT", "chown", name);
|
|
9778
|
-
return void 0;
|
|
9779
|
-
});
|
|
9827
|
+
chown(_path, _uid, _gid, req) {
|
|
9828
|
+
return answer(req, () => unsupportedMetadata("chown"));
|
|
9780
9829
|
},
|
|
9781
9830
|
fchown(_fd, _uid, _gid, req) {
|
|
9782
|
-
return answer(req, () =>
|
|
9831
|
+
return answer(req, () => unsupportedMetadata("fchown"));
|
|
9783
9832
|
},
|
|
9784
9833
|
lchown(_path, _uid, _gid, req) {
|
|
9785
|
-
return answer(req, () =>
|
|
9834
|
+
return answer(req, () => unsupportedMetadata("lchown"));
|
|
9786
9835
|
},
|
|
9787
|
-
utimes(
|
|
9788
|
-
return answer(req, () =>
|
|
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
|
+
});
|
|
9789
9841
|
},
|
|
9790
|
-
futimes(
|
|
9791
|
-
return answer(req, () =>
|
|
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
|
+
});
|
|
9792
9848
|
},
|
|
9793
|
-
lutimes(
|
|
9794
|
-
return answer(req, () =>
|
|
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
|
+
});
|
|
9795
9855
|
},
|
|
9796
9856
|
fsync(_fd, req) {
|
|
9797
9857
|
return answer(req, () => void 0);
|
|
@@ -9802,6 +9862,7 @@ const fsBinding = {
|
|
|
9802
9862
|
ftruncate(fd2, length, req) {
|
|
9803
9863
|
return answer(req, () => {
|
|
9804
9864
|
const file = fileFor(fd2);
|
|
9865
|
+
if ((file.flags & 3) === 0) throw createNodeError$1("EBADF", "ftruncate", file.path);
|
|
9805
9866
|
const tree2 = file.tree;
|
|
9806
9867
|
const bytes2 = file.cached ?? tree2.readFileSync(file.path);
|
|
9807
9868
|
const next2 = new Uint8Array(length);
|
|
@@ -26098,6 +26159,16 @@ lazyExport("stream", "pipeline");
|
|
|
26098
26159
|
lazyExport("stream", "finished");
|
|
26099
26160
|
lazyModule("stream/promises");
|
|
26100
26161
|
const streamPromisesModule = lazyModule("stream/promises");
|
|
26162
|
+
const nodeInodes = /* @__PURE__ */ new WeakMap();
|
|
26163
|
+
let nextInode = 1;
|
|
26164
|
+
function inodeFor(node) {
|
|
26165
|
+
let inode = nodeInodes.get(node);
|
|
26166
|
+
if (inode === void 0) {
|
|
26167
|
+
inode = nextInode++;
|
|
26168
|
+
nodeInodes.set(node, inode);
|
|
26169
|
+
}
|
|
26170
|
+
return inode;
|
|
26171
|
+
}
|
|
26101
26172
|
function createNodeError(code2, syscall, path2, message) {
|
|
26102
26173
|
const errno = {
|
|
26103
26174
|
ENOENT: -2,
|
|
@@ -26383,6 +26454,17 @@ class VirtualFS {
|
|
|
26383
26454
|
/**
|
|
26384
26455
|
* Get stats for path
|
|
26385
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
|
+
}
|
|
26386
26468
|
statSync(path2) {
|
|
26387
26469
|
var _a3;
|
|
26388
26470
|
const node = this.getNode(path2);
|
|
@@ -26401,7 +26483,7 @@ class VirtualFS {
|
|
|
26401
26483
|
isFIFO: () => false,
|
|
26402
26484
|
isSocket: () => false,
|
|
26403
26485
|
size,
|
|
26404
|
-
mode: node.type === "directory" ? 493 : 420,
|
|
26486
|
+
mode: node.mode ?? (node.type === "directory" ? 493 : 420),
|
|
26405
26487
|
mtime: new Date(mtime),
|
|
26406
26488
|
atime: new Date(atime),
|
|
26407
26489
|
ctime: new Date(mtime),
|
|
@@ -26414,7 +26496,7 @@ class VirtualFS {
|
|
|
26414
26496
|
uid: 1e3,
|
|
26415
26497
|
gid: 1e3,
|
|
26416
26498
|
dev: 0,
|
|
26417
|
-
ino:
|
|
26499
|
+
ino: inodeFor(node),
|
|
26418
26500
|
rdev: 0,
|
|
26419
26501
|
blksize: 4096,
|
|
26420
26502
|
blocks: Math.ceil(size / 512)
|
|
@@ -26453,7 +26535,7 @@ class VirtualFS {
|
|
|
26453
26535
|
uid: 1e3,
|
|
26454
26536
|
gid: 1e3,
|
|
26455
26537
|
dev: 0,
|
|
26456
|
-
ino:
|
|
26538
|
+
ino: inodeFor(node),
|
|
26457
26539
|
rdev: 0,
|
|
26458
26540
|
blksize: 4096,
|
|
26459
26541
|
blocks: 0
|
|
@@ -68748,7 +68830,7 @@ function initChildProcess(vfs2) {
|
|
|
68748
68830
|
};
|
|
68749
68831
|
};
|
|
68750
68832
|
const nodeCommand = uA("node", async (args, ctx) => {
|
|
68751
|
-
var _a3, _b3;
|
|
68833
|
+
var _a3, _b3, _c3, _d3;
|
|
68752
68834
|
if (!tree2) {
|
|
68753
68835
|
return { stdout: "", stderr: "VFS not initialized\n", exitCode: 1 };
|
|
68754
68836
|
}
|
|
@@ -68835,7 +68917,7 @@ function initChildProcess(vfs2) {
|
|
|
68835
68917
|
// open, as a pipe whose writer has not closed.
|
|
68836
68918
|
stdin: typeof ctx.stdin === "string" ? ctx.stdin : "",
|
|
68837
68919
|
...(streams == null ? void 0 : streams.held) || (streams == null ? void 0 : streams.stdinOpen) ? { stdinHeld: true } : {},
|
|
68838
|
-
...(streams == null ? void 0 : streams.held) ? { tty: true } : {},
|
|
68920
|
+
...(streams == null ? void 0 : streams.held) || (streams == null ? void 0 : streams.terminal) ? { tty: true } : {},
|
|
68839
68921
|
// The numbers this run was started with, so the guest's `process.pid`
|
|
68840
68922
|
// is the one its parent's handle carries.
|
|
68841
68923
|
...runPid(runToken) ? { pid: runPid(runToken).pid, ppid: runPid(runToken).ppid } : {}
|
|
@@ -68877,12 +68959,28 @@ function initChildProcess(vfs2) {
|
|
|
68877
68959
|
proc.argv0 = "node";
|
|
68878
68960
|
proc.execArgv = execArgv;
|
|
68879
68961
|
if (streams) streams.stdin = proc.stdin;
|
|
68880
|
-
if (streams == null ? void 0 : streams.held) {
|
|
68962
|
+
if ((streams == null ? void 0 : streams.held) || (streams == null ? void 0 : streams.terminal)) {
|
|
68881
68963
|
proc.stdout.isTTY = true;
|
|
68882
68964
|
proc.stderr.isTTY = true;
|
|
68883
68965
|
proc.stdin.isTTY = true;
|
|
68884
68966
|
proc.stdin.setRawMode = () => proc.stdin;
|
|
68885
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
|
+
};
|
|
68886
68984
|
if (Number.isInteger(channelFd) && channelFd >= 0 && runToken !== null) {
|
|
68887
68985
|
enterRun(runToken, () => {
|
|
68888
68986
|
attachChannel(proc, channelFd, channelSerialization);
|
|
@@ -68940,6 +69038,39 @@ ${reason.stack || ""}` : String(reason);
|
|
|
68940
69038
|
};
|
|
68941
69039
|
const detachUncaught = __onUncaughtException(proc, onUncaughtException);
|
|
68942
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
|
+
});
|
|
68943
69074
|
let entrySettling;
|
|
68944
69075
|
try {
|
|
68945
69076
|
const runEntry = () => runtime2.runFile(resolvedPath);
|
|
@@ -68977,7 +69108,7 @@ ${error.stack || ""}` : String(error);
|
|
|
68977
69108
|
}
|
|
68978
69109
|
}
|
|
68979
69110
|
const __ownsHandles = () => runToken !== null && (__ownedServerPorts(runToken).length > 0 || __ownedHandleCount(runToken) > 0);
|
|
68980
|
-
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();
|
|
68981
69112
|
if ((stdout.length > 0 || stderr.length > 0) && !__printedThenWorking()) {
|
|
68982
69113
|
await new Promise((r10) => (globalThis.__browserRuntimeNativeSetTimeout ?? setTimeout).call(globalThis, r10, 0));
|
|
68983
69114
|
if (exitCalled) return { stdout, stderr, exitCode };
|
|
@@ -69000,16 +69131,16 @@ ${error.stack || ""}` : String(error);
|
|
|
69000
69131
|
const startTime = Date.now();
|
|
69001
69132
|
let lastOutputLen = stdout.length + stderr.length;
|
|
69002
69133
|
let idleMs = 0;
|
|
69003
|
-
const stillWorking = () => pendingGuestTimers(proc) > 0 || __ownsHandles();
|
|
69134
|
+
const stillWorking = () => (streams == null ? void 0 : streams.stdinOpen) === true && inputReading() || pendingGuestTimers(proc) > 0 || __ownsHandles();
|
|
69004
69135
|
const isLongRunning = !!(streams == null ? void 0 : streams.held);
|
|
69005
69136
|
while (!exitCalled) {
|
|
69006
|
-
if ((
|
|
69137
|
+
if ((_b3 = streams == null ? void 0 : streams.signal) == null ? void 0 : _b3.aborted) break;
|
|
69007
69138
|
const raceResult = await Promise.race([
|
|
69008
69139
|
exitPromise.then(() => "exit"),
|
|
69009
69140
|
new Promise((r10) => (globalThis.__browserRuntimeNativeSetTimeout ?? setTimeout).call(globalThis, () => r10("tick"), CHECK_MS))
|
|
69010
69141
|
]);
|
|
69011
69142
|
if (raceResult === "exit" || exitCalled) break;
|
|
69012
|
-
if ((
|
|
69143
|
+
if ((_c3 = streams == null ? void 0 : streams.signal) == null ? void 0 : _c3.aborted) break;
|
|
69013
69144
|
const currentLen = stdout.length + stderr.length;
|
|
69014
69145
|
if (currentLen > lastOutputLen) {
|
|
69015
69146
|
lastOutputLen = currentLen;
|
|
@@ -69034,6 +69165,16 @@ ${error.stack || ""}` : String(error);
|
|
|
69034
69165
|
} finally {
|
|
69035
69166
|
detachRejections();
|
|
69036
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
|
+
}
|
|
69037
69178
|
if (runToken !== null) {
|
|
69038
69179
|
__releaseOwnedServers(runToken, false);
|
|
69039
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 */
|