sandboxedjs 0.1.26 → 0.1.28
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/README.md +28 -11
- package/dist/index.cjs +821 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -10
- package/dist/index.d.ts +45 -10
- package/dist/index.js +821 -55
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -6823,7 +6823,7 @@ var NetworkStack = class {
|
|
|
6823
6823
|
}
|
|
6824
6824
|
return [...out.values()].sort((a, b) => a.port - b.port);
|
|
6825
6825
|
}
|
|
6826
|
-
/** Ports
|
|
6826
|
+
/** Ports the pod's proxy has registered for this instance. */
|
|
6827
6827
|
knownPodPorts() {
|
|
6828
6828
|
try {
|
|
6829
6829
|
return this.pod.proxy.activePorts(this.pod.instanceId) ?? [];
|
|
@@ -7349,15 +7349,15 @@ var Parser = class {
|
|
|
7349
7349
|
if (this.isWord("-p")) this.next();
|
|
7350
7350
|
}
|
|
7351
7351
|
}
|
|
7352
|
-
const
|
|
7352
|
+
const commands12 = [this.parseCommand()];
|
|
7353
7353
|
const stderrToo = [];
|
|
7354
7354
|
while (this.isOp("|") || this.isOp("|&")) {
|
|
7355
7355
|
stderrToo.push(this.next().value === "|&");
|
|
7356
7356
|
this.skipNewlines();
|
|
7357
|
-
|
|
7357
|
+
commands12.push(this.parseCommand());
|
|
7358
7358
|
}
|
|
7359
|
-
if (
|
|
7360
|
-
return { type: "pipeline", commands:
|
|
7359
|
+
if (commands12.length === 1 && !negated && !timed) return commands12[0];
|
|
7360
|
+
return { type: "pipeline", commands: commands12, negated, stderrToo, timed };
|
|
7361
7361
|
}
|
|
7362
7362
|
// ── commands ─────────────────────────────────────────────────────────────
|
|
7363
7363
|
parseCommand() {
|
|
@@ -16980,6 +16980,145 @@ var helpCmd = defineCommand({
|
|
|
16980
16980
|
});
|
|
16981
16981
|
var commands10 = [man, whatis, apropos, less, helpCmd];
|
|
16982
16982
|
|
|
16983
|
+
// src/bin/clipboard.ts
|
|
16984
|
+
init_path();
|
|
16985
|
+
var CLIPBOARD_DIR = "/run/clipboard";
|
|
16986
|
+
function selectionPath(selection) {
|
|
16987
|
+
return join(CLIPBOARD_DIR, selection);
|
|
16988
|
+
}
|
|
16989
|
+
function readSelection(ctx, selection) {
|
|
16990
|
+
try {
|
|
16991
|
+
return ctx.vfs.readFile(selectionPath(selection), ctx.cred);
|
|
16992
|
+
} catch {
|
|
16993
|
+
return new Uint8Array();
|
|
16994
|
+
}
|
|
16995
|
+
}
|
|
16996
|
+
function writeSelection(ctx, selection, bytes2) {
|
|
16997
|
+
try {
|
|
16998
|
+
ctx.vfs.mkdir(CLIPBOARD_DIR, { recursive: true, mode: 511 });
|
|
16999
|
+
} catch {
|
|
17000
|
+
}
|
|
17001
|
+
ctx.vfs.writeFile(selectionPath(selection), bytes2, { privileged: true, mode: 438 });
|
|
17002
|
+
}
|
|
17003
|
+
var xsel = defineCommand({
|
|
17004
|
+
name: "xsel",
|
|
17005
|
+
summary: "access an X selection",
|
|
17006
|
+
usage: "xsel [--clipboard|--primary|--secondary] [--input|--output|--clear]",
|
|
17007
|
+
async run(ctx) {
|
|
17008
|
+
let selection = "primary";
|
|
17009
|
+
let mode = "output";
|
|
17010
|
+
for (const arg of ctx.args) {
|
|
17011
|
+
switch (arg) {
|
|
17012
|
+
case "-b":
|
|
17013
|
+
case "--clipboard":
|
|
17014
|
+
selection = "clipboard";
|
|
17015
|
+
break;
|
|
17016
|
+
case "-p":
|
|
17017
|
+
case "--primary":
|
|
17018
|
+
selection = "primary";
|
|
17019
|
+
break;
|
|
17020
|
+
case "-s":
|
|
17021
|
+
case "--secondary":
|
|
17022
|
+
selection = "secondary";
|
|
17023
|
+
break;
|
|
17024
|
+
case "-i":
|
|
17025
|
+
case "--input":
|
|
17026
|
+
case "-a":
|
|
17027
|
+
case "--append":
|
|
17028
|
+
mode = "input";
|
|
17029
|
+
break;
|
|
17030
|
+
case "-o":
|
|
17031
|
+
case "--output":
|
|
17032
|
+
mode = "output";
|
|
17033
|
+
break;
|
|
17034
|
+
case "-c":
|
|
17035
|
+
case "--clear":
|
|
17036
|
+
mode = "clear";
|
|
17037
|
+
break;
|
|
17038
|
+
}
|
|
17039
|
+
}
|
|
17040
|
+
if (mode === "clear") {
|
|
17041
|
+
writeSelection(ctx, selection, new Uint8Array());
|
|
17042
|
+
return 0;
|
|
17043
|
+
}
|
|
17044
|
+
if (mode === "input") {
|
|
17045
|
+
writeSelection(ctx, selection, await ctx.stdin.readAll());
|
|
17046
|
+
return 0;
|
|
17047
|
+
}
|
|
17048
|
+
ctx.write(readSelection(ctx, selection));
|
|
17049
|
+
return 0;
|
|
17050
|
+
}
|
|
17051
|
+
});
|
|
17052
|
+
var xclip = defineCommand({
|
|
17053
|
+
name: "xclip",
|
|
17054
|
+
summary: "access an X selection",
|
|
17055
|
+
usage: "xclip [-selection clipboard|primary|secondary] [-i|-o]",
|
|
17056
|
+
async run(ctx) {
|
|
17057
|
+
let selection = "primary";
|
|
17058
|
+
let mode = "input";
|
|
17059
|
+
const args = ctx.args;
|
|
17060
|
+
for (let index = 0; index < args.length; index++) {
|
|
17061
|
+
const arg = args[index];
|
|
17062
|
+
if (arg === "-selection" || arg === "-sel" || arg === "--selection") {
|
|
17063
|
+
const value = args[++index];
|
|
17064
|
+
if (value === "clipboard" || value === "primary" || value === "secondary") selection = value;
|
|
17065
|
+
continue;
|
|
17066
|
+
}
|
|
17067
|
+
if (arg === "-i" || arg === "-in") mode = "input";
|
|
17068
|
+
else if (arg === "-o" || arg === "-out") mode = "output";
|
|
17069
|
+
}
|
|
17070
|
+
if (mode === "input") {
|
|
17071
|
+
writeSelection(ctx, selection, await ctx.stdin.readAll());
|
|
17072
|
+
return 0;
|
|
17073
|
+
}
|
|
17074
|
+
ctx.write(readSelection(ctx, selection));
|
|
17075
|
+
return 0;
|
|
17076
|
+
}
|
|
17077
|
+
});
|
|
17078
|
+
var pbcopy = defineCommand({
|
|
17079
|
+
name: "pbcopy",
|
|
17080
|
+
summary: "copy standard input to the clipboard",
|
|
17081
|
+
usage: "pbcopy",
|
|
17082
|
+
async run(ctx) {
|
|
17083
|
+
writeSelection(ctx, "clipboard", await ctx.stdin.readAll());
|
|
17084
|
+
return 0;
|
|
17085
|
+
}
|
|
17086
|
+
});
|
|
17087
|
+
var pbpaste = defineCommand({
|
|
17088
|
+
name: "pbpaste",
|
|
17089
|
+
summary: "write the clipboard to standard output",
|
|
17090
|
+
usage: "pbpaste",
|
|
17091
|
+
run(ctx) {
|
|
17092
|
+
ctx.write(readSelection(ctx, "clipboard"));
|
|
17093
|
+
return 0;
|
|
17094
|
+
}
|
|
17095
|
+
});
|
|
17096
|
+
var wlCopy = defineCommand({
|
|
17097
|
+
name: "wl-copy",
|
|
17098
|
+
summary: "copy standard input to the Wayland clipboard",
|
|
17099
|
+
usage: "wl-copy [--primary] [text...]",
|
|
17100
|
+
async run(ctx) {
|
|
17101
|
+
const selection = ctx.args.includes("--primary") || ctx.args.includes("-p") ? "primary" : "clipboard";
|
|
17102
|
+
const operands = ctx.args.filter((arg) => !arg.startsWith("-"));
|
|
17103
|
+
const bytes2 = operands.length ? new TextEncoder().encode(operands.join(" ")) : await ctx.stdin.readAll();
|
|
17104
|
+
writeSelection(ctx, selection, bytes2);
|
|
17105
|
+
return 0;
|
|
17106
|
+
}
|
|
17107
|
+
});
|
|
17108
|
+
var wlPaste = defineCommand({
|
|
17109
|
+
name: "wl-paste",
|
|
17110
|
+
summary: "write the Wayland clipboard to standard output",
|
|
17111
|
+
usage: "wl-paste [--primary] [-n]",
|
|
17112
|
+
run(ctx) {
|
|
17113
|
+
const selection = ctx.args.includes("--primary") || ctx.args.includes("-p") ? "primary" : "clipboard";
|
|
17114
|
+
const bytes2 = readSelection(ctx, selection);
|
|
17115
|
+
ctx.write(bytes2);
|
|
17116
|
+
if (!ctx.args.includes("-n") && !ctx.args.includes("--no-newline")) ctx.write("\n");
|
|
17117
|
+
return 0;
|
|
17118
|
+
}
|
|
17119
|
+
});
|
|
17120
|
+
var commands11 = [xsel, xclip, pbcopy, pbpaste, wlCopy, wlPaste];
|
|
17121
|
+
|
|
16983
17122
|
// src/runtime/node.ts
|
|
16984
17123
|
init_path();
|
|
16985
17124
|
var NODE_VERSION = "v22.12.0";
|
|
@@ -18180,7 +18319,33 @@ function ffmpegCommands() {
|
|
|
18180
18319
|
return [ffmpeg, ffprobe];
|
|
18181
18320
|
}
|
|
18182
18321
|
var platformBuffer = globalThis.Buffer;
|
|
18183
|
-
var Buffer2 = platformBuffer ?? index_js.Buffer;
|
|
18322
|
+
var Buffer2 = platformBuffer ?? addBase64UrlSupport(index_js.Buffer);
|
|
18323
|
+
function addBase64UrlSupport(BufferClass) {
|
|
18324
|
+
const target = BufferClass;
|
|
18325
|
+
if (target.__sandboxedBase64Url) return BufferClass;
|
|
18326
|
+
Object.defineProperty(target, "__sandboxedBase64Url", { value: true });
|
|
18327
|
+
const from = target.from.bind(target);
|
|
18328
|
+
target.from = (value, encodingOrOffset, length) => from(value, normalizeEncoding(encodingOrOffset), length);
|
|
18329
|
+
const byteLength = target.byteLength.bind(target);
|
|
18330
|
+
target.byteLength = (value, encoding) => byteLength(value, normalizeEncoding(encoding));
|
|
18331
|
+
const isEncoding = target.isEncoding?.bind(target);
|
|
18332
|
+
if (isEncoding) target.isEncoding = (encoding) => encoding.toLowerCase() === "base64url" || isEncoding(encoding);
|
|
18333
|
+
const toString = target.prototype.toString;
|
|
18334
|
+
target.prototype.toString = function(encoding, start2, end) {
|
|
18335
|
+
if (encoding?.toLowerCase() !== "base64url") return toString.call(this, encoding, start2, end);
|
|
18336
|
+
return toString.call(this, "base64", start2, end).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
18337
|
+
};
|
|
18338
|
+
const write = target.prototype.write;
|
|
18339
|
+
target.prototype.write = function(...args) {
|
|
18340
|
+
const index = typeof args[1] === "string" ? 1 : typeof args[2] === "string" ? 2 : 3;
|
|
18341
|
+
if (typeof args[index] === "string") args[index] = normalizeEncoding(args[index]);
|
|
18342
|
+
return write.apply(this, args);
|
|
18343
|
+
};
|
|
18344
|
+
return BufferClass;
|
|
18345
|
+
}
|
|
18346
|
+
function normalizeEncoding(value) {
|
|
18347
|
+
return typeof value === "string" && value.toLowerCase() === "base64url" ? "base64" : value;
|
|
18348
|
+
}
|
|
18184
18349
|
|
|
18185
18350
|
// src/pkg/clean-installer.ts
|
|
18186
18351
|
init_path();
|
|
@@ -18222,6 +18387,9 @@ var CleanPackageInstaller = class _CleanPackageInstaller {
|
|
|
18222
18387
|
const version = resolveVersion(metadata, range);
|
|
18223
18388
|
const manifest = metadata.versions[version];
|
|
18224
18389
|
if (!manifest) throw new Error(`No matching version found for ${name}@${range}`);
|
|
18390
|
+
if (!supportsPlatform(manifest)) {
|
|
18391
|
+
throw new Error(`${name}@${version} is not compatible with linux/x64/glibc`);
|
|
18392
|
+
}
|
|
18225
18393
|
const identity = `${name}@${version}`;
|
|
18226
18394
|
const target = join(modulesRoot, name);
|
|
18227
18395
|
const installed2 = this.tryReadJson(join(target, "package.json"));
|
|
@@ -18316,6 +18484,15 @@ var CleanPackageInstaller = class _CleanPackageInstaller {
|
|
|
18316
18484
|
}
|
|
18317
18485
|
}
|
|
18318
18486
|
};
|
|
18487
|
+
function supportsPlatform(manifest) {
|
|
18488
|
+
return !manifest.main?.endsWith(".node") && platformListAllows(manifest.os, "linux") && platformListAllows(manifest.cpu, "x64") && platformListAllows(manifest.libc, "glibc");
|
|
18489
|
+
}
|
|
18490
|
+
function platformListAllows(values, current) {
|
|
18491
|
+
if (!values?.length) return true;
|
|
18492
|
+
if (values.includes(`!${current}`)) return false;
|
|
18493
|
+
const positive = values.filter((value) => !value.startsWith("!"));
|
|
18494
|
+
return positive.length === 0 || positive.includes(current) || positive.includes("any");
|
|
18495
|
+
}
|
|
18319
18496
|
function resolveVersion(metadata, range) {
|
|
18320
18497
|
const tag2 = metadata["dist-tags"]?.[range];
|
|
18321
18498
|
if (tag2) return tag2;
|
|
@@ -19298,6 +19475,7 @@ function allCommands() {
|
|
|
19298
19475
|
...commands8,
|
|
19299
19476
|
...commands9,
|
|
19300
19477
|
...commands10,
|
|
19478
|
+
...commands11,
|
|
19301
19479
|
...nodeCommands(),
|
|
19302
19480
|
...pythonCommands(),
|
|
19303
19481
|
...ffmpegCommands(),
|
|
@@ -19594,6 +19772,13 @@ var KernelChildProcess = class {
|
|
|
19594
19772
|
} catch {
|
|
19595
19773
|
}
|
|
19596
19774
|
}
|
|
19775
|
+
/** Signal EOF, so a child reading stdin to the end can finish. */
|
|
19776
|
+
endStdin() {
|
|
19777
|
+
try {
|
|
19778
|
+
this.stdin.end();
|
|
19779
|
+
} catch {
|
|
19780
|
+
}
|
|
19781
|
+
}
|
|
19597
19782
|
kill(signal = "SIGTERM") {
|
|
19598
19783
|
if (this.process) {
|
|
19599
19784
|
this.process.deliver(signal);
|
|
@@ -20505,6 +20690,55 @@ function splitSpecifier(specifier) {
|
|
|
20505
20690
|
return { name: parts.slice(0, size).join("/"), subpath: parts.slice(size).join("/") };
|
|
20506
20691
|
}
|
|
20507
20692
|
|
|
20693
|
+
// src/runtime/readable-from.ts
|
|
20694
|
+
function createReadableFrom(Readable) {
|
|
20695
|
+
return function from(source, options = {}) {
|
|
20696
|
+
if (source && typeof source.pipe === "function") return source;
|
|
20697
|
+
const iterator = source && typeof source[Symbol.asyncIterator] === "function" ? source[Symbol.asyncIterator]() : source && typeof source[Symbol.iterator] === "function" ? source[Symbol.iterator]() : (function* () {
|
|
20698
|
+
yield source;
|
|
20699
|
+
})();
|
|
20700
|
+
let reading = false;
|
|
20701
|
+
const stream = new Readable({
|
|
20702
|
+
...options,
|
|
20703
|
+
objectMode: options.objectMode ?? false,
|
|
20704
|
+
read() {
|
|
20705
|
+
if (reading) return;
|
|
20706
|
+
reading = true;
|
|
20707
|
+
void (async () => {
|
|
20708
|
+
try {
|
|
20709
|
+
for (; ; ) {
|
|
20710
|
+
const next = await iterator.next();
|
|
20711
|
+
if (next.done) {
|
|
20712
|
+
stream.push(null);
|
|
20713
|
+
return;
|
|
20714
|
+
}
|
|
20715
|
+
const value = next.value;
|
|
20716
|
+
if (!stream.push(value === void 0 ? null : value)) return;
|
|
20717
|
+
}
|
|
20718
|
+
} catch (error) {
|
|
20719
|
+
stream.destroy(error);
|
|
20720
|
+
} finally {
|
|
20721
|
+
reading = false;
|
|
20722
|
+
}
|
|
20723
|
+
})();
|
|
20724
|
+
},
|
|
20725
|
+
destroy(error, callback) {
|
|
20726
|
+
void (async () => {
|
|
20727
|
+
try {
|
|
20728
|
+
await iterator.return?.();
|
|
20729
|
+
} catch {
|
|
20730
|
+
}
|
|
20731
|
+
callback(error);
|
|
20732
|
+
})();
|
|
20733
|
+
}
|
|
20734
|
+
});
|
|
20735
|
+
return stream;
|
|
20736
|
+
};
|
|
20737
|
+
}
|
|
20738
|
+
function installReadableFrom(streamModule5) {
|
|
20739
|
+
streamModule5.Readable.from = createReadableFrom(streamModule5.Readable);
|
|
20740
|
+
}
|
|
20741
|
+
|
|
20508
20742
|
// src/runtime/util-module.ts
|
|
20509
20743
|
var customInspect = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
20510
20744
|
var promisifyCustom = /* @__PURE__ */ Symbol.for("nodejs.util.promisify.custom");
|
|
@@ -21392,6 +21626,10 @@ var VirtualHttpRouter = class {
|
|
|
21392
21626
|
unregister(port, server) {
|
|
21393
21627
|
if (this.servers.get(port)?.server === server) this.servers.delete(port);
|
|
21394
21628
|
}
|
|
21629
|
+
/** Whether anything in this container is listening on `port`. */
|
|
21630
|
+
activePortsIncludes(port) {
|
|
21631
|
+
return this.servers.has(port);
|
|
21632
|
+
}
|
|
21395
21633
|
activePorts(owner) {
|
|
21396
21634
|
return [...this.servers].filter(([, item]) => owner === void 0 || item.owner === owner).map(([port]) => port).sort((a, b) => a - b);
|
|
21397
21635
|
}
|
|
@@ -21415,13 +21653,269 @@ var VirtualHttpRouter = class {
|
|
|
21415
21653
|
}
|
|
21416
21654
|
}
|
|
21417
21655
|
};
|
|
21418
|
-
|
|
21656
|
+
var VirtualClientResponse = class extends streamModule4__default.default.Readable {
|
|
21657
|
+
constructor(statusCode, statusMessage, headers, body) {
|
|
21658
|
+
super();
|
|
21659
|
+
this.statusCode = statusCode;
|
|
21660
|
+
this.statusMessage = statusMessage;
|
|
21661
|
+
this.headers = headers;
|
|
21662
|
+
this.rawHeaders = Object.entries(headers).flatMap(([key, value]) => [key, value]);
|
|
21663
|
+
if (body.length) this.push(Buffer2.from(body));
|
|
21664
|
+
this.push(null);
|
|
21665
|
+
this.complete = true;
|
|
21666
|
+
}
|
|
21667
|
+
statusCode;
|
|
21668
|
+
statusMessage;
|
|
21669
|
+
headers;
|
|
21670
|
+
httpVersion = "1.1";
|
|
21671
|
+
httpVersionMajor = 1;
|
|
21672
|
+
httpVersionMinor = 1;
|
|
21673
|
+
socket = socketStub();
|
|
21674
|
+
connection = this.socket;
|
|
21675
|
+
rawHeaders;
|
|
21676
|
+
complete = false;
|
|
21677
|
+
_read() {
|
|
21678
|
+
}
|
|
21679
|
+
setTimeout(_milliseconds, callback) {
|
|
21680
|
+
if (callback) this.once("timeout", callback);
|
|
21681
|
+
return this;
|
|
21682
|
+
}
|
|
21683
|
+
};
|
|
21684
|
+
function resolveTarget(input, overrides, defaultProtocol) {
|
|
21685
|
+
const options = {};
|
|
21686
|
+
if (typeof input === "string" || input instanceof URL) {
|
|
21687
|
+
const url = new URL(String(input));
|
|
21688
|
+
options.protocol = url.protocol;
|
|
21689
|
+
options.hostname = url.hostname;
|
|
21690
|
+
if (url.port) options.port = Number(url.port);
|
|
21691
|
+
options.path = `${url.pathname}${url.search}`;
|
|
21692
|
+
if (url.username || url.password) options.auth = `${url.username}:${url.password}`;
|
|
21693
|
+
} else if (input && typeof input === "object") {
|
|
21694
|
+
Object.assign(options, input);
|
|
21695
|
+
}
|
|
21696
|
+
if (overrides) Object.assign(options, overrides);
|
|
21697
|
+
const protocol = String(options.protocol ?? defaultProtocol).replace(/:?$/, ":");
|
|
21698
|
+
const headers = {};
|
|
21699
|
+
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
21700
|
+
if (value === void 0 || value === null) continue;
|
|
21701
|
+
headers[String(name)] = Array.isArray(value) ? value.join(", ") : String(value);
|
|
21702
|
+
}
|
|
21703
|
+
if (options.auth && headers.authorization === void 0) {
|
|
21704
|
+
headers.authorization = `Basic ${Buffer2.from(String(options.auth)).toString("base64")}`;
|
|
21705
|
+
}
|
|
21706
|
+
const rawHost = String(options.hostname ?? options.host ?? "localhost");
|
|
21707
|
+
const hostMatch = /^(\[[^\]]*\]|[^:]*)(?::(\d+))?$/.exec(rawHost);
|
|
21708
|
+
const hostname = (hostMatch?.[1] ?? rawHost).replace(/^\[|\]$/g, "");
|
|
21709
|
+
const explicitPort = options.port ?? hostMatch?.[2];
|
|
21710
|
+
const port = explicitPort === void 0 || explicitPort === null || explicitPort === "" || Number.isNaN(Number(explicitPort)) ? protocol === "https:" ? 443 : 80 : Number(explicitPort);
|
|
21711
|
+
return {
|
|
21712
|
+
protocol,
|
|
21713
|
+
hostname,
|
|
21714
|
+
port,
|
|
21715
|
+
path: String(options.path ?? "/"),
|
|
21716
|
+
method: String(options.method ?? "GET").toUpperCase(),
|
|
21717
|
+
headers
|
|
21718
|
+
};
|
|
21719
|
+
}
|
|
21720
|
+
function isLoopback(hostname) {
|
|
21721
|
+
return hostname === "localhost" || hostname === "0.0.0.0" || hostname === "::1" || hostname === "::" || hostname.startsWith("127.") || hostname.endsWith(".localhost");
|
|
21722
|
+
}
|
|
21723
|
+
var VirtualClientRequest = class extends streamModule4__default.default.Writable {
|
|
21724
|
+
constructor(target, router, fetchImpl, trackRequest) {
|
|
21725
|
+
super();
|
|
21726
|
+
this.target = target;
|
|
21727
|
+
this.router = router;
|
|
21728
|
+
this.fetchImpl = fetchImpl;
|
|
21729
|
+
this.trackRequest = trackRequest;
|
|
21730
|
+
for (const [name, value] of Object.entries(target.headers)) this.setHeader(name, value);
|
|
21731
|
+
}
|
|
21732
|
+
target;
|
|
21733
|
+
router;
|
|
21734
|
+
fetchImpl;
|
|
21735
|
+
trackRequest;
|
|
21736
|
+
socket = socketStub();
|
|
21737
|
+
connection = this.socket;
|
|
21738
|
+
chunks = [];
|
|
21739
|
+
headerMap = /* @__PURE__ */ new Map();
|
|
21740
|
+
dispatched = false;
|
|
21741
|
+
destroyedByUser = false;
|
|
21742
|
+
timer;
|
|
21743
|
+
aborted = false;
|
|
21744
|
+
finished = false;
|
|
21745
|
+
reusedSocket = false;
|
|
21746
|
+
get method() {
|
|
21747
|
+
return this.target.method;
|
|
21748
|
+
}
|
|
21749
|
+
get path() {
|
|
21750
|
+
return this.target.path;
|
|
21751
|
+
}
|
|
21752
|
+
get host() {
|
|
21753
|
+
return this.target.hostname;
|
|
21754
|
+
}
|
|
21755
|
+
get protocol() {
|
|
21756
|
+
return this.target.protocol;
|
|
21757
|
+
}
|
|
21758
|
+
setHeader(name, value) {
|
|
21759
|
+
validateHeaderName(name);
|
|
21760
|
+
validateHeaderValue(name, value);
|
|
21761
|
+
this.headerMap.set(name.toLowerCase(), { name, value: Array.isArray(value) ? [...value].map(String).join(", ") : String(value) });
|
|
21762
|
+
return this;
|
|
21763
|
+
}
|
|
21764
|
+
getHeader(name) {
|
|
21765
|
+
return this.headerMap.get(name.toLowerCase())?.value;
|
|
21766
|
+
}
|
|
21767
|
+
getHeaders() {
|
|
21768
|
+
return Object.fromEntries([...this.headerMap].map(([key, entry]) => [key, entry.value]));
|
|
21769
|
+
}
|
|
21770
|
+
getHeaderNames() {
|
|
21771
|
+
return [...this.headerMap.keys()];
|
|
21772
|
+
}
|
|
21773
|
+
hasHeader(name) {
|
|
21774
|
+
return this.headerMap.has(name.toLowerCase());
|
|
21775
|
+
}
|
|
21776
|
+
removeHeader(name) {
|
|
21777
|
+
this.headerMap.delete(name.toLowerCase());
|
|
21778
|
+
}
|
|
21779
|
+
flushHeaders() {
|
|
21780
|
+
}
|
|
21781
|
+
setNoDelay() {
|
|
21782
|
+
}
|
|
21783
|
+
setSocketKeepAlive() {
|
|
21784
|
+
}
|
|
21785
|
+
ref() {
|
|
21786
|
+
return this;
|
|
21787
|
+
}
|
|
21788
|
+
unref() {
|
|
21789
|
+
return this;
|
|
21790
|
+
}
|
|
21791
|
+
setTimeout(milliseconds, callback) {
|
|
21792
|
+
if (callback) this.once("timeout", callback);
|
|
21793
|
+
clearTimeout(this.timer);
|
|
21794
|
+
this.timer = setTimeout(() => this.emit("timeout"), milliseconds);
|
|
21795
|
+
return this;
|
|
21796
|
+
}
|
|
21797
|
+
abort() {
|
|
21798
|
+
this.destroyRequest();
|
|
21799
|
+
}
|
|
21800
|
+
destroy(error) {
|
|
21801
|
+
this.destroyRequest(error);
|
|
21802
|
+
return this;
|
|
21803
|
+
}
|
|
21804
|
+
destroyRequest(error) {
|
|
21805
|
+
if (this.destroyedByUser) return;
|
|
21806
|
+
this.destroyedByUser = true;
|
|
21807
|
+
this.aborted = true;
|
|
21808
|
+
clearTimeout(this.timer);
|
|
21809
|
+
this.emit("abort");
|
|
21810
|
+
if (error) this.emit("error", error);
|
|
21811
|
+
this.emit("close");
|
|
21812
|
+
}
|
|
21813
|
+
_write(chunk, encoding, callback) {
|
|
21814
|
+
this.chunks.push(Buffer2.isBuffer(chunk) ? chunk : Buffer2.from(chunk, encoding));
|
|
21815
|
+
callback();
|
|
21816
|
+
}
|
|
21817
|
+
_final(callback) {
|
|
21818
|
+
this.finished = true;
|
|
21819
|
+
callback();
|
|
21820
|
+
void this.dispatch();
|
|
21821
|
+
}
|
|
21822
|
+
async dispatch() {
|
|
21823
|
+
if (this.dispatched || this.destroyedByUser) return;
|
|
21824
|
+
this.dispatched = true;
|
|
21825
|
+
const body = Buffer2.concat(this.chunks);
|
|
21826
|
+
const release = this.trackRequest?.();
|
|
21827
|
+
let released = false;
|
|
21828
|
+
const untrack = () => {
|
|
21829
|
+
if (released || !release) return;
|
|
21830
|
+
released = true;
|
|
21831
|
+
release();
|
|
21832
|
+
};
|
|
21833
|
+
let settled = false;
|
|
21834
|
+
try {
|
|
21835
|
+
const response = this.router.activePortsIncludes(this.target.port) && isLoopback(this.target.hostname) ? await this.viaRouter(body) : await this.viaFetch(body);
|
|
21836
|
+
if (this.destroyedByUser) return;
|
|
21837
|
+
clearTimeout(this.timer);
|
|
21838
|
+
settled = true;
|
|
21839
|
+
response.once("end", untrack);
|
|
21840
|
+
response.once("close", untrack);
|
|
21841
|
+
response.once("error", untrack);
|
|
21842
|
+
this.emit("response", response);
|
|
21843
|
+
queueMicrotask(() => {
|
|
21844
|
+
if (this.listenerCount("response") === 0) response.resume();
|
|
21845
|
+
});
|
|
21846
|
+
} catch (error) {
|
|
21847
|
+
clearTimeout(this.timer);
|
|
21848
|
+
if (this.destroyedByUser) return;
|
|
21849
|
+
const failure = error instanceof Error ? error : new Error(String(error));
|
|
21850
|
+
if (!("code" in failure)) Object.assign(failure, { code: "ECONNREFUSED" });
|
|
21851
|
+
this.emit("error", failure);
|
|
21852
|
+
} finally {
|
|
21853
|
+
if (!settled) untrack();
|
|
21854
|
+
}
|
|
21855
|
+
}
|
|
21856
|
+
async viaRouter(body) {
|
|
21857
|
+
const result = await this.router.request(this.target.port, {
|
|
21858
|
+
method: this.target.method,
|
|
21859
|
+
path: this.target.path,
|
|
21860
|
+
headers: this.getHeaders(),
|
|
21861
|
+
body: body.length ? new Uint8Array(body) : null
|
|
21862
|
+
});
|
|
21863
|
+
const body_ = result.body;
|
|
21864
|
+
const bytes2 = typeof body_ === "string" ? new TextEncoder().encode(body_) : body_ instanceof ArrayBuffer ? new Uint8Array(body_) : body_ ?? new Uint8Array();
|
|
21865
|
+
const status = result.statusCode ?? 200;
|
|
21866
|
+
return new VirtualClientResponse(status, result.statusMessage ?? STATUS_CODES[status] ?? "", lowercaseHeaders(result.headers), bytes2);
|
|
21867
|
+
}
|
|
21868
|
+
async viaFetch(body) {
|
|
21869
|
+
const fetchImpl = this.fetchImpl ?? globalThis.fetch;
|
|
21870
|
+
if (typeof fetchImpl !== "function") {
|
|
21871
|
+
throw Object.assign(new Error(`getaddrinfo ENOTFOUND ${this.target.hostname}`), { code: "ENOTFOUND" });
|
|
21872
|
+
}
|
|
21873
|
+
const portSuffix = this.target.protocol === "https:" && this.target.port === 443 || this.target.protocol === "http:" && this.target.port === 80 ? "" : `:${this.target.port}`;
|
|
21874
|
+
const url = `${this.target.protocol}//${this.target.hostname}${portSuffix}${this.target.path}`;
|
|
21875
|
+
const bodyless = this.target.method === "GET" || this.target.method === "HEAD";
|
|
21876
|
+
const headers = this.getHeaders();
|
|
21877
|
+
delete headers.host;
|
|
21878
|
+
delete headers.connection;
|
|
21879
|
+
delete headers["content-length"];
|
|
21880
|
+
const response = await fetchImpl(url, {
|
|
21881
|
+
method: this.target.method,
|
|
21882
|
+
headers,
|
|
21883
|
+
...bodyless || body.length === 0 ? {} : { body: new Uint8Array(body) },
|
|
21884
|
+
redirect: "follow"
|
|
21885
|
+
});
|
|
21886
|
+
const received = {};
|
|
21887
|
+
response.headers.forEach((value, key) => {
|
|
21888
|
+
received[key.toLowerCase()] = value;
|
|
21889
|
+
});
|
|
21890
|
+
const bytes2 = new Uint8Array(await response.arrayBuffer());
|
|
21891
|
+
return new VirtualClientResponse(response.status, response.statusText, received, bytes2);
|
|
21892
|
+
}
|
|
21893
|
+
};
|
|
21894
|
+
function lowercaseHeaders(headers) {
|
|
21895
|
+
return Object.fromEntries(Object.entries(headers ?? {}).map(([key, value]) => [key.toLowerCase(), String(value)]));
|
|
21896
|
+
}
|
|
21897
|
+
function createHttpModule(router, owner, options = {}, defaultProtocol = "http:") {
|
|
21419
21898
|
const createServer = (listener) => new VirtualHttpServer(router, owner, listener);
|
|
21420
|
-
const
|
|
21899
|
+
const request = (input, second, third) => {
|
|
21900
|
+
const overrides = second && typeof second === "object" && !(second instanceof Function) ? second : void 0;
|
|
21901
|
+
const callback = [second, third].find((value) => typeof value === "function");
|
|
21902
|
+
const req = new VirtualClientRequest(resolveTarget(input, overrides, defaultProtocol), router, options.fetch, options.trackRequest);
|
|
21903
|
+
if (callback) req.on("response", callback);
|
|
21904
|
+
return req;
|
|
21905
|
+
};
|
|
21906
|
+
const get = (input, second, third) => {
|
|
21907
|
+
const req = request(input, second, third);
|
|
21908
|
+
req.end();
|
|
21909
|
+
return req;
|
|
21910
|
+
};
|
|
21911
|
+
return {
|
|
21421
21912
|
createServer,
|
|
21913
|
+
request,
|
|
21914
|
+
get,
|
|
21422
21915
|
Server: VirtualHttpServer,
|
|
21423
21916
|
ServerResponse: VirtualServerResponse,
|
|
21424
21917
|
IncomingMessage: VirtualIncomingMessage,
|
|
21918
|
+
ClientRequest: VirtualClientRequest,
|
|
21425
21919
|
METHODS,
|
|
21426
21920
|
STATUS_CODES,
|
|
21427
21921
|
maxHeaderSize: 16 * 1024,
|
|
@@ -21431,10 +21925,6 @@ function createHttpModule(router, owner) {
|
|
|
21431
21925
|
Agent: class Agent {
|
|
21432
21926
|
}
|
|
21433
21927
|
};
|
|
21434
|
-
return { ...module, request: unsupportedClient, get: unsupportedClient };
|
|
21435
|
-
}
|
|
21436
|
-
function unsupportedClient() {
|
|
21437
|
-
throw Object.assign(new Error("http client requests are not implemented yet"), { code: "ERR_NOT_IMPLEMENTED" });
|
|
21438
21928
|
}
|
|
21439
21929
|
function validateHeaderName(name) {
|
|
21440
21930
|
if (!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(name)) throw Object.assign(new TypeError(`Header name must be a valid HTTP token [${name}]`), { code: "ERR_INVALID_HTTP_TOKEN" });
|
|
@@ -21574,6 +22064,13 @@ var ChildProcess = class extends EventEmitter4__default.default {
|
|
|
21574
22064
|
} catch {
|
|
21575
22065
|
}
|
|
21576
22066
|
done();
|
|
22067
|
+
},
|
|
22068
|
+
final: (done) => {
|
|
22069
|
+
try {
|
|
22070
|
+
handle.endStdin?.();
|
|
22071
|
+
} catch {
|
|
22072
|
+
}
|
|
22073
|
+
done();
|
|
21577
22074
|
}
|
|
21578
22075
|
});
|
|
21579
22076
|
this.stdio = [this.stdin, this.stdout, this.stderr];
|
|
@@ -21812,7 +22309,7 @@ function emitKeypressEvents(stream) {
|
|
|
21812
22309
|
}
|
|
21813
22310
|
});
|
|
21814
22311
|
}
|
|
21815
|
-
function createReadlineModule(defaultInput) {
|
|
22312
|
+
function createReadlineModule(defaultInput, defaultOutput = () => void 0) {
|
|
21816
22313
|
class Interface extends EventEmitter4__default.default {
|
|
21817
22314
|
constructor(input, output, terminal = false) {
|
|
21818
22315
|
super();
|
|
@@ -21823,6 +22320,14 @@ function createReadlineModule(defaultInput) {
|
|
|
21823
22320
|
if (terminal) {
|
|
21824
22321
|
emitKeypressEvents(input);
|
|
21825
22322
|
input?.on?.("keypress", this.onTerminalKeypress);
|
|
22323
|
+
if (typeof input?.setRawMode === "function") {
|
|
22324
|
+
try {
|
|
22325
|
+
input.setRawMode(true);
|
|
22326
|
+
this.ownsRawMode = true;
|
|
22327
|
+
} catch {
|
|
22328
|
+
}
|
|
22329
|
+
}
|
|
22330
|
+
input?.resume?.();
|
|
21826
22331
|
} else {
|
|
21827
22332
|
input?.on?.("data", (chunk) => this.receive(String(chunk)));
|
|
21828
22333
|
}
|
|
@@ -21834,6 +22339,10 @@ function createReadlineModule(defaultInput) {
|
|
|
21834
22339
|
buffer = "";
|
|
21835
22340
|
pending = [];
|
|
21836
22341
|
lines = [];
|
|
22342
|
+
/** Set while `question` is waiting, so the echoed line carries the query. */
|
|
22343
|
+
questionPrompt = null;
|
|
22344
|
+
/** Raw mode is only ours to restore if we were the one to enable it. */
|
|
22345
|
+
ownsRawMode = false;
|
|
21837
22346
|
line = "";
|
|
21838
22347
|
cursor = 0;
|
|
21839
22348
|
terminal;
|
|
@@ -21841,20 +22350,31 @@ function createReadlineModule(defaultInput) {
|
|
|
21841
22350
|
/** Split incoming data into lines, answering any waiting `question`. */
|
|
21842
22351
|
receive(text2) {
|
|
21843
22352
|
this.buffer += text2;
|
|
21844
|
-
let
|
|
21845
|
-
while (
|
|
21846
|
-
const line = this.buffer.slice(0,
|
|
21847
|
-
this.buffer = this.buffer.slice(
|
|
21848
|
-
|
|
21849
|
-
|
|
21850
|
-
|
|
21851
|
-
|
|
21852
|
-
|
|
21853
|
-
|
|
21854
|
-
|
|
22353
|
+
let match2 = /\r\n|\r|\n/.exec(this.buffer);
|
|
22354
|
+
while (match2) {
|
|
22355
|
+
const line = this.buffer.slice(0, match2.index);
|
|
22356
|
+
this.buffer = this.buffer.slice(match2.index + match2[0].length);
|
|
22357
|
+
this.deliver(line);
|
|
22358
|
+
match2 = /\r\n|\r|\n/.exec(this.buffer);
|
|
22359
|
+
}
|
|
22360
|
+
}
|
|
22361
|
+
/** Hand a completed line to whoever is waiting for it. */
|
|
22362
|
+
deliver(line) {
|
|
22363
|
+
const waiting = this.pending.shift();
|
|
22364
|
+
if (waiting) {
|
|
22365
|
+
this.questionPrompt = null;
|
|
22366
|
+
waiting(line);
|
|
22367
|
+
return;
|
|
21855
22368
|
}
|
|
22369
|
+
this.lines.push(line);
|
|
22370
|
+
this.emit("line", line);
|
|
21856
22371
|
}
|
|
21857
22372
|
question(query, callback) {
|
|
22373
|
+
if (this.terminal) {
|
|
22374
|
+
this.questionPrompt = query;
|
|
22375
|
+
this.line = "";
|
|
22376
|
+
this.cursor = 0;
|
|
22377
|
+
}
|
|
21858
22378
|
this.output?.write?.(query);
|
|
21859
22379
|
if (callback) {
|
|
21860
22380
|
this.pending.push(callback);
|
|
@@ -21869,6 +22389,9 @@ function createReadlineModule(defaultInput) {
|
|
|
21869
22389
|
setPrompt(text2) {
|
|
21870
22390
|
this.promptText = text2;
|
|
21871
22391
|
}
|
|
22392
|
+
getPrompt() {
|
|
22393
|
+
return this.promptText;
|
|
22394
|
+
}
|
|
21872
22395
|
pause() {
|
|
21873
22396
|
this.input?.pause?.();
|
|
21874
22397
|
return this;
|
|
@@ -21896,21 +22419,48 @@ function createReadlineModule(defaultInput) {
|
|
|
21896
22419
|
if (text2) {
|
|
21897
22420
|
this.line = this.line.slice(0, this.cursor) + text2 + this.line.slice(this.cursor);
|
|
21898
22421
|
this.cursor += text2.length;
|
|
22422
|
+
this.refresh();
|
|
21899
22423
|
}
|
|
21900
22424
|
}
|
|
21901
22425
|
getCursorPos() {
|
|
21902
|
-
return { rows: 0, cols: this.cursor + this.
|
|
22426
|
+
return { rows: 0, cols: this.cursor + this.currentPrompt().length };
|
|
21903
22427
|
}
|
|
21904
22428
|
close() {
|
|
21905
22429
|
if (this.closed) return;
|
|
21906
22430
|
this.closed = true;
|
|
21907
22431
|
if (this.terminal) {
|
|
21908
22432
|
this.input?.off?.("keypress", this.onTerminalKeypress);
|
|
22433
|
+
if (this.ownsRawMode) {
|
|
22434
|
+
this.ownsRawMode = false;
|
|
22435
|
+
try {
|
|
22436
|
+
this.input?.setRawMode?.(false);
|
|
22437
|
+
} catch {
|
|
22438
|
+
}
|
|
22439
|
+
}
|
|
21909
22440
|
this.input?.pause?.();
|
|
21910
22441
|
}
|
|
21911
22442
|
for (const waiting of this.pending.splice(0)) waiting("");
|
|
21912
22443
|
this.emit("close");
|
|
21913
22444
|
}
|
|
22445
|
+
/** The text shown to the left of the edited line. */
|
|
22446
|
+
currentPrompt() {
|
|
22447
|
+
return this.questionPrompt ?? this.promptText;
|
|
22448
|
+
}
|
|
22449
|
+
/**
|
|
22450
|
+
* Repaint the edited line.
|
|
22451
|
+
*
|
|
22452
|
+
* In raw mode nothing echoes on its own, so an Interface that does not do
|
|
22453
|
+
* this leaves the user typing blind. Libraries that draw their own frame
|
|
22454
|
+
* (clack, inquirer) simply overwrite this, exactly as they do on Node.
|
|
22455
|
+
*/
|
|
22456
|
+
refresh() {
|
|
22457
|
+
if (!this.terminal) return;
|
|
22458
|
+
const prompt = this.currentPrompt();
|
|
22459
|
+
let text2 = `\r\x1B[0K${prompt}${this.line}`;
|
|
22460
|
+
const back = this.line.length - this.cursor;
|
|
22461
|
+
if (back > 0) text2 += `\x1B[${back}D`;
|
|
22462
|
+
this.output?.write?.(text2);
|
|
22463
|
+
}
|
|
21914
22464
|
edit(sequence, key) {
|
|
21915
22465
|
if (this.closed) return;
|
|
21916
22466
|
const name = key.name;
|
|
@@ -21918,48 +22468,62 @@ function createReadlineModule(defaultInput) {
|
|
|
21918
22468
|
const value = this.line;
|
|
21919
22469
|
this.line = "";
|
|
21920
22470
|
this.cursor = 0;
|
|
21921
|
-
this.
|
|
22471
|
+
this.output?.write?.("\r\n");
|
|
22472
|
+
this.deliver(value);
|
|
21922
22473
|
return;
|
|
21923
22474
|
}
|
|
21924
22475
|
if (name === "left") {
|
|
21925
22476
|
this.cursor = Math.max(0, this.cursor - 1);
|
|
22477
|
+
this.refresh();
|
|
21926
22478
|
return;
|
|
21927
22479
|
}
|
|
21928
22480
|
if (name === "right") {
|
|
21929
22481
|
this.cursor = Math.min(this.line.length, this.cursor + 1);
|
|
22482
|
+
this.refresh();
|
|
21930
22483
|
return;
|
|
21931
22484
|
}
|
|
21932
22485
|
if (name === "home" || key.ctrl && name === "a") {
|
|
21933
22486
|
this.cursor = 0;
|
|
22487
|
+
this.refresh();
|
|
21934
22488
|
return;
|
|
21935
22489
|
}
|
|
21936
22490
|
if (name === "end" || key.ctrl && name === "e") {
|
|
21937
22491
|
this.cursor = this.line.length;
|
|
22492
|
+
this.refresh();
|
|
21938
22493
|
return;
|
|
21939
22494
|
}
|
|
21940
22495
|
if (name === "backspace" || key.ctrl && name === "h") {
|
|
21941
22496
|
if (this.cursor > 0) {
|
|
21942
22497
|
this.line = this.line.slice(0, this.cursor - 1) + this.line.slice(this.cursor);
|
|
21943
22498
|
this.cursor--;
|
|
22499
|
+
this.refresh();
|
|
21944
22500
|
}
|
|
21945
22501
|
return;
|
|
21946
22502
|
}
|
|
21947
22503
|
if (name === "delete") {
|
|
21948
|
-
if (this.cursor < this.line.length)
|
|
22504
|
+
if (this.cursor < this.line.length) {
|
|
22505
|
+
this.line = this.line.slice(0, this.cursor) + this.line.slice(this.cursor + 1);
|
|
22506
|
+
this.refresh();
|
|
22507
|
+
}
|
|
21949
22508
|
return;
|
|
21950
22509
|
}
|
|
21951
22510
|
if (key.ctrl && name === "u") {
|
|
21952
22511
|
this.line = this.line.slice(this.cursor);
|
|
21953
22512
|
this.cursor = 0;
|
|
22513
|
+
this.refresh();
|
|
21954
22514
|
return;
|
|
21955
22515
|
}
|
|
21956
22516
|
if (key.ctrl && name === "k") {
|
|
21957
22517
|
this.line = this.line.slice(0, this.cursor);
|
|
22518
|
+
this.refresh();
|
|
21958
22519
|
return;
|
|
21959
22520
|
}
|
|
21960
22521
|
if (key.ctrl || key.meta || sequence.length !== 1 || sequence < " ") return;
|
|
22522
|
+
const atEnd = this.cursor === this.line.length;
|
|
21961
22523
|
this.line = this.line.slice(0, this.cursor) + sequence + this.line.slice(this.cursor);
|
|
21962
22524
|
this.cursor += sequence.length;
|
|
22525
|
+
if (atEnd) this.output?.write?.(sequence);
|
|
22526
|
+
else this.refresh();
|
|
21963
22527
|
}
|
|
21964
22528
|
async *[Symbol.asyncIterator]() {
|
|
21965
22529
|
while (!this.closed || this.lines.length) {
|
|
@@ -21989,13 +22553,23 @@ function createReadlineModule(defaultInput) {
|
|
|
21989
22553
|
}
|
|
21990
22554
|
}
|
|
21991
22555
|
}
|
|
22556
|
+
const isTerminal = (options, output) => {
|
|
22557
|
+
if (typeof options?.terminal === "boolean") return options.terminal;
|
|
22558
|
+
return Boolean(output?.isTTY);
|
|
22559
|
+
};
|
|
21992
22560
|
const createInterface = (options, output) => {
|
|
21993
22561
|
if (options && typeof options === "object" && !options.on) {
|
|
21994
|
-
const
|
|
22562
|
+
const resolvedOutput2 = options.output ?? defaultOutput();
|
|
22563
|
+
const instance = new Interface(
|
|
22564
|
+
options.input ?? defaultInput(),
|
|
22565
|
+
resolvedOutput2,
|
|
22566
|
+
isTerminal(options, resolvedOutput2)
|
|
22567
|
+
);
|
|
21995
22568
|
if (typeof options.prompt === "string") instance.setPrompt(options.prompt);
|
|
21996
22569
|
return instance;
|
|
21997
22570
|
}
|
|
21998
|
-
|
|
22571
|
+
const resolvedOutput = output ?? defaultOutput();
|
|
22572
|
+
return new Interface(options ?? defaultInput(), resolvedOutput, isTerminal(void 0, resolvedOutput));
|
|
21999
22573
|
};
|
|
22000
22574
|
const noop = () => {
|
|
22001
22575
|
};
|
|
@@ -22012,6 +22586,7 @@ function createReadlineModule(defaultInput) {
|
|
|
22012
22586
|
}
|
|
22013
22587
|
|
|
22014
22588
|
// src/runtime/core-modules.ts
|
|
22589
|
+
installReadableFrom(streamModule4__default.default);
|
|
22015
22590
|
var Dirent = class {
|
|
22016
22591
|
/** Node 20+ exposes the containing directory, and `fs.glob` consumers read it. */
|
|
22017
22592
|
constructor(name, stat2, parentPath = "") {
|
|
@@ -22217,9 +22792,20 @@ function createCoreModules(options) {
|
|
|
22217
22792
|
throw new Error("createRequire is only available inside a loaded module");
|
|
22218
22793
|
}
|
|
22219
22794
|
};
|
|
22220
|
-
|
|
22795
|
+
let inFlightRequests = 0;
|
|
22796
|
+
const httpOptions = {
|
|
22797
|
+
...options.http?.fetch ? { fetch: options.http.fetch } : {},
|
|
22798
|
+
trackRequest: () => {
|
|
22799
|
+
inFlightRequests++;
|
|
22800
|
+
return () => {
|
|
22801
|
+
inFlightRequests--;
|
|
22802
|
+
};
|
|
22803
|
+
}
|
|
22804
|
+
};
|
|
22805
|
+
const http = options.http ? createHttpModule(options.http.router, options.http.owner, httpOptions, "http:") : createUnsupportedModule("http");
|
|
22806
|
+
const https = options.http ? createHttpModule(options.http.router, options.http.owner, httpOptions, "https:") : createUnsupportedModule("https");
|
|
22221
22807
|
const childProcess = options.spawnChild ? createChildProcessModule(options.spawnChild, () => cwd) : createUnsupportedModule("child_process");
|
|
22222
|
-
const readline = createReadlineModule(() => processObject.stdin);
|
|
22808
|
+
const readline = createReadlineModule(() => processObject.stdin, () => processObject.stdout);
|
|
22223
22809
|
const dns = createDnsModule();
|
|
22224
22810
|
const builtins = {
|
|
22225
22811
|
assert: assert_module_default,
|
|
@@ -22237,7 +22823,7 @@ function createCoreModules(options) {
|
|
|
22237
22823
|
"fs/promises": fs.promises,
|
|
22238
22824
|
module: moduleBuiltin,
|
|
22239
22825
|
http,
|
|
22240
|
-
https
|
|
22826
|
+
https,
|
|
22241
22827
|
os,
|
|
22242
22828
|
path,
|
|
22243
22829
|
"path/posix": path,
|
|
@@ -22276,6 +22862,9 @@ function createCoreModules(options) {
|
|
|
22276
22862
|
globals,
|
|
22277
22863
|
process: processObject,
|
|
22278
22864
|
pendingHandles: timers.pending,
|
|
22865
|
+
pendingUnrefed: timers.pendingUnrefed,
|
|
22866
|
+
/** Client requests sent but not yet read to completion. */
|
|
22867
|
+
pendingRequests: () => inFlightRequests,
|
|
22279
22868
|
writeStdin: (data) => {
|
|
22280
22869
|
if (options.interactiveStdin) stdin.write(data);
|
|
22281
22870
|
},
|
|
@@ -22503,9 +23092,20 @@ function createFsModule(volume, cwd, stdinPath) {
|
|
|
22503
23092
|
if (position == null) file3.position = start2 + chunk.length;
|
|
22504
23093
|
return chunk.length;
|
|
22505
23094
|
},
|
|
22506
|
-
createReadStream: (path) => {
|
|
22507
|
-
const
|
|
22508
|
-
|
|
23095
|
+
createReadStream: (path, options) => {
|
|
23096
|
+
const target = abs(path);
|
|
23097
|
+
const settings = typeof options === "string" ? { encoding: options } : options ?? {};
|
|
23098
|
+
const whole = Buffer2.from(volume.readFileSync(resolveLinks(volume, target)));
|
|
23099
|
+
const start2 = settings.start ?? 0;
|
|
23100
|
+
const end = settings.end === void 0 ? whole.length : Math.min(settings.end + 1, whole.length);
|
|
23101
|
+
const slice = whole.subarray(start2, Math.max(start2, end));
|
|
23102
|
+
const stream = streamModule4__default.default.Readable.from([settings.encoding ? slice.toString(settings.encoding) : slice]);
|
|
23103
|
+
Object.assign(stream, { path: target, bytesRead: slice.length, close: () => stream.destroy() });
|
|
23104
|
+
queueMicrotask(() => {
|
|
23105
|
+
stream.emit("open", 0);
|
|
23106
|
+
stream.emit("ready");
|
|
23107
|
+
});
|
|
23108
|
+
return stream;
|
|
22509
23109
|
},
|
|
22510
23110
|
createWriteStream: (path, options) => {
|
|
22511
23111
|
const target = abs(path);
|
|
@@ -22871,33 +23471,78 @@ var ERRNO_CONSTANTS = {
|
|
|
22871
23471
|
};
|
|
22872
23472
|
function createTrackedTimers() {
|
|
22873
23473
|
const live = /* @__PURE__ */ new Set();
|
|
22874
|
-
const
|
|
23474
|
+
const unrefed = /* @__PURE__ */ new Set();
|
|
23475
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
23476
|
+
const track = (native) => {
|
|
23477
|
+
const state = { native, active: true, referenced: true };
|
|
23478
|
+
const handle = {
|
|
23479
|
+
ref() {
|
|
23480
|
+
state.referenced = true;
|
|
23481
|
+
unrefed.delete(handle);
|
|
23482
|
+
if (state.active) live.add(handle);
|
|
23483
|
+
state.native?.ref?.();
|
|
23484
|
+
return handle;
|
|
23485
|
+
},
|
|
23486
|
+
unref() {
|
|
23487
|
+
state.referenced = false;
|
|
23488
|
+
live.delete(handle);
|
|
23489
|
+
if (state.active) unrefed.add(handle);
|
|
23490
|
+
state.native?.unref?.();
|
|
23491
|
+
return handle;
|
|
23492
|
+
},
|
|
23493
|
+
hasRef: () => state.referenced,
|
|
23494
|
+
refresh() {
|
|
23495
|
+
state.native?.refresh?.();
|
|
23496
|
+
return handle;
|
|
23497
|
+
},
|
|
23498
|
+
[Symbol.toPrimitive]: () => Number(state.native)
|
|
23499
|
+
};
|
|
23500
|
+
states.set(handle, state);
|
|
22875
23501
|
live.add(handle);
|
|
22876
23502
|
return handle;
|
|
22877
23503
|
};
|
|
23504
|
+
const complete = (handle) => {
|
|
23505
|
+
const state = states.get(handle);
|
|
23506
|
+
if (state) state.active = false;
|
|
23507
|
+
live.delete(handle);
|
|
23508
|
+
unrefed.delete(handle);
|
|
23509
|
+
};
|
|
22878
23510
|
const setTimeoutTracked = (fn, delay, ...args) => {
|
|
22879
|
-
|
|
23511
|
+
let handle;
|
|
23512
|
+
const native = setTimeout(
|
|
22880
23513
|
(...inner) => {
|
|
22881
|
-
|
|
23514
|
+
complete(handle);
|
|
22882
23515
|
fn(...inner);
|
|
22883
23516
|
},
|
|
22884
23517
|
delay,
|
|
22885
23518
|
...args
|
|
22886
23519
|
);
|
|
22887
|
-
|
|
23520
|
+
handle = track(native);
|
|
22888
23521
|
return handle;
|
|
22889
23522
|
};
|
|
22890
23523
|
const setIntervalTracked = (fn, delay, ...args) => track(setInterval(fn, delay, ...args));
|
|
22891
23524
|
const hostSetImmediate = globalThis.setImmediate;
|
|
22892
23525
|
const setImmediateTracked = (fn, ...args) => {
|
|
22893
|
-
|
|
22894
|
-
|
|
23526
|
+
if (!hostSetImmediate) return setTimeoutTracked(fn, 0, ...args);
|
|
23527
|
+
let handle;
|
|
23528
|
+
const native = hostSetImmediate((...inner) => {
|
|
23529
|
+
complete(handle);
|
|
22895
23530
|
fn(...inner);
|
|
22896
|
-
}, ...args)
|
|
22897
|
-
|
|
23531
|
+
}, ...args);
|
|
23532
|
+
handle = track(native);
|
|
22898
23533
|
return handle;
|
|
22899
23534
|
};
|
|
22900
23535
|
const clear2 = (handle, native) => {
|
|
23536
|
+
if (typeof handle === "object" && handle !== null) {
|
|
23537
|
+
const state = states.get(handle);
|
|
23538
|
+
if (state) {
|
|
23539
|
+
state.active = false;
|
|
23540
|
+
live.delete(handle);
|
|
23541
|
+
unrefed.delete(handle);
|
|
23542
|
+
native(state.native);
|
|
23543
|
+
return;
|
|
23544
|
+
}
|
|
23545
|
+
}
|
|
22901
23546
|
live.delete(handle);
|
|
22902
23547
|
native(handle);
|
|
22903
23548
|
};
|
|
@@ -22910,7 +23555,8 @@ function createTrackedTimers() {
|
|
|
22910
23555
|
clearInterval: (handle) => clear2(handle, clearInterval),
|
|
22911
23556
|
clearImmediate: (handle) => clear2(handle, globalThis.clearImmediate ?? clearTimeout)
|
|
22912
23557
|
},
|
|
22913
|
-
pending: () => live.size
|
|
23558
|
+
pending: () => live.size,
|
|
23559
|
+
pendingUnrefed: () => unrefed.size
|
|
22914
23560
|
};
|
|
22915
23561
|
}
|
|
22916
23562
|
function createTimerPromises() {
|
|
@@ -23432,7 +24078,26 @@ function ensureProcessGlobal() {
|
|
|
23432
24078
|
});
|
|
23433
24079
|
}
|
|
23434
24080
|
|
|
24081
|
+
// src/runtime/host-rolldown.ts
|
|
24082
|
+
async function loadHostRolldownBinding() {
|
|
24083
|
+
if (typeof window !== "undefined" && globalThis.crossOriginIsolated !== true) {
|
|
24084
|
+
throw new Error(
|
|
24085
|
+
"Vite 8/Rolldown requires cross-origin isolation. Serve the app with Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp headers."
|
|
24086
|
+
);
|
|
24087
|
+
}
|
|
24088
|
+
try {
|
|
24089
|
+
const loaded = await import('@rolldown/binding-wasm32-wasi');
|
|
24090
|
+
return "__fs" in loaded ? { ...loaded } : loaded.default ?? loaded;
|
|
24091
|
+
} catch (error) {
|
|
24092
|
+
if (typeof process !== "undefined" && process.env?.SANDBOXEDJS_DEBUG) {
|
|
24093
|
+
console.error("[sandboxedjs] Rolldown WASI binding unavailable:", error);
|
|
24094
|
+
}
|
|
24095
|
+
throw new Error("The optional Rolldown WASI binding could not be loaded.", { cause: error });
|
|
24096
|
+
}
|
|
24097
|
+
}
|
|
24098
|
+
|
|
23435
24099
|
// src/runtime/local-runtime-pod.ts
|
|
24100
|
+
init_path();
|
|
23436
24101
|
var WASM_ALIASES = {
|
|
23437
24102
|
esbuild: "esbuild-wasm",
|
|
23438
24103
|
rollup: "@rollup/wasm-node"
|
|
@@ -23557,6 +24222,11 @@ var PodChildProcess = class {
|
|
|
23557
24222
|
started = false;
|
|
23558
24223
|
cancelled = false;
|
|
23559
24224
|
child;
|
|
24225
|
+
/* The child is launched asynchronously, but a parent may write and close
|
|
24226
|
+
* its input synchronously right after spawning. Holding both until the
|
|
24227
|
+
* child exists is what keeps `echo hi | child` from losing the `hi`. */
|
|
24228
|
+
pendingInput = "";
|
|
24229
|
+
inputEnded = false;
|
|
23560
24230
|
on(event, listener) {
|
|
23561
24231
|
let set = this.listeners.get(event);
|
|
23562
24232
|
if (!set) this.listeners.set(event, set = /* @__PURE__ */ new Set());
|
|
@@ -23579,6 +24249,11 @@ var PodChildProcess = class {
|
|
|
23579
24249
|
(child) => {
|
|
23580
24250
|
this.child = child;
|
|
23581
24251
|
if (this.cancelled) child.kill();
|
|
24252
|
+
if (this.pendingInput !== "") {
|
|
24253
|
+
child.write(this.pendingInput);
|
|
24254
|
+
this.pendingInput = "";
|
|
24255
|
+
}
|
|
24256
|
+
if (this.inputEnded) child.endInput?.();
|
|
23582
24257
|
child.on("output", (text2) => {
|
|
23583
24258
|
this.stdout += text2;
|
|
23584
24259
|
this.emit("stdout", text2);
|
|
@@ -23601,7 +24276,13 @@ var PodChildProcess = class {
|
|
|
23601
24276
|
});
|
|
23602
24277
|
}
|
|
23603
24278
|
sendStdin(data) {
|
|
23604
|
-
this.child
|
|
24279
|
+
if (this.child) this.child.write(data);
|
|
24280
|
+
else this.pendingInput += data;
|
|
24281
|
+
}
|
|
24282
|
+
/** Signal EOF, so a child reading stdin to the end can finish. */
|
|
24283
|
+
endStdin() {
|
|
24284
|
+
if (this.child) this.child.endInput?.();
|
|
24285
|
+
else this.inputEnded = true;
|
|
23605
24286
|
}
|
|
23606
24287
|
kill(signal = "SIGTERM") {
|
|
23607
24288
|
if (this.child) this.child.kill(signal);
|
|
@@ -23683,6 +24364,9 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23683
24364
|
aliases;
|
|
23684
24365
|
modules;
|
|
23685
24366
|
esbuild;
|
|
24367
|
+
rolldownBinding;
|
|
24368
|
+
/** Backs outbound `http`/`https` client requests from inside the sandbox. */
|
|
24369
|
+
fetch;
|
|
23686
24370
|
constructor(options) {
|
|
23687
24371
|
ensureProcessGlobal();
|
|
23688
24372
|
this.workdir = options.workdir ?? "/";
|
|
@@ -23697,6 +24381,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23697
24381
|
const notify = options.onServerReady;
|
|
23698
24382
|
this.router.onListen = (port) => notify(port, `http://localhost:${port}`);
|
|
23699
24383
|
}
|
|
24384
|
+
if (options.fetch) this.fetch = options.fetch;
|
|
23700
24385
|
this.packages = new CleanPackageInstaller(this.volume, {
|
|
23701
24386
|
cwd: this.workdir,
|
|
23702
24387
|
...options.registry ? { registry: options.registry } : {},
|
|
@@ -23716,6 +24401,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23716
24401
|
const env2 = { ...this.env, ...isRecord(options.env) ? options.env : {} };
|
|
23717
24402
|
const owner = `${this.instanceId}:${Math.random().toString(36).slice(2)}`;
|
|
23718
24403
|
return new LocalProcess(async (proc) => {
|
|
24404
|
+
await this.prepareRolldown(cwd, env2);
|
|
23719
24405
|
const untrack = trackProcess(proc);
|
|
23720
24406
|
let requestedExit = 0;
|
|
23721
24407
|
let engine;
|
|
@@ -23735,7 +24421,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23735
24421
|
proc.exitNow(code);
|
|
23736
24422
|
if (engine?.isEvaluating) throw new ProcessExit(code);
|
|
23737
24423
|
},
|
|
23738
|
-
http: { router: this.router, owner },
|
|
24424
|
+
http: { router: this.router, owner, ...this.fetch ? { fetch: this.fetch } : {} },
|
|
23739
24425
|
spawnChild: (config) => this.processManager.spawn(config),
|
|
23740
24426
|
...typeof options.stdinPath === "string" ? { stdinPath: options.stdinPath } : {},
|
|
23741
24427
|
...options.interactiveStdin ? { interactiveStdin: true } : {},
|
|
@@ -23752,7 +24438,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23752
24438
|
});
|
|
23753
24439
|
try {
|
|
23754
24440
|
await engine.run(script);
|
|
23755
|
-
await this.settle(owner, core.pendingHandles, core.readingStdin);
|
|
24441
|
+
await this.settle(owner, core.pendingHandles, core.pendingUnrefed, core.readingStdin, core.pendingRequests);
|
|
23756
24442
|
if (this.router.activePorts(owner).length) {
|
|
23757
24443
|
await proc.waitForKill();
|
|
23758
24444
|
return 137;
|
|
@@ -23764,6 +24450,25 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23764
24450
|
}
|
|
23765
24451
|
});
|
|
23766
24452
|
}
|
|
24453
|
+
/**
|
|
24454
|
+
* Rolldown's JavaScript API synchronously requires its compiled binding.
|
|
24455
|
+
* When a project contains Rolldown, preload the official WASI build in the
|
|
24456
|
+
* host and expose it through the module override table before evaluation.
|
|
24457
|
+
* Keeping this demand-driven avoids adding WASM startup cost to ordinary
|
|
24458
|
+
* shells and Node programs.
|
|
24459
|
+
*/
|
|
24460
|
+
async prepareRolldown(cwd, env2) {
|
|
24461
|
+
const specifier = "@rolldown/binding-wasm32-wasi";
|
|
24462
|
+
if (!this.modules[specifier] && packageInstalled(this.volume, cwd, "rolldown")) {
|
|
24463
|
+
this.rolldownBinding ??= loadHostRolldownBinding();
|
|
24464
|
+
const binding = await this.rolldownBinding;
|
|
24465
|
+
if (binding) this.modules[specifier] = binding;
|
|
24466
|
+
}
|
|
24467
|
+
if (this.modules[specifier]) {
|
|
24468
|
+
syncRolldownFileSystem(this.modules[specifier], this.volume, cwd);
|
|
24469
|
+
env2.NAPI_RS_FORCE_WASI ??= "true";
|
|
24470
|
+
}
|
|
24471
|
+
}
|
|
23767
24472
|
/**
|
|
23768
24473
|
* Wait until the process has either started serving or genuinely run out of
|
|
23769
24474
|
* work.
|
|
@@ -23779,12 +24484,18 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23779
24484
|
* A plain script that has genuinely finished falls straight through both,
|
|
23780
24485
|
* costing a handful of empty turns.
|
|
23781
24486
|
*/
|
|
23782
|
-
async settle(owner, pendingHandles, readingStdin) {
|
|
24487
|
+
async settle(owner, pendingHandles, pendingUnrefed, readingStdin, pendingRequests) {
|
|
23783
24488
|
for (let turn = 0; turn < DRAIN_TURNS; turn++) {
|
|
23784
24489
|
if (this.router.activePorts(owner).length) return;
|
|
23785
24490
|
await new Promise((resolve2) => setTimeout(resolve2, 0));
|
|
23786
24491
|
}
|
|
23787
|
-
|
|
24492
|
+
if (pendingHandles() === 0 && pendingRequests() === 0 && pendingUnrefed() > 0 && !readingStdin()) {
|
|
24493
|
+
const deadline = Date.now() + 1e3;
|
|
24494
|
+
while (!this.router.activePorts(owner).length && Date.now() < deadline) {
|
|
24495
|
+
await new Promise((resolve2) => setTimeout(resolve2, 5));
|
|
24496
|
+
}
|
|
24497
|
+
}
|
|
24498
|
+
while (!this.router.activePorts(owner).length && (pendingHandles() > 0 || pendingRequests() > 0 || readingStdin())) {
|
|
23788
24499
|
await new Promise((resolve2) => setTimeout(resolve2, 5));
|
|
23789
24500
|
}
|
|
23790
24501
|
}
|
|
@@ -23836,6 +24547,60 @@ function formatError(error) {
|
|
|
23836
24547
|
function isRecord(value) {
|
|
23837
24548
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23838
24549
|
}
|
|
24550
|
+
function packageInstalled(volume, cwd, wanted) {
|
|
24551
|
+
for (let dir3 = clean(cwd); ; dir3 = dirname(dir3)) {
|
|
24552
|
+
if (packageTreeContains(volume, join(dir3, "node_modules"), wanted, /* @__PURE__ */ new Set())) return true;
|
|
24553
|
+
if (dir3 === "/") return false;
|
|
24554
|
+
}
|
|
24555
|
+
}
|
|
24556
|
+
function packageTreeContains(volume, modulesRoot, wanted, visited) {
|
|
24557
|
+
if (visited.has(modulesRoot) || !directory(volume, modulesRoot)) return false;
|
|
24558
|
+
visited.add(modulesRoot);
|
|
24559
|
+
if (directory(volume, join(modulesRoot, wanted))) return true;
|
|
24560
|
+
for (const entry of volume.readdirSync(modulesRoot)) {
|
|
24561
|
+
if (entry === ".bin") continue;
|
|
24562
|
+
const first = join(modulesRoot, entry);
|
|
24563
|
+
const packages = entry.startsWith("@") && directory(volume, first) ? volume.readdirSync(first).map((name) => join(first, name)) : [first];
|
|
24564
|
+
for (const root of packages) {
|
|
24565
|
+
if (directory(volume, root) && packageTreeContains(volume, join(root, "node_modules"), wanted, visited)) {
|
|
24566
|
+
return true;
|
|
24567
|
+
}
|
|
24568
|
+
}
|
|
24569
|
+
}
|
|
24570
|
+
return false;
|
|
24571
|
+
}
|
|
24572
|
+
function directory(volume, path) {
|
|
24573
|
+
try {
|
|
24574
|
+
return volume.lstatSync(path).isDirectory();
|
|
24575
|
+
} catch {
|
|
24576
|
+
return false;
|
|
24577
|
+
}
|
|
24578
|
+
}
|
|
24579
|
+
function syncRolldownFileSystem(binding, volume, root) {
|
|
24580
|
+
const fs = binding?.__fs;
|
|
24581
|
+
if (!fs?.mkdirSync || !fs?.writeFileSync) return;
|
|
24582
|
+
try {
|
|
24583
|
+
fs.rmSync?.(root, { recursive: true, force: true });
|
|
24584
|
+
} catch {
|
|
24585
|
+
}
|
|
24586
|
+
const copy = (path) => {
|
|
24587
|
+
const stat2 = volume.lstatSync(path);
|
|
24588
|
+
if (stat2.isDirectory()) {
|
|
24589
|
+
fs.mkdirSync(path, { recursive: true });
|
|
24590
|
+
for (const name of volume.readdirSync(path)) copy(join(path, name));
|
|
24591
|
+
} else if (stat2.isSymbolicLink()) {
|
|
24592
|
+
fs.mkdirSync(dirname(path), { recursive: true });
|
|
24593
|
+
try {
|
|
24594
|
+
fs.symlinkSync(volume.readlinkSync(path), path);
|
|
24595
|
+
} catch {
|
|
24596
|
+
}
|
|
24597
|
+
} else if (!path.endsWith(".node")) {
|
|
24598
|
+
fs.mkdirSync(dirname(path), { recursive: true });
|
|
24599
|
+
fs.writeFileSync(path, volume.readFileSync(path));
|
|
24600
|
+
}
|
|
24601
|
+
};
|
|
24602
|
+
copy(clean(root));
|
|
24603
|
+
}
|
|
23839
24604
|
|
|
23840
24605
|
// src/container/container.ts
|
|
23841
24606
|
var Container = class _Container {
|
|
@@ -24179,7 +24944,7 @@ var Container = class _Container {
|
|
|
24179
24944
|
/**
|
|
24180
24945
|
* Deliver a request whose body is bytes, without letting them become text.
|
|
24181
24946
|
*
|
|
24182
|
-
*
|
|
24947
|
+
* A RuntimePod's public `request()` may run the body through `toString("utf8")` on
|
|
24183
24948
|
* its way in, so anything above `0x7f` is replaced: a five-byte payload
|
|
24184
24949
|
* containing `0x89` and `0xff` arrives as nine. That silently destroys every
|
|
24185
24950
|
* upload — an image or a video reaches the server the wrong size and no
|
|
@@ -24281,7 +25046,7 @@ var Container = class _Container {
|
|
|
24281
25046
|
assertActive() {
|
|
24282
25047
|
if (this.disposed) throw new Error("container has been disposed");
|
|
24283
25048
|
}
|
|
24284
|
-
/** Tear down every process and release the
|
|
25049
|
+
/** Tear down every process and release the runtime pod. */
|
|
24285
25050
|
dispose() {
|
|
24286
25051
|
if (this.disposed) return;
|
|
24287
25052
|
this.disposed = true;
|
|
@@ -24391,17 +25156,18 @@ var Terminal = class {
|
|
|
24391
25156
|
// ── key handling ──────────────────────────────────────────────────────────
|
|
24392
25157
|
key(ch) {
|
|
24393
25158
|
if (this.running) {
|
|
24394
|
-
|
|
25159
|
+
const raw = this.currentStdin?.rawMode === true;
|
|
25160
|
+
if (ch === CTRL_C && !raw) {
|
|
24395
25161
|
this.session.proc.deliver("SIGINT");
|
|
24396
25162
|
this.write("^C\r\n");
|
|
24397
25163
|
return;
|
|
24398
25164
|
}
|
|
24399
|
-
if (ch === CTRL_D) {
|
|
25165
|
+
if (ch === CTRL_D && !raw) {
|
|
24400
25166
|
this.currentStdin?.end();
|
|
24401
25167
|
return;
|
|
24402
25168
|
}
|
|
24403
|
-
if (!
|
|
24404
|
-
this.currentStdin?.write(ch === "\r" ? "\n" : ch);
|
|
25169
|
+
if (!raw) this.write(ch === "\r" ? "\r\n" : ch);
|
|
25170
|
+
this.currentStdin?.write(!raw && ch === "\r" ? "\n" : ch);
|
|
24405
25171
|
return;
|
|
24406
25172
|
}
|
|
24407
25173
|
if (this.escapeBuffer !== "") {
|