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.js
CHANGED
|
@@ -6806,7 +6806,7 @@ var NetworkStack = class {
|
|
|
6806
6806
|
}
|
|
6807
6807
|
return [...out.values()].sort((a, b) => a.port - b.port);
|
|
6808
6808
|
}
|
|
6809
|
-
/** Ports
|
|
6809
|
+
/** Ports the pod's proxy has registered for this instance. */
|
|
6810
6810
|
knownPodPorts() {
|
|
6811
6811
|
try {
|
|
6812
6812
|
return this.pod.proxy.activePorts(this.pod.instanceId) ?? [];
|
|
@@ -7332,15 +7332,15 @@ var Parser = class {
|
|
|
7332
7332
|
if (this.isWord("-p")) this.next();
|
|
7333
7333
|
}
|
|
7334
7334
|
}
|
|
7335
|
-
const
|
|
7335
|
+
const commands12 = [this.parseCommand()];
|
|
7336
7336
|
const stderrToo = [];
|
|
7337
7337
|
while (this.isOp("|") || this.isOp("|&")) {
|
|
7338
7338
|
stderrToo.push(this.next().value === "|&");
|
|
7339
7339
|
this.skipNewlines();
|
|
7340
|
-
|
|
7340
|
+
commands12.push(this.parseCommand());
|
|
7341
7341
|
}
|
|
7342
|
-
if (
|
|
7343
|
-
return { type: "pipeline", commands:
|
|
7342
|
+
if (commands12.length === 1 && !negated && !timed) return commands12[0];
|
|
7343
|
+
return { type: "pipeline", commands: commands12, negated, stderrToo, timed };
|
|
7344
7344
|
}
|
|
7345
7345
|
// ── commands ─────────────────────────────────────────────────────────────
|
|
7346
7346
|
parseCommand() {
|
|
@@ -16963,6 +16963,145 @@ var helpCmd = defineCommand({
|
|
|
16963
16963
|
});
|
|
16964
16964
|
var commands10 = [man, whatis, apropos, less, helpCmd];
|
|
16965
16965
|
|
|
16966
|
+
// src/bin/clipboard.ts
|
|
16967
|
+
init_path();
|
|
16968
|
+
var CLIPBOARD_DIR = "/run/clipboard";
|
|
16969
|
+
function selectionPath(selection) {
|
|
16970
|
+
return join(CLIPBOARD_DIR, selection);
|
|
16971
|
+
}
|
|
16972
|
+
function readSelection(ctx, selection) {
|
|
16973
|
+
try {
|
|
16974
|
+
return ctx.vfs.readFile(selectionPath(selection), ctx.cred);
|
|
16975
|
+
} catch {
|
|
16976
|
+
return new Uint8Array();
|
|
16977
|
+
}
|
|
16978
|
+
}
|
|
16979
|
+
function writeSelection(ctx, selection, bytes2) {
|
|
16980
|
+
try {
|
|
16981
|
+
ctx.vfs.mkdir(CLIPBOARD_DIR, { recursive: true, mode: 511 });
|
|
16982
|
+
} catch {
|
|
16983
|
+
}
|
|
16984
|
+
ctx.vfs.writeFile(selectionPath(selection), bytes2, { privileged: true, mode: 438 });
|
|
16985
|
+
}
|
|
16986
|
+
var xsel = defineCommand({
|
|
16987
|
+
name: "xsel",
|
|
16988
|
+
summary: "access an X selection",
|
|
16989
|
+
usage: "xsel [--clipboard|--primary|--secondary] [--input|--output|--clear]",
|
|
16990
|
+
async run(ctx) {
|
|
16991
|
+
let selection = "primary";
|
|
16992
|
+
let mode = "output";
|
|
16993
|
+
for (const arg of ctx.args) {
|
|
16994
|
+
switch (arg) {
|
|
16995
|
+
case "-b":
|
|
16996
|
+
case "--clipboard":
|
|
16997
|
+
selection = "clipboard";
|
|
16998
|
+
break;
|
|
16999
|
+
case "-p":
|
|
17000
|
+
case "--primary":
|
|
17001
|
+
selection = "primary";
|
|
17002
|
+
break;
|
|
17003
|
+
case "-s":
|
|
17004
|
+
case "--secondary":
|
|
17005
|
+
selection = "secondary";
|
|
17006
|
+
break;
|
|
17007
|
+
case "-i":
|
|
17008
|
+
case "--input":
|
|
17009
|
+
case "-a":
|
|
17010
|
+
case "--append":
|
|
17011
|
+
mode = "input";
|
|
17012
|
+
break;
|
|
17013
|
+
case "-o":
|
|
17014
|
+
case "--output":
|
|
17015
|
+
mode = "output";
|
|
17016
|
+
break;
|
|
17017
|
+
case "-c":
|
|
17018
|
+
case "--clear":
|
|
17019
|
+
mode = "clear";
|
|
17020
|
+
break;
|
|
17021
|
+
}
|
|
17022
|
+
}
|
|
17023
|
+
if (mode === "clear") {
|
|
17024
|
+
writeSelection(ctx, selection, new Uint8Array());
|
|
17025
|
+
return 0;
|
|
17026
|
+
}
|
|
17027
|
+
if (mode === "input") {
|
|
17028
|
+
writeSelection(ctx, selection, await ctx.stdin.readAll());
|
|
17029
|
+
return 0;
|
|
17030
|
+
}
|
|
17031
|
+
ctx.write(readSelection(ctx, selection));
|
|
17032
|
+
return 0;
|
|
17033
|
+
}
|
|
17034
|
+
});
|
|
17035
|
+
var xclip = defineCommand({
|
|
17036
|
+
name: "xclip",
|
|
17037
|
+
summary: "access an X selection",
|
|
17038
|
+
usage: "xclip [-selection clipboard|primary|secondary] [-i|-o]",
|
|
17039
|
+
async run(ctx) {
|
|
17040
|
+
let selection = "primary";
|
|
17041
|
+
let mode = "input";
|
|
17042
|
+
const args = ctx.args;
|
|
17043
|
+
for (let index = 0; index < args.length; index++) {
|
|
17044
|
+
const arg = args[index];
|
|
17045
|
+
if (arg === "-selection" || arg === "-sel" || arg === "--selection") {
|
|
17046
|
+
const value = args[++index];
|
|
17047
|
+
if (value === "clipboard" || value === "primary" || value === "secondary") selection = value;
|
|
17048
|
+
continue;
|
|
17049
|
+
}
|
|
17050
|
+
if (arg === "-i" || arg === "-in") mode = "input";
|
|
17051
|
+
else if (arg === "-o" || arg === "-out") mode = "output";
|
|
17052
|
+
}
|
|
17053
|
+
if (mode === "input") {
|
|
17054
|
+
writeSelection(ctx, selection, await ctx.stdin.readAll());
|
|
17055
|
+
return 0;
|
|
17056
|
+
}
|
|
17057
|
+
ctx.write(readSelection(ctx, selection));
|
|
17058
|
+
return 0;
|
|
17059
|
+
}
|
|
17060
|
+
});
|
|
17061
|
+
var pbcopy = defineCommand({
|
|
17062
|
+
name: "pbcopy",
|
|
17063
|
+
summary: "copy standard input to the clipboard",
|
|
17064
|
+
usage: "pbcopy",
|
|
17065
|
+
async run(ctx) {
|
|
17066
|
+
writeSelection(ctx, "clipboard", await ctx.stdin.readAll());
|
|
17067
|
+
return 0;
|
|
17068
|
+
}
|
|
17069
|
+
});
|
|
17070
|
+
var pbpaste = defineCommand({
|
|
17071
|
+
name: "pbpaste",
|
|
17072
|
+
summary: "write the clipboard to standard output",
|
|
17073
|
+
usage: "pbpaste",
|
|
17074
|
+
run(ctx) {
|
|
17075
|
+
ctx.write(readSelection(ctx, "clipboard"));
|
|
17076
|
+
return 0;
|
|
17077
|
+
}
|
|
17078
|
+
});
|
|
17079
|
+
var wlCopy = defineCommand({
|
|
17080
|
+
name: "wl-copy",
|
|
17081
|
+
summary: "copy standard input to the Wayland clipboard",
|
|
17082
|
+
usage: "wl-copy [--primary] [text...]",
|
|
17083
|
+
async run(ctx) {
|
|
17084
|
+
const selection = ctx.args.includes("--primary") || ctx.args.includes("-p") ? "primary" : "clipboard";
|
|
17085
|
+
const operands = ctx.args.filter((arg) => !arg.startsWith("-"));
|
|
17086
|
+
const bytes2 = operands.length ? new TextEncoder().encode(operands.join(" ")) : await ctx.stdin.readAll();
|
|
17087
|
+
writeSelection(ctx, selection, bytes2);
|
|
17088
|
+
return 0;
|
|
17089
|
+
}
|
|
17090
|
+
});
|
|
17091
|
+
var wlPaste = defineCommand({
|
|
17092
|
+
name: "wl-paste",
|
|
17093
|
+
summary: "write the Wayland clipboard to standard output",
|
|
17094
|
+
usage: "wl-paste [--primary] [-n]",
|
|
17095
|
+
run(ctx) {
|
|
17096
|
+
const selection = ctx.args.includes("--primary") || ctx.args.includes("-p") ? "primary" : "clipboard";
|
|
17097
|
+
const bytes2 = readSelection(ctx, selection);
|
|
17098
|
+
ctx.write(bytes2);
|
|
17099
|
+
if (!ctx.args.includes("-n") && !ctx.args.includes("--no-newline")) ctx.write("\n");
|
|
17100
|
+
return 0;
|
|
17101
|
+
}
|
|
17102
|
+
});
|
|
17103
|
+
var commands11 = [xsel, xclip, pbcopy, pbpaste, wlCopy, wlPaste];
|
|
17104
|
+
|
|
16966
17105
|
// src/runtime/node.ts
|
|
16967
17106
|
init_path();
|
|
16968
17107
|
var NODE_VERSION = "v22.12.0";
|
|
@@ -18163,7 +18302,33 @@ function ffmpegCommands() {
|
|
|
18163
18302
|
return [ffmpeg, ffprobe];
|
|
18164
18303
|
}
|
|
18165
18304
|
var platformBuffer = globalThis.Buffer;
|
|
18166
|
-
var Buffer2 = platformBuffer ?? Buffer$1;
|
|
18305
|
+
var Buffer2 = platformBuffer ?? addBase64UrlSupport(Buffer$1);
|
|
18306
|
+
function addBase64UrlSupport(BufferClass) {
|
|
18307
|
+
const target = BufferClass;
|
|
18308
|
+
if (target.__sandboxedBase64Url) return BufferClass;
|
|
18309
|
+
Object.defineProperty(target, "__sandboxedBase64Url", { value: true });
|
|
18310
|
+
const from = target.from.bind(target);
|
|
18311
|
+
target.from = (value, encodingOrOffset, length) => from(value, normalizeEncoding(encodingOrOffset), length);
|
|
18312
|
+
const byteLength = target.byteLength.bind(target);
|
|
18313
|
+
target.byteLength = (value, encoding) => byteLength(value, normalizeEncoding(encoding));
|
|
18314
|
+
const isEncoding = target.isEncoding?.bind(target);
|
|
18315
|
+
if (isEncoding) target.isEncoding = (encoding) => encoding.toLowerCase() === "base64url" || isEncoding(encoding);
|
|
18316
|
+
const toString = target.prototype.toString;
|
|
18317
|
+
target.prototype.toString = function(encoding, start2, end) {
|
|
18318
|
+
if (encoding?.toLowerCase() !== "base64url") return toString.call(this, encoding, start2, end);
|
|
18319
|
+
return toString.call(this, "base64", start2, end).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
18320
|
+
};
|
|
18321
|
+
const write = target.prototype.write;
|
|
18322
|
+
target.prototype.write = function(...args) {
|
|
18323
|
+
const index = typeof args[1] === "string" ? 1 : typeof args[2] === "string" ? 2 : 3;
|
|
18324
|
+
if (typeof args[index] === "string") args[index] = normalizeEncoding(args[index]);
|
|
18325
|
+
return write.apply(this, args);
|
|
18326
|
+
};
|
|
18327
|
+
return BufferClass;
|
|
18328
|
+
}
|
|
18329
|
+
function normalizeEncoding(value) {
|
|
18330
|
+
return typeof value === "string" && value.toLowerCase() === "base64url" ? "base64" : value;
|
|
18331
|
+
}
|
|
18167
18332
|
|
|
18168
18333
|
// src/pkg/clean-installer.ts
|
|
18169
18334
|
init_path();
|
|
@@ -18205,6 +18370,9 @@ var CleanPackageInstaller = class _CleanPackageInstaller {
|
|
|
18205
18370
|
const version = resolveVersion(metadata, range);
|
|
18206
18371
|
const manifest = metadata.versions[version];
|
|
18207
18372
|
if (!manifest) throw new Error(`No matching version found for ${name}@${range}`);
|
|
18373
|
+
if (!supportsPlatform(manifest)) {
|
|
18374
|
+
throw new Error(`${name}@${version} is not compatible with linux/x64/glibc`);
|
|
18375
|
+
}
|
|
18208
18376
|
const identity = `${name}@${version}`;
|
|
18209
18377
|
const target = join(modulesRoot, name);
|
|
18210
18378
|
const installed2 = this.tryReadJson(join(target, "package.json"));
|
|
@@ -18299,6 +18467,15 @@ var CleanPackageInstaller = class _CleanPackageInstaller {
|
|
|
18299
18467
|
}
|
|
18300
18468
|
}
|
|
18301
18469
|
};
|
|
18470
|
+
function supportsPlatform(manifest) {
|
|
18471
|
+
return !manifest.main?.endsWith(".node") && platformListAllows(manifest.os, "linux") && platformListAllows(manifest.cpu, "x64") && platformListAllows(manifest.libc, "glibc");
|
|
18472
|
+
}
|
|
18473
|
+
function platformListAllows(values, current) {
|
|
18474
|
+
if (!values?.length) return true;
|
|
18475
|
+
if (values.includes(`!${current}`)) return false;
|
|
18476
|
+
const positive = values.filter((value) => !value.startsWith("!"));
|
|
18477
|
+
return positive.length === 0 || positive.includes(current) || positive.includes("any");
|
|
18478
|
+
}
|
|
18302
18479
|
function resolveVersion(metadata, range) {
|
|
18303
18480
|
const tag2 = metadata["dist-tags"]?.[range];
|
|
18304
18481
|
if (tag2) return tag2;
|
|
@@ -19281,6 +19458,7 @@ function allCommands() {
|
|
|
19281
19458
|
...commands8,
|
|
19282
19459
|
...commands9,
|
|
19283
19460
|
...commands10,
|
|
19461
|
+
...commands11,
|
|
19284
19462
|
...nodeCommands(),
|
|
19285
19463
|
...pythonCommands(),
|
|
19286
19464
|
...ffmpegCommands(),
|
|
@@ -19577,6 +19755,13 @@ var KernelChildProcess = class {
|
|
|
19577
19755
|
} catch {
|
|
19578
19756
|
}
|
|
19579
19757
|
}
|
|
19758
|
+
/** Signal EOF, so a child reading stdin to the end can finish. */
|
|
19759
|
+
endStdin() {
|
|
19760
|
+
try {
|
|
19761
|
+
this.stdin.end();
|
|
19762
|
+
} catch {
|
|
19763
|
+
}
|
|
19764
|
+
}
|
|
19580
19765
|
kill(signal = "SIGTERM") {
|
|
19581
19766
|
if (this.process) {
|
|
19582
19767
|
this.process.deliver(signal);
|
|
@@ -20488,6 +20673,55 @@ function splitSpecifier(specifier) {
|
|
|
20488
20673
|
return { name: parts.slice(0, size).join("/"), subpath: parts.slice(size).join("/") };
|
|
20489
20674
|
}
|
|
20490
20675
|
|
|
20676
|
+
// src/runtime/readable-from.ts
|
|
20677
|
+
function createReadableFrom(Readable) {
|
|
20678
|
+
return function from(source, options = {}) {
|
|
20679
|
+
if (source && typeof source.pipe === "function") return source;
|
|
20680
|
+
const iterator = source && typeof source[Symbol.asyncIterator] === "function" ? source[Symbol.asyncIterator]() : source && typeof source[Symbol.iterator] === "function" ? source[Symbol.iterator]() : (function* () {
|
|
20681
|
+
yield source;
|
|
20682
|
+
})();
|
|
20683
|
+
let reading = false;
|
|
20684
|
+
const stream = new Readable({
|
|
20685
|
+
...options,
|
|
20686
|
+
objectMode: options.objectMode ?? false,
|
|
20687
|
+
read() {
|
|
20688
|
+
if (reading) return;
|
|
20689
|
+
reading = true;
|
|
20690
|
+
void (async () => {
|
|
20691
|
+
try {
|
|
20692
|
+
for (; ; ) {
|
|
20693
|
+
const next = await iterator.next();
|
|
20694
|
+
if (next.done) {
|
|
20695
|
+
stream.push(null);
|
|
20696
|
+
return;
|
|
20697
|
+
}
|
|
20698
|
+
const value = next.value;
|
|
20699
|
+
if (!stream.push(value === void 0 ? null : value)) return;
|
|
20700
|
+
}
|
|
20701
|
+
} catch (error) {
|
|
20702
|
+
stream.destroy(error);
|
|
20703
|
+
} finally {
|
|
20704
|
+
reading = false;
|
|
20705
|
+
}
|
|
20706
|
+
})();
|
|
20707
|
+
},
|
|
20708
|
+
destroy(error, callback) {
|
|
20709
|
+
void (async () => {
|
|
20710
|
+
try {
|
|
20711
|
+
await iterator.return?.();
|
|
20712
|
+
} catch {
|
|
20713
|
+
}
|
|
20714
|
+
callback(error);
|
|
20715
|
+
})();
|
|
20716
|
+
}
|
|
20717
|
+
});
|
|
20718
|
+
return stream;
|
|
20719
|
+
};
|
|
20720
|
+
}
|
|
20721
|
+
function installReadableFrom(streamModule5) {
|
|
20722
|
+
streamModule5.Readable.from = createReadableFrom(streamModule5.Readable);
|
|
20723
|
+
}
|
|
20724
|
+
|
|
20491
20725
|
// src/runtime/util-module.ts
|
|
20492
20726
|
var customInspect = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
20493
20727
|
var promisifyCustom = /* @__PURE__ */ Symbol.for("nodejs.util.promisify.custom");
|
|
@@ -21375,6 +21609,10 @@ var VirtualHttpRouter = class {
|
|
|
21375
21609
|
unregister(port, server) {
|
|
21376
21610
|
if (this.servers.get(port)?.server === server) this.servers.delete(port);
|
|
21377
21611
|
}
|
|
21612
|
+
/** Whether anything in this container is listening on `port`. */
|
|
21613
|
+
activePortsIncludes(port) {
|
|
21614
|
+
return this.servers.has(port);
|
|
21615
|
+
}
|
|
21378
21616
|
activePorts(owner) {
|
|
21379
21617
|
return [...this.servers].filter(([, item]) => owner === void 0 || item.owner === owner).map(([port]) => port).sort((a, b) => a - b);
|
|
21380
21618
|
}
|
|
@@ -21398,13 +21636,269 @@ var VirtualHttpRouter = class {
|
|
|
21398
21636
|
}
|
|
21399
21637
|
}
|
|
21400
21638
|
};
|
|
21401
|
-
|
|
21639
|
+
var VirtualClientResponse = class extends streamModule4.Readable {
|
|
21640
|
+
constructor(statusCode, statusMessage, headers, body) {
|
|
21641
|
+
super();
|
|
21642
|
+
this.statusCode = statusCode;
|
|
21643
|
+
this.statusMessage = statusMessage;
|
|
21644
|
+
this.headers = headers;
|
|
21645
|
+
this.rawHeaders = Object.entries(headers).flatMap(([key, value]) => [key, value]);
|
|
21646
|
+
if (body.length) this.push(Buffer2.from(body));
|
|
21647
|
+
this.push(null);
|
|
21648
|
+
this.complete = true;
|
|
21649
|
+
}
|
|
21650
|
+
statusCode;
|
|
21651
|
+
statusMessage;
|
|
21652
|
+
headers;
|
|
21653
|
+
httpVersion = "1.1";
|
|
21654
|
+
httpVersionMajor = 1;
|
|
21655
|
+
httpVersionMinor = 1;
|
|
21656
|
+
socket = socketStub();
|
|
21657
|
+
connection = this.socket;
|
|
21658
|
+
rawHeaders;
|
|
21659
|
+
complete = false;
|
|
21660
|
+
_read() {
|
|
21661
|
+
}
|
|
21662
|
+
setTimeout(_milliseconds, callback) {
|
|
21663
|
+
if (callback) this.once("timeout", callback);
|
|
21664
|
+
return this;
|
|
21665
|
+
}
|
|
21666
|
+
};
|
|
21667
|
+
function resolveTarget(input, overrides, defaultProtocol) {
|
|
21668
|
+
const options = {};
|
|
21669
|
+
if (typeof input === "string" || input instanceof URL) {
|
|
21670
|
+
const url = new URL(String(input));
|
|
21671
|
+
options.protocol = url.protocol;
|
|
21672
|
+
options.hostname = url.hostname;
|
|
21673
|
+
if (url.port) options.port = Number(url.port);
|
|
21674
|
+
options.path = `${url.pathname}${url.search}`;
|
|
21675
|
+
if (url.username || url.password) options.auth = `${url.username}:${url.password}`;
|
|
21676
|
+
} else if (input && typeof input === "object") {
|
|
21677
|
+
Object.assign(options, input);
|
|
21678
|
+
}
|
|
21679
|
+
if (overrides) Object.assign(options, overrides);
|
|
21680
|
+
const protocol = String(options.protocol ?? defaultProtocol).replace(/:?$/, ":");
|
|
21681
|
+
const headers = {};
|
|
21682
|
+
for (const [name, value] of Object.entries(options.headers ?? {})) {
|
|
21683
|
+
if (value === void 0 || value === null) continue;
|
|
21684
|
+
headers[String(name)] = Array.isArray(value) ? value.join(", ") : String(value);
|
|
21685
|
+
}
|
|
21686
|
+
if (options.auth && headers.authorization === void 0) {
|
|
21687
|
+
headers.authorization = `Basic ${Buffer2.from(String(options.auth)).toString("base64")}`;
|
|
21688
|
+
}
|
|
21689
|
+
const rawHost = String(options.hostname ?? options.host ?? "localhost");
|
|
21690
|
+
const hostMatch = /^(\[[^\]]*\]|[^:]*)(?::(\d+))?$/.exec(rawHost);
|
|
21691
|
+
const hostname = (hostMatch?.[1] ?? rawHost).replace(/^\[|\]$/g, "");
|
|
21692
|
+
const explicitPort = options.port ?? hostMatch?.[2];
|
|
21693
|
+
const port = explicitPort === void 0 || explicitPort === null || explicitPort === "" || Number.isNaN(Number(explicitPort)) ? protocol === "https:" ? 443 : 80 : Number(explicitPort);
|
|
21694
|
+
return {
|
|
21695
|
+
protocol,
|
|
21696
|
+
hostname,
|
|
21697
|
+
port,
|
|
21698
|
+
path: String(options.path ?? "/"),
|
|
21699
|
+
method: String(options.method ?? "GET").toUpperCase(),
|
|
21700
|
+
headers
|
|
21701
|
+
};
|
|
21702
|
+
}
|
|
21703
|
+
function isLoopback(hostname) {
|
|
21704
|
+
return hostname === "localhost" || hostname === "0.0.0.0" || hostname === "::1" || hostname === "::" || hostname.startsWith("127.") || hostname.endsWith(".localhost");
|
|
21705
|
+
}
|
|
21706
|
+
var VirtualClientRequest = class extends streamModule4.Writable {
|
|
21707
|
+
constructor(target, router, fetchImpl, trackRequest) {
|
|
21708
|
+
super();
|
|
21709
|
+
this.target = target;
|
|
21710
|
+
this.router = router;
|
|
21711
|
+
this.fetchImpl = fetchImpl;
|
|
21712
|
+
this.trackRequest = trackRequest;
|
|
21713
|
+
for (const [name, value] of Object.entries(target.headers)) this.setHeader(name, value);
|
|
21714
|
+
}
|
|
21715
|
+
target;
|
|
21716
|
+
router;
|
|
21717
|
+
fetchImpl;
|
|
21718
|
+
trackRequest;
|
|
21719
|
+
socket = socketStub();
|
|
21720
|
+
connection = this.socket;
|
|
21721
|
+
chunks = [];
|
|
21722
|
+
headerMap = /* @__PURE__ */ new Map();
|
|
21723
|
+
dispatched = false;
|
|
21724
|
+
destroyedByUser = false;
|
|
21725
|
+
timer;
|
|
21726
|
+
aborted = false;
|
|
21727
|
+
finished = false;
|
|
21728
|
+
reusedSocket = false;
|
|
21729
|
+
get method() {
|
|
21730
|
+
return this.target.method;
|
|
21731
|
+
}
|
|
21732
|
+
get path() {
|
|
21733
|
+
return this.target.path;
|
|
21734
|
+
}
|
|
21735
|
+
get host() {
|
|
21736
|
+
return this.target.hostname;
|
|
21737
|
+
}
|
|
21738
|
+
get protocol() {
|
|
21739
|
+
return this.target.protocol;
|
|
21740
|
+
}
|
|
21741
|
+
setHeader(name, value) {
|
|
21742
|
+
validateHeaderName(name);
|
|
21743
|
+
validateHeaderValue(name, value);
|
|
21744
|
+
this.headerMap.set(name.toLowerCase(), { name, value: Array.isArray(value) ? [...value].map(String).join(", ") : String(value) });
|
|
21745
|
+
return this;
|
|
21746
|
+
}
|
|
21747
|
+
getHeader(name) {
|
|
21748
|
+
return this.headerMap.get(name.toLowerCase())?.value;
|
|
21749
|
+
}
|
|
21750
|
+
getHeaders() {
|
|
21751
|
+
return Object.fromEntries([...this.headerMap].map(([key, entry]) => [key, entry.value]));
|
|
21752
|
+
}
|
|
21753
|
+
getHeaderNames() {
|
|
21754
|
+
return [...this.headerMap.keys()];
|
|
21755
|
+
}
|
|
21756
|
+
hasHeader(name) {
|
|
21757
|
+
return this.headerMap.has(name.toLowerCase());
|
|
21758
|
+
}
|
|
21759
|
+
removeHeader(name) {
|
|
21760
|
+
this.headerMap.delete(name.toLowerCase());
|
|
21761
|
+
}
|
|
21762
|
+
flushHeaders() {
|
|
21763
|
+
}
|
|
21764
|
+
setNoDelay() {
|
|
21765
|
+
}
|
|
21766
|
+
setSocketKeepAlive() {
|
|
21767
|
+
}
|
|
21768
|
+
ref() {
|
|
21769
|
+
return this;
|
|
21770
|
+
}
|
|
21771
|
+
unref() {
|
|
21772
|
+
return this;
|
|
21773
|
+
}
|
|
21774
|
+
setTimeout(milliseconds, callback) {
|
|
21775
|
+
if (callback) this.once("timeout", callback);
|
|
21776
|
+
clearTimeout(this.timer);
|
|
21777
|
+
this.timer = setTimeout(() => this.emit("timeout"), milliseconds);
|
|
21778
|
+
return this;
|
|
21779
|
+
}
|
|
21780
|
+
abort() {
|
|
21781
|
+
this.destroyRequest();
|
|
21782
|
+
}
|
|
21783
|
+
destroy(error) {
|
|
21784
|
+
this.destroyRequest(error);
|
|
21785
|
+
return this;
|
|
21786
|
+
}
|
|
21787
|
+
destroyRequest(error) {
|
|
21788
|
+
if (this.destroyedByUser) return;
|
|
21789
|
+
this.destroyedByUser = true;
|
|
21790
|
+
this.aborted = true;
|
|
21791
|
+
clearTimeout(this.timer);
|
|
21792
|
+
this.emit("abort");
|
|
21793
|
+
if (error) this.emit("error", error);
|
|
21794
|
+
this.emit("close");
|
|
21795
|
+
}
|
|
21796
|
+
_write(chunk, encoding, callback) {
|
|
21797
|
+
this.chunks.push(Buffer2.isBuffer(chunk) ? chunk : Buffer2.from(chunk, encoding));
|
|
21798
|
+
callback();
|
|
21799
|
+
}
|
|
21800
|
+
_final(callback) {
|
|
21801
|
+
this.finished = true;
|
|
21802
|
+
callback();
|
|
21803
|
+
void this.dispatch();
|
|
21804
|
+
}
|
|
21805
|
+
async dispatch() {
|
|
21806
|
+
if (this.dispatched || this.destroyedByUser) return;
|
|
21807
|
+
this.dispatched = true;
|
|
21808
|
+
const body = Buffer2.concat(this.chunks);
|
|
21809
|
+
const release = this.trackRequest?.();
|
|
21810
|
+
let released = false;
|
|
21811
|
+
const untrack = () => {
|
|
21812
|
+
if (released || !release) return;
|
|
21813
|
+
released = true;
|
|
21814
|
+
release();
|
|
21815
|
+
};
|
|
21816
|
+
let settled = false;
|
|
21817
|
+
try {
|
|
21818
|
+
const response = this.router.activePortsIncludes(this.target.port) && isLoopback(this.target.hostname) ? await this.viaRouter(body) : await this.viaFetch(body);
|
|
21819
|
+
if (this.destroyedByUser) return;
|
|
21820
|
+
clearTimeout(this.timer);
|
|
21821
|
+
settled = true;
|
|
21822
|
+
response.once("end", untrack);
|
|
21823
|
+
response.once("close", untrack);
|
|
21824
|
+
response.once("error", untrack);
|
|
21825
|
+
this.emit("response", response);
|
|
21826
|
+
queueMicrotask(() => {
|
|
21827
|
+
if (this.listenerCount("response") === 0) response.resume();
|
|
21828
|
+
});
|
|
21829
|
+
} catch (error) {
|
|
21830
|
+
clearTimeout(this.timer);
|
|
21831
|
+
if (this.destroyedByUser) return;
|
|
21832
|
+
const failure = error instanceof Error ? error : new Error(String(error));
|
|
21833
|
+
if (!("code" in failure)) Object.assign(failure, { code: "ECONNREFUSED" });
|
|
21834
|
+
this.emit("error", failure);
|
|
21835
|
+
} finally {
|
|
21836
|
+
if (!settled) untrack();
|
|
21837
|
+
}
|
|
21838
|
+
}
|
|
21839
|
+
async viaRouter(body) {
|
|
21840
|
+
const result = await this.router.request(this.target.port, {
|
|
21841
|
+
method: this.target.method,
|
|
21842
|
+
path: this.target.path,
|
|
21843
|
+
headers: this.getHeaders(),
|
|
21844
|
+
body: body.length ? new Uint8Array(body) : null
|
|
21845
|
+
});
|
|
21846
|
+
const body_ = result.body;
|
|
21847
|
+
const bytes2 = typeof body_ === "string" ? new TextEncoder().encode(body_) : body_ instanceof ArrayBuffer ? new Uint8Array(body_) : body_ ?? new Uint8Array();
|
|
21848
|
+
const status = result.statusCode ?? 200;
|
|
21849
|
+
return new VirtualClientResponse(status, result.statusMessage ?? STATUS_CODES[status] ?? "", lowercaseHeaders(result.headers), bytes2);
|
|
21850
|
+
}
|
|
21851
|
+
async viaFetch(body) {
|
|
21852
|
+
const fetchImpl = this.fetchImpl ?? globalThis.fetch;
|
|
21853
|
+
if (typeof fetchImpl !== "function") {
|
|
21854
|
+
throw Object.assign(new Error(`getaddrinfo ENOTFOUND ${this.target.hostname}`), { code: "ENOTFOUND" });
|
|
21855
|
+
}
|
|
21856
|
+
const portSuffix = this.target.protocol === "https:" && this.target.port === 443 || this.target.protocol === "http:" && this.target.port === 80 ? "" : `:${this.target.port}`;
|
|
21857
|
+
const url = `${this.target.protocol}//${this.target.hostname}${portSuffix}${this.target.path}`;
|
|
21858
|
+
const bodyless = this.target.method === "GET" || this.target.method === "HEAD";
|
|
21859
|
+
const headers = this.getHeaders();
|
|
21860
|
+
delete headers.host;
|
|
21861
|
+
delete headers.connection;
|
|
21862
|
+
delete headers["content-length"];
|
|
21863
|
+
const response = await fetchImpl(url, {
|
|
21864
|
+
method: this.target.method,
|
|
21865
|
+
headers,
|
|
21866
|
+
...bodyless || body.length === 0 ? {} : { body: new Uint8Array(body) },
|
|
21867
|
+
redirect: "follow"
|
|
21868
|
+
});
|
|
21869
|
+
const received = {};
|
|
21870
|
+
response.headers.forEach((value, key) => {
|
|
21871
|
+
received[key.toLowerCase()] = value;
|
|
21872
|
+
});
|
|
21873
|
+
const bytes2 = new Uint8Array(await response.arrayBuffer());
|
|
21874
|
+
return new VirtualClientResponse(response.status, response.statusText, received, bytes2);
|
|
21875
|
+
}
|
|
21876
|
+
};
|
|
21877
|
+
function lowercaseHeaders(headers) {
|
|
21878
|
+
return Object.fromEntries(Object.entries(headers ?? {}).map(([key, value]) => [key.toLowerCase(), String(value)]));
|
|
21879
|
+
}
|
|
21880
|
+
function createHttpModule(router, owner, options = {}, defaultProtocol = "http:") {
|
|
21402
21881
|
const createServer = (listener) => new VirtualHttpServer(router, owner, listener);
|
|
21403
|
-
const
|
|
21882
|
+
const request = (input, second, third) => {
|
|
21883
|
+
const overrides = second && typeof second === "object" && !(second instanceof Function) ? second : void 0;
|
|
21884
|
+
const callback = [second, third].find((value) => typeof value === "function");
|
|
21885
|
+
const req = new VirtualClientRequest(resolveTarget(input, overrides, defaultProtocol), router, options.fetch, options.trackRequest);
|
|
21886
|
+
if (callback) req.on("response", callback);
|
|
21887
|
+
return req;
|
|
21888
|
+
};
|
|
21889
|
+
const get = (input, second, third) => {
|
|
21890
|
+
const req = request(input, second, third);
|
|
21891
|
+
req.end();
|
|
21892
|
+
return req;
|
|
21893
|
+
};
|
|
21894
|
+
return {
|
|
21404
21895
|
createServer,
|
|
21896
|
+
request,
|
|
21897
|
+
get,
|
|
21405
21898
|
Server: VirtualHttpServer,
|
|
21406
21899
|
ServerResponse: VirtualServerResponse,
|
|
21407
21900
|
IncomingMessage: VirtualIncomingMessage,
|
|
21901
|
+
ClientRequest: VirtualClientRequest,
|
|
21408
21902
|
METHODS,
|
|
21409
21903
|
STATUS_CODES,
|
|
21410
21904
|
maxHeaderSize: 16 * 1024,
|
|
@@ -21414,10 +21908,6 @@ function createHttpModule(router, owner) {
|
|
|
21414
21908
|
Agent: class Agent {
|
|
21415
21909
|
}
|
|
21416
21910
|
};
|
|
21417
|
-
return { ...module, request: unsupportedClient, get: unsupportedClient };
|
|
21418
|
-
}
|
|
21419
|
-
function unsupportedClient() {
|
|
21420
|
-
throw Object.assign(new Error("http client requests are not implemented yet"), { code: "ERR_NOT_IMPLEMENTED" });
|
|
21421
21911
|
}
|
|
21422
21912
|
function validateHeaderName(name) {
|
|
21423
21913
|
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" });
|
|
@@ -21557,6 +22047,13 @@ var ChildProcess = class extends EventEmitter4 {
|
|
|
21557
22047
|
} catch {
|
|
21558
22048
|
}
|
|
21559
22049
|
done();
|
|
22050
|
+
},
|
|
22051
|
+
final: (done) => {
|
|
22052
|
+
try {
|
|
22053
|
+
handle.endStdin?.();
|
|
22054
|
+
} catch {
|
|
22055
|
+
}
|
|
22056
|
+
done();
|
|
21560
22057
|
}
|
|
21561
22058
|
});
|
|
21562
22059
|
this.stdio = [this.stdin, this.stdout, this.stderr];
|
|
@@ -21795,7 +22292,7 @@ function emitKeypressEvents(stream) {
|
|
|
21795
22292
|
}
|
|
21796
22293
|
});
|
|
21797
22294
|
}
|
|
21798
|
-
function createReadlineModule(defaultInput) {
|
|
22295
|
+
function createReadlineModule(defaultInput, defaultOutput = () => void 0) {
|
|
21799
22296
|
class Interface extends EventEmitter4 {
|
|
21800
22297
|
constructor(input, output, terminal = false) {
|
|
21801
22298
|
super();
|
|
@@ -21806,6 +22303,14 @@ function createReadlineModule(defaultInput) {
|
|
|
21806
22303
|
if (terminal) {
|
|
21807
22304
|
emitKeypressEvents(input);
|
|
21808
22305
|
input?.on?.("keypress", this.onTerminalKeypress);
|
|
22306
|
+
if (typeof input?.setRawMode === "function") {
|
|
22307
|
+
try {
|
|
22308
|
+
input.setRawMode(true);
|
|
22309
|
+
this.ownsRawMode = true;
|
|
22310
|
+
} catch {
|
|
22311
|
+
}
|
|
22312
|
+
}
|
|
22313
|
+
input?.resume?.();
|
|
21809
22314
|
} else {
|
|
21810
22315
|
input?.on?.("data", (chunk) => this.receive(String(chunk)));
|
|
21811
22316
|
}
|
|
@@ -21817,6 +22322,10 @@ function createReadlineModule(defaultInput) {
|
|
|
21817
22322
|
buffer = "";
|
|
21818
22323
|
pending = [];
|
|
21819
22324
|
lines = [];
|
|
22325
|
+
/** Set while `question` is waiting, so the echoed line carries the query. */
|
|
22326
|
+
questionPrompt = null;
|
|
22327
|
+
/** Raw mode is only ours to restore if we were the one to enable it. */
|
|
22328
|
+
ownsRawMode = false;
|
|
21820
22329
|
line = "";
|
|
21821
22330
|
cursor = 0;
|
|
21822
22331
|
terminal;
|
|
@@ -21824,20 +22333,31 @@ function createReadlineModule(defaultInput) {
|
|
|
21824
22333
|
/** Split incoming data into lines, answering any waiting `question`. */
|
|
21825
22334
|
receive(text2) {
|
|
21826
22335
|
this.buffer += text2;
|
|
21827
|
-
let
|
|
21828
|
-
while (
|
|
21829
|
-
const line = this.buffer.slice(0,
|
|
21830
|
-
this.buffer = this.buffer.slice(
|
|
21831
|
-
|
|
21832
|
-
|
|
21833
|
-
|
|
21834
|
-
|
|
21835
|
-
|
|
21836
|
-
|
|
21837
|
-
|
|
22336
|
+
let match2 = /\r\n|\r|\n/.exec(this.buffer);
|
|
22337
|
+
while (match2) {
|
|
22338
|
+
const line = this.buffer.slice(0, match2.index);
|
|
22339
|
+
this.buffer = this.buffer.slice(match2.index + match2[0].length);
|
|
22340
|
+
this.deliver(line);
|
|
22341
|
+
match2 = /\r\n|\r|\n/.exec(this.buffer);
|
|
22342
|
+
}
|
|
22343
|
+
}
|
|
22344
|
+
/** Hand a completed line to whoever is waiting for it. */
|
|
22345
|
+
deliver(line) {
|
|
22346
|
+
const waiting = this.pending.shift();
|
|
22347
|
+
if (waiting) {
|
|
22348
|
+
this.questionPrompt = null;
|
|
22349
|
+
waiting(line);
|
|
22350
|
+
return;
|
|
21838
22351
|
}
|
|
22352
|
+
this.lines.push(line);
|
|
22353
|
+
this.emit("line", line);
|
|
21839
22354
|
}
|
|
21840
22355
|
question(query, callback) {
|
|
22356
|
+
if (this.terminal) {
|
|
22357
|
+
this.questionPrompt = query;
|
|
22358
|
+
this.line = "";
|
|
22359
|
+
this.cursor = 0;
|
|
22360
|
+
}
|
|
21841
22361
|
this.output?.write?.(query);
|
|
21842
22362
|
if (callback) {
|
|
21843
22363
|
this.pending.push(callback);
|
|
@@ -21852,6 +22372,9 @@ function createReadlineModule(defaultInput) {
|
|
|
21852
22372
|
setPrompt(text2) {
|
|
21853
22373
|
this.promptText = text2;
|
|
21854
22374
|
}
|
|
22375
|
+
getPrompt() {
|
|
22376
|
+
return this.promptText;
|
|
22377
|
+
}
|
|
21855
22378
|
pause() {
|
|
21856
22379
|
this.input?.pause?.();
|
|
21857
22380
|
return this;
|
|
@@ -21879,21 +22402,48 @@ function createReadlineModule(defaultInput) {
|
|
|
21879
22402
|
if (text2) {
|
|
21880
22403
|
this.line = this.line.slice(0, this.cursor) + text2 + this.line.slice(this.cursor);
|
|
21881
22404
|
this.cursor += text2.length;
|
|
22405
|
+
this.refresh();
|
|
21882
22406
|
}
|
|
21883
22407
|
}
|
|
21884
22408
|
getCursorPos() {
|
|
21885
|
-
return { rows: 0, cols: this.cursor + this.
|
|
22409
|
+
return { rows: 0, cols: this.cursor + this.currentPrompt().length };
|
|
21886
22410
|
}
|
|
21887
22411
|
close() {
|
|
21888
22412
|
if (this.closed) return;
|
|
21889
22413
|
this.closed = true;
|
|
21890
22414
|
if (this.terminal) {
|
|
21891
22415
|
this.input?.off?.("keypress", this.onTerminalKeypress);
|
|
22416
|
+
if (this.ownsRawMode) {
|
|
22417
|
+
this.ownsRawMode = false;
|
|
22418
|
+
try {
|
|
22419
|
+
this.input?.setRawMode?.(false);
|
|
22420
|
+
} catch {
|
|
22421
|
+
}
|
|
22422
|
+
}
|
|
21892
22423
|
this.input?.pause?.();
|
|
21893
22424
|
}
|
|
21894
22425
|
for (const waiting of this.pending.splice(0)) waiting("");
|
|
21895
22426
|
this.emit("close");
|
|
21896
22427
|
}
|
|
22428
|
+
/** The text shown to the left of the edited line. */
|
|
22429
|
+
currentPrompt() {
|
|
22430
|
+
return this.questionPrompt ?? this.promptText;
|
|
22431
|
+
}
|
|
22432
|
+
/**
|
|
22433
|
+
* Repaint the edited line.
|
|
22434
|
+
*
|
|
22435
|
+
* In raw mode nothing echoes on its own, so an Interface that does not do
|
|
22436
|
+
* this leaves the user typing blind. Libraries that draw their own frame
|
|
22437
|
+
* (clack, inquirer) simply overwrite this, exactly as they do on Node.
|
|
22438
|
+
*/
|
|
22439
|
+
refresh() {
|
|
22440
|
+
if (!this.terminal) return;
|
|
22441
|
+
const prompt = this.currentPrompt();
|
|
22442
|
+
let text2 = `\r\x1B[0K${prompt}${this.line}`;
|
|
22443
|
+
const back = this.line.length - this.cursor;
|
|
22444
|
+
if (back > 0) text2 += `\x1B[${back}D`;
|
|
22445
|
+
this.output?.write?.(text2);
|
|
22446
|
+
}
|
|
21897
22447
|
edit(sequence, key) {
|
|
21898
22448
|
if (this.closed) return;
|
|
21899
22449
|
const name = key.name;
|
|
@@ -21901,48 +22451,62 @@ function createReadlineModule(defaultInput) {
|
|
|
21901
22451
|
const value = this.line;
|
|
21902
22452
|
this.line = "";
|
|
21903
22453
|
this.cursor = 0;
|
|
21904
|
-
this.
|
|
22454
|
+
this.output?.write?.("\r\n");
|
|
22455
|
+
this.deliver(value);
|
|
21905
22456
|
return;
|
|
21906
22457
|
}
|
|
21907
22458
|
if (name === "left") {
|
|
21908
22459
|
this.cursor = Math.max(0, this.cursor - 1);
|
|
22460
|
+
this.refresh();
|
|
21909
22461
|
return;
|
|
21910
22462
|
}
|
|
21911
22463
|
if (name === "right") {
|
|
21912
22464
|
this.cursor = Math.min(this.line.length, this.cursor + 1);
|
|
22465
|
+
this.refresh();
|
|
21913
22466
|
return;
|
|
21914
22467
|
}
|
|
21915
22468
|
if (name === "home" || key.ctrl && name === "a") {
|
|
21916
22469
|
this.cursor = 0;
|
|
22470
|
+
this.refresh();
|
|
21917
22471
|
return;
|
|
21918
22472
|
}
|
|
21919
22473
|
if (name === "end" || key.ctrl && name === "e") {
|
|
21920
22474
|
this.cursor = this.line.length;
|
|
22475
|
+
this.refresh();
|
|
21921
22476
|
return;
|
|
21922
22477
|
}
|
|
21923
22478
|
if (name === "backspace" || key.ctrl && name === "h") {
|
|
21924
22479
|
if (this.cursor > 0) {
|
|
21925
22480
|
this.line = this.line.slice(0, this.cursor - 1) + this.line.slice(this.cursor);
|
|
21926
22481
|
this.cursor--;
|
|
22482
|
+
this.refresh();
|
|
21927
22483
|
}
|
|
21928
22484
|
return;
|
|
21929
22485
|
}
|
|
21930
22486
|
if (name === "delete") {
|
|
21931
|
-
if (this.cursor < this.line.length)
|
|
22487
|
+
if (this.cursor < this.line.length) {
|
|
22488
|
+
this.line = this.line.slice(0, this.cursor) + this.line.slice(this.cursor + 1);
|
|
22489
|
+
this.refresh();
|
|
22490
|
+
}
|
|
21932
22491
|
return;
|
|
21933
22492
|
}
|
|
21934
22493
|
if (key.ctrl && name === "u") {
|
|
21935
22494
|
this.line = this.line.slice(this.cursor);
|
|
21936
22495
|
this.cursor = 0;
|
|
22496
|
+
this.refresh();
|
|
21937
22497
|
return;
|
|
21938
22498
|
}
|
|
21939
22499
|
if (key.ctrl && name === "k") {
|
|
21940
22500
|
this.line = this.line.slice(0, this.cursor);
|
|
22501
|
+
this.refresh();
|
|
21941
22502
|
return;
|
|
21942
22503
|
}
|
|
21943
22504
|
if (key.ctrl || key.meta || sequence.length !== 1 || sequence < " ") return;
|
|
22505
|
+
const atEnd = this.cursor === this.line.length;
|
|
21944
22506
|
this.line = this.line.slice(0, this.cursor) + sequence + this.line.slice(this.cursor);
|
|
21945
22507
|
this.cursor += sequence.length;
|
|
22508
|
+
if (atEnd) this.output?.write?.(sequence);
|
|
22509
|
+
else this.refresh();
|
|
21946
22510
|
}
|
|
21947
22511
|
async *[Symbol.asyncIterator]() {
|
|
21948
22512
|
while (!this.closed || this.lines.length) {
|
|
@@ -21972,13 +22536,23 @@ function createReadlineModule(defaultInput) {
|
|
|
21972
22536
|
}
|
|
21973
22537
|
}
|
|
21974
22538
|
}
|
|
22539
|
+
const isTerminal = (options, output) => {
|
|
22540
|
+
if (typeof options?.terminal === "boolean") return options.terminal;
|
|
22541
|
+
return Boolean(output?.isTTY);
|
|
22542
|
+
};
|
|
21975
22543
|
const createInterface = (options, output) => {
|
|
21976
22544
|
if (options && typeof options === "object" && !options.on) {
|
|
21977
|
-
const
|
|
22545
|
+
const resolvedOutput2 = options.output ?? defaultOutput();
|
|
22546
|
+
const instance = new Interface(
|
|
22547
|
+
options.input ?? defaultInput(),
|
|
22548
|
+
resolvedOutput2,
|
|
22549
|
+
isTerminal(options, resolvedOutput2)
|
|
22550
|
+
);
|
|
21978
22551
|
if (typeof options.prompt === "string") instance.setPrompt(options.prompt);
|
|
21979
22552
|
return instance;
|
|
21980
22553
|
}
|
|
21981
|
-
|
|
22554
|
+
const resolvedOutput = output ?? defaultOutput();
|
|
22555
|
+
return new Interface(options ?? defaultInput(), resolvedOutput, isTerminal(void 0, resolvedOutput));
|
|
21982
22556
|
};
|
|
21983
22557
|
const noop = () => {
|
|
21984
22558
|
};
|
|
@@ -21995,6 +22569,7 @@ function createReadlineModule(defaultInput) {
|
|
|
21995
22569
|
}
|
|
21996
22570
|
|
|
21997
22571
|
// src/runtime/core-modules.ts
|
|
22572
|
+
installReadableFrom(streamModule4);
|
|
21998
22573
|
var Dirent = class {
|
|
21999
22574
|
/** Node 20+ exposes the containing directory, and `fs.glob` consumers read it. */
|
|
22000
22575
|
constructor(name, stat2, parentPath = "") {
|
|
@@ -22200,9 +22775,20 @@ function createCoreModules(options) {
|
|
|
22200
22775
|
throw new Error("createRequire is only available inside a loaded module");
|
|
22201
22776
|
}
|
|
22202
22777
|
};
|
|
22203
|
-
|
|
22778
|
+
let inFlightRequests = 0;
|
|
22779
|
+
const httpOptions = {
|
|
22780
|
+
...options.http?.fetch ? { fetch: options.http.fetch } : {},
|
|
22781
|
+
trackRequest: () => {
|
|
22782
|
+
inFlightRequests++;
|
|
22783
|
+
return () => {
|
|
22784
|
+
inFlightRequests--;
|
|
22785
|
+
};
|
|
22786
|
+
}
|
|
22787
|
+
};
|
|
22788
|
+
const http = options.http ? createHttpModule(options.http.router, options.http.owner, httpOptions, "http:") : createUnsupportedModule("http");
|
|
22789
|
+
const https = options.http ? createHttpModule(options.http.router, options.http.owner, httpOptions, "https:") : createUnsupportedModule("https");
|
|
22204
22790
|
const childProcess = options.spawnChild ? createChildProcessModule(options.spawnChild, () => cwd) : createUnsupportedModule("child_process");
|
|
22205
|
-
const readline = createReadlineModule(() => processObject.stdin);
|
|
22791
|
+
const readline = createReadlineModule(() => processObject.stdin, () => processObject.stdout);
|
|
22206
22792
|
const dns = createDnsModule();
|
|
22207
22793
|
const builtins = {
|
|
22208
22794
|
assert: assert_module_default,
|
|
@@ -22220,7 +22806,7 @@ function createCoreModules(options) {
|
|
|
22220
22806
|
"fs/promises": fs.promises,
|
|
22221
22807
|
module: moduleBuiltin,
|
|
22222
22808
|
http,
|
|
22223
|
-
https
|
|
22809
|
+
https,
|
|
22224
22810
|
os,
|
|
22225
22811
|
path,
|
|
22226
22812
|
"path/posix": path,
|
|
@@ -22259,6 +22845,9 @@ function createCoreModules(options) {
|
|
|
22259
22845
|
globals,
|
|
22260
22846
|
process: processObject,
|
|
22261
22847
|
pendingHandles: timers.pending,
|
|
22848
|
+
pendingUnrefed: timers.pendingUnrefed,
|
|
22849
|
+
/** Client requests sent but not yet read to completion. */
|
|
22850
|
+
pendingRequests: () => inFlightRequests,
|
|
22262
22851
|
writeStdin: (data) => {
|
|
22263
22852
|
if (options.interactiveStdin) stdin.write(data);
|
|
22264
22853
|
},
|
|
@@ -22486,9 +23075,20 @@ function createFsModule(volume, cwd, stdinPath) {
|
|
|
22486
23075
|
if (position == null) file3.position = start2 + chunk.length;
|
|
22487
23076
|
return chunk.length;
|
|
22488
23077
|
},
|
|
22489
|
-
createReadStream: (path) => {
|
|
22490
|
-
const
|
|
22491
|
-
|
|
23078
|
+
createReadStream: (path, options) => {
|
|
23079
|
+
const target = abs(path);
|
|
23080
|
+
const settings = typeof options === "string" ? { encoding: options } : options ?? {};
|
|
23081
|
+
const whole = Buffer2.from(volume.readFileSync(resolveLinks(volume, target)));
|
|
23082
|
+
const start2 = settings.start ?? 0;
|
|
23083
|
+
const end = settings.end === void 0 ? whole.length : Math.min(settings.end + 1, whole.length);
|
|
23084
|
+
const slice = whole.subarray(start2, Math.max(start2, end));
|
|
23085
|
+
const stream = streamModule4.Readable.from([settings.encoding ? slice.toString(settings.encoding) : slice]);
|
|
23086
|
+
Object.assign(stream, { path: target, bytesRead: slice.length, close: () => stream.destroy() });
|
|
23087
|
+
queueMicrotask(() => {
|
|
23088
|
+
stream.emit("open", 0);
|
|
23089
|
+
stream.emit("ready");
|
|
23090
|
+
});
|
|
23091
|
+
return stream;
|
|
22492
23092
|
},
|
|
22493
23093
|
createWriteStream: (path, options) => {
|
|
22494
23094
|
const target = abs(path);
|
|
@@ -22854,33 +23454,78 @@ var ERRNO_CONSTANTS = {
|
|
|
22854
23454
|
};
|
|
22855
23455
|
function createTrackedTimers() {
|
|
22856
23456
|
const live = /* @__PURE__ */ new Set();
|
|
22857
|
-
const
|
|
23457
|
+
const unrefed = /* @__PURE__ */ new Set();
|
|
23458
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
23459
|
+
const track = (native) => {
|
|
23460
|
+
const state = { native, active: true, referenced: true };
|
|
23461
|
+
const handle = {
|
|
23462
|
+
ref() {
|
|
23463
|
+
state.referenced = true;
|
|
23464
|
+
unrefed.delete(handle);
|
|
23465
|
+
if (state.active) live.add(handle);
|
|
23466
|
+
state.native?.ref?.();
|
|
23467
|
+
return handle;
|
|
23468
|
+
},
|
|
23469
|
+
unref() {
|
|
23470
|
+
state.referenced = false;
|
|
23471
|
+
live.delete(handle);
|
|
23472
|
+
if (state.active) unrefed.add(handle);
|
|
23473
|
+
state.native?.unref?.();
|
|
23474
|
+
return handle;
|
|
23475
|
+
},
|
|
23476
|
+
hasRef: () => state.referenced,
|
|
23477
|
+
refresh() {
|
|
23478
|
+
state.native?.refresh?.();
|
|
23479
|
+
return handle;
|
|
23480
|
+
},
|
|
23481
|
+
[Symbol.toPrimitive]: () => Number(state.native)
|
|
23482
|
+
};
|
|
23483
|
+
states.set(handle, state);
|
|
22858
23484
|
live.add(handle);
|
|
22859
23485
|
return handle;
|
|
22860
23486
|
};
|
|
23487
|
+
const complete = (handle) => {
|
|
23488
|
+
const state = states.get(handle);
|
|
23489
|
+
if (state) state.active = false;
|
|
23490
|
+
live.delete(handle);
|
|
23491
|
+
unrefed.delete(handle);
|
|
23492
|
+
};
|
|
22861
23493
|
const setTimeoutTracked = (fn, delay, ...args) => {
|
|
22862
|
-
|
|
23494
|
+
let handle;
|
|
23495
|
+
const native = setTimeout(
|
|
22863
23496
|
(...inner) => {
|
|
22864
|
-
|
|
23497
|
+
complete(handle);
|
|
22865
23498
|
fn(...inner);
|
|
22866
23499
|
},
|
|
22867
23500
|
delay,
|
|
22868
23501
|
...args
|
|
22869
23502
|
);
|
|
22870
|
-
|
|
23503
|
+
handle = track(native);
|
|
22871
23504
|
return handle;
|
|
22872
23505
|
};
|
|
22873
23506
|
const setIntervalTracked = (fn, delay, ...args) => track(setInterval(fn, delay, ...args));
|
|
22874
23507
|
const hostSetImmediate = globalThis.setImmediate;
|
|
22875
23508
|
const setImmediateTracked = (fn, ...args) => {
|
|
22876
|
-
|
|
22877
|
-
|
|
23509
|
+
if (!hostSetImmediate) return setTimeoutTracked(fn, 0, ...args);
|
|
23510
|
+
let handle;
|
|
23511
|
+
const native = hostSetImmediate((...inner) => {
|
|
23512
|
+
complete(handle);
|
|
22878
23513
|
fn(...inner);
|
|
22879
|
-
}, ...args)
|
|
22880
|
-
|
|
23514
|
+
}, ...args);
|
|
23515
|
+
handle = track(native);
|
|
22881
23516
|
return handle;
|
|
22882
23517
|
};
|
|
22883
23518
|
const clear2 = (handle, native) => {
|
|
23519
|
+
if (typeof handle === "object" && handle !== null) {
|
|
23520
|
+
const state = states.get(handle);
|
|
23521
|
+
if (state) {
|
|
23522
|
+
state.active = false;
|
|
23523
|
+
live.delete(handle);
|
|
23524
|
+
unrefed.delete(handle);
|
|
23525
|
+
native(state.native);
|
|
23526
|
+
return;
|
|
23527
|
+
}
|
|
23528
|
+
}
|
|
22884
23529
|
live.delete(handle);
|
|
22885
23530
|
native(handle);
|
|
22886
23531
|
};
|
|
@@ -22893,7 +23538,8 @@ function createTrackedTimers() {
|
|
|
22893
23538
|
clearInterval: (handle) => clear2(handle, clearInterval),
|
|
22894
23539
|
clearImmediate: (handle) => clear2(handle, globalThis.clearImmediate ?? clearTimeout)
|
|
22895
23540
|
},
|
|
22896
|
-
pending: () => live.size
|
|
23541
|
+
pending: () => live.size,
|
|
23542
|
+
pendingUnrefed: () => unrefed.size
|
|
22897
23543
|
};
|
|
22898
23544
|
}
|
|
22899
23545
|
function createTimerPromises() {
|
|
@@ -23415,7 +24061,26 @@ function ensureProcessGlobal() {
|
|
|
23415
24061
|
});
|
|
23416
24062
|
}
|
|
23417
24063
|
|
|
24064
|
+
// src/runtime/host-rolldown.ts
|
|
24065
|
+
async function loadHostRolldownBinding() {
|
|
24066
|
+
if (typeof window !== "undefined" && globalThis.crossOriginIsolated !== true) {
|
|
24067
|
+
throw new Error(
|
|
24068
|
+
"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."
|
|
24069
|
+
);
|
|
24070
|
+
}
|
|
24071
|
+
try {
|
|
24072
|
+
const loaded = await import('@rolldown/binding-wasm32-wasi');
|
|
24073
|
+
return "__fs" in loaded ? { ...loaded } : loaded.default ?? loaded;
|
|
24074
|
+
} catch (error) {
|
|
24075
|
+
if (typeof process !== "undefined" && process.env?.SANDBOXEDJS_DEBUG) {
|
|
24076
|
+
console.error("[sandboxedjs] Rolldown WASI binding unavailable:", error);
|
|
24077
|
+
}
|
|
24078
|
+
throw new Error("The optional Rolldown WASI binding could not be loaded.", { cause: error });
|
|
24079
|
+
}
|
|
24080
|
+
}
|
|
24081
|
+
|
|
23418
24082
|
// src/runtime/local-runtime-pod.ts
|
|
24083
|
+
init_path();
|
|
23419
24084
|
var WASM_ALIASES = {
|
|
23420
24085
|
esbuild: "esbuild-wasm",
|
|
23421
24086
|
rollup: "@rollup/wasm-node"
|
|
@@ -23540,6 +24205,11 @@ var PodChildProcess = class {
|
|
|
23540
24205
|
started = false;
|
|
23541
24206
|
cancelled = false;
|
|
23542
24207
|
child;
|
|
24208
|
+
/* The child is launched asynchronously, but a parent may write and close
|
|
24209
|
+
* its input synchronously right after spawning. Holding both until the
|
|
24210
|
+
* child exists is what keeps `echo hi | child` from losing the `hi`. */
|
|
24211
|
+
pendingInput = "";
|
|
24212
|
+
inputEnded = false;
|
|
23543
24213
|
on(event, listener) {
|
|
23544
24214
|
let set = this.listeners.get(event);
|
|
23545
24215
|
if (!set) this.listeners.set(event, set = /* @__PURE__ */ new Set());
|
|
@@ -23562,6 +24232,11 @@ var PodChildProcess = class {
|
|
|
23562
24232
|
(child) => {
|
|
23563
24233
|
this.child = child;
|
|
23564
24234
|
if (this.cancelled) child.kill();
|
|
24235
|
+
if (this.pendingInput !== "") {
|
|
24236
|
+
child.write(this.pendingInput);
|
|
24237
|
+
this.pendingInput = "";
|
|
24238
|
+
}
|
|
24239
|
+
if (this.inputEnded) child.endInput?.();
|
|
23565
24240
|
child.on("output", (text2) => {
|
|
23566
24241
|
this.stdout += text2;
|
|
23567
24242
|
this.emit("stdout", text2);
|
|
@@ -23584,7 +24259,13 @@ var PodChildProcess = class {
|
|
|
23584
24259
|
});
|
|
23585
24260
|
}
|
|
23586
24261
|
sendStdin(data) {
|
|
23587
|
-
this.child
|
|
24262
|
+
if (this.child) this.child.write(data);
|
|
24263
|
+
else this.pendingInput += data;
|
|
24264
|
+
}
|
|
24265
|
+
/** Signal EOF, so a child reading stdin to the end can finish. */
|
|
24266
|
+
endStdin() {
|
|
24267
|
+
if (this.child) this.child.endInput?.();
|
|
24268
|
+
else this.inputEnded = true;
|
|
23588
24269
|
}
|
|
23589
24270
|
kill(signal = "SIGTERM") {
|
|
23590
24271
|
if (this.child) this.child.kill(signal);
|
|
@@ -23666,6 +24347,9 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23666
24347
|
aliases;
|
|
23667
24348
|
modules;
|
|
23668
24349
|
esbuild;
|
|
24350
|
+
rolldownBinding;
|
|
24351
|
+
/** Backs outbound `http`/`https` client requests from inside the sandbox. */
|
|
24352
|
+
fetch;
|
|
23669
24353
|
constructor(options) {
|
|
23670
24354
|
ensureProcessGlobal();
|
|
23671
24355
|
this.workdir = options.workdir ?? "/";
|
|
@@ -23680,6 +24364,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23680
24364
|
const notify = options.onServerReady;
|
|
23681
24365
|
this.router.onListen = (port) => notify(port, `http://localhost:${port}`);
|
|
23682
24366
|
}
|
|
24367
|
+
if (options.fetch) this.fetch = options.fetch;
|
|
23683
24368
|
this.packages = new CleanPackageInstaller(this.volume, {
|
|
23684
24369
|
cwd: this.workdir,
|
|
23685
24370
|
...options.registry ? { registry: options.registry } : {},
|
|
@@ -23699,6 +24384,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23699
24384
|
const env2 = { ...this.env, ...isRecord(options.env) ? options.env : {} };
|
|
23700
24385
|
const owner = `${this.instanceId}:${Math.random().toString(36).slice(2)}`;
|
|
23701
24386
|
return new LocalProcess(async (proc) => {
|
|
24387
|
+
await this.prepareRolldown(cwd, env2);
|
|
23702
24388
|
const untrack = trackProcess(proc);
|
|
23703
24389
|
let requestedExit = 0;
|
|
23704
24390
|
let engine;
|
|
@@ -23718,7 +24404,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23718
24404
|
proc.exitNow(code);
|
|
23719
24405
|
if (engine?.isEvaluating) throw new ProcessExit(code);
|
|
23720
24406
|
},
|
|
23721
|
-
http: { router: this.router, owner },
|
|
24407
|
+
http: { router: this.router, owner, ...this.fetch ? { fetch: this.fetch } : {} },
|
|
23722
24408
|
spawnChild: (config) => this.processManager.spawn(config),
|
|
23723
24409
|
...typeof options.stdinPath === "string" ? { stdinPath: options.stdinPath } : {},
|
|
23724
24410
|
...options.interactiveStdin ? { interactiveStdin: true } : {},
|
|
@@ -23735,7 +24421,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23735
24421
|
});
|
|
23736
24422
|
try {
|
|
23737
24423
|
await engine.run(script);
|
|
23738
|
-
await this.settle(owner, core.pendingHandles, core.readingStdin);
|
|
24424
|
+
await this.settle(owner, core.pendingHandles, core.pendingUnrefed, core.readingStdin, core.pendingRequests);
|
|
23739
24425
|
if (this.router.activePorts(owner).length) {
|
|
23740
24426
|
await proc.waitForKill();
|
|
23741
24427
|
return 137;
|
|
@@ -23747,6 +24433,25 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23747
24433
|
}
|
|
23748
24434
|
});
|
|
23749
24435
|
}
|
|
24436
|
+
/**
|
|
24437
|
+
* Rolldown's JavaScript API synchronously requires its compiled binding.
|
|
24438
|
+
* When a project contains Rolldown, preload the official WASI build in the
|
|
24439
|
+
* host and expose it through the module override table before evaluation.
|
|
24440
|
+
* Keeping this demand-driven avoids adding WASM startup cost to ordinary
|
|
24441
|
+
* shells and Node programs.
|
|
24442
|
+
*/
|
|
24443
|
+
async prepareRolldown(cwd, env2) {
|
|
24444
|
+
const specifier = "@rolldown/binding-wasm32-wasi";
|
|
24445
|
+
if (!this.modules[specifier] && packageInstalled(this.volume, cwd, "rolldown")) {
|
|
24446
|
+
this.rolldownBinding ??= loadHostRolldownBinding();
|
|
24447
|
+
const binding = await this.rolldownBinding;
|
|
24448
|
+
if (binding) this.modules[specifier] = binding;
|
|
24449
|
+
}
|
|
24450
|
+
if (this.modules[specifier]) {
|
|
24451
|
+
syncRolldownFileSystem(this.modules[specifier], this.volume, cwd);
|
|
24452
|
+
env2.NAPI_RS_FORCE_WASI ??= "true";
|
|
24453
|
+
}
|
|
24454
|
+
}
|
|
23750
24455
|
/**
|
|
23751
24456
|
* Wait until the process has either started serving or genuinely run out of
|
|
23752
24457
|
* work.
|
|
@@ -23762,12 +24467,18 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23762
24467
|
* A plain script that has genuinely finished falls straight through both,
|
|
23763
24468
|
* costing a handful of empty turns.
|
|
23764
24469
|
*/
|
|
23765
|
-
async settle(owner, pendingHandles, readingStdin) {
|
|
24470
|
+
async settle(owner, pendingHandles, pendingUnrefed, readingStdin, pendingRequests) {
|
|
23766
24471
|
for (let turn = 0; turn < DRAIN_TURNS; turn++) {
|
|
23767
24472
|
if (this.router.activePorts(owner).length) return;
|
|
23768
24473
|
await new Promise((resolve2) => setTimeout(resolve2, 0));
|
|
23769
24474
|
}
|
|
23770
|
-
|
|
24475
|
+
if (pendingHandles() === 0 && pendingRequests() === 0 && pendingUnrefed() > 0 && !readingStdin()) {
|
|
24476
|
+
const deadline = Date.now() + 1e3;
|
|
24477
|
+
while (!this.router.activePorts(owner).length && Date.now() < deadline) {
|
|
24478
|
+
await new Promise((resolve2) => setTimeout(resolve2, 5));
|
|
24479
|
+
}
|
|
24480
|
+
}
|
|
24481
|
+
while (!this.router.activePorts(owner).length && (pendingHandles() > 0 || pendingRequests() > 0 || readingStdin())) {
|
|
23771
24482
|
await new Promise((resolve2) => setTimeout(resolve2, 5));
|
|
23772
24483
|
}
|
|
23773
24484
|
}
|
|
@@ -23819,6 +24530,60 @@ function formatError(error) {
|
|
|
23819
24530
|
function isRecord(value) {
|
|
23820
24531
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23821
24532
|
}
|
|
24533
|
+
function packageInstalled(volume, cwd, wanted) {
|
|
24534
|
+
for (let dir3 = clean(cwd); ; dir3 = dirname(dir3)) {
|
|
24535
|
+
if (packageTreeContains(volume, join(dir3, "node_modules"), wanted, /* @__PURE__ */ new Set())) return true;
|
|
24536
|
+
if (dir3 === "/") return false;
|
|
24537
|
+
}
|
|
24538
|
+
}
|
|
24539
|
+
function packageTreeContains(volume, modulesRoot, wanted, visited) {
|
|
24540
|
+
if (visited.has(modulesRoot) || !directory(volume, modulesRoot)) return false;
|
|
24541
|
+
visited.add(modulesRoot);
|
|
24542
|
+
if (directory(volume, join(modulesRoot, wanted))) return true;
|
|
24543
|
+
for (const entry of volume.readdirSync(modulesRoot)) {
|
|
24544
|
+
if (entry === ".bin") continue;
|
|
24545
|
+
const first = join(modulesRoot, entry);
|
|
24546
|
+
const packages = entry.startsWith("@") && directory(volume, first) ? volume.readdirSync(first).map((name) => join(first, name)) : [first];
|
|
24547
|
+
for (const root of packages) {
|
|
24548
|
+
if (directory(volume, root) && packageTreeContains(volume, join(root, "node_modules"), wanted, visited)) {
|
|
24549
|
+
return true;
|
|
24550
|
+
}
|
|
24551
|
+
}
|
|
24552
|
+
}
|
|
24553
|
+
return false;
|
|
24554
|
+
}
|
|
24555
|
+
function directory(volume, path) {
|
|
24556
|
+
try {
|
|
24557
|
+
return volume.lstatSync(path).isDirectory();
|
|
24558
|
+
} catch {
|
|
24559
|
+
return false;
|
|
24560
|
+
}
|
|
24561
|
+
}
|
|
24562
|
+
function syncRolldownFileSystem(binding, volume, root) {
|
|
24563
|
+
const fs = binding?.__fs;
|
|
24564
|
+
if (!fs?.mkdirSync || !fs?.writeFileSync) return;
|
|
24565
|
+
try {
|
|
24566
|
+
fs.rmSync?.(root, { recursive: true, force: true });
|
|
24567
|
+
} catch {
|
|
24568
|
+
}
|
|
24569
|
+
const copy = (path) => {
|
|
24570
|
+
const stat2 = volume.lstatSync(path);
|
|
24571
|
+
if (stat2.isDirectory()) {
|
|
24572
|
+
fs.mkdirSync(path, { recursive: true });
|
|
24573
|
+
for (const name of volume.readdirSync(path)) copy(join(path, name));
|
|
24574
|
+
} else if (stat2.isSymbolicLink()) {
|
|
24575
|
+
fs.mkdirSync(dirname(path), { recursive: true });
|
|
24576
|
+
try {
|
|
24577
|
+
fs.symlinkSync(volume.readlinkSync(path), path);
|
|
24578
|
+
} catch {
|
|
24579
|
+
}
|
|
24580
|
+
} else if (!path.endsWith(".node")) {
|
|
24581
|
+
fs.mkdirSync(dirname(path), { recursive: true });
|
|
24582
|
+
fs.writeFileSync(path, volume.readFileSync(path));
|
|
24583
|
+
}
|
|
24584
|
+
};
|
|
24585
|
+
copy(clean(root));
|
|
24586
|
+
}
|
|
23822
24587
|
|
|
23823
24588
|
// src/container/container.ts
|
|
23824
24589
|
var Container = class _Container {
|
|
@@ -24162,7 +24927,7 @@ var Container = class _Container {
|
|
|
24162
24927
|
/**
|
|
24163
24928
|
* Deliver a request whose body is bytes, without letting them become text.
|
|
24164
24929
|
*
|
|
24165
|
-
*
|
|
24930
|
+
* A RuntimePod's public `request()` may run the body through `toString("utf8")` on
|
|
24166
24931
|
* its way in, so anything above `0x7f` is replaced: a five-byte payload
|
|
24167
24932
|
* containing `0x89` and `0xff` arrives as nine. That silently destroys every
|
|
24168
24933
|
* upload — an image or a video reaches the server the wrong size and no
|
|
@@ -24264,7 +25029,7 @@ var Container = class _Container {
|
|
|
24264
25029
|
assertActive() {
|
|
24265
25030
|
if (this.disposed) throw new Error("container has been disposed");
|
|
24266
25031
|
}
|
|
24267
|
-
/** Tear down every process and release the
|
|
25032
|
+
/** Tear down every process and release the runtime pod. */
|
|
24268
25033
|
dispose() {
|
|
24269
25034
|
if (this.disposed) return;
|
|
24270
25035
|
this.disposed = true;
|
|
@@ -24374,17 +25139,18 @@ var Terminal = class {
|
|
|
24374
25139
|
// ── key handling ──────────────────────────────────────────────────────────
|
|
24375
25140
|
key(ch) {
|
|
24376
25141
|
if (this.running) {
|
|
24377
|
-
|
|
25142
|
+
const raw = this.currentStdin?.rawMode === true;
|
|
25143
|
+
if (ch === CTRL_C && !raw) {
|
|
24378
25144
|
this.session.proc.deliver("SIGINT");
|
|
24379
25145
|
this.write("^C\r\n");
|
|
24380
25146
|
return;
|
|
24381
25147
|
}
|
|
24382
|
-
if (ch === CTRL_D) {
|
|
25148
|
+
if (ch === CTRL_D && !raw) {
|
|
24383
25149
|
this.currentStdin?.end();
|
|
24384
25150
|
return;
|
|
24385
25151
|
}
|
|
24386
|
-
if (!
|
|
24387
|
-
this.currentStdin?.write(ch === "\r" ? "\n" : ch);
|
|
25152
|
+
if (!raw) this.write(ch === "\r" ? "\r\n" : ch);
|
|
25153
|
+
this.currentStdin?.write(!raw && ch === "\r" ? "\n" : ch);
|
|
24388
25154
|
return;
|
|
24389
25155
|
}
|
|
24390
25156
|
if (this.escapeBuffer !== "") {
|