sandboxedjs 0.1.27 → 0.1.29
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 +52 -7
- package/dist/index.cjs +1540 -107
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +219 -8
- package/dist/index.d.ts +219 -8
- package/dist/index.js +1539 -108
- package/dist/index.js.map +1 -1
- package/dist/worker-entry.js +30822 -0
- package/dist/worker-entry.js.map +1 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -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";
|
|
@@ -17820,22 +17959,22 @@ async function runCPythonProgram(ctx, source, argv, scriptDir, stdinText) {
|
|
|
17820
17959
|
});
|
|
17821
17960
|
} catch {
|
|
17822
17961
|
}
|
|
17823
|
-
const
|
|
17824
|
-
const
|
|
17962
|
+
const encoder8 = new TextEncoder();
|
|
17963
|
+
const decoder8 = new TextDecoder();
|
|
17825
17964
|
py.setStdout({
|
|
17826
17965
|
write: (buffer) => {
|
|
17827
|
-
ctx.write(
|
|
17966
|
+
ctx.write(decoder8.decode(buffer));
|
|
17828
17967
|
return buffer.length;
|
|
17829
17968
|
}
|
|
17830
17969
|
});
|
|
17831
17970
|
py.setStderr({
|
|
17832
17971
|
write: (buffer) => {
|
|
17833
|
-
ctx.stderr.write(
|
|
17972
|
+
ctx.stderr.write(decoder8.decode(buffer));
|
|
17834
17973
|
return buffer.length;
|
|
17835
17974
|
}
|
|
17836
17975
|
});
|
|
17837
17976
|
if (stdinText !== null) {
|
|
17838
|
-
const bytes2 =
|
|
17977
|
+
const bytes2 = encoder8.encode(stdinText);
|
|
17839
17978
|
let offset = 0;
|
|
17840
17979
|
py.setStdin({
|
|
17841
17980
|
read: (buffer) => {
|
|
@@ -17886,9 +18025,9 @@ async function runCPythonRepl(ctx) {
|
|
|
17886
18025
|
}
|
|
17887
18026
|
mountContainerDirs(py, ctx);
|
|
17888
18027
|
bootstrap(py, ctx, [""], null);
|
|
17889
|
-
const
|
|
17890
|
-
py.setStdout({ write: (data) => (ctx.write(
|
|
17891
|
-
py.setStderr({ write: (data) => (ctx.stderr.write(
|
|
18028
|
+
const decoder8 = new TextDecoder();
|
|
18029
|
+
py.setStdout({ write: (data) => (ctx.write(decoder8.decode(data)), data.length) });
|
|
18030
|
+
py.setStderr({ write: (data) => (ctx.stderr.write(decoder8.decode(data)), data.length) });
|
|
17892
18031
|
ctx.line(`Python ${String(py.runPython("import sys; sys.version.split()[0]"))} (Pyodide)`);
|
|
17893
18032
|
ctx.line('Type "help()" for more information.');
|
|
17894
18033
|
let source = "";
|
|
@@ -19336,6 +19475,7 @@ function allCommands() {
|
|
|
19336
19475
|
...commands8,
|
|
19337
19476
|
...commands9,
|
|
19338
19477
|
...commands10,
|
|
19478
|
+
...commands11,
|
|
19339
19479
|
...nodeCommands(),
|
|
19340
19480
|
...pythonCommands(),
|
|
19341
19481
|
...ffmpegCommands(),
|
|
@@ -19498,15 +19638,15 @@ var Session = class {
|
|
|
19498
19638
|
async run(command, opts = {}) {
|
|
19499
19639
|
if (this.closed) throw new Error("session is closed");
|
|
19500
19640
|
const combined = [];
|
|
19501
|
-
const
|
|
19641
|
+
const decoder8 = new TextDecoder();
|
|
19502
19642
|
const stdout = new BufferSink((chunk) => {
|
|
19503
|
-
const text2 =
|
|
19643
|
+
const text2 = decoder8.decode(chunk, { stream: true });
|
|
19504
19644
|
combined.push(text2);
|
|
19505
19645
|
opts.onStdout?.(text2);
|
|
19506
19646
|
this.hooks.onStdout?.(text2);
|
|
19507
19647
|
});
|
|
19508
19648
|
const stderr = new BufferSink((chunk) => {
|
|
19509
|
-
const text2 =
|
|
19649
|
+
const text2 = decoder8.decode(chunk, { stream: true });
|
|
19510
19650
|
combined.push(text2);
|
|
19511
19651
|
opts.onStderr?.(text2);
|
|
19512
19652
|
this.hooks.onStderr?.(text2);
|
|
@@ -19632,6 +19772,13 @@ var KernelChildProcess = class {
|
|
|
19632
19772
|
} catch {
|
|
19633
19773
|
}
|
|
19634
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
|
+
}
|
|
19635
19782
|
kill(signal = "SIGTERM") {
|
|
19636
19783
|
if (this.process) {
|
|
19637
19784
|
this.process.deliver(signal);
|
|
@@ -20543,6 +20690,55 @@ function splitSpecifier(specifier) {
|
|
|
20543
20690
|
return { name: parts.slice(0, size).join("/"), subpath: parts.slice(size).join("/") };
|
|
20544
20691
|
}
|
|
20545
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
|
+
|
|
20546
20742
|
// src/runtime/util-module.ts
|
|
20547
20743
|
var customInspect = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
20548
20744
|
var promisifyCustom = /* @__PURE__ */ Symbol.for("nodejs.util.promisify.custom");
|
|
@@ -21430,6 +21626,10 @@ var VirtualHttpRouter = class {
|
|
|
21430
21626
|
unregister(port, server) {
|
|
21431
21627
|
if (this.servers.get(port)?.server === server) this.servers.delete(port);
|
|
21432
21628
|
}
|
|
21629
|
+
/** Whether anything in this container is listening on `port`. */
|
|
21630
|
+
activePortsIncludes(port) {
|
|
21631
|
+
return this.servers.has(port);
|
|
21632
|
+
}
|
|
21433
21633
|
activePorts(owner) {
|
|
21434
21634
|
return [...this.servers].filter(([, item]) => owner === void 0 || item.owner === owner).map(([port]) => port).sort((a, b) => a - b);
|
|
21435
21635
|
}
|
|
@@ -21453,13 +21653,275 @@ var VirtualHttpRouter = class {
|
|
|
21453
21653
|
}
|
|
21454
21654
|
}
|
|
21455
21655
|
};
|
|
21456
|
-
|
|
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 = 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
|
+
if (!this.router.activePortsIncludes(this.target.port)) {
|
|
21858
|
+
throw Object.assign(
|
|
21859
|
+
new Error(`connect ECONNREFUSED ${this.target.hostname}:${this.target.port}`),
|
|
21860
|
+
{ code: "ECONNREFUSED", errno: -61, syscall: "connect", address: this.target.hostname, port: this.target.port }
|
|
21861
|
+
);
|
|
21862
|
+
}
|
|
21863
|
+
const result = await this.router.request(this.target.port, {
|
|
21864
|
+
method: this.target.method,
|
|
21865
|
+
path: this.target.path,
|
|
21866
|
+
headers: this.getHeaders(),
|
|
21867
|
+
body: body.length ? new Uint8Array(body) : null
|
|
21868
|
+
});
|
|
21869
|
+
const body_ = result.body;
|
|
21870
|
+
const bytes2 = typeof body_ === "string" ? new TextEncoder().encode(body_) : body_ instanceof ArrayBuffer ? new Uint8Array(body_) : body_ ?? new Uint8Array();
|
|
21871
|
+
const status = result.statusCode ?? 200;
|
|
21872
|
+
return new VirtualClientResponse(status, result.statusMessage ?? STATUS_CODES[status] ?? "", lowercaseHeaders(result.headers), bytes2);
|
|
21873
|
+
}
|
|
21874
|
+
async viaFetch(body) {
|
|
21875
|
+
const fetchImpl = this.fetchImpl ?? globalThis.fetch;
|
|
21876
|
+
if (typeof fetchImpl !== "function") {
|
|
21877
|
+
throw Object.assign(new Error(`getaddrinfo ENOTFOUND ${this.target.hostname}`), { code: "ENOTFOUND" });
|
|
21878
|
+
}
|
|
21879
|
+
const portSuffix = this.target.protocol === "https:" && this.target.port === 443 || this.target.protocol === "http:" && this.target.port === 80 ? "" : `:${this.target.port}`;
|
|
21880
|
+
const url = `${this.target.protocol}//${this.target.hostname}${portSuffix}${this.target.path}`;
|
|
21881
|
+
const bodyless = this.target.method === "GET" || this.target.method === "HEAD";
|
|
21882
|
+
const headers = this.getHeaders();
|
|
21883
|
+
delete headers.host;
|
|
21884
|
+
delete headers.connection;
|
|
21885
|
+
delete headers["content-length"];
|
|
21886
|
+
const response = await fetchImpl(url, {
|
|
21887
|
+
method: this.target.method,
|
|
21888
|
+
headers,
|
|
21889
|
+
...bodyless || body.length === 0 ? {} : { body: new Uint8Array(body) },
|
|
21890
|
+
redirect: "follow"
|
|
21891
|
+
});
|
|
21892
|
+
const received = {};
|
|
21893
|
+
response.headers.forEach((value, key) => {
|
|
21894
|
+
received[key.toLowerCase()] = value;
|
|
21895
|
+
});
|
|
21896
|
+
const bytes2 = new Uint8Array(await response.arrayBuffer());
|
|
21897
|
+
return new VirtualClientResponse(response.status, response.statusText, received, bytes2);
|
|
21898
|
+
}
|
|
21899
|
+
};
|
|
21900
|
+
function lowercaseHeaders(headers) {
|
|
21901
|
+
return Object.fromEntries(Object.entries(headers ?? {}).map(([key, value]) => [key.toLowerCase(), String(value)]));
|
|
21902
|
+
}
|
|
21903
|
+
function createHttpModule(router, owner, options = {}, defaultProtocol = "http:") {
|
|
21457
21904
|
const createServer = (listener) => new VirtualHttpServer(router, owner, listener);
|
|
21458
|
-
const
|
|
21905
|
+
const request = (input, second, third) => {
|
|
21906
|
+
const overrides = second && typeof second === "object" && !(second instanceof Function) ? second : void 0;
|
|
21907
|
+
const callback = [second, third].find((value) => typeof value === "function");
|
|
21908
|
+
const req = new VirtualClientRequest(resolveTarget(input, overrides, defaultProtocol), router, options.fetch, options.trackRequest);
|
|
21909
|
+
if (callback) req.on("response", callback);
|
|
21910
|
+
return req;
|
|
21911
|
+
};
|
|
21912
|
+
const get = (input, second, third) => {
|
|
21913
|
+
const req = request(input, second, third);
|
|
21914
|
+
req.end();
|
|
21915
|
+
return req;
|
|
21916
|
+
};
|
|
21917
|
+
return {
|
|
21459
21918
|
createServer,
|
|
21919
|
+
request,
|
|
21920
|
+
get,
|
|
21460
21921
|
Server: VirtualHttpServer,
|
|
21461
21922
|
ServerResponse: VirtualServerResponse,
|
|
21462
21923
|
IncomingMessage: VirtualIncomingMessage,
|
|
21924
|
+
ClientRequest: VirtualClientRequest,
|
|
21463
21925
|
METHODS,
|
|
21464
21926
|
STATUS_CODES,
|
|
21465
21927
|
maxHeaderSize: 16 * 1024,
|
|
@@ -21469,10 +21931,6 @@ function createHttpModule(router, owner) {
|
|
|
21469
21931
|
Agent: class Agent {
|
|
21470
21932
|
}
|
|
21471
21933
|
};
|
|
21472
|
-
return { ...module, request: unsupportedClient, get: unsupportedClient };
|
|
21473
|
-
}
|
|
21474
|
-
function unsupportedClient() {
|
|
21475
|
-
throw Object.assign(new Error("http client requests are not implemented yet"), { code: "ERR_NOT_IMPLEMENTED" });
|
|
21476
21934
|
}
|
|
21477
21935
|
function validateHeaderName(name) {
|
|
21478
21936
|
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" });
|
|
@@ -21612,6 +22070,13 @@ var ChildProcess = class extends EventEmitter4__default.default {
|
|
|
21612
22070
|
} catch {
|
|
21613
22071
|
}
|
|
21614
22072
|
done();
|
|
22073
|
+
},
|
|
22074
|
+
final: (done) => {
|
|
22075
|
+
try {
|
|
22076
|
+
handle.endStdin?.();
|
|
22077
|
+
} catch {
|
|
22078
|
+
}
|
|
22079
|
+
done();
|
|
21615
22080
|
}
|
|
21616
22081
|
});
|
|
21617
22082
|
this.stdio = [this.stdin, this.stdout, this.stderr];
|
|
@@ -21651,7 +22116,7 @@ var ChildProcess = class extends EventEmitter4__default.default {
|
|
|
21651
22116
|
queueMicrotask(() => this.emit("close", code, null));
|
|
21652
22117
|
}
|
|
21653
22118
|
};
|
|
21654
|
-
function createChildProcessModule(spawnChild, defaultCwd) {
|
|
22119
|
+
function createChildProcessModule(spawnChild, defaultCwd, syncSpawn) {
|
|
21655
22120
|
const throughShell = (command, options) => {
|
|
21656
22121
|
const shell = typeof options.shell === "string" ? options.shell : "/bin/sh";
|
|
21657
22122
|
return { file: shell, args: ["-c", command] };
|
|
@@ -21708,20 +22173,79 @@ ${err.join("")}`),
|
|
|
21708
22173
|
exec,
|
|
21709
22174
|
execFile,
|
|
21710
22175
|
fork: (modulePath, args = [], options = {}) => spawn("node", [modulePath, ...args], options),
|
|
21711
|
-
|
|
21712
|
-
execFileSync: unavailable("execFileSync"),
|
|
21713
|
-
spawnSync: unavailable("spawnSync"),
|
|
22176
|
+
...buildSyncFamily(syncSpawn, throughShell, defaultCwd),
|
|
21714
22177
|
ChildProcess
|
|
21715
22178
|
};
|
|
21716
22179
|
}
|
|
22180
|
+
function buildSyncFamily(syncSpawn, throughShell, defaultCwd) {
|
|
22181
|
+
if (!syncSpawn) {
|
|
22182
|
+
return {
|
|
22183
|
+
execSync: unavailable("execSync"),
|
|
22184
|
+
execFileSync: unavailable("execFileSync"),
|
|
22185
|
+
spawnSync: unavailable("spawnSync")
|
|
22186
|
+
};
|
|
22187
|
+
}
|
|
22188
|
+
const run = (file3, args, options) => {
|
|
22189
|
+
const resolved = options.shell ? throughShell([file3, ...args].join(" "), options) : { file: file3, args };
|
|
22190
|
+
const input = options.input === void 0 ? void 0 : typeof options.input === "string" ? options.input : new TextDecoder().decode(options.input);
|
|
22191
|
+
return syncSpawn({
|
|
22192
|
+
command: resolved.file,
|
|
22193
|
+
args: resolved.args,
|
|
22194
|
+
cwd: options.cwd ?? defaultCwd(),
|
|
22195
|
+
...options.env ? { env: options.env } : {},
|
|
22196
|
+
...input === void 0 ? {} : { input }
|
|
22197
|
+
});
|
|
22198
|
+
};
|
|
22199
|
+
const asOutput = (text2, options) => options.encoding === "buffer" || options.encoding === void 0 ? Buffer2.from(text2) : text2;
|
|
22200
|
+
const orThrow = (result, command, options) => {
|
|
22201
|
+
if (result.error) {
|
|
22202
|
+
throw Object.assign(new Error(result.error.message), {
|
|
22203
|
+
...result.error.code ? { code: result.error.code } : {},
|
|
22204
|
+
stdout: asOutput(result.stdout, options),
|
|
22205
|
+
stderr: asOutput(result.stderr, options)
|
|
22206
|
+
});
|
|
22207
|
+
}
|
|
22208
|
+
if (result.status !== 0) {
|
|
22209
|
+
throw Object.assign(new Error(`Command failed: ${command}
|
|
22210
|
+
${result.stderr}`), {
|
|
22211
|
+
status: result.status,
|
|
22212
|
+
stdout: asOutput(result.stdout, options),
|
|
22213
|
+
stderr: asOutput(result.stderr, options)
|
|
22214
|
+
});
|
|
22215
|
+
}
|
|
22216
|
+
return asOutput(result.stdout, options);
|
|
22217
|
+
};
|
|
22218
|
+
const spawnSync = (file3, args = [], options = {}) => {
|
|
22219
|
+
const [list, opts] = Array.isArray(args) ? [args, options] : [[], args];
|
|
22220
|
+
const result = run(file3, list, opts);
|
|
22221
|
+
return {
|
|
22222
|
+
pid: 0,
|
|
22223
|
+
status: result.status,
|
|
22224
|
+
signal: result.signal,
|
|
22225
|
+
stdout: asOutput(result.stdout, opts),
|
|
22226
|
+
stderr: asOutput(result.stderr, opts),
|
|
22227
|
+
output: [null, asOutput(result.stdout, opts), asOutput(result.stderr, opts)],
|
|
22228
|
+
...result.error ? { error: Object.assign(new Error(result.error.message), result.error.code ? { code: result.error.code } : {}) } : {}
|
|
22229
|
+
};
|
|
22230
|
+
};
|
|
22231
|
+
const execFileSync = (file3, args = [], options = {}) => {
|
|
22232
|
+
const [list, opts] = Array.isArray(args) ? [args, options] : [[], args];
|
|
22233
|
+
return orThrow(run(file3, list, opts), [file3, ...list].join(" "), opts);
|
|
22234
|
+
};
|
|
22235
|
+
const execSync = (command, options = {}) => orThrow(run(command, [], { ...options, shell: options.shell ?? true }), command, options);
|
|
22236
|
+
return { spawnSync, execFileSync, execSync };
|
|
22237
|
+
}
|
|
21717
22238
|
function normalize2(options, callback) {
|
|
21718
22239
|
if (typeof options === "function") return [{}, options];
|
|
21719
22240
|
return [options ?? {}, callback];
|
|
21720
22241
|
}
|
|
21721
22242
|
function unavailable(name) {
|
|
21722
|
-
return () => {
|
|
22243
|
+
return (...args) => {
|
|
22244
|
+
const file3 = typeof args[0] === "string" ? args[0] : void 0;
|
|
22245
|
+
const list = Array.isArray(args[1]) ? args[1].map(String) : [];
|
|
22246
|
+
const command = file3 ? [file3, ...list].join(" ") : void 0;
|
|
21723
22247
|
const error = new Error(
|
|
21724
|
-
`child_process.${name} is not supported in the sandboxed runtime
|
|
22248
|
+
`child_process.${name} is not supported in the sandboxed runtime` + (command ? ` (tried to run: ${command})` : "") + `: the caller, the child and the event loop share one thread, so blocking the caller would also stop the child. Run it with the asynchronous form (spawn/exec/execFile), or run the command from the container shell.`
|
|
21725
22249
|
);
|
|
21726
22250
|
error.code = "ERR_FEATURE_UNAVAILABLE_ON_PLATFORM";
|
|
21727
22251
|
throw error;
|
|
@@ -21785,7 +22309,11 @@ function parseKeys(input) {
|
|
|
21785
22309
|
const name = CSI_KEYS[sequence];
|
|
21786
22310
|
keys.push({
|
|
21787
22311
|
sequence: `\x1B${sequence}`,
|
|
21788
|
-
|
|
22312
|
+
/* Node leaves this undefined for a sequence it does not recognise.
|
|
22313
|
+
* The string "undefined" is not the same thing: a caller testing
|
|
22314
|
+
* `key.name === undefined` would take an unknown key for a known
|
|
22315
|
+
* one. */
|
|
22316
|
+
name,
|
|
21789
22317
|
ctrl: false,
|
|
21790
22318
|
/* xterm reports modifiers as `;5` (control) and `;2` (shift) before
|
|
21791
22319
|
* the final letter. */
|
|
@@ -21850,7 +22378,7 @@ function emitKeypressEvents(stream) {
|
|
|
21850
22378
|
}
|
|
21851
22379
|
});
|
|
21852
22380
|
}
|
|
21853
|
-
function createReadlineModule(defaultInput) {
|
|
22381
|
+
function createReadlineModule(defaultInput, defaultOutput = () => void 0) {
|
|
21854
22382
|
class Interface extends EventEmitter4__default.default {
|
|
21855
22383
|
constructor(input, output, terminal = false) {
|
|
21856
22384
|
super();
|
|
@@ -21861,6 +22389,14 @@ function createReadlineModule(defaultInput) {
|
|
|
21861
22389
|
if (terminal) {
|
|
21862
22390
|
emitKeypressEvents(input);
|
|
21863
22391
|
input?.on?.("keypress", this.onTerminalKeypress);
|
|
22392
|
+
if (typeof input?.setRawMode === "function") {
|
|
22393
|
+
try {
|
|
22394
|
+
input.setRawMode(true);
|
|
22395
|
+
this.ownsRawMode = true;
|
|
22396
|
+
} catch {
|
|
22397
|
+
}
|
|
22398
|
+
}
|
|
22399
|
+
input?.resume?.();
|
|
21864
22400
|
} else {
|
|
21865
22401
|
input?.on?.("data", (chunk) => this.receive(String(chunk)));
|
|
21866
22402
|
}
|
|
@@ -21872,6 +22408,10 @@ function createReadlineModule(defaultInput) {
|
|
|
21872
22408
|
buffer = "";
|
|
21873
22409
|
pending = [];
|
|
21874
22410
|
lines = [];
|
|
22411
|
+
/** Set while `question` is waiting, so the echoed line carries the query. */
|
|
22412
|
+
questionPrompt = null;
|
|
22413
|
+
/** Raw mode is only ours to restore if we were the one to enable it. */
|
|
22414
|
+
ownsRawMode = false;
|
|
21875
22415
|
line = "";
|
|
21876
22416
|
cursor = 0;
|
|
21877
22417
|
terminal;
|
|
@@ -21879,20 +22419,31 @@ function createReadlineModule(defaultInput) {
|
|
|
21879
22419
|
/** Split incoming data into lines, answering any waiting `question`. */
|
|
21880
22420
|
receive(text2) {
|
|
21881
22421
|
this.buffer += text2;
|
|
21882
|
-
let
|
|
21883
|
-
while (
|
|
21884
|
-
const line = this.buffer.slice(0,
|
|
21885
|
-
this.buffer = this.buffer.slice(
|
|
21886
|
-
|
|
21887
|
-
|
|
21888
|
-
|
|
21889
|
-
|
|
21890
|
-
|
|
21891
|
-
|
|
21892
|
-
|
|
22422
|
+
let match2 = /\r\n|\r|\n/.exec(this.buffer);
|
|
22423
|
+
while (match2) {
|
|
22424
|
+
const line = this.buffer.slice(0, match2.index);
|
|
22425
|
+
this.buffer = this.buffer.slice(match2.index + match2[0].length);
|
|
22426
|
+
this.deliver(line);
|
|
22427
|
+
match2 = /\r\n|\r|\n/.exec(this.buffer);
|
|
22428
|
+
}
|
|
22429
|
+
}
|
|
22430
|
+
/** Hand a completed line to whoever is waiting for it. */
|
|
22431
|
+
deliver(line) {
|
|
22432
|
+
const waiting = this.pending.shift();
|
|
22433
|
+
if (waiting) {
|
|
22434
|
+
this.questionPrompt = null;
|
|
22435
|
+
waiting(line);
|
|
22436
|
+
return;
|
|
21893
22437
|
}
|
|
22438
|
+
this.lines.push(line);
|
|
22439
|
+
this.emit("line", line);
|
|
21894
22440
|
}
|
|
21895
22441
|
question(query, callback) {
|
|
22442
|
+
if (this.terminal) {
|
|
22443
|
+
this.questionPrompt = query;
|
|
22444
|
+
this.line = "";
|
|
22445
|
+
this.cursor = 0;
|
|
22446
|
+
}
|
|
21896
22447
|
this.output?.write?.(query);
|
|
21897
22448
|
if (callback) {
|
|
21898
22449
|
this.pending.push(callback);
|
|
@@ -21907,6 +22458,9 @@ function createReadlineModule(defaultInput) {
|
|
|
21907
22458
|
setPrompt(text2) {
|
|
21908
22459
|
this.promptText = text2;
|
|
21909
22460
|
}
|
|
22461
|
+
getPrompt() {
|
|
22462
|
+
return this.promptText;
|
|
22463
|
+
}
|
|
21910
22464
|
pause() {
|
|
21911
22465
|
this.input?.pause?.();
|
|
21912
22466
|
return this;
|
|
@@ -21934,21 +22488,48 @@ function createReadlineModule(defaultInput) {
|
|
|
21934
22488
|
if (text2) {
|
|
21935
22489
|
this.line = this.line.slice(0, this.cursor) + text2 + this.line.slice(this.cursor);
|
|
21936
22490
|
this.cursor += text2.length;
|
|
22491
|
+
this.refresh();
|
|
21937
22492
|
}
|
|
21938
22493
|
}
|
|
21939
22494
|
getCursorPos() {
|
|
21940
|
-
return { rows: 0, cols: this.cursor + this.
|
|
22495
|
+
return { rows: 0, cols: this.cursor + this.currentPrompt().length };
|
|
21941
22496
|
}
|
|
21942
22497
|
close() {
|
|
21943
22498
|
if (this.closed) return;
|
|
21944
22499
|
this.closed = true;
|
|
21945
22500
|
if (this.terminal) {
|
|
21946
22501
|
this.input?.off?.("keypress", this.onTerminalKeypress);
|
|
22502
|
+
if (this.ownsRawMode) {
|
|
22503
|
+
this.ownsRawMode = false;
|
|
22504
|
+
try {
|
|
22505
|
+
this.input?.setRawMode?.(false);
|
|
22506
|
+
} catch {
|
|
22507
|
+
}
|
|
22508
|
+
}
|
|
21947
22509
|
this.input?.pause?.();
|
|
21948
22510
|
}
|
|
21949
22511
|
for (const waiting of this.pending.splice(0)) waiting("");
|
|
21950
22512
|
this.emit("close");
|
|
21951
22513
|
}
|
|
22514
|
+
/** The text shown to the left of the edited line. */
|
|
22515
|
+
currentPrompt() {
|
|
22516
|
+
return this.questionPrompt ?? this.promptText;
|
|
22517
|
+
}
|
|
22518
|
+
/**
|
|
22519
|
+
* Repaint the edited line.
|
|
22520
|
+
*
|
|
22521
|
+
* In raw mode nothing echoes on its own, so an Interface that does not do
|
|
22522
|
+
* this leaves the user typing blind. Libraries that draw their own frame
|
|
22523
|
+
* (clack, inquirer) simply overwrite this, exactly as they do on Node.
|
|
22524
|
+
*/
|
|
22525
|
+
refresh() {
|
|
22526
|
+
if (!this.terminal) return;
|
|
22527
|
+
const prompt = this.currentPrompt();
|
|
22528
|
+
let text2 = `\r\x1B[0K${prompt}${this.line}`;
|
|
22529
|
+
const back = this.line.length - this.cursor;
|
|
22530
|
+
if (back > 0) text2 += `\x1B[${back}D`;
|
|
22531
|
+
this.output?.write?.(text2);
|
|
22532
|
+
}
|
|
21952
22533
|
edit(sequence, key) {
|
|
21953
22534
|
if (this.closed) return;
|
|
21954
22535
|
const name = key.name;
|
|
@@ -21956,48 +22537,62 @@ function createReadlineModule(defaultInput) {
|
|
|
21956
22537
|
const value = this.line;
|
|
21957
22538
|
this.line = "";
|
|
21958
22539
|
this.cursor = 0;
|
|
21959
|
-
this.
|
|
22540
|
+
this.output?.write?.("\r\n");
|
|
22541
|
+
this.deliver(value);
|
|
21960
22542
|
return;
|
|
21961
22543
|
}
|
|
21962
22544
|
if (name === "left") {
|
|
21963
22545
|
this.cursor = Math.max(0, this.cursor - 1);
|
|
22546
|
+
this.refresh();
|
|
21964
22547
|
return;
|
|
21965
22548
|
}
|
|
21966
22549
|
if (name === "right") {
|
|
21967
22550
|
this.cursor = Math.min(this.line.length, this.cursor + 1);
|
|
22551
|
+
this.refresh();
|
|
21968
22552
|
return;
|
|
21969
22553
|
}
|
|
21970
22554
|
if (name === "home" || key.ctrl && name === "a") {
|
|
21971
22555
|
this.cursor = 0;
|
|
22556
|
+
this.refresh();
|
|
21972
22557
|
return;
|
|
21973
22558
|
}
|
|
21974
22559
|
if (name === "end" || key.ctrl && name === "e") {
|
|
21975
22560
|
this.cursor = this.line.length;
|
|
22561
|
+
this.refresh();
|
|
21976
22562
|
return;
|
|
21977
22563
|
}
|
|
21978
22564
|
if (name === "backspace" || key.ctrl && name === "h") {
|
|
21979
22565
|
if (this.cursor > 0) {
|
|
21980
22566
|
this.line = this.line.slice(0, this.cursor - 1) + this.line.slice(this.cursor);
|
|
21981
22567
|
this.cursor--;
|
|
22568
|
+
this.refresh();
|
|
21982
22569
|
}
|
|
21983
22570
|
return;
|
|
21984
22571
|
}
|
|
21985
22572
|
if (name === "delete") {
|
|
21986
|
-
if (this.cursor < this.line.length)
|
|
22573
|
+
if (this.cursor < this.line.length) {
|
|
22574
|
+
this.line = this.line.slice(0, this.cursor) + this.line.slice(this.cursor + 1);
|
|
22575
|
+
this.refresh();
|
|
22576
|
+
}
|
|
21987
22577
|
return;
|
|
21988
22578
|
}
|
|
21989
22579
|
if (key.ctrl && name === "u") {
|
|
21990
22580
|
this.line = this.line.slice(this.cursor);
|
|
21991
22581
|
this.cursor = 0;
|
|
22582
|
+
this.refresh();
|
|
21992
22583
|
return;
|
|
21993
22584
|
}
|
|
21994
22585
|
if (key.ctrl && name === "k") {
|
|
21995
22586
|
this.line = this.line.slice(0, this.cursor);
|
|
22587
|
+
this.refresh();
|
|
21996
22588
|
return;
|
|
21997
22589
|
}
|
|
21998
22590
|
if (key.ctrl || key.meta || sequence.length !== 1 || sequence < " ") return;
|
|
22591
|
+
const atEnd = this.cursor === this.line.length;
|
|
21999
22592
|
this.line = this.line.slice(0, this.cursor) + sequence + this.line.slice(this.cursor);
|
|
22000
22593
|
this.cursor += sequence.length;
|
|
22594
|
+
if (atEnd) this.output?.write?.(sequence);
|
|
22595
|
+
else this.refresh();
|
|
22001
22596
|
}
|
|
22002
22597
|
async *[Symbol.asyncIterator]() {
|
|
22003
22598
|
while (!this.closed || this.lines.length) {
|
|
@@ -22027,13 +22622,23 @@ function createReadlineModule(defaultInput) {
|
|
|
22027
22622
|
}
|
|
22028
22623
|
}
|
|
22029
22624
|
}
|
|
22625
|
+
const isTerminal = (options, output) => {
|
|
22626
|
+
if (typeof options?.terminal === "boolean") return options.terminal;
|
|
22627
|
+
return Boolean(output?.isTTY);
|
|
22628
|
+
};
|
|
22030
22629
|
const createInterface = (options, output) => {
|
|
22031
22630
|
if (options && typeof options === "object" && !options.on) {
|
|
22032
|
-
const
|
|
22631
|
+
const resolvedOutput2 = options.output ?? defaultOutput();
|
|
22632
|
+
const instance = new Interface(
|
|
22633
|
+
options.input ?? defaultInput(),
|
|
22634
|
+
resolvedOutput2,
|
|
22635
|
+
isTerminal(options, resolvedOutput2)
|
|
22636
|
+
);
|
|
22033
22637
|
if (typeof options.prompt === "string") instance.setPrompt(options.prompt);
|
|
22034
22638
|
return instance;
|
|
22035
22639
|
}
|
|
22036
|
-
|
|
22640
|
+
const resolvedOutput = output ?? defaultOutput();
|
|
22641
|
+
return new Interface(options ?? defaultInput(), resolvedOutput, isTerminal(void 0, resolvedOutput));
|
|
22037
22642
|
};
|
|
22038
22643
|
const noop = () => {
|
|
22039
22644
|
};
|
|
@@ -22050,6 +22655,7 @@ function createReadlineModule(defaultInput) {
|
|
|
22050
22655
|
}
|
|
22051
22656
|
|
|
22052
22657
|
// src/runtime/core-modules.ts
|
|
22658
|
+
installReadableFrom(streamModule4__default.default);
|
|
22053
22659
|
var Dirent = class {
|
|
22054
22660
|
/** Node 20+ exposes the containing directory, and `fs.glob` consumers read it. */
|
|
22055
22661
|
constructor(name, stat2, parentPath = "") {
|
|
@@ -22255,9 +22861,20 @@ function createCoreModules(options) {
|
|
|
22255
22861
|
throw new Error("createRequire is only available inside a loaded module");
|
|
22256
22862
|
}
|
|
22257
22863
|
};
|
|
22258
|
-
|
|
22259
|
-
const
|
|
22260
|
-
|
|
22864
|
+
let inFlightRequests = 0;
|
|
22865
|
+
const httpOptions = {
|
|
22866
|
+
...options.http?.fetch ? { fetch: options.http.fetch } : {},
|
|
22867
|
+
trackRequest: () => {
|
|
22868
|
+
inFlightRequests++;
|
|
22869
|
+
return () => {
|
|
22870
|
+
inFlightRequests--;
|
|
22871
|
+
};
|
|
22872
|
+
}
|
|
22873
|
+
};
|
|
22874
|
+
const http = options.http ? createHttpModule(options.http.router, options.http.owner, httpOptions, "http:") : createUnsupportedModule("http");
|
|
22875
|
+
const https = options.http ? createHttpModule(options.http.router, options.http.owner, httpOptions, "https:") : createUnsupportedModule("https");
|
|
22876
|
+
const childProcess = options.spawnChild ? createChildProcessModule(options.spawnChild, () => cwd, options.syncSpawn) : createUnsupportedModule("child_process");
|
|
22877
|
+
const readline = createReadlineModule(() => processObject.stdin, () => processObject.stdout);
|
|
22261
22878
|
const dns = createDnsModule();
|
|
22262
22879
|
const builtins = {
|
|
22263
22880
|
assert: assert_module_default,
|
|
@@ -22275,7 +22892,7 @@ function createCoreModules(options) {
|
|
|
22275
22892
|
"fs/promises": fs.promises,
|
|
22276
22893
|
module: moduleBuiltin,
|
|
22277
22894
|
http,
|
|
22278
|
-
https
|
|
22895
|
+
https,
|
|
22279
22896
|
os,
|
|
22280
22897
|
path,
|
|
22281
22898
|
"path/posix": path,
|
|
@@ -22315,6 +22932,9 @@ function createCoreModules(options) {
|
|
|
22315
22932
|
process: processObject,
|
|
22316
22933
|
pendingHandles: timers.pending,
|
|
22317
22934
|
pendingUnrefed: timers.pendingUnrefed,
|
|
22935
|
+
/** Client requests sent but not yet read to completion. */
|
|
22936
|
+
pendingRequests: () => inFlightRequests,
|
|
22937
|
+
cancelTimers: timers.cancelAll,
|
|
22318
22938
|
writeStdin: (data) => {
|
|
22319
22939
|
if (options.interactiveStdin) stdin.write(data);
|
|
22320
22940
|
},
|
|
@@ -22542,9 +23162,20 @@ function createFsModule(volume, cwd, stdinPath) {
|
|
|
22542
23162
|
if (position == null) file3.position = start2 + chunk.length;
|
|
22543
23163
|
return chunk.length;
|
|
22544
23164
|
},
|
|
22545
|
-
createReadStream: (path) => {
|
|
22546
|
-
const
|
|
22547
|
-
|
|
23165
|
+
createReadStream: (path, options) => {
|
|
23166
|
+
const target = abs(path);
|
|
23167
|
+
const settings = typeof options === "string" ? { encoding: options } : options ?? {};
|
|
23168
|
+
const whole = Buffer2.from(volume.readFileSync(resolveLinks(volume, target)));
|
|
23169
|
+
const start2 = settings.start ?? 0;
|
|
23170
|
+
const end = settings.end === void 0 ? whole.length : Math.min(settings.end + 1, whole.length);
|
|
23171
|
+
const slice = whole.subarray(start2, Math.max(start2, end));
|
|
23172
|
+
const stream = streamModule4__default.default.Readable.from([settings.encoding ? slice.toString(settings.encoding) : slice]);
|
|
23173
|
+
Object.assign(stream, { path: target, bytesRead: slice.length, close: () => stream.destroy() });
|
|
23174
|
+
queueMicrotask(() => {
|
|
23175
|
+
stream.emit("open", 0);
|
|
23176
|
+
stream.emit("ready");
|
|
23177
|
+
});
|
|
23178
|
+
return stream;
|
|
22548
23179
|
},
|
|
22549
23180
|
createWriteStream: (path, options) => {
|
|
22550
23181
|
const target = abs(path);
|
|
@@ -22985,6 +23616,27 @@ function createTrackedTimers() {
|
|
|
22985
23616
|
live.delete(handle);
|
|
22986
23617
|
native(handle);
|
|
22987
23618
|
};
|
|
23619
|
+
const cancelAll = () => {
|
|
23620
|
+
for (const handle of [...live, ...unrefed]) {
|
|
23621
|
+
const state = states.get(handle);
|
|
23622
|
+
if (!state) continue;
|
|
23623
|
+
state.active = false;
|
|
23624
|
+
try {
|
|
23625
|
+
clearTimeout(state.native);
|
|
23626
|
+
} catch {
|
|
23627
|
+
}
|
|
23628
|
+
try {
|
|
23629
|
+
clearInterval(state.native);
|
|
23630
|
+
} catch {
|
|
23631
|
+
}
|
|
23632
|
+
try {
|
|
23633
|
+
(globalThis.clearImmediate ?? clearTimeout)(state.native);
|
|
23634
|
+
} catch {
|
|
23635
|
+
}
|
|
23636
|
+
}
|
|
23637
|
+
live.clear();
|
|
23638
|
+
unrefed.clear();
|
|
23639
|
+
};
|
|
22988
23640
|
return {
|
|
22989
23641
|
api: {
|
|
22990
23642
|
setTimeout: setTimeoutTracked,
|
|
@@ -22995,7 +23647,8 @@ function createTrackedTimers() {
|
|
|
22995
23647
|
clearImmediate: (handle) => clear2(handle, globalThis.clearImmediate ?? clearTimeout)
|
|
22996
23648
|
},
|
|
22997
23649
|
pending: () => live.size,
|
|
22998
|
-
pendingUnrefed: () => unrefed.size
|
|
23650
|
+
pendingUnrefed: () => unrefed.size,
|
|
23651
|
+
cancelAll
|
|
22999
23652
|
};
|
|
23000
23653
|
}
|
|
23001
23654
|
function createTimerPromises() {
|
|
@@ -23449,22 +24102,209 @@ var MemoryVolume = class {
|
|
|
23449
24102
|
}
|
|
23450
24103
|
};
|
|
23451
24104
|
|
|
23452
|
-
// src/runtime/
|
|
23453
|
-
|
|
23454
|
-
|
|
23455
|
-
|
|
23456
|
-
|
|
23457
|
-
|
|
23458
|
-
|
|
23459
|
-
|
|
23460
|
-
|
|
23461
|
-
|
|
23462
|
-
|
|
23463
|
-
|
|
23464
|
-
|
|
23465
|
-
|
|
23466
|
-
|
|
23467
|
-
|
|
24105
|
+
// src/runtime/mirroring-volume.ts
|
|
24106
|
+
init_path();
|
|
24107
|
+
var MirroringVolume = class {
|
|
24108
|
+
constructor(inner = new MemoryVolume()) {
|
|
24109
|
+
this.inner = inner;
|
|
24110
|
+
}
|
|
24111
|
+
inner;
|
|
24112
|
+
mirror;
|
|
24113
|
+
root = "/";
|
|
24114
|
+
/**
|
|
24115
|
+
* Start mirroring the tree under `root`, seeding it with what is there now.
|
|
24116
|
+
*
|
|
24117
|
+
* Called once the Rolldown binding is known to be in play; before that a
|
|
24118
|
+
* container pays nothing for this.
|
|
24119
|
+
*/
|
|
24120
|
+
attach(mirror, root) {
|
|
24121
|
+
this.mirror = mirror;
|
|
24122
|
+
this.root = clean(root);
|
|
24123
|
+
this.seed();
|
|
24124
|
+
}
|
|
24125
|
+
detach() {
|
|
24126
|
+
this.mirror = void 0;
|
|
24127
|
+
}
|
|
24128
|
+
/** Copy the whole subtree across. The only bulk operation that remains. */
|
|
24129
|
+
seed() {
|
|
24130
|
+
const mirror = this.mirror;
|
|
24131
|
+
if (!mirror) return;
|
|
24132
|
+
try {
|
|
24133
|
+
mirror.rmSync?.(this.root, { recursive: true, force: true });
|
|
24134
|
+
} catch {
|
|
24135
|
+
}
|
|
24136
|
+
const copy = (path) => {
|
|
24137
|
+
let stat2;
|
|
24138
|
+
try {
|
|
24139
|
+
stat2 = this.inner.lstatSync(path);
|
|
24140
|
+
} catch {
|
|
24141
|
+
return;
|
|
24142
|
+
}
|
|
24143
|
+
if (stat2.isDirectory()) {
|
|
24144
|
+
this.safely(() => mirror.mkdirSync(path, { recursive: true }));
|
|
24145
|
+
for (const name of this.inner.readdirSync(path)) copy(join(path, name));
|
|
24146
|
+
} else if (stat2.isSymbolicLink()) {
|
|
24147
|
+
this.safely(() => {
|
|
24148
|
+
mirror.mkdirSync(dirname(path), { recursive: true });
|
|
24149
|
+
mirror.symlinkSync(this.inner.readlinkSync(path), path);
|
|
24150
|
+
});
|
|
24151
|
+
} else if (!path.endsWith(".node")) {
|
|
24152
|
+
this.safely(() => {
|
|
24153
|
+
mirror.mkdirSync(dirname(path), { recursive: true });
|
|
24154
|
+
mirror.writeFileSync(path, this.inner.readFileSync(path));
|
|
24155
|
+
});
|
|
24156
|
+
}
|
|
24157
|
+
};
|
|
24158
|
+
copy(this.root);
|
|
24159
|
+
}
|
|
24160
|
+
/** Is this path inside the mirrored subtree? */
|
|
24161
|
+
mirrored(path) {
|
|
24162
|
+
if (!this.mirror) return false;
|
|
24163
|
+
const clean2 = clean(path);
|
|
24164
|
+
return this.root === "/" || clean2 === this.root || clean2.startsWith(`${this.root}/`);
|
|
24165
|
+
}
|
|
24166
|
+
/**
|
|
24167
|
+
* Run a mirror update, swallowing failure.
|
|
24168
|
+
*
|
|
24169
|
+
* The mirror is a read-only cache for another engine. If it rejects
|
|
24170
|
+
* something — an unsupported operation, a path it has not seen — the
|
|
24171
|
+
* container's own write has still happened and must still succeed.
|
|
24172
|
+
*/
|
|
24173
|
+
safely(update) {
|
|
24174
|
+
try {
|
|
24175
|
+
update();
|
|
24176
|
+
} catch {
|
|
24177
|
+
}
|
|
24178
|
+
}
|
|
24179
|
+
/** Push a path's current state across, whatever it is now. */
|
|
24180
|
+
sync(path) {
|
|
24181
|
+
const mirror = this.mirror;
|
|
24182
|
+
if (!mirror || !this.mirrored(path)) return;
|
|
24183
|
+
let stat2;
|
|
24184
|
+
try {
|
|
24185
|
+
stat2 = this.inner.lstatSync(path);
|
|
24186
|
+
} catch {
|
|
24187
|
+
this.safely(() => {
|
|
24188
|
+
if (mirror.rmSync) mirror.rmSync(path, { recursive: true, force: true });
|
|
24189
|
+
else mirror.unlinkSync?.(path);
|
|
24190
|
+
});
|
|
24191
|
+
return;
|
|
24192
|
+
}
|
|
24193
|
+
if (stat2.isDirectory()) {
|
|
24194
|
+
this.safely(() => mirror.mkdirSync(path, { recursive: true }));
|
|
24195
|
+
return;
|
|
24196
|
+
}
|
|
24197
|
+
if (stat2.isSymbolicLink()) {
|
|
24198
|
+
this.safely(() => {
|
|
24199
|
+
mirror.mkdirSync(dirname(path), { recursive: true });
|
|
24200
|
+
mirror.symlinkSync(this.inner.readlinkSync(path), path);
|
|
24201
|
+
});
|
|
24202
|
+
return;
|
|
24203
|
+
}
|
|
24204
|
+
if (path.endsWith(".node")) return;
|
|
24205
|
+
this.safely(() => {
|
|
24206
|
+
mirror.mkdirSync(dirname(path), { recursive: true });
|
|
24207
|
+
mirror.writeFileSync(path, this.inner.readFileSync(path));
|
|
24208
|
+
});
|
|
24209
|
+
}
|
|
24210
|
+
// ── reads: straight through ───────────────────────────────────────────────
|
|
24211
|
+
readFileSync(path) {
|
|
24212
|
+
return this.inner.readFileSync(path);
|
|
24213
|
+
}
|
|
24214
|
+
readdirSync(path) {
|
|
24215
|
+
return this.inner.readdirSync(path);
|
|
24216
|
+
}
|
|
24217
|
+
lstatSync(path) {
|
|
24218
|
+
return this.inner.lstatSync(path);
|
|
24219
|
+
}
|
|
24220
|
+
readlinkSync(path) {
|
|
24221
|
+
return this.inner.readlinkSync(path);
|
|
24222
|
+
}
|
|
24223
|
+
getStats() {
|
|
24224
|
+
return this.inner.getStats();
|
|
24225
|
+
}
|
|
24226
|
+
// ── writes: applied, then mirrored ────────────────────────────────────────
|
|
24227
|
+
writeFileSync(path, data) {
|
|
24228
|
+
this.inner.writeFileSync(path, data);
|
|
24229
|
+
this.sync(path);
|
|
24230
|
+
}
|
|
24231
|
+
appendFileSync(path, data) {
|
|
24232
|
+
this.inner.appendFileSync(path, data);
|
|
24233
|
+
this.sync(path);
|
|
24234
|
+
}
|
|
24235
|
+
mkdirSync(path, options) {
|
|
24236
|
+
this.inner.mkdirSync(path, options);
|
|
24237
|
+
this.sync(path);
|
|
24238
|
+
}
|
|
24239
|
+
rmdirSync(path) {
|
|
24240
|
+
this.inner.rmdirSync(path);
|
|
24241
|
+
this.sync(path);
|
|
24242
|
+
}
|
|
24243
|
+
unlinkSync(path) {
|
|
24244
|
+
this.inner.unlinkSync(path);
|
|
24245
|
+
this.sync(path);
|
|
24246
|
+
}
|
|
24247
|
+
renameSync(from, to) {
|
|
24248
|
+
this.inner.renameSync(from, to);
|
|
24249
|
+
this.sync(from);
|
|
24250
|
+
this.sync(to);
|
|
24251
|
+
}
|
|
24252
|
+
symlinkSync(target, path) {
|
|
24253
|
+
this.inner.symlinkSync(target, path);
|
|
24254
|
+
this.sync(path);
|
|
24255
|
+
}
|
|
24256
|
+
linkSync(existing, path) {
|
|
24257
|
+
this.inner.linkSync(existing, path);
|
|
24258
|
+
this.sync(path);
|
|
24259
|
+
}
|
|
24260
|
+
truncateSync(path, length) {
|
|
24261
|
+
this.inner.truncateSync(path, length);
|
|
24262
|
+
this.sync(path);
|
|
24263
|
+
}
|
|
24264
|
+
/* Permissions and timestamps do not change what a bundler resolves, and
|
|
24265
|
+
* `memfs` is stricter about them than this volume is. Applied here only. */
|
|
24266
|
+
chmodSync(path, mode) {
|
|
24267
|
+
this.inner.chmodSync(path, mode);
|
|
24268
|
+
}
|
|
24269
|
+
lchmodSync(path, mode) {
|
|
24270
|
+
this.inner.lchmodSync(path, mode);
|
|
24271
|
+
}
|
|
24272
|
+
chownSync(path, uid, gid) {
|
|
24273
|
+
this.inner.chownSync(path, uid, gid);
|
|
24274
|
+
}
|
|
24275
|
+
lchownSync(path, uid, gid) {
|
|
24276
|
+
this.inner.lchownSync(path, uid, gid);
|
|
24277
|
+
}
|
|
24278
|
+
utimesSync(path, atime, mtime) {
|
|
24279
|
+
this.inner.utimesSync(path, atime, mtime);
|
|
24280
|
+
}
|
|
24281
|
+
// ── snapshots ─────────────────────────────────────────────────────────────
|
|
24282
|
+
snapshot() {
|
|
24283
|
+
return this.inner.snapshot();
|
|
24284
|
+
}
|
|
24285
|
+
/** A restore replaces everything, so the mirror is rebuilt rather than patched. */
|
|
24286
|
+
restore(entries) {
|
|
24287
|
+
this.inner.restore(entries);
|
|
24288
|
+
this.seed();
|
|
24289
|
+
}
|
|
24290
|
+
};
|
|
24291
|
+
|
|
24292
|
+
// src/runtime/host-esbuild.ts
|
|
24293
|
+
var ASYNC_API = ["transform", "build", "context", "formatMessages", "analyzeMetafile"];
|
|
24294
|
+
function createHostEsbuild() {
|
|
24295
|
+
let loading = null;
|
|
24296
|
+
let started = null;
|
|
24297
|
+
const ensure = async () => {
|
|
24298
|
+
loading ??= start().then((api) => started = api);
|
|
24299
|
+
return loading;
|
|
24300
|
+
};
|
|
24301
|
+
const module = new Proxy({}, {
|
|
24302
|
+
get(_target, key) {
|
|
24303
|
+
if (typeof key !== "string") return void 0;
|
|
24304
|
+
if (ASYNC_API.includes(key)) {
|
|
24305
|
+
return async (...args) => {
|
|
24306
|
+
const api = await ensure();
|
|
24307
|
+
if (!api) throw esbuildUnavailable();
|
|
23468
24308
|
return api[key](...args);
|
|
23469
24309
|
};
|
|
23470
24310
|
}
|
|
@@ -23518,6 +24358,7 @@ function ensureProcessGlobal() {
|
|
|
23518
24358
|
}
|
|
23519
24359
|
|
|
23520
24360
|
// src/runtime/host-rolldown.ts
|
|
24361
|
+
var BUNDLER_HINT = "If this is a bundler pre-bundling the worker away, exclude the binding from dependency optimisation \u2014 in Vite:\n\n optimizeDeps: { exclude: ['@rolldown/binding-wasm32-wasi'] }";
|
|
23521
24362
|
async function loadHostRolldownBinding() {
|
|
23522
24363
|
if (typeof window !== "undefined" && globalThis.crossOriginIsolated !== true) {
|
|
23523
24364
|
throw new Error(
|
|
@@ -23531,7 +24372,13 @@ async function loadHostRolldownBinding() {
|
|
|
23531
24372
|
if (typeof process !== "undefined" && process.env?.SANDBOXEDJS_DEBUG) {
|
|
23532
24373
|
console.error("[sandboxedjs] Rolldown WASI binding unavailable:", error);
|
|
23533
24374
|
}
|
|
23534
|
-
|
|
24375
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
24376
|
+
throw new Error(
|
|
24377
|
+
`The optional Rolldown WASI binding could not be loaded: ${reason}` + (typeof window === "undefined" ? "" : `
|
|
24378
|
+
|
|
24379
|
+
${BUNDLER_HINT}`),
|
|
24380
|
+
{ cause: error }
|
|
24381
|
+
);
|
|
23535
24382
|
}
|
|
23536
24383
|
}
|
|
23537
24384
|
|
|
@@ -23571,6 +24418,7 @@ var LocalProcess = class extends EventEmitter4__default.default {
|
|
|
23571
24418
|
inputEnded = false;
|
|
23572
24419
|
pendingInput = [];
|
|
23573
24420
|
resolveKilled;
|
|
24421
|
+
cleanup;
|
|
23574
24422
|
killedPromise = new Promise((resolve2) => {
|
|
23575
24423
|
this.resolveKilled = resolve2;
|
|
23576
24424
|
});
|
|
@@ -23609,13 +24457,32 @@ var LocalProcess = class extends EventEmitter4__default.default {
|
|
|
23609
24457
|
for (const chunk of this.pendingInput.splice(0)) input(chunk);
|
|
23610
24458
|
if (this.inputEnded) end();
|
|
23611
24459
|
}
|
|
24460
|
+
/**
|
|
24461
|
+
* End the process now.
|
|
24462
|
+
*
|
|
24463
|
+
* Killing has to settle `completion`, not merely record the intent. A
|
|
24464
|
+
* program with an interval outstanding has work pending forever, so the
|
|
24465
|
+
* runtime's own idle check will never end it — before this, killing such a
|
|
24466
|
+
* process left the caller awaiting a promise that could not resolve.
|
|
24467
|
+
*/
|
|
23612
24468
|
kill(_signal = "SIGTERM") {
|
|
24469
|
+
if (this.killed) return;
|
|
23613
24470
|
this.killed = true;
|
|
23614
24471
|
this.resolveKilled();
|
|
24472
|
+
this.cleanup?.();
|
|
24473
|
+
this.finish(137);
|
|
23615
24474
|
}
|
|
23616
24475
|
waitForKill() {
|
|
23617
24476
|
return this.killedPromise;
|
|
23618
24477
|
}
|
|
24478
|
+
isKilled() {
|
|
24479
|
+
return this.killed;
|
|
24480
|
+
}
|
|
24481
|
+
/** Registered by the task so a kill can release what the program still holds. */
|
|
24482
|
+
onKill(cleanup) {
|
|
24483
|
+
this.cleanup = cleanup;
|
|
24484
|
+
if (this.killed) cleanup();
|
|
24485
|
+
}
|
|
23619
24486
|
/** End the process now, for an asynchronous `process.exit`. */
|
|
23620
24487
|
exitNow(code) {
|
|
23621
24488
|
this.finish(code);
|
|
@@ -23661,6 +24528,11 @@ var PodChildProcess = class {
|
|
|
23661
24528
|
started = false;
|
|
23662
24529
|
cancelled = false;
|
|
23663
24530
|
child;
|
|
24531
|
+
/* The child is launched asynchronously, but a parent may write and close
|
|
24532
|
+
* its input synchronously right after spawning. Holding both until the
|
|
24533
|
+
* child exists is what keeps `echo hi | child` from losing the `hi`. */
|
|
24534
|
+
pendingInput = "";
|
|
24535
|
+
inputEnded = false;
|
|
23664
24536
|
on(event, listener) {
|
|
23665
24537
|
let set = this.listeners.get(event);
|
|
23666
24538
|
if (!set) this.listeners.set(event, set = /* @__PURE__ */ new Set());
|
|
@@ -23683,6 +24555,11 @@ var PodChildProcess = class {
|
|
|
23683
24555
|
(child) => {
|
|
23684
24556
|
this.child = child;
|
|
23685
24557
|
if (this.cancelled) child.kill();
|
|
24558
|
+
if (this.pendingInput !== "") {
|
|
24559
|
+
child.write(this.pendingInput);
|
|
24560
|
+
this.pendingInput = "";
|
|
24561
|
+
}
|
|
24562
|
+
if (this.inputEnded) child.endInput?.();
|
|
23686
24563
|
child.on("output", (text2) => {
|
|
23687
24564
|
this.stdout += text2;
|
|
23688
24565
|
this.emit("stdout", text2);
|
|
@@ -23705,7 +24582,13 @@ var PodChildProcess = class {
|
|
|
23705
24582
|
});
|
|
23706
24583
|
}
|
|
23707
24584
|
sendStdin(data) {
|
|
23708
|
-
this.child
|
|
24585
|
+
if (this.child) this.child.write(data);
|
|
24586
|
+
else this.pendingInput += data;
|
|
24587
|
+
}
|
|
24588
|
+
/** Signal EOF, so a child reading stdin to the end can finish. */
|
|
24589
|
+
endStdin() {
|
|
24590
|
+
if (this.child) this.child.endInput?.();
|
|
24591
|
+
else this.inputEnded = true;
|
|
23709
24592
|
}
|
|
23710
24593
|
kill(signal = "SIGTERM") {
|
|
23711
24594
|
if (this.child) this.child.kill(signal);
|
|
@@ -23761,7 +24644,10 @@ function removeEscapedErrorReporting() {
|
|
|
23761
24644
|
}
|
|
23762
24645
|
var DRAIN_TURNS = 4;
|
|
23763
24646
|
var LocalRuntimePod = class _LocalRuntimePod {
|
|
23764
|
-
|
|
24647
|
+
/* Wrapped so that a foreign filesystem — Rolldown's WebAssembly memfs — can
|
|
24648
|
+
* be kept in step as writes happen, rather than deep-copied once per spawn.
|
|
24649
|
+
* With nothing attached this is a straight pass-through. */
|
|
24650
|
+
volume = new MirroringVolume(new MemoryVolume());
|
|
23765
24651
|
packages;
|
|
23766
24652
|
instanceId = `sbx-${Math.random().toString(36).slice(2)}`;
|
|
23767
24653
|
router = new VirtualHttpRouter();
|
|
@@ -23788,6 +24674,8 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23788
24674
|
modules;
|
|
23789
24675
|
esbuild;
|
|
23790
24676
|
rolldownBinding;
|
|
24677
|
+
/** Backs outbound `http`/`https` client requests from inside the sandbox. */
|
|
24678
|
+
fetch;
|
|
23791
24679
|
constructor(options) {
|
|
23792
24680
|
ensureProcessGlobal();
|
|
23793
24681
|
this.workdir = options.workdir ?? "/";
|
|
@@ -23802,6 +24690,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23802
24690
|
const notify = options.onServerReady;
|
|
23803
24691
|
this.router.onListen = (port) => notify(port, `http://localhost:${port}`);
|
|
23804
24692
|
}
|
|
24693
|
+
if (options.fetch) this.fetch = options.fetch;
|
|
23805
24694
|
this.packages = new CleanPackageInstaller(this.volume, {
|
|
23806
24695
|
cwd: this.workdir,
|
|
23807
24696
|
...options.registry ? { registry: options.registry } : {},
|
|
@@ -23841,7 +24730,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23841
24730
|
proc.exitNow(code);
|
|
23842
24731
|
if (engine?.isEvaluating) throw new ProcessExit(code);
|
|
23843
24732
|
},
|
|
23844
|
-
http: { router: this.router, owner },
|
|
24733
|
+
http: { router: this.router, owner, ...this.fetch ? { fetch: this.fetch } : {} },
|
|
23845
24734
|
spawnChild: (config) => this.processManager.spawn(config),
|
|
23846
24735
|
...typeof options.stdinPath === "string" ? { stdinPath: options.stdinPath } : {},
|
|
23847
24736
|
...options.interactiveStdin ? { interactiveStdin: true } : {},
|
|
@@ -23849,6 +24738,10 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23849
24738
|
onRawMode: (enabled) => proc.emit("rawmode", enabled)
|
|
23850
24739
|
});
|
|
23851
24740
|
proc.acceptInput((data) => core.writeStdin(data), () => core.endStdin());
|
|
24741
|
+
proc.onKill(() => {
|
|
24742
|
+
core.cancelTimers();
|
|
24743
|
+
this.router.closeOwner(owner);
|
|
24744
|
+
});
|
|
23852
24745
|
engine = new CommonJsEngine(this.volume, {
|
|
23853
24746
|
cwd,
|
|
23854
24747
|
builtins: core.builtins,
|
|
@@ -23858,7 +24751,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23858
24751
|
});
|
|
23859
24752
|
try {
|
|
23860
24753
|
await engine.run(script);
|
|
23861
|
-
await this.settle(owner, core.pendingHandles, core.pendingUnrefed, core.readingStdin);
|
|
24754
|
+
await this.settle(owner, core.pendingHandles, core.pendingUnrefed, core.readingStdin, core.pendingRequests, () => proc.isKilled());
|
|
23862
24755
|
if (this.router.activePorts(owner).length) {
|
|
23863
24756
|
await proc.waitForKill();
|
|
23864
24757
|
return 137;
|
|
@@ -23879,13 +24772,13 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23879
24772
|
*/
|
|
23880
24773
|
async prepareRolldown(cwd, env2) {
|
|
23881
24774
|
const specifier = "@rolldown/binding-wasm32-wasi";
|
|
23882
|
-
if (!this.modules[specifier] &&
|
|
24775
|
+
if (!this.modules[specifier] && packageIsInstalled(this.volume, cwd, "rolldown")) {
|
|
23883
24776
|
this.rolldownBinding ??= loadHostRolldownBinding();
|
|
23884
24777
|
const binding = await this.rolldownBinding;
|
|
23885
24778
|
if (binding) this.modules[specifier] = binding;
|
|
23886
24779
|
}
|
|
23887
24780
|
if (this.modules[specifier]) {
|
|
23888
|
-
|
|
24781
|
+
attachRolldownMirror(this.modules[specifier], this.volume, cwd);
|
|
23889
24782
|
env2.NAPI_RS_FORCE_WASI ??= "true";
|
|
23890
24783
|
}
|
|
23891
24784
|
}
|
|
@@ -23904,18 +24797,18 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
23904
24797
|
* A plain script that has genuinely finished falls straight through both,
|
|
23905
24798
|
* costing a handful of empty turns.
|
|
23906
24799
|
*/
|
|
23907
|
-
async settle(owner, pendingHandles, pendingUnrefed, readingStdin) {
|
|
24800
|
+
async settle(owner, pendingHandles, pendingUnrefed, readingStdin, pendingRequests, killed) {
|
|
23908
24801
|
for (let turn = 0; turn < DRAIN_TURNS; turn++) {
|
|
23909
|
-
if (this.router.activePorts(owner).length) return;
|
|
24802
|
+
if (this.router.activePorts(owner).length || killed()) return;
|
|
23910
24803
|
await new Promise((resolve2) => setTimeout(resolve2, 0));
|
|
23911
24804
|
}
|
|
23912
|
-
if (pendingHandles() === 0 && pendingUnrefed() > 0 && !readingStdin()) {
|
|
24805
|
+
if (pendingHandles() === 0 && pendingRequests() === 0 && pendingUnrefed() > 0 && !readingStdin()) {
|
|
23913
24806
|
const deadline = Date.now() + 1e3;
|
|
23914
|
-
while (!this.router.activePorts(owner).length && Date.now() < deadline) {
|
|
24807
|
+
while (!this.router.activePorts(owner).length && !killed() && Date.now() < deadline) {
|
|
23915
24808
|
await new Promise((resolve2) => setTimeout(resolve2, 5));
|
|
23916
24809
|
}
|
|
23917
24810
|
}
|
|
23918
|
-
while (!this.router.activePorts(owner).length && (pendingHandles() > 0 || readingStdin())) {
|
|
24811
|
+
while (!this.router.activePorts(owner).length && !killed() && (pendingHandles() > 0 || pendingRequests() > 0 || readingStdin())) {
|
|
23919
24812
|
await new Promise((resolve2) => setTimeout(resolve2, 5));
|
|
23920
24813
|
}
|
|
23921
24814
|
}
|
|
@@ -23967,7 +24860,7 @@ function formatError(error) {
|
|
|
23967
24860
|
function isRecord(value) {
|
|
23968
24861
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23969
24862
|
}
|
|
23970
|
-
function
|
|
24863
|
+
function packageIsInstalled(volume, cwd, wanted) {
|
|
23971
24864
|
for (let dir3 = clean(cwd); ; dir3 = dirname(dir3)) {
|
|
23972
24865
|
if (packageTreeContains(volume, join(dir3, "node_modules"), wanted, /* @__PURE__ */ new Set())) return true;
|
|
23973
24866
|
if (dir3 === "/") return false;
|
|
@@ -23996,30 +24889,565 @@ function directory(volume, path) {
|
|
|
23996
24889
|
return false;
|
|
23997
24890
|
}
|
|
23998
24891
|
}
|
|
23999
|
-
function
|
|
24892
|
+
function attachRolldownMirror(binding, volume, root) {
|
|
24000
24893
|
const fs = binding?.__fs;
|
|
24001
24894
|
if (!fs?.mkdirSync || !fs?.writeFileSync) return;
|
|
24002
|
-
|
|
24003
|
-
|
|
24004
|
-
|
|
24895
|
+
volume.attach(fs, root);
|
|
24896
|
+
}
|
|
24897
|
+
|
|
24898
|
+
// src/runtime/sync-channel.ts
|
|
24899
|
+
var STATE = 0;
|
|
24900
|
+
var LENGTH = 1;
|
|
24901
|
+
var MORE = 2;
|
|
24902
|
+
var CONTROL_WORDS = 4;
|
|
24903
|
+
var STATE_REQUEST = 1;
|
|
24904
|
+
var STATE_RESPONSE = 2;
|
|
24905
|
+
var STATE_CONTINUE = 3;
|
|
24906
|
+
var STATE_CLOSED = 4;
|
|
24907
|
+
function createSyncChannelBuffers(capacityBytes = 1 << 20) {
|
|
24908
|
+
return {
|
|
24909
|
+
control: new SharedArrayBuffer(CONTROL_WORDS * Int32Array.BYTES_PER_ELEMENT),
|
|
24910
|
+
data: new SharedArrayBuffer(capacityBytes)
|
|
24911
|
+
};
|
|
24912
|
+
}
|
|
24913
|
+
function syncChannelSupported() {
|
|
24914
|
+
if (typeof SharedArrayBuffer !== "function") return false;
|
|
24915
|
+
if (typeof Atomics !== "object" || typeof Atomics.wait !== "function") return false;
|
|
24916
|
+
if (typeof window !== "undefined" && globalThis.crossOriginIsolated !== true) return false;
|
|
24917
|
+
return true;
|
|
24918
|
+
}
|
|
24919
|
+
var SyncChannelServer = class {
|
|
24920
|
+
constructor(buffers, handle) {
|
|
24921
|
+
this.handle = handle;
|
|
24922
|
+
this.control = new Int32Array(buffers.control);
|
|
24923
|
+
this.data = new Uint8Array(buffers.data);
|
|
24924
|
+
this.capacity = this.data.length;
|
|
24005
24925
|
}
|
|
24006
|
-
|
|
24007
|
-
|
|
24008
|
-
|
|
24009
|
-
|
|
24010
|
-
|
|
24011
|
-
|
|
24012
|
-
|
|
24926
|
+
handle;
|
|
24927
|
+
control;
|
|
24928
|
+
data;
|
|
24929
|
+
capacity;
|
|
24930
|
+
/** Request chunks gathered so far, and the response still to be sent. */
|
|
24931
|
+
incoming = [];
|
|
24932
|
+
outgoing = null;
|
|
24933
|
+
sent = 0;
|
|
24934
|
+
closed = false;
|
|
24935
|
+
/** Call from the wake message the client sends after each chunk. */
|
|
24936
|
+
async pump() {
|
|
24937
|
+
if (this.closed) return;
|
|
24938
|
+
const state = Atomics.load(this.control, STATE);
|
|
24939
|
+
if (state === STATE_REQUEST) {
|
|
24940
|
+
const size = Atomics.load(this.control, LENGTH);
|
|
24941
|
+
this.incoming.push(this.data.slice(0, size));
|
|
24942
|
+
if (Atomics.load(this.control, MORE) === 1) {
|
|
24943
|
+
this.publish(STATE_CONTINUE);
|
|
24944
|
+
return;
|
|
24945
|
+
}
|
|
24946
|
+
const request = concat3(this.incoming);
|
|
24947
|
+
this.incoming = [];
|
|
24948
|
+
let response;
|
|
24013
24949
|
try {
|
|
24014
|
-
|
|
24950
|
+
response = await this.handle(request);
|
|
24015
24951
|
} catch {
|
|
24952
|
+
response = new Uint8Array();
|
|
24953
|
+
}
|
|
24954
|
+
if (this.closed) return;
|
|
24955
|
+
this.outgoing = response;
|
|
24956
|
+
this.sent = 0;
|
|
24957
|
+
this.sendChunk();
|
|
24958
|
+
return;
|
|
24959
|
+
}
|
|
24960
|
+
if (state === STATE_CONTINUE) this.sendChunk();
|
|
24961
|
+
}
|
|
24962
|
+
/** Release a blocked client, e.g. when the container is torn down. */
|
|
24963
|
+
close() {
|
|
24964
|
+
if (this.closed) return;
|
|
24965
|
+
this.closed = true;
|
|
24966
|
+
Atomics.store(this.control, STATE, STATE_CLOSED);
|
|
24967
|
+
Atomics.notify(this.control, STATE);
|
|
24968
|
+
}
|
|
24969
|
+
sendChunk() {
|
|
24970
|
+
const payload = this.outgoing ?? new Uint8Array();
|
|
24971
|
+
const size = Math.min(this.capacity, payload.length - this.sent);
|
|
24972
|
+
this.data.set(payload.subarray(this.sent, this.sent + size), 0);
|
|
24973
|
+
this.sent += size;
|
|
24974
|
+
Atomics.store(this.control, LENGTH, size);
|
|
24975
|
+
Atomics.store(this.control, MORE, this.sent < payload.length ? 1 : 0);
|
|
24976
|
+
this.publish(STATE_RESPONSE);
|
|
24977
|
+
}
|
|
24978
|
+
publish(state) {
|
|
24979
|
+
Atomics.store(this.control, STATE, state);
|
|
24980
|
+
Atomics.notify(this.control, STATE);
|
|
24981
|
+
}
|
|
24982
|
+
};
|
|
24983
|
+
function concat3(parts) {
|
|
24984
|
+
if (parts.length === 1) return parts[0];
|
|
24985
|
+
const total = parts.reduce((sum, part) => sum + part.length, 0);
|
|
24986
|
+
const joined = new Uint8Array(total);
|
|
24987
|
+
let at = 0;
|
|
24988
|
+
for (const part of parts) {
|
|
24989
|
+
joined.set(part, at);
|
|
24990
|
+
at += part.length;
|
|
24991
|
+
}
|
|
24992
|
+
return joined;
|
|
24993
|
+
}
|
|
24994
|
+
|
|
24995
|
+
// src/runtime/remote-volume.ts
|
|
24996
|
+
var encoder7 = new TextEncoder();
|
|
24997
|
+
var decoder7 = new TextDecoder();
|
|
24998
|
+
function encodeFrame(header, body) {
|
|
24999
|
+
const json = encoder7.encode(JSON.stringify(header));
|
|
25000
|
+
const frame = new Uint8Array(4 + json.length + (body?.length ?? 0));
|
|
25001
|
+
new DataView(frame.buffer).setUint32(0, json.length, true);
|
|
25002
|
+
frame.set(json, 4);
|
|
25003
|
+
if (body?.length) frame.set(body, 4 + json.length);
|
|
25004
|
+
return frame;
|
|
25005
|
+
}
|
|
25006
|
+
function decodeFrame(frame) {
|
|
25007
|
+
const view = new DataView(frame.buffer, frame.byteOffset, frame.byteLength);
|
|
25008
|
+
const headerLength = view.getUint32(0, true);
|
|
25009
|
+
const header = JSON.parse(decoder7.decode(frame.subarray(4, 4 + headerLength)));
|
|
25010
|
+
return { header, body: frame.subarray(4 + headerLength) };
|
|
25011
|
+
}
|
|
25012
|
+
function flattenStat(stat2) {
|
|
25013
|
+
return {
|
|
25014
|
+
kind: stat2.isDirectory() ? "directory" : stat2.isSymbolicLink() ? "symlink" : "file",
|
|
25015
|
+
mode: stat2.mode,
|
|
25016
|
+
size: stat2.size,
|
|
25017
|
+
uid: stat2.uid,
|
|
25018
|
+
gid: stat2.gid,
|
|
25019
|
+
ino: stat2.ino,
|
|
25020
|
+
nlink: stat2.nlink,
|
|
25021
|
+
atimeMs: stat2.atimeMs,
|
|
25022
|
+
mtimeMs: stat2.mtimeMs,
|
|
25023
|
+
ctimeMs: stat2.ctimeMs,
|
|
25024
|
+
birthtimeMs: stat2.birthtimeMs
|
|
25025
|
+
};
|
|
25026
|
+
}
|
|
25027
|
+
var BINARY_RESULTS = /* @__PURE__ */ new Set(["readFileSync"]);
|
|
25028
|
+
var BINARY_ARGUMENTS = /* @__PURE__ */ new Set(["writeFileSync", "appendFileSync"]);
|
|
25029
|
+
function serveVolume(volume) {
|
|
25030
|
+
return (request) => {
|
|
25031
|
+
const { header, body } = decodeFrame(request);
|
|
25032
|
+
const target = volume;
|
|
25033
|
+
try {
|
|
25034
|
+
const method = target[header.op];
|
|
25035
|
+
if (typeof method !== "function") {
|
|
25036
|
+
return encodeFrame({ ok: false, error: { message: `unknown volume operation: ${header.op}` } });
|
|
25037
|
+
}
|
|
25038
|
+
const plain = header.args.map((value) => value === null ? void 0 : value);
|
|
25039
|
+
const args = BINARY_ARGUMENTS.has(header.op) ? [plain[0], body] : header.op === "utimesSync" ? [plain[0], new Date(plain[1]), new Date(plain[2])] : plain;
|
|
25040
|
+
const result = method.apply(volume, args);
|
|
25041
|
+
if (BINARY_RESULTS.has(header.op)) {
|
|
25042
|
+
return encodeFrame({ ok: true }, result);
|
|
24016
25043
|
}
|
|
24017
|
-
|
|
24018
|
-
|
|
24019
|
-
|
|
25044
|
+
if (header.op === "lstatSync") {
|
|
25045
|
+
return encodeFrame({ ok: true, value: flattenStat(result) });
|
|
25046
|
+
}
|
|
25047
|
+
return encodeFrame({ ok: true, value: result });
|
|
25048
|
+
} catch (error) {
|
|
25049
|
+
const failure = error;
|
|
25050
|
+
return encodeFrame({
|
|
25051
|
+
ok: false,
|
|
25052
|
+
error: { ...failure.code ? { code: failure.code } : {}, message: failure.message ?? String(error) }
|
|
25053
|
+
});
|
|
24020
25054
|
}
|
|
24021
25055
|
};
|
|
24022
|
-
|
|
25056
|
+
}
|
|
25057
|
+
|
|
25058
|
+
// src/runtime/sync-syscalls.ts
|
|
25059
|
+
var SPAWN_OP = "spawnSync";
|
|
25060
|
+
function serveSyncSyscalls(options) {
|
|
25061
|
+
const volumeHandler = serveVolume(options.volume);
|
|
25062
|
+
return async (request) => {
|
|
25063
|
+
const { header } = decodeFrame(request);
|
|
25064
|
+
if (header.op !== SPAWN_OP) return volumeHandler(request);
|
|
25065
|
+
try {
|
|
25066
|
+
const result = await options.spawnChild(header.args[0]);
|
|
25067
|
+
return encodeFrame({ ok: true, value: result });
|
|
25068
|
+
} catch (error) {
|
|
25069
|
+
const failure = error;
|
|
25070
|
+
return encodeFrame({
|
|
25071
|
+
ok: true,
|
|
25072
|
+
value: {
|
|
25073
|
+
status: null,
|
|
25074
|
+
stdout: "",
|
|
25075
|
+
stderr: "",
|
|
25076
|
+
signal: null,
|
|
25077
|
+
error: { ...failure.code ? { code: failure.code } : {}, message: failure.message ?? String(error) }
|
|
25078
|
+
}
|
|
25079
|
+
});
|
|
25080
|
+
}
|
|
25081
|
+
};
|
|
25082
|
+
}
|
|
25083
|
+
|
|
25084
|
+
// src/runtime/worker-host.ts
|
|
25085
|
+
function defaultWorkerUrl() {
|
|
25086
|
+
return new URL("./worker-entry.js", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
25087
|
+
}
|
|
25088
|
+
function hasDomWorker() {
|
|
25089
|
+
return typeof Worker === "function" && typeof document !== "undefined";
|
|
25090
|
+
}
|
|
25091
|
+
async function startRuntimeWorker(options = {}) {
|
|
25092
|
+
const url = options.url ?? defaultWorkerUrl();
|
|
25093
|
+
const worker = hasDomWorker() ? await startDomWorker(url) : await startNodeWorker(url, options.workerData ?? {});
|
|
25094
|
+
await new Promise((resolve2, reject) => {
|
|
25095
|
+
const timer = setTimeout(() => reject(new Error("the runtime worker did not start in time")), options.timeoutMs ?? 1e4);
|
|
25096
|
+
worker.onMessage((message) => {
|
|
25097
|
+
if (message?.type === "sandboxedjs:ready") {
|
|
25098
|
+
clearTimeout(timer);
|
|
25099
|
+
resolve2();
|
|
25100
|
+
}
|
|
25101
|
+
});
|
|
25102
|
+
worker.onError((error) => {
|
|
25103
|
+
clearTimeout(timer);
|
|
25104
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
25105
|
+
});
|
|
25106
|
+
});
|
|
25107
|
+
return worker;
|
|
25108
|
+
}
|
|
25109
|
+
async function startDomWorker(url) {
|
|
25110
|
+
const worker = new Worker(url, { type: "module" });
|
|
25111
|
+
const listeners = [];
|
|
25112
|
+
const errors = [];
|
|
25113
|
+
worker.addEventListener("message", (event) => {
|
|
25114
|
+
for (const listener of listeners) listener(event.data);
|
|
25115
|
+
});
|
|
25116
|
+
worker.addEventListener("error", (event) => {
|
|
25117
|
+
const detail = event.message || "the runtime worker failed to load";
|
|
25118
|
+
for (const listener of errors) listener(new Error(detail));
|
|
25119
|
+
});
|
|
25120
|
+
return {
|
|
25121
|
+
postMessage: (message) => worker.postMessage(message),
|
|
25122
|
+
onMessage: (listener) => {
|
|
25123
|
+
listeners.push(listener);
|
|
25124
|
+
},
|
|
25125
|
+
onError: (listener) => {
|
|
25126
|
+
errors.push(listener);
|
|
25127
|
+
},
|
|
25128
|
+
terminate: () => worker.terminate()
|
|
25129
|
+
};
|
|
25130
|
+
}
|
|
25131
|
+
async function startNodeWorker(url, workerData) {
|
|
25132
|
+
const specifier = ["node", "worker_threads"].join(":");
|
|
25133
|
+
const { Worker: NodeWorker } = await import(
|
|
25134
|
+
/* @vite-ignore */
|
|
25135
|
+
/* webpackIgnore: true */
|
|
25136
|
+
specifier
|
|
25137
|
+
);
|
|
25138
|
+
const worker = new NodeWorker(url, { workerData });
|
|
25139
|
+
return {
|
|
25140
|
+
postMessage: (message) => worker.postMessage(message),
|
|
25141
|
+
onMessage: (listener) => worker.on("message", listener),
|
|
25142
|
+
onError: (listener) => worker.on("error", listener),
|
|
25143
|
+
terminate: () => worker.terminate()
|
|
25144
|
+
};
|
|
25145
|
+
}
|
|
25146
|
+
var WorkerProcess = class extends EventEmitter4__default.default {
|
|
25147
|
+
constructor(worker, release) {
|
|
25148
|
+
super();
|
|
25149
|
+
this.worker = worker;
|
|
25150
|
+
this.release = release;
|
|
25151
|
+
super.on("error", () => {
|
|
25152
|
+
});
|
|
25153
|
+
this.completion = new Promise((resolve2) => {
|
|
25154
|
+
this.resolveCompletion = resolve2;
|
|
25155
|
+
});
|
|
25156
|
+
}
|
|
25157
|
+
worker;
|
|
25158
|
+
release;
|
|
25159
|
+
completion;
|
|
25160
|
+
resolveCompletion;
|
|
25161
|
+
settled = false;
|
|
25162
|
+
out = [];
|
|
25163
|
+
err = [];
|
|
25164
|
+
started = false;
|
|
25165
|
+
pendingInput = [];
|
|
25166
|
+
inputEnded = false;
|
|
25167
|
+
on(event, listener) {
|
|
25168
|
+
return super.on(event, listener);
|
|
25169
|
+
}
|
|
25170
|
+
/** Called once the guest has been told to start; releases anything buffered. */
|
|
25171
|
+
begin() {
|
|
25172
|
+
this.started = true;
|
|
25173
|
+
for (const chunk of this.pendingInput.splice(0)) this.worker.postMessage({ type: "stdin", data: chunk });
|
|
25174
|
+
if (this.inputEnded) this.worker.postMessage({ type: "stdin-end" });
|
|
25175
|
+
}
|
|
25176
|
+
output(text2) {
|
|
25177
|
+
this.out.push(text2);
|
|
25178
|
+
this.emit("output", text2);
|
|
25179
|
+
}
|
|
25180
|
+
error(text2) {
|
|
25181
|
+
this.err.push(text2);
|
|
25182
|
+
this.emit("error", text2);
|
|
25183
|
+
}
|
|
25184
|
+
/**
|
|
25185
|
+
* Deliver input to the running program.
|
|
25186
|
+
*
|
|
25187
|
+
* Held until the guest has been started, for the same reason the in-realm
|
|
25188
|
+
* pod holds it: an interactive session's first keystrokes arrive while the
|
|
25189
|
+
* program is still loading, and dropping them loses the answer to a prompt.
|
|
25190
|
+
*/
|
|
25191
|
+
write(data) {
|
|
25192
|
+
if (this.started) this.worker.postMessage({ type: "stdin", data });
|
|
25193
|
+
else this.pendingInput.push(data);
|
|
25194
|
+
}
|
|
25195
|
+
endInput() {
|
|
25196
|
+
this.inputEnded = true;
|
|
25197
|
+
if (this.started) this.worker.postMessage({ type: "stdin-end" });
|
|
25198
|
+
}
|
|
25199
|
+
kill(_signal = "SIGTERM") {
|
|
25200
|
+
this.worker.postMessage({ type: "kill" });
|
|
25201
|
+
this.finish(137);
|
|
25202
|
+
}
|
|
25203
|
+
finish(exitCode) {
|
|
25204
|
+
if (this.settled) return;
|
|
25205
|
+
this.settled = true;
|
|
25206
|
+
this.emit("exit", exitCode);
|
|
25207
|
+
this.resolveCompletion({ exitCode, stdout: this.out.join(""), stderr: this.err.join("") });
|
|
25208
|
+
this.release();
|
|
25209
|
+
}
|
|
25210
|
+
};
|
|
25211
|
+
var WorkerRuntimePod = class _WorkerRuntimePod extends LocalRuntimePod {
|
|
25212
|
+
workerUrl;
|
|
25213
|
+
/** Live workers, so teardown can stop them all. */
|
|
25214
|
+
live = /* @__PURE__ */ new Set();
|
|
25215
|
+
constructor(options) {
|
|
25216
|
+
super(options);
|
|
25217
|
+
this.workerUrl = options.workerUrl;
|
|
25218
|
+
}
|
|
25219
|
+
/**
|
|
25220
|
+
* Boot a Worker-backed pod, or return null when this host cannot support one.
|
|
25221
|
+
*
|
|
25222
|
+
* Declining is a first-class outcome. `SharedArrayBuffer` needs cross-origin
|
|
25223
|
+
* isolation, a bundler may have made the guest script unreachable, and a host
|
|
25224
|
+
* that supplied its own module objects has handed over things no thread
|
|
25225
|
+
* boundary can carry. In every case the caller falls back to the in-realm pod
|
|
25226
|
+
* and keeps working.
|
|
25227
|
+
*/
|
|
25228
|
+
static async tryBoot(options = {}) {
|
|
25229
|
+
if (!syncChannelSupported()) return null;
|
|
25230
|
+
if (options.modules && Object.keys(options.modules).length > 0) return null;
|
|
25231
|
+
const pod = new _WorkerRuntimePod(options);
|
|
25232
|
+
try {
|
|
25233
|
+
const probe = await startRuntimeWorker({ ...options.workerUrl ? { url: options.workerUrl } : {}, timeoutMs: 1e4 });
|
|
25234
|
+
await probe.terminate();
|
|
25235
|
+
return pod;
|
|
25236
|
+
} catch {
|
|
25237
|
+
pod.teardown();
|
|
25238
|
+
return null;
|
|
25239
|
+
}
|
|
25240
|
+
}
|
|
25241
|
+
async spawn(command, args = [], options = {}) {
|
|
25242
|
+
if (command !== "node" && command !== "nodejs") return super.spawn(command, args, options);
|
|
25243
|
+
const script = args[0];
|
|
25244
|
+
if (!script) return super.spawn(command, args, options);
|
|
25245
|
+
const cwd = typeof options.cwd === "string" ? options.cwd : this.workdir;
|
|
25246
|
+
if (this.needsHostModules(cwd)) return super.spawn(command, args, options);
|
|
25247
|
+
return await this.spawnInWorker(script, args, cwd, options);
|
|
25248
|
+
}
|
|
25249
|
+
async spawnInWorker(script, args, cwd, options) {
|
|
25250
|
+
const env2 = { ...this.env, ...isRecord2(options.env) ? options.env : {} };
|
|
25251
|
+
const owner = `${this.instanceId}:${Math.random().toString(36).slice(2)}`;
|
|
25252
|
+
const buffers = createSyncChannelBuffers();
|
|
25253
|
+
const worker = await startRuntimeWorker({
|
|
25254
|
+
...this.workerUrl ? { url: this.workerUrl } : {},
|
|
25255
|
+
timeoutMs: 15e3
|
|
25256
|
+
});
|
|
25257
|
+
const server = new SyncChannelServer(buffers, serveSyncSyscalls({
|
|
25258
|
+
volume: this.volume,
|
|
25259
|
+
spawnChild: (request) => this.runChildToCompletion(request)
|
|
25260
|
+
}));
|
|
25261
|
+
const entry = { worker, server };
|
|
25262
|
+
this.live.add(entry);
|
|
25263
|
+
const process2 = new WorkerProcess(worker, () => {
|
|
25264
|
+
this.live.delete(entry);
|
|
25265
|
+
server.close();
|
|
25266
|
+
this.closeProxies(owner);
|
|
25267
|
+
void worker.terminate();
|
|
25268
|
+
});
|
|
25269
|
+
const children = /* @__PURE__ */ new Map();
|
|
25270
|
+
worker.onMessage((raw) => {
|
|
25271
|
+
const message = raw;
|
|
25272
|
+
switch (message?.type) {
|
|
25273
|
+
case "wake":
|
|
25274
|
+
void server.pump();
|
|
25275
|
+
return;
|
|
25276
|
+
case "output":
|
|
25277
|
+
process2.output(String(message.text));
|
|
25278
|
+
return;
|
|
25279
|
+
case "error":
|
|
25280
|
+
process2.error(String(message.text));
|
|
25281
|
+
return;
|
|
25282
|
+
case "rawmode":
|
|
25283
|
+
process2.emit("rawmode", Boolean(message.enabled));
|
|
25284
|
+
return;
|
|
25285
|
+
case "exit":
|
|
25286
|
+
process2.finish(Number(message.code));
|
|
25287
|
+
return;
|
|
25288
|
+
case "listen":
|
|
25289
|
+
this.proxyPort(Number(message.port), owner, worker);
|
|
25290
|
+
return;
|
|
25291
|
+
case "http-response":
|
|
25292
|
+
this.settleProxied(Number(message.id), message.response);
|
|
25293
|
+
return;
|
|
25294
|
+
case "child-start":
|
|
25295
|
+
this.startChild(worker, children, message);
|
|
25296
|
+
return;
|
|
25297
|
+
case "child-stdin":
|
|
25298
|
+
children.get(message.id)?.sendStdin?.(String(message.data));
|
|
25299
|
+
return;
|
|
25300
|
+
case "child-stdin-end":
|
|
25301
|
+
children.get(message.id)?.endStdin?.();
|
|
25302
|
+
return;
|
|
25303
|
+
case "child-kill":
|
|
25304
|
+
children.get(message.id)?.kill(String(message.signal));
|
|
25305
|
+
return;
|
|
25306
|
+
default:
|
|
25307
|
+
return;
|
|
25308
|
+
}
|
|
25309
|
+
});
|
|
25310
|
+
worker.postMessage({
|
|
25311
|
+
type: "start",
|
|
25312
|
+
buffers,
|
|
25313
|
+
script,
|
|
25314
|
+
cwd,
|
|
25315
|
+
env: env2,
|
|
25316
|
+
argv: Array.isArray(options.argv) ? options.argv : ["/usr/bin/node", script, ...args.slice(1)],
|
|
25317
|
+
aliases: this.aliases,
|
|
25318
|
+
...typeof options.stdinPath === "string" ? { stdinPath: options.stdinPath } : {},
|
|
25319
|
+
...options.interactiveStdin ? { interactiveStdin: true } : {},
|
|
25320
|
+
...options.tty ? { tty: true } : {}
|
|
25321
|
+
});
|
|
25322
|
+
process2.begin();
|
|
25323
|
+
return process2;
|
|
25324
|
+
}
|
|
25325
|
+
/** Start an asynchronous child on the host's behalf and relay its events. */
|
|
25326
|
+
startChild(worker, children, message) {
|
|
25327
|
+
const handle = this.processManager.spawn(message.config);
|
|
25328
|
+
children.set(message.id, handle);
|
|
25329
|
+
for (const event of ["stdout", "stderr", "exit"]) {
|
|
25330
|
+
handle.on(event, (value) => worker.postMessage({ type: "child-event", id: message.id, event, value }));
|
|
25331
|
+
}
|
|
25332
|
+
handle.exec();
|
|
25333
|
+
}
|
|
25334
|
+
/** Run a child to completion and collect it, for the guest's `spawnSync`. */
|
|
25335
|
+
runChildToCompletion(request) {
|
|
25336
|
+
return new Promise((resolve2) => {
|
|
25337
|
+
let handle;
|
|
25338
|
+
try {
|
|
25339
|
+
handle = this.processManager.spawn({
|
|
25340
|
+
command: request.command,
|
|
25341
|
+
args: request.args,
|
|
25342
|
+
cwd: request.cwd,
|
|
25343
|
+
...request.env ? { env: request.env } : {}
|
|
25344
|
+
});
|
|
25345
|
+
} catch (error) {
|
|
25346
|
+
const failure = error;
|
|
25347
|
+
resolve2({ status: null, stdout: "", stderr: "", signal: null, error: { ...failure.code ? { code: failure.code } : {}, message: failure.message } });
|
|
25348
|
+
return;
|
|
25349
|
+
}
|
|
25350
|
+
let stdout = "";
|
|
25351
|
+
let stderr = "";
|
|
25352
|
+
handle.on("stdout", (text2) => {
|
|
25353
|
+
stdout += text2;
|
|
25354
|
+
});
|
|
25355
|
+
handle.on("stderr", (text2) => {
|
|
25356
|
+
stderr += text2;
|
|
25357
|
+
});
|
|
25358
|
+
handle.on("exit", (code) => resolve2({ status: code, stdout, stderr, signal: null }));
|
|
25359
|
+
handle.exec();
|
|
25360
|
+
if (request.input !== void 0) {
|
|
25361
|
+
handle.sendStdin?.(request.input);
|
|
25362
|
+
}
|
|
25363
|
+
handle.endStdin?.();
|
|
25364
|
+
});
|
|
25365
|
+
}
|
|
25366
|
+
// ── HTTP servers living on another thread ─────────────────────────────────
|
|
25367
|
+
proxies = /* @__PURE__ */ new Map();
|
|
25368
|
+
waiting = /* @__PURE__ */ new Map();
|
|
25369
|
+
nextRequestId = 1;
|
|
25370
|
+
/**
|
|
25371
|
+
* Register a stand-in for a server that is actually running in the Worker.
|
|
25372
|
+
*
|
|
25373
|
+
* The router only knows how to reach servers on this thread, so each bound
|
|
25374
|
+
* port gets a local server whose whole job is to forward and wait.
|
|
25375
|
+
*/
|
|
25376
|
+
proxyPort(port, owner, worker) {
|
|
25377
|
+
if (this.proxies.has(port)) return;
|
|
25378
|
+
const server = new VirtualHttpServer(this.router, owner, (request, response) => {
|
|
25379
|
+
void this.forward(worker, port, request, response);
|
|
25380
|
+
});
|
|
25381
|
+
try {
|
|
25382
|
+
server.listen(port);
|
|
25383
|
+
this.proxies.set(port, server);
|
|
25384
|
+
} catch {
|
|
25385
|
+
}
|
|
25386
|
+
}
|
|
25387
|
+
async forward(worker, port, request, response) {
|
|
25388
|
+
const chunks = [];
|
|
25389
|
+
for await (const chunk of request) chunks.push(chunk);
|
|
25390
|
+
const body = concat4(chunks);
|
|
25391
|
+
const id = this.nextRequestId++;
|
|
25392
|
+
const answered = new Promise((resolve2) => this.waiting.set(id, resolve2));
|
|
25393
|
+
worker.postMessage({
|
|
25394
|
+
type: "http-request",
|
|
25395
|
+
id,
|
|
25396
|
+
port,
|
|
25397
|
+
init: { method: request.method, path: request.url, headers: request.headers, body }
|
|
25398
|
+
});
|
|
25399
|
+
let result;
|
|
25400
|
+
try {
|
|
25401
|
+
result = await answered;
|
|
25402
|
+
} catch (error) {
|
|
25403
|
+
this.waiting.delete(id);
|
|
25404
|
+
response.writeHead(500, "Internal Server Error", {});
|
|
25405
|
+
response.end(new TextEncoder().encode(error instanceof Error ? error.message : String(error)));
|
|
25406
|
+
return;
|
|
25407
|
+
}
|
|
25408
|
+
response.writeHead(Number(result.statusCode ?? 200), String(result.statusMessage ?? ""), result.headers ?? {});
|
|
25409
|
+
response.end(result.body ?? new Uint8Array());
|
|
25410
|
+
}
|
|
25411
|
+
settleProxied(id, response) {
|
|
25412
|
+
const resolve2 = this.waiting.get(id);
|
|
25413
|
+
if (!resolve2) return;
|
|
25414
|
+
this.waiting.delete(id);
|
|
25415
|
+
resolve2(response);
|
|
25416
|
+
}
|
|
25417
|
+
closeProxies(owner) {
|
|
25418
|
+
for (const [port, server] of [...this.proxies]) {
|
|
25419
|
+
if (server.owner !== owner) continue;
|
|
25420
|
+
server.close();
|
|
25421
|
+
this.proxies.delete(port);
|
|
25422
|
+
}
|
|
25423
|
+
}
|
|
25424
|
+
teardown() {
|
|
25425
|
+
for (const { worker, server } of [...this.live]) {
|
|
25426
|
+
server.close();
|
|
25427
|
+
void worker.terminate();
|
|
25428
|
+
}
|
|
25429
|
+
this.live.clear();
|
|
25430
|
+
super.teardown();
|
|
25431
|
+
}
|
|
25432
|
+
/** Does anything under `cwd` need a module only the host can supply? */
|
|
25433
|
+
needsHostModules(cwd) {
|
|
25434
|
+
return packageIsInstalled(this.volume, cwd, "rolldown");
|
|
25435
|
+
}
|
|
25436
|
+
};
|
|
25437
|
+
function isRecord2(value) {
|
|
25438
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25439
|
+
}
|
|
25440
|
+
function concat4(parts) {
|
|
25441
|
+
if (parts.length === 0) return new Uint8Array();
|
|
25442
|
+
if (parts.length === 1) return parts[0];
|
|
25443
|
+
const total = parts.reduce((sum, part) => sum + part.length, 0);
|
|
25444
|
+
const joined = new Uint8Array(total);
|
|
25445
|
+
let at = 0;
|
|
25446
|
+
for (const part of parts) {
|
|
25447
|
+
joined.set(part, at);
|
|
25448
|
+
at += part.length;
|
|
25449
|
+
}
|
|
25450
|
+
return joined;
|
|
24023
25451
|
}
|
|
24024
25452
|
|
|
24025
25453
|
// src/container/container.ts
|
|
@@ -24066,11 +25494,13 @@ var Container = class _Container {
|
|
|
24066
25494
|
// ── boot ──────────────────────────────────────────────────────────────────
|
|
24067
25495
|
static async create(opts = {}) {
|
|
24068
25496
|
if (opts.python) configurePython(opts.python);
|
|
24069
|
-
const
|
|
25497
|
+
const podOptions = {
|
|
24070
25498
|
workdir: opts.cwd ?? "/",
|
|
24071
25499
|
env: opts.env ?? {},
|
|
24072
25500
|
...opts.onServerReady ? { onServerReady: opts.onServerReady } : {}
|
|
24073
|
-
}
|
|
25501
|
+
};
|
|
25502
|
+
const workerOptions = { ...podOptions, ...opts.workerUrl ? { workerUrl: opts.workerUrl } : {} };
|
|
25503
|
+
const pod = opts.pod ?? (opts.isolation === "realm" ? null : await WorkerRuntimePod.tryBoot(workerOptions)) ?? await LocalRuntimePod.boot(podOptions);
|
|
24074
25504
|
const kernel = new Kernel({
|
|
24075
25505
|
pod,
|
|
24076
25506
|
hostname: opts.hostname ?? "sandbox",
|
|
@@ -24312,15 +25742,15 @@ var Container = class _Container {
|
|
|
24312
25742
|
}
|
|
24313
25743
|
makeStdio(opts) {
|
|
24314
25744
|
const combined = [];
|
|
24315
|
-
const
|
|
25745
|
+
const decoder8 = new TextDecoder();
|
|
24316
25746
|
const stdout = new BufferSink((chunk) => {
|
|
24317
|
-
const text2 =
|
|
25747
|
+
const text2 = decoder8.decode(chunk, { stream: true });
|
|
24318
25748
|
combined.push(text2);
|
|
24319
25749
|
opts.onStdout?.(text2);
|
|
24320
25750
|
this.hooks.onStdout?.(text2);
|
|
24321
25751
|
});
|
|
24322
25752
|
const stderr = new BufferSink((chunk) => {
|
|
24323
|
-
const text2 =
|
|
25753
|
+
const text2 = decoder8.decode(chunk, { stream: true });
|
|
24324
25754
|
combined.push(text2);
|
|
24325
25755
|
opts.onStderr?.(text2);
|
|
24326
25756
|
this.hooks.onStderr?.(text2);
|
|
@@ -24576,17 +26006,18 @@ var Terminal = class {
|
|
|
24576
26006
|
// ── key handling ──────────────────────────────────────────────────────────
|
|
24577
26007
|
key(ch) {
|
|
24578
26008
|
if (this.running) {
|
|
24579
|
-
|
|
26009
|
+
const raw = this.currentStdin?.rawMode === true;
|
|
26010
|
+
if (ch === CTRL_C && !raw) {
|
|
24580
26011
|
this.session.proc.deliver("SIGINT");
|
|
24581
26012
|
this.write("^C\r\n");
|
|
24582
26013
|
return;
|
|
24583
26014
|
}
|
|
24584
|
-
if (ch === CTRL_D) {
|
|
26015
|
+
if (ch === CTRL_D && !raw) {
|
|
24585
26016
|
this.currentStdin?.end();
|
|
24586
26017
|
return;
|
|
24587
26018
|
}
|
|
24588
|
-
if (!
|
|
24589
|
-
this.currentStdin?.write(ch === "\r" ? "\n" : ch);
|
|
26019
|
+
if (!raw) this.write(ch === "\r" ? "\r\n" : ch);
|
|
26020
|
+
this.currentStdin?.write(!raw && ch === "\r" ? "\n" : ch);
|
|
24590
26021
|
return;
|
|
24591
26022
|
}
|
|
24592
26023
|
if (this.escapeBuffer !== "") {
|
|
@@ -25013,7 +26444,9 @@ exports.parseUmask = parseUmask;
|
|
|
25013
26444
|
exports.posixPath = path_exports;
|
|
25014
26445
|
exports.resetPidCounter = resetPidCounter;
|
|
25015
26446
|
exports.shellQuote = shellQuote;
|
|
26447
|
+
exports.startRuntimeWorker = startRuntimeWorker;
|
|
25016
26448
|
exports.strerror = strerror;
|
|
26449
|
+
exports.syncChannelSupported = syncChannelSupported;
|
|
25017
26450
|
exports.transformEsm = transformEsm;
|
|
25018
26451
|
exports.unameInfo = unameInfo;
|
|
25019
26452
|
//# sourceMappingURL=index.cjs.map
|