@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.
- package/dist/assets/{runtime-worker-CUO9SNFs.js → runtime-worker-DoV8lqBn.js} +163 -46
- package/dist/index.d.ts +6 -0
- package/dist/index.mjs +190 -63
- package/dist/node-lib/binding/fs.d.ts +6 -6
- 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 +41 -35
- 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 +15 -1
package/dist/index.mjs
CHANGED
|
@@ -6344,6 +6344,7 @@ function processByPid(pid) {
|
|
|
6344
6344
|
return void 0;
|
|
6345
6345
|
}
|
|
6346
6346
|
const owners = /* @__PURE__ */ new Map();
|
|
6347
|
+
const allOwned = /* @__PURE__ */ new Map();
|
|
6347
6348
|
const heldBy = /* @__PURE__ */ new WeakMap();
|
|
6348
6349
|
const refHeld = /* @__PURE__ */ new WeakSet();
|
|
6349
6350
|
const activeHandles = /* @__PURE__ */ new WeakSet();
|
|
@@ -6374,6 +6375,15 @@ function ownerOf(handle) {
|
|
|
6374
6375
|
}
|
|
6375
6376
|
function registerHandle(handle) {
|
|
6376
6377
|
heldBy.set(handle, currentOwner());
|
|
6378
|
+
const token = heldBy.get(handle);
|
|
6379
|
+
if (token != null) {
|
|
6380
|
+
let owned = allOwned.get(token);
|
|
6381
|
+
if (!owned) {
|
|
6382
|
+
owned = /* @__PURE__ */ new Set();
|
|
6383
|
+
allOwned.set(token, owned);
|
|
6384
|
+
}
|
|
6385
|
+
owned.add(handle);
|
|
6386
|
+
}
|
|
6377
6387
|
refHeld.add(handle);
|
|
6378
6388
|
activeHandles.add(handle);
|
|
6379
6389
|
hold(handle);
|
|
@@ -6395,6 +6405,12 @@ function handleHasRef(handle) {
|
|
|
6395
6405
|
}
|
|
6396
6406
|
function releaseHandle(handle) {
|
|
6397
6407
|
drop(handle);
|
|
6408
|
+
const token = heldBy.get(handle);
|
|
6409
|
+
if (token != null) {
|
|
6410
|
+
const owned = allOwned.get(token);
|
|
6411
|
+
owned == null ? void 0 : owned.delete(handle);
|
|
6412
|
+
if ((owned == null ? void 0 : owned.size) === 0) allOwned.delete(token);
|
|
6413
|
+
}
|
|
6398
6414
|
heldBy.delete(handle);
|
|
6399
6415
|
refHeld.delete(handle);
|
|
6400
6416
|
activeHandles.delete(handle);
|
|
@@ -6428,8 +6444,9 @@ function __releaseOwnedServers(token, stopTimers = true, stopProcess) {
|
|
|
6428
6444
|
}
|
|
6429
6445
|
}
|
|
6430
6446
|
function __releaseOwnedHandles(token) {
|
|
6431
|
-
const held =
|
|
6447
|
+
const held = allOwned.get(token);
|
|
6432
6448
|
if (!held) return;
|
|
6449
|
+
allOwned.delete(token);
|
|
6433
6450
|
owners.delete(token);
|
|
6434
6451
|
for (const handle of [...held]) {
|
|
6435
6452
|
try {
|
|
@@ -6441,7 +6458,21 @@ function __releaseOwnedHandles(token) {
|
|
|
6441
6458
|
function __adoptHandle(handle, token) {
|
|
6442
6459
|
if (!handle) return;
|
|
6443
6460
|
drop(handle);
|
|
6461
|
+
const previous = heldBy.get(handle);
|
|
6462
|
+
if (previous != null) {
|
|
6463
|
+
const owned = allOwned.get(previous);
|
|
6464
|
+
owned == null ? void 0 : owned.delete(handle);
|
|
6465
|
+
if ((owned == null ? void 0 : owned.size) === 0) allOwned.delete(previous);
|
|
6466
|
+
}
|
|
6444
6467
|
heldBy.set(handle, token);
|
|
6468
|
+
if (token !== null) {
|
|
6469
|
+
let owned = allOwned.get(token);
|
|
6470
|
+
if (!owned) {
|
|
6471
|
+
owned = /* @__PURE__ */ new Set();
|
|
6472
|
+
allOwned.set(token, owned);
|
|
6473
|
+
}
|
|
6474
|
+
owned.add(handle);
|
|
6475
|
+
}
|
|
6445
6476
|
hold(handle);
|
|
6446
6477
|
}
|
|
6447
6478
|
function ownedBytes$1(view) {
|
|
@@ -8790,7 +8821,9 @@ function refuseLinks(syscall, path2) {
|
|
|
8790
8821
|
{ code: "EPERM", errno: -1, syscall, path: path2 }
|
|
8791
8822
|
);
|
|
8792
8823
|
}
|
|
8793
|
-
|
|
8824
|
+
function unsupportedMetadata(syscall) {
|
|
8825
|
+
throw Object.assign(new Error(`ENOTSUP: filesystem does not support ${syscall}`), { code: "ENOTSUP", syscall });
|
|
8826
|
+
}
|
|
8794
8827
|
function treeHoldsLinks() {
|
|
8795
8828
|
return vfs().holdsLinks === true;
|
|
8796
8829
|
}
|
|
@@ -8854,19 +8887,18 @@ function fileFor(fd) {
|
|
|
8854
8887
|
return file;
|
|
8855
8888
|
}
|
|
8856
8889
|
function statArray(stats, bigint, path2) {
|
|
8857
|
-
var _a2, _b2;
|
|
8890
|
+
var _a2, _b2, _c2;
|
|
8858
8891
|
const mtime = stats.mtime instanceof Date ? stats.mtime.getTime() : Number(stats.mtimeMs ?? 0);
|
|
8859
8892
|
const atime = stats.atime instanceof Date ? stats.atime.getTime() : Number(stats.atimeMs ?? mtime);
|
|
8860
8893
|
const ctime = stats.ctime instanceof Date ? stats.ctime.getTime() : Number(stats.ctimeMs ?? mtime);
|
|
8861
8894
|
const birth = stats.birthtime instanceof Date ? stats.birthtime.getTime() : Number(stats.birthtimeMs ?? mtime);
|
|
8862
8895
|
const seconds = (ms) => Math.floor(ms / 1e3);
|
|
8863
8896
|
const nanos = (ms) => Math.floor(ms % 1e3 * 1e6);
|
|
8864
|
-
const
|
|
8865
|
-
const
|
|
8866
|
-
const type2 = ((_a2 = stats.isDirectory) == null ? void 0 : _a2.call(stats)) ? S_IFDIR : ((_b2 = stats.isSymbolicLink) == null ? void 0 : _b2.call(stats)) ? S_IFLNK : S_IFREG;
|
|
8897
|
+
const permissions = Number(stats.mode ?? (((_a2 = stats.isDirectory) == null ? void 0 : _a2.call(stats)) ? 493 : 420)) & 4095;
|
|
8898
|
+
const type2 = ((_b2 = stats.isDirectory) == null ? void 0 : _b2.call(stats)) ? S_IFDIR : ((_c2 = stats.isSymbolicLink) == null ? void 0 : _c2.call(stats)) ? S_IFLNK : S_IFREG;
|
|
8867
8899
|
const values = [
|
|
8868
8900
|
Number(stats.dev ?? 0),
|
|
8869
|
-
type2 |
|
|
8901
|
+
type2 | permissions,
|
|
8870
8902
|
Number(stats.nlink ?? 1),
|
|
8871
8903
|
Number(stats.uid ?? 0),
|
|
8872
8904
|
Number(stats.gid ?? 0),
|
|
@@ -9012,15 +9044,23 @@ class FSEvent {
|
|
|
9012
9044
|
__privateAdd(this, _watcher, null);
|
|
9013
9045
|
__publicField(this, "initialized", false);
|
|
9014
9046
|
}
|
|
9015
|
-
start(path2,
|
|
9047
|
+
start(path2, persistent, recursive, _encoding2) {
|
|
9016
9048
|
const name = asPath(path2);
|
|
9017
9049
|
const tree2 = vfs();
|
|
9050
|
+
const cwd = callingCwd();
|
|
9051
|
+
const owner = currentOwner();
|
|
9018
9052
|
try {
|
|
9019
9053
|
__privateSet(this, _watcher, tree2.watch(name, { recursive: Boolean(recursive) }, (event, filename) => {
|
|
9020
|
-
|
|
9021
|
-
|
|
9054
|
+
const notify = () => withFilesystem(tree2, () => withCwd(cwd, () => {
|
|
9055
|
+
var _a2;
|
|
9056
|
+
return (_a2 = this.onchange) == null ? void 0 : _a2.call(this, 0, event === "rename" ? "rename" : "change", filename ?? "");
|
|
9057
|
+
}));
|
|
9058
|
+
if (owner === null) notify();
|
|
9059
|
+
else enterRun(owner, notify);
|
|
9022
9060
|
}));
|
|
9023
9061
|
this.initialized = true;
|
|
9062
|
+
registerHandle(this);
|
|
9063
|
+
if (persistent === false) unrefHandle(this);
|
|
9024
9064
|
return 0;
|
|
9025
9065
|
} catch (error) {
|
|
9026
9066
|
const code2 = error.code;
|
|
@@ -9029,6 +9069,7 @@ class FSEvent {
|
|
|
9029
9069
|
}
|
|
9030
9070
|
close() {
|
|
9031
9071
|
var _a2;
|
|
9072
|
+
releaseHandle(this);
|
|
9032
9073
|
this.initialized = false;
|
|
9033
9074
|
try {
|
|
9034
9075
|
(_a2 = __privateGet(this, _watcher)) == null ? void 0 : _a2.close();
|
|
@@ -9037,14 +9078,16 @@ class FSEvent {
|
|
|
9037
9078
|
__privateSet(this, _watcher, null);
|
|
9038
9079
|
}
|
|
9039
9080
|
ref() {
|
|
9081
|
+
if (this.initialized) refHandle(this);
|
|
9040
9082
|
}
|
|
9041
9083
|
unref() {
|
|
9084
|
+
unrefHandle(this);
|
|
9042
9085
|
}
|
|
9043
9086
|
getAsyncId() {
|
|
9044
9087
|
return 0;
|
|
9045
9088
|
}
|
|
9046
9089
|
hasRef() {
|
|
9047
|
-
return this.initialized;
|
|
9090
|
+
return this.initialized && handleHasRef(this);
|
|
9048
9091
|
}
|
|
9049
9092
|
}
|
|
9050
9093
|
_watcher = new WeakMap();
|
|
@@ -9141,6 +9184,9 @@ const fsBinding = {
|
|
|
9141
9184
|
const tree2 = vfs();
|
|
9142
9185
|
const bits = flagBits();
|
|
9143
9186
|
const exists = tree2.existsSync(name);
|
|
9187
|
+
if (exists && ((flags & 3) !== 0 || (flags & (bits.create | bits.truncate | bits.append)) !== 0)) {
|
|
9188
|
+
tree2.accessSync(name, 2);
|
|
9189
|
+
}
|
|
9144
9190
|
if ((flags & bits.excl) !== 0 && (flags & bits.create) !== 0 && exists) throw createNodeError$1("EEXIST", "open", name);
|
|
9145
9191
|
if (!exists) {
|
|
9146
9192
|
if ((flags & bits.create) === 0) throw createNodeError$1("ENOENT", "open", name);
|
|
@@ -9292,10 +9338,10 @@ const fsBinding = {
|
|
|
9292
9338
|
return bigint ? BigInt64Array.from(values.map((value) => BigInt(value))) : Float64Array.from(values);
|
|
9293
9339
|
});
|
|
9294
9340
|
},
|
|
9295
|
-
access(path2,
|
|
9341
|
+
access(path2, mode, req) {
|
|
9296
9342
|
return answer(req, () => {
|
|
9297
9343
|
const name = asPath(path2);
|
|
9298
|
-
|
|
9344
|
+
vfs().accessSync(name, mode);
|
|
9299
9345
|
return void 0;
|
|
9300
9346
|
});
|
|
9301
9347
|
},
|
|
@@ -9400,13 +9446,10 @@ const fsBinding = {
|
|
|
9400
9446
|
if (tree2.existsSync(name)) {
|
|
9401
9447
|
const stats = tree2.statSync(name);
|
|
9402
9448
|
if (!recursive || !stats.isDirectory()) throw createNodeError$1("EEXIST", "mkdir", name);
|
|
9403
|
-
const stored = pathModes.get(name);
|
|
9404
|
-
if (stored !== void 0 && (stored & 511) !== wanted) throw createNodeError$1("EEXIST", "mkdir", name);
|
|
9405
|
-
pathModes.set(name, wanted);
|
|
9406
9449
|
return void 0;
|
|
9407
9450
|
}
|
|
9408
9451
|
tree2.mkdirSync(name, { recursive });
|
|
9409
|
-
|
|
9452
|
+
tree2.chmodSync(name, wanted);
|
|
9410
9453
|
return void 0;
|
|
9411
9454
|
});
|
|
9412
9455
|
},
|
|
@@ -9478,46 +9521,50 @@ const fsBinding = {
|
|
|
9478
9521
|
}
|
|
9479
9522
|
});
|
|
9480
9523
|
},
|
|
9481
|
-
//
|
|
9482
|
-
//
|
|
9483
|
-
// are kept here, because a program that sets a mode and stats it back must
|
|
9484
|
-
// see what it set, and a missing path is ENOENT as Node's is.
|
|
9524
|
+
// Metadata belongs to the filesystem, including a host's permission view.
|
|
9525
|
+
// Never keep a realm-global mode table or bypass that view for descriptors.
|
|
9485
9526
|
chmod(path2, mode, req) {
|
|
9486
9527
|
return answer(req, () => {
|
|
9487
9528
|
const name = asPath(path2);
|
|
9488
|
-
|
|
9489
|
-
pathModes.set(name, mode & 4095);
|
|
9529
|
+
vfs().chmodSync(name, mode);
|
|
9490
9530
|
return void 0;
|
|
9491
9531
|
});
|
|
9492
9532
|
},
|
|
9493
9533
|
fchmod(fd, mode, req) {
|
|
9494
9534
|
return answer(req, () => {
|
|
9495
9535
|
const file = fileFor(fd);
|
|
9496
|
-
|
|
9536
|
+
file.tree.chmodSync(file.path, mode);
|
|
9497
9537
|
return void 0;
|
|
9498
9538
|
});
|
|
9499
9539
|
},
|
|
9500
|
-
chown(
|
|
9501
|
-
return answer(req, () =>
|
|
9502
|
-
const name = asPath(path2);
|
|
9503
|
-
if (!vfs().existsSync(name)) throw createNodeError$1("ENOENT", "chown", name);
|
|
9504
|
-
return void 0;
|
|
9505
|
-
});
|
|
9540
|
+
chown(_path, _uid, _gid, req) {
|
|
9541
|
+
return answer(req, () => unsupportedMetadata("chown"));
|
|
9506
9542
|
},
|
|
9507
9543
|
fchown(_fd, _uid, _gid, req) {
|
|
9508
|
-
return answer(req, () =>
|
|
9544
|
+
return answer(req, () => unsupportedMetadata("fchown"));
|
|
9509
9545
|
},
|
|
9510
9546
|
lchown(_path, _uid, _gid, req) {
|
|
9511
|
-
return answer(req, () =>
|
|
9547
|
+
return answer(req, () => unsupportedMetadata("lchown"));
|
|
9512
9548
|
},
|
|
9513
|
-
utimes(
|
|
9514
|
-
return answer(req, () =>
|
|
9549
|
+
utimes(path2, atime, mtime, req) {
|
|
9550
|
+
return answer(req, () => {
|
|
9551
|
+
vfs().utimesSync(asPath(path2), new Date(atime * 1e3), new Date(mtime * 1e3));
|
|
9552
|
+
return void 0;
|
|
9553
|
+
});
|
|
9515
9554
|
},
|
|
9516
|
-
futimes(
|
|
9517
|
-
return answer(req, () =>
|
|
9555
|
+
futimes(fd, atime, mtime, req) {
|
|
9556
|
+
return answer(req, () => {
|
|
9557
|
+
const file = fileFor(fd);
|
|
9558
|
+
file.tree.utimesSync(file.path, new Date(atime * 1e3), new Date(mtime * 1e3));
|
|
9559
|
+
return void 0;
|
|
9560
|
+
});
|
|
9518
9561
|
},
|
|
9519
|
-
lutimes(
|
|
9520
|
-
return answer(req, () =>
|
|
9562
|
+
lutimes(path2, atime, mtime, req) {
|
|
9563
|
+
return answer(req, () => {
|
|
9564
|
+
if (treeHoldsLinks()) return unsupportedMetadata("lutimes");
|
|
9565
|
+
vfs().utimesSync(asPath(path2), new Date(atime * 1e3), new Date(mtime * 1e3));
|
|
9566
|
+
return void 0;
|
|
9567
|
+
});
|
|
9521
9568
|
},
|
|
9522
9569
|
fsync(_fd, req) {
|
|
9523
9570
|
return answer(req, () => void 0);
|
|
@@ -26140,6 +26187,17 @@ class VirtualFS {
|
|
|
26140
26187
|
/**
|
|
26141
26188
|
* Get stats for path
|
|
26142
26189
|
*/
|
|
26190
|
+
chmodSync(path2, mode) {
|
|
26191
|
+
const node = this.getNode(path2);
|
|
26192
|
+
if (!node) throw createNodeError("ENOENT", "chmod", path2);
|
|
26193
|
+
node.mode = mode & 4095;
|
|
26194
|
+
}
|
|
26195
|
+
utimesSync(path2, atime, mtime) {
|
|
26196
|
+
const node = this.getNode(path2);
|
|
26197
|
+
if (!node) throw createNodeError("ENOENT", "utimes", path2);
|
|
26198
|
+
node.atime = atime instanceof Date ? atime.getTime() : atime * 1e3;
|
|
26199
|
+
node.mtime = mtime instanceof Date ? mtime.getTime() : mtime * 1e3;
|
|
26200
|
+
}
|
|
26143
26201
|
statSync(path2) {
|
|
26144
26202
|
var _a2;
|
|
26145
26203
|
const node = this.getNode(path2);
|
|
@@ -26158,7 +26216,7 @@ class VirtualFS {
|
|
|
26158
26216
|
isFIFO: () => false,
|
|
26159
26217
|
isSocket: () => false,
|
|
26160
26218
|
size,
|
|
26161
|
-
mode: node.type === "directory" ? 493 : 420,
|
|
26219
|
+
mode: node.mode ?? (node.type === "directory" ? 493 : 420),
|
|
26162
26220
|
mtime: new Date(mtime),
|
|
26163
26221
|
atime: new Date(atime),
|
|
26164
26222
|
ctime: new Date(mtime),
|
|
@@ -27892,7 +27950,7 @@ function initChildProcess(vfs2) {
|
|
|
27892
27950
|
};
|
|
27893
27951
|
};
|
|
27894
27952
|
const nodeCommand = defineCommand("node", async (args, ctx) => {
|
|
27895
|
-
var _a2, _b2;
|
|
27953
|
+
var _a2, _b2, _c2, _d2;
|
|
27896
27954
|
if (!tree2) {
|
|
27897
27955
|
return { stdout: "", stderr: "VFS not initialized\n", exitCode: 1 };
|
|
27898
27956
|
}
|
|
@@ -27979,7 +28037,7 @@ function initChildProcess(vfs2) {
|
|
|
27979
28037
|
// open, as a pipe whose writer has not closed.
|
|
27980
28038
|
stdin: typeof ctx.stdin === "string" ? ctx.stdin : "",
|
|
27981
28039
|
...(streams == null ? void 0 : streams.held) || (streams == null ? void 0 : streams.stdinOpen) ? { stdinHeld: true } : {},
|
|
27982
|
-
...(streams == null ? void 0 : streams.held) ? { tty: true } : {},
|
|
28040
|
+
...(streams == null ? void 0 : streams.held) || (streams == null ? void 0 : streams.terminal) ? { tty: true } : {},
|
|
27983
28041
|
// The numbers this run was started with, so the guest's `process.pid`
|
|
27984
28042
|
// is the one its parent's handle carries.
|
|
27985
28043
|
...runPid(runToken) ? { pid: runPid(runToken).pid, ppid: runPid(runToken).ppid } : {}
|
|
@@ -28021,12 +28079,28 @@ function initChildProcess(vfs2) {
|
|
|
28021
28079
|
proc.argv0 = "node";
|
|
28022
28080
|
proc.execArgv = execArgv;
|
|
28023
28081
|
if (streams) streams.stdin = proc.stdin;
|
|
28024
|
-
if (streams == null ? void 0 : streams.held) {
|
|
28082
|
+
if ((streams == null ? void 0 : streams.held) || (streams == null ? void 0 : streams.terminal)) {
|
|
28025
28083
|
proc.stdout.isTTY = true;
|
|
28026
28084
|
proc.stderr.isTTY = true;
|
|
28027
28085
|
proc.stdin.isTTY = true;
|
|
28028
28086
|
proc.stdin.setRawMode = () => proc.stdin;
|
|
28029
28087
|
}
|
|
28088
|
+
const terminal = streams == null ? void 0 : streams.terminal;
|
|
28089
|
+
const resize = (columns, rows) => {
|
|
28090
|
+
for (const stream of [proc.stdout, proc.stderr]) {
|
|
28091
|
+
stream.columns = columns;
|
|
28092
|
+
stream.rows = rows;
|
|
28093
|
+
stream.emit("resize");
|
|
28094
|
+
}
|
|
28095
|
+
};
|
|
28096
|
+
let stopResize;
|
|
28097
|
+
let inputActive = true;
|
|
28098
|
+
let inputIterator;
|
|
28099
|
+
const readableInput = proc.stdin;
|
|
28100
|
+
const inputReading = () => {
|
|
28101
|
+
var _a3, _b3;
|
|
28102
|
+
return readableInput.readableFlowing === true || ((_a3 = readableInput._readableState) == null ? void 0 : _a3.reading) === true || ((_b3 = readableInput._readableState) == null ? void 0 : _b3.needReadable) === true || readableInput.listenerCount("data") > 0 || readableInput.listenerCount("readable") > 0;
|
|
28103
|
+
};
|
|
28030
28104
|
if (Number.isInteger(channelFd) && channelFd >= 0 && runToken !== null) {
|
|
28031
28105
|
enterRun(runToken, () => {
|
|
28032
28106
|
attachChannel(proc, channelFd, channelSerialization);
|
|
@@ -28084,6 +28158,39 @@ ${reason.stack || ""}` : String(reason);
|
|
|
28084
28158
|
};
|
|
28085
28159
|
const detachUncaught = __onUncaughtException(proc, onUncaughtException);
|
|
28086
28160
|
try {
|
|
28161
|
+
if (streams == null ? void 0 : streams.stdinStream) {
|
|
28162
|
+
inputIterator = streams.stdinStream[Symbol.asyncIterator]();
|
|
28163
|
+
const input = inputIterator;
|
|
28164
|
+
void (async () => {
|
|
28165
|
+
var _a3, _b3, _c3, _d3, _e2;
|
|
28166
|
+
const push = (chunk) => {
|
|
28167
|
+
if (runToken === null) proc.stdin.push(chunk);
|
|
28168
|
+
else enterRun(runToken, () => proc.stdin.push(chunk));
|
|
28169
|
+
};
|
|
28170
|
+
try {
|
|
28171
|
+
while (inputActive && !((_a3 = streams.signal) == null ? void 0 : _a3.aborted)) {
|
|
28172
|
+
while (inputActive && !((_b3 = streams.signal) == null ? void 0 : _b3.aborted) && (!inputReading() || readableInput.readableLength >= readableInput.readableHighWaterMark)) {
|
|
28173
|
+
await new Promise((resolve2) => (globalThis.__browserRuntimeNativeSetTimeout ?? setTimeout).call(globalThis, resolve2, 10));
|
|
28174
|
+
}
|
|
28175
|
+
if (!inputActive || ((_c3 = streams.signal) == null ? void 0 : _c3.aborted)) break;
|
|
28176
|
+
const next = await input.next();
|
|
28177
|
+
if (next.done) break;
|
|
28178
|
+
if (!inputActive || ((_d3 = streams.signal) == null ? void 0 : _d3.aborted)) break;
|
|
28179
|
+
push(next.value);
|
|
28180
|
+
}
|
|
28181
|
+
if (inputActive && !((_e2 = streams.signal) == null ? void 0 : _e2.aborted)) push(null);
|
|
28182
|
+
} catch (error) {
|
|
28183
|
+
if (inputActive) onUncaughtException(error);
|
|
28184
|
+
} finally {
|
|
28185
|
+
streams.stdinOpen = false;
|
|
28186
|
+
}
|
|
28187
|
+
})();
|
|
28188
|
+
}
|
|
28189
|
+
if (terminal) resize(terminal.columns, terminal.rows);
|
|
28190
|
+
stopResize = (_a2 = terminal == null ? void 0 : terminal.onResize) == null ? void 0 : _a2.call(terminal, (columns, rows) => {
|
|
28191
|
+
if (runToken === null) resize(columns, rows);
|
|
28192
|
+
else enterRun(runToken, () => resize(columns, rows));
|
|
28193
|
+
});
|
|
28087
28194
|
let entrySettling;
|
|
28088
28195
|
try {
|
|
28089
28196
|
const runEntry = () => runtime.runFile(resolvedPath);
|
|
@@ -28121,7 +28228,7 @@ ${error.stack || ""}` : String(error);
|
|
|
28121
28228
|
}
|
|
28122
28229
|
}
|
|
28123
28230
|
const __ownsHandles = () => runToken !== null && (__ownedServerPorts(runToken).length > 0 || __ownedHandleCount(runToken) > 0);
|
|
28124
|
-
const __printedThenWorking = () => pendingGuestTimers(proc) > 0 || heldWork().count > 0 || __ownsHandles();
|
|
28231
|
+
const __printedThenWorking = () => (streams == null ? void 0 : streams.stdinOpen) === true && inputReading() || pendingGuestTimers(proc) > 0 || heldWork().count > 0 || __ownsHandles();
|
|
28125
28232
|
if ((stdout.length > 0 || stderr.length > 0) && !__printedThenWorking()) {
|
|
28126
28233
|
await new Promise((r) => (globalThis.__browserRuntimeNativeSetTimeout ?? setTimeout).call(globalThis, r, 0));
|
|
28127
28234
|
if (exitCalled) return { stdout, stderr, exitCode };
|
|
@@ -28144,16 +28251,16 @@ ${error.stack || ""}` : String(error);
|
|
|
28144
28251
|
const startTime = Date.now();
|
|
28145
28252
|
let lastOutputLen = stdout.length + stderr.length;
|
|
28146
28253
|
let idleMs = 0;
|
|
28147
|
-
const stillWorking = () => pendingGuestTimers(proc) > 0 || __ownsHandles();
|
|
28254
|
+
const stillWorking = () => (streams == null ? void 0 : streams.stdinOpen) === true && inputReading() || pendingGuestTimers(proc) > 0 || __ownsHandles();
|
|
28148
28255
|
const isLongRunning = !!(streams == null ? void 0 : streams.held);
|
|
28149
28256
|
while (!exitCalled) {
|
|
28150
|
-
if ((
|
|
28257
|
+
if ((_b2 = streams == null ? void 0 : streams.signal) == null ? void 0 : _b2.aborted) break;
|
|
28151
28258
|
const raceResult = await Promise.race([
|
|
28152
28259
|
exitPromise.then(() => "exit"),
|
|
28153
28260
|
new Promise((r) => (globalThis.__browserRuntimeNativeSetTimeout ?? setTimeout).call(globalThis, () => r("tick"), CHECK_MS))
|
|
28154
28261
|
]);
|
|
28155
28262
|
if (raceResult === "exit" || exitCalled) break;
|
|
28156
|
-
if ((
|
|
28263
|
+
if ((_c2 = streams == null ? void 0 : streams.signal) == null ? void 0 : _c2.aborted) break;
|
|
28157
28264
|
const currentLen = stdout.length + stderr.length;
|
|
28158
28265
|
if (currentLen > lastOutputLen) {
|
|
28159
28266
|
lastOutputLen = currentLen;
|
|
@@ -28178,6 +28285,16 @@ ${error.stack || ""}` : String(error);
|
|
|
28178
28285
|
} finally {
|
|
28179
28286
|
detachRejections();
|
|
28180
28287
|
detachUncaught();
|
|
28288
|
+
inputActive = false;
|
|
28289
|
+
try {
|
|
28290
|
+
void Promise.resolve((_d2 = inputIterator == null ? void 0 : inputIterator.return) == null ? void 0 : _d2.call(inputIterator)).catch(() => {
|
|
28291
|
+
});
|
|
28292
|
+
} catch {
|
|
28293
|
+
}
|
|
28294
|
+
try {
|
|
28295
|
+
stopResize == null ? void 0 : stopResize();
|
|
28296
|
+
} catch {
|
|
28297
|
+
}
|
|
28181
28298
|
if (runToken !== null) {
|
|
28182
28299
|
__releaseOwnedServers(runToken, false);
|
|
28183
28300
|
__releaseOwnedHandles(runToken);
|
|
@@ -33810,7 +33927,7 @@ class WorkerRuntime {
|
|
|
33810
33927
|
this.worker = new Worker(
|
|
33811
33928
|
new URL(
|
|
33812
33929
|
/* @vite-ignore */
|
|
33813
|
-
"/assets/runtime-worker-
|
|
33930
|
+
"/assets/runtime-worker-DoV8lqBn.js",
|
|
33814
33931
|
import.meta.url
|
|
33815
33932
|
),
|
|
33816
33933
|
{ type: "module" }
|
|
@@ -35228,7 +35345,7 @@ function ownedBytes(view) {
|
|
|
35228
35345
|
return copy2;
|
|
35229
35346
|
}
|
|
35230
35347
|
function guestListeningServer(port, address) {
|
|
35231
|
-
const hostname2 = address
|
|
35348
|
+
const hostname2 = address;
|
|
35232
35349
|
return {
|
|
35233
35350
|
listening: true,
|
|
35234
35351
|
address: () => ({
|
|
@@ -35472,6 +35589,18 @@ const _ServerBridge = class _ServerBridge extends EventEmitter {
|
|
|
35472
35589
|
__publicField(this, "upgradeChannel", null);
|
|
35473
35590
|
__publicField(this, "serviceWorkerReady", false);
|
|
35474
35591
|
__publicField(this, "keepaliveInterval", null);
|
|
35592
|
+
/**
|
|
35593
|
+
* Give back everything this bridge opened: the upgrade channel and the
|
|
35594
|
+
* service worker keepalive. A host that is done with a container calls it
|
|
35595
|
+
* and has its process back; calling it twice is nothing.
|
|
35596
|
+
*/
|
|
35597
|
+
/**
|
|
35598
|
+
* Every port a guest starts listening on becomes a server this bridge can
|
|
35599
|
+
* answer for, and every port it stops listening on stops being one. The
|
|
35600
|
+
* news comes from the net binding, because that is where a port is taken;
|
|
35601
|
+
* the engine's `http` is Node's own file and knows nothing of a page.
|
|
35602
|
+
*/
|
|
35603
|
+
__publicField(this, "guestServers", /* @__PURE__ */ new WeakSet());
|
|
35475
35604
|
/** The server the service worker answers at the origin's root, the preview's; null for none. */
|
|
35476
35605
|
__publicField(this, "primaryPort", null);
|
|
35477
35606
|
__publicField(this, "ownDocuments");
|
|
@@ -35484,27 +35613,21 @@ const _ServerBridge = class _ServerBridge extends EventEmitter {
|
|
|
35484
35613
|
this.watchGuestPorts();
|
|
35485
35614
|
this.upgradeChannel = __substrateListenForUpgrades();
|
|
35486
35615
|
}
|
|
35487
|
-
/**
|
|
35488
|
-
* Give back everything this bridge opened: the upgrade channel and the
|
|
35489
|
-
* service worker keepalive. A host that is done with a container calls it
|
|
35490
|
-
* and has its process back; calling it twice is nothing.
|
|
35491
|
-
*/
|
|
35492
|
-
/**
|
|
35493
|
-
* Every port a guest starts listening on becomes a server this bridge can
|
|
35494
|
-
* answer for, and every port it stops listening on stops being one. The
|
|
35495
|
-
* news comes from the net binding, because that is where a port is taken;
|
|
35496
|
-
* the engine's `http` is Node's own file and knows nothing of a page.
|
|
35497
|
-
*/
|
|
35498
35616
|
watchGuestPorts() {
|
|
35499
35617
|
setPortWatchers(
|
|
35500
35618
|
(port, address) => {
|
|
35501
35619
|
if (this.servers.has(port)) return;
|
|
35502
35620
|
const hostname2 = address || "0.0.0.0";
|
|
35503
|
-
|
|
35621
|
+
const server = guestListeningServer(port, hostname2);
|
|
35622
|
+
this.guestServers.add(server);
|
|
35623
|
+
this.registerServer(server, port, hostname2);
|
|
35504
35624
|
},
|
|
35505
35625
|
(port) => {
|
|
35506
35626
|
const entry = this.servers.get(port);
|
|
35507
|
-
if (entry && entry.server === null
|
|
35627
|
+
if (entry && (entry.server === null || this.guestServers.has(entry.server))) {
|
|
35628
|
+
if (entry.server) entry.server.listening = false;
|
|
35629
|
+
this.unregisterServer(port);
|
|
35630
|
+
}
|
|
35508
35631
|
}
|
|
35509
35632
|
);
|
|
35510
35633
|
}
|
|
@@ -35955,15 +36078,19 @@ function createContainer(options) {
|
|
|
35955
36078
|
onStdout: runOptions == null ? void 0 : runOptions.onStdout,
|
|
35956
36079
|
onStderr: runOptions == null ? void 0 : runOptions.onStderr,
|
|
35957
36080
|
signal: runOptions == null ? void 0 : runOptions.signal,
|
|
35958
|
-
held: (runOptions == null ? void 0 : runOptions.held) === true
|
|
36081
|
+
held: (runOptions == null ? void 0 : runOptions.held) === true,
|
|
36082
|
+
stdinStream: runOptions == null ? void 0 : runOptions.stdinStream,
|
|
36083
|
+
stdinOpen: (runOptions == null ? void 0 : runOptions.stdinStream) !== void 0,
|
|
36084
|
+
terminal: runOptions == null ? void 0 : runOptions.terminal
|
|
35959
36085
|
});
|
|
35960
36086
|
return new Promise((resolve2) => {
|
|
35961
36087
|
runCommand(command, { cwd: runOptions == null ? void 0 : runOptions.cwd, env: runOptions == null ? void 0 : runOptions.env, stdin: typeof (runOptions == null ? void 0 : runOptions.stdin) === "string" ? runOptions.stdin : void 0, processToken, vfs: vfs2 }, (error, stdout, stderr) => {
|
|
36088
|
+
var _a3;
|
|
35962
36089
|
releaseRunStreams(processToken);
|
|
35963
36090
|
resolve2({
|
|
35964
36091
|
stdout: String(stdout),
|
|
35965
36092
|
stderr: String(stderr),
|
|
35966
|
-
exitCode: error ? error.code ?? 1 : 0
|
|
36093
|
+
exitCode: ((_a3 = runOptions == null ? void 0 : runOptions.signal) == null ? void 0 : _a3.aborted) ? 143 : error ? error.code ?? 1 : 0
|
|
35967
36094
|
});
|
|
35968
36095
|
});
|
|
35969
36096
|
});
|
|
@@ -45,7 +45,7 @@ export declare class FSEvent {
|
|
|
45
45
|
#private;
|
|
46
46
|
onchange: ((status: number, event: string, filename: string) => void) | null;
|
|
47
47
|
initialized: boolean;
|
|
48
|
-
start(path: unknown,
|
|
48
|
+
start(path: unknown, persistent?: boolean, recursive?: boolean, _encoding?: string): number;
|
|
49
49
|
close(): void;
|
|
50
50
|
ref(): void;
|
|
51
51
|
unref(): void;
|
|
@@ -109,7 +109,7 @@ export declare const fsBinding: {
|
|
|
109
109
|
* a disk: a block size, and a count no program can exhaust.
|
|
110
110
|
*/
|
|
111
111
|
statfs(_path: unknown, bigint: boolean, req?: FSReq): Float64Array | BigInt64Array | undefined;
|
|
112
|
-
access(path: unknown,
|
|
112
|
+
access(path: unknown, mode: number, req?: FSReq): undefined;
|
|
113
113
|
existsSync(path: unknown): boolean;
|
|
114
114
|
/**
|
|
115
115
|
* Node's `cpSync` asks this before it copies: a directory is not a file,
|
|
@@ -143,12 +143,12 @@ export declare const fsBinding: {
|
|
|
143
143
|
mkdtemp(prefix: unknown, encoding: string, req?: FSReq): string | Uint8Array | undefined;
|
|
144
144
|
chmod(path: unknown, mode: number, req?: FSReq): undefined;
|
|
145
145
|
fchmod(fd: number, mode: number, req?: FSReq): undefined;
|
|
146
|
-
chown(
|
|
146
|
+
chown(_path: unknown, _uid: number, _gid: number, req?: FSReq): undefined;
|
|
147
147
|
fchown(_fd: number, _uid: number, _gid: number, req?: FSReq): undefined;
|
|
148
148
|
lchown(_path: unknown, _uid: number, _gid: number, req?: FSReq): undefined;
|
|
149
|
-
utimes(
|
|
150
|
-
futimes(
|
|
151
|
-
lutimes(
|
|
149
|
+
utimes(path: unknown, atime: number, mtime: number, req?: FSReq): undefined;
|
|
150
|
+
futimes(fd: number, atime: number, mtime: number, req?: FSReq): undefined;
|
|
151
|
+
lutimes(path: unknown, atime: number, mtime: number, req?: FSReq): undefined;
|
|
152
152
|
fsync(_fd: number, req?: FSReq): undefined;
|
|
153
153
|
fdatasync(_fd: number, req?: FSReq): undefined;
|
|
154
154
|
ftruncate(fd: number, length: number, req?: FSReq): undefined;
|
package/dist/server-bridge.d.ts
CHANGED
|
@@ -65,6 +65,7 @@ export declare class ServerBridge extends EventEmitter {
|
|
|
65
65
|
* news comes from the net binding, because that is where a port is taken;
|
|
66
66
|
* the engine's `http` is Node's own file and knows nothing of a page.
|
|
67
67
|
*/
|
|
68
|
+
private readonly guestServers;
|
|
68
69
|
private watchGuestPorts;
|
|
69
70
|
close(): void;
|
|
70
71
|
/**
|
|
@@ -32,6 +32,12 @@ type RunStdin = {
|
|
|
32
32
|
* output went down the child's channel.
|
|
33
33
|
*/
|
|
34
34
|
export interface RunStreams {
|
|
35
|
+
stdinStream?: AsyncIterable<Uint8Array>;
|
|
36
|
+
terminal?: {
|
|
37
|
+
columns: number;
|
|
38
|
+
rows: number;
|
|
39
|
+
onResize?: (listener: (columns: number, rows: number) => void) => () => void;
|
|
40
|
+
};
|
|
35
41
|
onStdout?: (data: string) => void;
|
|
36
42
|
onStderr?: (data: string) => void;
|
|
37
43
|
signal?: AbortSignal;
|
package/dist/virtual-fs.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ export interface FSNode {
|
|
|
28
28
|
target?: string;
|
|
29
29
|
children?: Map<string, FSNode>;
|
|
30
30
|
mtime: number;
|
|
31
|
+
mode?: number;
|
|
31
32
|
/**
|
|
32
33
|
* When the file was last read. Node reports it apart from the write time
|
|
33
34
|
* and `utimes` sets the two separately; this filesystem reported the write
|
|
@@ -154,6 +155,8 @@ export declare class VirtualFS {
|
|
|
154
155
|
/**
|
|
155
156
|
* Get stats for path
|
|
156
157
|
*/
|
|
158
|
+
chmodSync(path: string, mode: number): void;
|
|
159
|
+
utimesSync(path: string, atime: number | Date, mtime: number | Date): void;
|
|
157
160
|
statSync(path: string): Stats;
|
|
158
161
|
/**
|
|
159
162
|
* lstatSync - same as statSync for our virtual FS (no symlinks)
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -68,6 +68,8 @@ export interface RunOptions {
|
|
|
68
68
|
env?: Record<string, string>;
|
|
69
69
|
/** What the shell reads on stdin, so a builtin reads what was piped to it. */
|
|
70
70
|
stdin?: string;
|
|
71
|
+
stdinStream?: AsyncIterable<Uint8Array>;
|
|
72
|
+
terminal?: { columns: number; rows: number; onResize?: (listener: (columns: number, rows: number) => void) => () => void };
|
|
71
73
|
/** Callback for streaming stdout chunks as they arrive (for long-running commands like vitest watch) */
|
|
72
74
|
onStdout?: (data: string) => void;
|
|
73
75
|
/** Callback for streaming stderr chunks as they arrive */
|
|
@@ -168,6 +170,9 @@ export function createContainer(options?: ContainerOptions): {
|
|
|
168
170
|
onStderr: runOptions?.onStderr,
|
|
169
171
|
signal: runOptions?.signal,
|
|
170
172
|
held: runOptions?.held === true,
|
|
173
|
+
stdinStream: runOptions?.stdinStream,
|
|
174
|
+
stdinOpen: runOptions?.stdinStream !== undefined,
|
|
175
|
+
terminal: runOptions?.terminal,
|
|
171
176
|
});
|
|
172
177
|
|
|
173
178
|
return new Promise((resolve) => {
|
|
@@ -180,7 +185,7 @@ export function createContainer(options?: ContainerOptions): {
|
|
|
180
185
|
resolve({
|
|
181
186
|
stdout: String(stdout),
|
|
182
187
|
stderr: String(stderr),
|
|
183
|
-
exitCode: error ? (error.code ?? 1) : 0,
|
|
188
|
+
exitCode: runOptions?.signal?.aborted ? 143 : error ? (error.code ?? 1) : 0,
|
|
184
189
|
});
|
|
185
190
|
});
|
|
186
191
|
});
|