sandboxedjs 0.1.73 → 0.1.74
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 +25 -2
- package/dist/agent.d.cts +2 -2
- package/dist/agent.d.ts +2 -2
- package/dist/{container-B5X6stfx.d.ts → container-CsLNpeyi.d.ts} +18 -3
- package/dist/{container-BxEoVOmX.d.cts → container-DAWPIkGG.d.cts} +18 -3
- package/dist/{contracts-CVgctitO.d.cts → contracts-C2_dTgk3.d.cts} +30 -1
- package/dist/{contracts-CVgctitO.d.ts → contracts-C2_dTgk3.d.ts} +30 -1
- package/dist/index.cjs +2425 -1235
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -5
- package/dist/index.d.ts +57 -5
- package/dist/index.js +2426 -1236
- package/dist/index.js.map +1 -1
- package/dist/{memory-volume-CWuWScIs.d.ts → memory-volume-CG56p660.d.ts} +1 -1
- package/dist/{memory-volume-DlMSAh-K.d.cts → memory-volume-DqEWFo7t.d.cts} +1 -1
- package/dist/python-abi.d.cts +3 -3
- package/dist/python-abi.d.ts +3 -3
- package/dist/rolldown-wasi-worker.js +5 -1
- package/dist/rolldown-wasi-worker.js.map +1 -1
- package/dist/worker-entry.js +861 -55
- package/dist/worker-entry.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var pako = require('pako');
|
|
6
|
+
var acorn = require('acorn');
|
|
7
|
+
var jsx = require('acorn-jsx');
|
|
6
8
|
var sha256 = require('@noble/hashes/sha256');
|
|
7
9
|
var index_js = require('buffer/index.js');
|
|
8
10
|
var sha512 = require('@noble/hashes/sha512');
|
|
9
11
|
var sha1 = require('@noble/hashes/sha1');
|
|
10
12
|
var semver = require('semver');
|
|
11
|
-
var acorn = require('acorn');
|
|
12
13
|
var EventEmitter4 = require('events/events.js');
|
|
13
|
-
var jsx = require('acorn-jsx');
|
|
14
14
|
var resolve_exports = require('resolve.exports');
|
|
15
15
|
var pathModule = require('path-browserify');
|
|
16
16
|
var streamModule4 = require('stream-browserify');
|
|
@@ -25,8 +25,8 @@ var hmac = require('@noble/hashes/hmac');
|
|
|
25
25
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
26
26
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
27
27
|
|
|
28
|
-
var EventEmitter4__default = /*#__PURE__*/_interopDefault(EventEmitter4);
|
|
29
28
|
var jsx__default = /*#__PURE__*/_interopDefault(jsx);
|
|
29
|
+
var EventEmitter4__default = /*#__PURE__*/_interopDefault(EventEmitter4);
|
|
30
30
|
var pathModule__default = /*#__PURE__*/_interopDefault(pathModule);
|
|
31
31
|
var streamModule4__default = /*#__PURE__*/_interopDefault(streamModule4);
|
|
32
32
|
var processShim__default = /*#__PURE__*/_interopDefault(processShim);
|
|
@@ -3824,7 +3824,10 @@ function builtinKill({ shell, argv, io }) {
|
|
|
3824
3824
|
for (const target of args.slice(i)) {
|
|
3825
3825
|
if (target.startsWith("%")) {
|
|
3826
3826
|
const job = shell.jobs.find((j) => j.id === Number(target.slice(1)));
|
|
3827
|
-
if (job)
|
|
3827
|
+
if (job) {
|
|
3828
|
+
if (job.state !== "done") shell.kernel.procs.signal(job.pgid, signal);
|
|
3829
|
+
continue;
|
|
3830
|
+
}
|
|
3828
3831
|
io.stderr.write(`kill: ${target}: no such job
|
|
3829
3832
|
`);
|
|
3830
3833
|
status = 1;
|
|
@@ -5420,6 +5423,51 @@ var BufferSink = class {
|
|
|
5420
5423
|
this.total = 0;
|
|
5421
5424
|
}
|
|
5422
5425
|
};
|
|
5426
|
+
var DetachableOutput = class {
|
|
5427
|
+
constructor(inner, onDetached) {
|
|
5428
|
+
this.inner = inner;
|
|
5429
|
+
this.onDetached = onDetached;
|
|
5430
|
+
}
|
|
5431
|
+
inner;
|
|
5432
|
+
onDetached;
|
|
5433
|
+
attached = true;
|
|
5434
|
+
decoder = new TextDecoder();
|
|
5435
|
+
get closed() {
|
|
5436
|
+
return this.attached ? this.inner.closed : false;
|
|
5437
|
+
}
|
|
5438
|
+
get isTTY() {
|
|
5439
|
+
return this.inner.isTTY;
|
|
5440
|
+
}
|
|
5441
|
+
set isTTY(value) {
|
|
5442
|
+
this.inner.isTTY = value;
|
|
5443
|
+
}
|
|
5444
|
+
get columns() {
|
|
5445
|
+
return this.inner.columns;
|
|
5446
|
+
}
|
|
5447
|
+
set columns(value) {
|
|
5448
|
+
this.inner.columns = value;
|
|
5449
|
+
}
|
|
5450
|
+
get rows() {
|
|
5451
|
+
return this.inner.rows;
|
|
5452
|
+
}
|
|
5453
|
+
set rows(value) {
|
|
5454
|
+
this.inner.rows = value;
|
|
5455
|
+
}
|
|
5456
|
+
write(data) {
|
|
5457
|
+
if (this.attached) {
|
|
5458
|
+
this.inner.write(data);
|
|
5459
|
+
return;
|
|
5460
|
+
}
|
|
5461
|
+
if (!this.onDetached) return;
|
|
5462
|
+
this.onDetached(typeof data === "string" ? data : this.decoder.decode(data, { stream: true }));
|
|
5463
|
+
}
|
|
5464
|
+
end() {
|
|
5465
|
+
if (this.attached) this.inner.end();
|
|
5466
|
+
}
|
|
5467
|
+
detach() {
|
|
5468
|
+
this.attached = false;
|
|
5469
|
+
}
|
|
5470
|
+
};
|
|
5423
5471
|
var CallbackSink = class {
|
|
5424
5472
|
constructor(sink, opts = {}) {
|
|
5425
5473
|
this.sink = sink;
|
|
@@ -7282,6 +7330,77 @@ function createSysProvider(kernel) {
|
|
|
7282
7330
|
};
|
|
7283
7331
|
}
|
|
7284
7332
|
|
|
7333
|
+
// src/net/policy.ts
|
|
7334
|
+
function isLoopbackHostname(hostname) {
|
|
7335
|
+
const host2 = hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
7336
|
+
return host2 === "localhost" || host2 === "0.0.0.0" || host2 === "::1" || host2 === "::" || host2.startsWith("127.") || host2.endsWith(".localhost");
|
|
7337
|
+
}
|
|
7338
|
+
function outboundAllowed(policy, url) {
|
|
7339
|
+
if (!policy.allowOutbound) return false;
|
|
7340
|
+
let hostname;
|
|
7341
|
+
try {
|
|
7342
|
+
hostname = new URL(url).hostname;
|
|
7343
|
+
} catch {
|
|
7344
|
+
return false;
|
|
7345
|
+
}
|
|
7346
|
+
if (isLoopbackHostname(hostname)) return false;
|
|
7347
|
+
const hosts = policy.allowedHosts;
|
|
7348
|
+
if (!hosts) return true;
|
|
7349
|
+
return hosts.some((allowed) => hostname === allowed || hostname.endsWith(`.${allowed}`));
|
|
7350
|
+
}
|
|
7351
|
+
function outboundBlockedError(url) {
|
|
7352
|
+
let host2 = url;
|
|
7353
|
+
try {
|
|
7354
|
+
host2 = new URL(url).host;
|
|
7355
|
+
} catch {
|
|
7356
|
+
}
|
|
7357
|
+
return Object.assign(
|
|
7358
|
+
new Error(
|
|
7359
|
+
`connect ENETUNREACH ${host2}: outbound network access is disabled for this container (allowed by the host with network.allowOutbound and network.allowedHosts)`
|
|
7360
|
+
),
|
|
7361
|
+
{ code: "ENETUNREACH", errno: -101, syscall: "connect", hostname: host2 }
|
|
7362
|
+
);
|
|
7363
|
+
}
|
|
7364
|
+
function requestUrl(input) {
|
|
7365
|
+
if (typeof input === "string") return input;
|
|
7366
|
+
if (input instanceof URL) return input.href;
|
|
7367
|
+
return input.url;
|
|
7368
|
+
}
|
|
7369
|
+
function policedFetch(policy, fetchImpl) {
|
|
7370
|
+
return (async (input, init) => {
|
|
7371
|
+
const url = requestUrl(input);
|
|
7372
|
+
if (!outboundAllowed(policy, url)) {
|
|
7373
|
+
throw Object.assign(new TypeError("fetch failed"), { cause: outboundBlockedError(url) });
|
|
7374
|
+
}
|
|
7375
|
+
return fetchImpl(input, init);
|
|
7376
|
+
});
|
|
7377
|
+
}
|
|
7378
|
+
function policedWebSocket(Native, policy) {
|
|
7379
|
+
const Base = Native;
|
|
7380
|
+
return class PolicedWebSocket extends Base {
|
|
7381
|
+
constructor(url, protocols) {
|
|
7382
|
+
const href = url instanceof URL ? url.href : String(url);
|
|
7383
|
+
let parsed = null;
|
|
7384
|
+
try {
|
|
7385
|
+
parsed = new URL(href);
|
|
7386
|
+
} catch {
|
|
7387
|
+
}
|
|
7388
|
+
if (parsed && isLoopbackHostname(parsed.hostname)) {
|
|
7389
|
+
throw Object.assign(
|
|
7390
|
+
new Error(
|
|
7391
|
+
`WebSocket to ${parsed.host} is not available from a program inside the container; reach servers in the container over HTTP`
|
|
7392
|
+
),
|
|
7393
|
+
{ code: "ERR_UNSUPPORTED" }
|
|
7394
|
+
);
|
|
7395
|
+
}
|
|
7396
|
+
if (parsed && !outboundAllowed(policy, href.replace(/^ws(s?):/i, "http$1:"))) {
|
|
7397
|
+
throw outboundBlockedError(href);
|
|
7398
|
+
}
|
|
7399
|
+
super(url, protocols);
|
|
7400
|
+
}
|
|
7401
|
+
};
|
|
7402
|
+
}
|
|
7403
|
+
|
|
7285
7404
|
// src/net/stack.ts
|
|
7286
7405
|
var NetworkStack = class {
|
|
7287
7406
|
constructor(pod, vfs, options = {}) {
|
|
@@ -7420,16 +7539,12 @@ var NetworkStack = class {
|
|
|
7420
7539
|
return false;
|
|
7421
7540
|
}
|
|
7422
7541
|
// ── outbound policy ──────────────────────────────────────────────────────
|
|
7542
|
+
/** The policy every way out of the container applies, not only the shell's. */
|
|
7543
|
+
get policy() {
|
|
7544
|
+
return { allowOutbound: this.options.allowOutbound, allowedHosts: this.options.allowedHosts ?? null };
|
|
7545
|
+
}
|
|
7423
7546
|
outboundAllowed(url) {
|
|
7424
|
-
|
|
7425
|
-
const hosts = this.options.allowedHosts;
|
|
7426
|
-
if (hosts === null || hosts === void 0) return true;
|
|
7427
|
-
try {
|
|
7428
|
-
const { hostname } = new URL(url);
|
|
7429
|
-
return hosts.some((h) => hostname === h || hostname.endsWith("." + h));
|
|
7430
|
-
} catch {
|
|
7431
|
-
return false;
|
|
7432
|
-
}
|
|
7547
|
+
return outboundAllowed(this.policy, url);
|
|
7433
7548
|
}
|
|
7434
7549
|
// ── /proc plumbing ───────────────────────────────────────────────────────
|
|
7435
7550
|
procNetDev() {
|
|
@@ -8577,11 +8692,16 @@ var Shell = class _Shell {
|
|
|
8577
8692
|
}
|
|
8578
8693
|
return path;
|
|
8579
8694
|
}
|
|
8580
|
-
/**
|
|
8581
|
-
|
|
8695
|
+
/**
|
|
8696
|
+
* A copy that shares nothing mutable with this shell.
|
|
8697
|
+
*
|
|
8698
|
+
* Subshells and pipeline stages run as part of this shell's process. A
|
|
8699
|
+
* background job passes a process of its own, the way fork(2) gives one.
|
|
8700
|
+
*/
|
|
8701
|
+
fork(proc = this.proc) {
|
|
8582
8702
|
const sub = new _Shell({
|
|
8583
8703
|
kernel: this.kernel,
|
|
8584
|
-
proc
|
|
8704
|
+
proc,
|
|
8585
8705
|
cwd: this.cwd,
|
|
8586
8706
|
cred: this.cred,
|
|
8587
8707
|
env: {},
|
|
@@ -8736,29 +8856,42 @@ sys ${fmt2(Math.floor(ms * 0.2))}
|
|
|
8736
8856
|
`);
|
|
8737
8857
|
}
|
|
8738
8858
|
startBackgroundJob(node2, io) {
|
|
8739
|
-
const
|
|
8859
|
+
const jobProc = this.kernel.procs.create({
|
|
8860
|
+
argv: [this.scriptName],
|
|
8861
|
+
cwd: this.cwd,
|
|
8862
|
+
env: this.vars.environment(),
|
|
8863
|
+
cred: this.cred,
|
|
8864
|
+
ppid: this.proc.pid,
|
|
8865
|
+
kind: "shell",
|
|
8866
|
+
tty: this.proc.tty,
|
|
8867
|
+
stdio: { stdin: new NullInput(), stdout: io.stdout, stderr: io.stderr }
|
|
8868
|
+
});
|
|
8869
|
+
const sub = this.fork(jobProc);
|
|
8740
8870
|
const id = this.nextJobId++;
|
|
8741
8871
|
const command = describeNode(node2);
|
|
8742
8872
|
const job = {
|
|
8743
8873
|
id,
|
|
8744
|
-
pgid:
|
|
8874
|
+
pgid: jobProc.pid,
|
|
8745
8875
|
command,
|
|
8746
8876
|
state: "running",
|
|
8747
8877
|
exitCode: null,
|
|
8748
|
-
pids: [],
|
|
8878
|
+
pids: [jobProc.pid],
|
|
8749
8879
|
promise: Promise.resolve(0)
|
|
8750
8880
|
};
|
|
8751
8881
|
job.promise = (async () => {
|
|
8882
|
+
let code;
|
|
8752
8883
|
try {
|
|
8753
|
-
|
|
8754
|
-
job.exitCode = code;
|
|
8755
|
-
job.state = "done";
|
|
8756
|
-
return code;
|
|
8884
|
+
code = await sub.run(node2, { stdin: new NullInput(), stdout: io.stdout, stderr: io.stderr });
|
|
8757
8885
|
} catch (e) {
|
|
8758
|
-
|
|
8759
|
-
job.exitCode = e instanceof ShellExit ? e.code : 1;
|
|
8760
|
-
return job.exitCode;
|
|
8886
|
+
code = e instanceof ShellExit ? e.code : 1;
|
|
8761
8887
|
}
|
|
8888
|
+
jobProc.exit(code);
|
|
8889
|
+
job.exitCode = jobProc.exitCode ?? code;
|
|
8890
|
+
job.state = "done";
|
|
8891
|
+
queueMicrotask(() => {
|
|
8892
|
+
if (jobProc.children.size === 0) this.kernel.procs.remove(jobProc.pid);
|
|
8893
|
+
});
|
|
8894
|
+
return job.exitCode;
|
|
8762
8895
|
})();
|
|
8763
8896
|
this.jobs.push(job);
|
|
8764
8897
|
this.lastBackgroundPid = job.pgid;
|
|
@@ -17495,437 +17628,1110 @@ var commands11 = [xsel, xclip, pbcopy, pbpaste, wlCopy, wlPaste];
|
|
|
17495
17628
|
|
|
17496
17629
|
// src/node/node.ts
|
|
17497
17630
|
init_path();
|
|
17498
|
-
var
|
|
17499
|
-
|
|
17500
|
-
|
|
17501
|
-
|
|
17502
|
-
|
|
17503
|
-
|
|
17504
|
-
|
|
17505
|
-
|
|
17506
|
-
|
|
17507
|
-
|
|
17508
|
-
|
|
17509
|
-
|
|
17510
|
-
|
|
17511
|
-
|
|
17512
|
-
|
|
17513
|
-
|
|
17514
|
-
|
|
17515
|
-
|
|
17516
|
-
|
|
17517
|
-
|
|
17518
|
-
|
|
17519
|
-
|
|
17520
|
-
|
|
17521
|
-
|
|
17522
|
-
|
|
17523
|
-
try { widen(globalThis.Buffer); } catch (e) {}
|
|
17524
|
-
try { widen(require('buffer').Buffer); } catch (e) {}
|
|
17525
|
-
})();
|
|
17526
|
-
`;
|
|
17527
|
-
function buildPrelude(scriptPath, argv, stdinPath) {
|
|
17528
|
-
const argvLiteral = JSON.stringify(["/usr/bin/node", scriptPath, ...argv]);
|
|
17529
|
-
const pathLiteral = JSON.stringify(scriptPath);
|
|
17530
|
-
const stdinLiteral = JSON.stringify(stdinPath);
|
|
17531
|
-
return `${BUFFER_COMPAT_SHIM}
|
|
17532
|
-
process.argv = ${argvLiteral};
|
|
17533
|
-
try {
|
|
17534
|
-
__filename = ${pathLiteral};
|
|
17535
|
-
module.filename = ${pathLiteral};
|
|
17536
|
-
module.id = ${pathLiteral};
|
|
17537
|
-
if (require.main === module) require.main.filename = ${pathLiteral};
|
|
17538
|
-
} catch (e) {}
|
|
17539
|
-
${stdinPath === null ? "" : `(function () {
|
|
17540
|
-
const fs = require('fs');
|
|
17541
|
-
const { Readable } = require('stream');
|
|
17542
|
-
let data;
|
|
17543
|
-
try { data = fs.readFileSync(${stdinLiteral}); } catch (e) { data = Buffer.alloc(0); }
|
|
17544
|
-
const stream = Readable.from([data]);
|
|
17545
|
-
stream.isTTY = false;
|
|
17546
|
-
stream.fd = 0;
|
|
17547
|
-
stream.setRawMode = function () { return this; };
|
|
17548
|
-
try {
|
|
17549
|
-
Object.defineProperty(process, 'stdin', { value: stream, configurable: true, writable: true });
|
|
17550
|
-
} catch (e) { process.stdin = stream; }
|
|
17551
|
-
})();
|
|
17552
|
-
`}`;
|
|
17631
|
+
var HELPERS = {
|
|
17632
|
+
/** Import a specifier and return an ES-module-shaped namespace. */
|
|
17633
|
+
import: "__sbxImport",
|
|
17634
|
+
/** `import(...)`, returning a promise of a namespace. */
|
|
17635
|
+
dynamic: "__sbxDynamicImport",
|
|
17636
|
+
/** `export * from` — copy live bindings onto `exports`. */
|
|
17637
|
+
exportAll: "__sbxExportAll",
|
|
17638
|
+
/** `import.meta`. */
|
|
17639
|
+
meta: "__sbxMeta",
|
|
17640
|
+
/**
|
|
17641
|
+
* The exports object, under a name of the engine's choosing.
|
|
17642
|
+
*
|
|
17643
|
+
* An ES module is free to declare its own top-level `exports`, `require` or
|
|
17644
|
+
* `__dirname` — they are ordinary identifiers there, and real packages use
|
|
17645
|
+
* all three (`const require = createRequire(import.meta.url)` is close to
|
|
17646
|
+
* idiomatic). Naming the wrapper's binding something no source would write
|
|
17647
|
+
* removes that entire class of collision instead of patching it up after a
|
|
17648
|
+
* `SyntaxError`.
|
|
17649
|
+
*/
|
|
17650
|
+
exports: "__sbxExports"
|
|
17651
|
+
};
|
|
17652
|
+
var DEFAULT_LOCAL = "__sbxDefault";
|
|
17653
|
+
var MAYBE_ESM = /(^|[\s;}(])(?:import|export)(?:[\s({[*"']|$)|\bimport\s*\.\s*meta\b/;
|
|
17654
|
+
function looksLikeEsm(source) {
|
|
17655
|
+
return MAYBE_ESM.test(source);
|
|
17553
17656
|
}
|
|
17554
|
-
|
|
17555
|
-
|
|
17556
|
-
|
|
17557
|
-
const tty = ctx.stdin.isTTY;
|
|
17558
|
-
let exitCode = 0;
|
|
17657
|
+
function transformEsm(source, filename = "module.js") {
|
|
17658
|
+
if (!looksLikeEsm(source)) return null;
|
|
17659
|
+
let ast;
|
|
17559
17660
|
try {
|
|
17560
|
-
|
|
17561
|
-
|
|
17562
|
-
|
|
17563
|
-
argv: ["/usr/bin/node", invocation.argvPath ?? invocation.script, ...invocation.argv],
|
|
17564
|
-
...invocation.stdinPath ? { stdinPath: invocation.stdinPath } : {},
|
|
17565
|
-
/* An interactive caller's input was not captured to a file, so the
|
|
17566
|
-
* program's stdin has to stay open and be fed as it arrives — and be
|
|
17567
|
-
* reported as a terminal, since that is what decides whether a CLI
|
|
17568
|
-
* prompts or takes its defaults. */
|
|
17569
|
-
...live ? { interactiveStdin: true } : {},
|
|
17570
|
-
...tty ? { tty: true } : {}
|
|
17571
|
-
});
|
|
17572
|
-
proc.on("output", (chunk) => {
|
|
17573
|
-
try {
|
|
17574
|
-
ctx.write(chunk);
|
|
17575
|
-
} catch {
|
|
17576
|
-
}
|
|
17577
|
-
});
|
|
17578
|
-
proc.on("error", (chunk) => {
|
|
17579
|
-
try {
|
|
17580
|
-
ctx.stderr.write(chunk);
|
|
17581
|
-
} catch {
|
|
17582
|
-
}
|
|
17583
|
-
});
|
|
17584
|
-
proc.on("rawmode", (enabled) => {
|
|
17585
|
-
ctx.stdin.rawMode = enabled;
|
|
17586
|
-
});
|
|
17587
|
-
let forwarding = false;
|
|
17588
|
-
if (live) {
|
|
17589
|
-
forwarding = true;
|
|
17590
|
-
void (async () => {
|
|
17591
|
-
while (forwarding) {
|
|
17592
|
-
const chunk = await ctx.stdin.read();
|
|
17593
|
-
if (chunk === null) {
|
|
17594
|
-
proc.endInput?.();
|
|
17595
|
-
break;
|
|
17596
|
-
}
|
|
17597
|
-
try {
|
|
17598
|
-
proc.write(new TextDecoder().decode(chunk));
|
|
17599
|
-
} catch {
|
|
17600
|
-
break;
|
|
17601
|
-
}
|
|
17602
|
-
}
|
|
17603
|
-
})();
|
|
17604
|
-
}
|
|
17605
|
-
let onAbort;
|
|
17606
|
-
const aborted = new Promise((resolve3) => {
|
|
17607
|
-
onAbort = () => {
|
|
17608
|
-
try {
|
|
17609
|
-
proc.kill();
|
|
17610
|
-
} catch {
|
|
17611
|
-
}
|
|
17612
|
-
resolve3({ exitCode: 137 });
|
|
17613
|
-
};
|
|
17614
|
-
if (ctx.signal.aborted) onAbort();
|
|
17615
|
-
else ctx.signal.addEventListener("abort", onAbort, { once: true });
|
|
17616
|
-
});
|
|
17617
|
-
const result = await Promise.race([proc.completion, aborted]);
|
|
17618
|
-
forwarding = false;
|
|
17619
|
-
if (onAbort) ctx.signal.removeEventListener("abort", onAbort);
|
|
17620
|
-
exitCode = result.exitCode;
|
|
17621
|
-
} catch (e) {
|
|
17622
|
-
ctx.stderr.write(`node: ${e instanceof Error ? e.message : String(e)}
|
|
17623
|
-
`);
|
|
17624
|
-
exitCode = 1;
|
|
17625
|
-
} finally {
|
|
17626
|
-
for (const temp of invocation.temps) {
|
|
17627
|
-
try {
|
|
17628
|
-
ctx.vfs.unlink(temp);
|
|
17629
|
-
} catch {
|
|
17630
|
-
}
|
|
17631
|
-
}
|
|
17661
|
+
ast = parseModule(source, filename);
|
|
17662
|
+
} catch {
|
|
17663
|
+
return null;
|
|
17632
17664
|
}
|
|
17633
|
-
|
|
17634
|
-
|
|
17635
|
-
|
|
17636
|
-
|
|
17637
|
-
const
|
|
17638
|
-
|
|
17639
|
-
|
|
17640
|
-
|
|
17641
|
-
|
|
17642
|
-
|
|
17643
|
-
|
|
17644
|
-
|
|
17645
|
-
|
|
17646
|
-
|
|
17647
|
-
|
|
17648
|
-
|
|
17649
|
-
|
|
17650
|
-
|
|
17651
|
-
|
|
17652
|
-
|
|
17653
|
-
|
|
17654
|
-
|
|
17655
|
-
|
|
17656
|
-
|
|
17657
|
-
let printResult = false;
|
|
17658
|
-
let scriptArg;
|
|
17659
|
-
for (; i < argv.length; i++) {
|
|
17660
|
-
const arg = argv[i];
|
|
17661
|
-
if (arg === "-v" || arg === "--version") {
|
|
17662
|
-
ctx.line(NODE_VERSION);
|
|
17663
|
-
return 0;
|
|
17664
|
-
}
|
|
17665
|
-
if (arg === "-h" || arg === "--help") {
|
|
17666
|
-
printHelp(ctx);
|
|
17667
|
-
return 0;
|
|
17668
|
-
}
|
|
17669
|
-
if (arg === "-e" || arg === "--eval") {
|
|
17670
|
-
evalSource = argv[++i] ?? "";
|
|
17671
|
-
i++;
|
|
17672
|
-
break;
|
|
17673
|
-
}
|
|
17674
|
-
if (arg === "-p" || arg === "--print") {
|
|
17675
|
-
printResult = true;
|
|
17676
|
-
evalSource = argv[++i] ?? "";
|
|
17677
|
-
i++;
|
|
17678
|
-
break;
|
|
17679
|
-
}
|
|
17680
|
-
if (arg.startsWith("--eval=")) {
|
|
17681
|
-
evalSource = arg.slice("--eval=".length);
|
|
17682
|
-
i++;
|
|
17665
|
+
const body = ast.body;
|
|
17666
|
+
const hasModuleSyntax = body.some(
|
|
17667
|
+
(node2) => node2.type.startsWith("Import") || node2.type.startsWith("Export")
|
|
17668
|
+
);
|
|
17669
|
+
const usesImportMeta = !hasModuleSyntax && containsImportMeta(ast);
|
|
17670
|
+
const esm = hasModuleSyntax || usesImportMeta;
|
|
17671
|
+
if (!esm && !containsImportExpression(ast)) return null;
|
|
17672
|
+
const edits = [];
|
|
17673
|
+
const prelude = [];
|
|
17674
|
+
const importBindings = /* @__PURE__ */ new Map();
|
|
17675
|
+
const exportGetters = /* @__PURE__ */ new Map();
|
|
17676
|
+
let namespaceCount = 0;
|
|
17677
|
+
const namespaceFor = (specifier) => {
|
|
17678
|
+
const id = `__sbxNs${namespaceCount++}`;
|
|
17679
|
+
prelude.push(`var ${id} = ${HELPERS.import}(${JSON.stringify(specifier)});`);
|
|
17680
|
+
return id;
|
|
17681
|
+
};
|
|
17682
|
+
for (const node2 of body) {
|
|
17683
|
+
if (node2.type === "ImportDeclaration") collectImport(node2);
|
|
17684
|
+
}
|
|
17685
|
+
for (const node2 of body) {
|
|
17686
|
+
switch (node2.type) {
|
|
17687
|
+
case "ExportNamedDeclaration":
|
|
17688
|
+
collectNamedExport(node2);
|
|
17683
17689
|
break;
|
|
17684
|
-
|
|
17685
|
-
|
|
17686
|
-
printResult = true;
|
|
17687
|
-
evalSource = arg.slice("--print=".length);
|
|
17688
|
-
i++;
|
|
17690
|
+
case "ExportDefaultDeclaration":
|
|
17691
|
+
collectDefaultExport(node2);
|
|
17689
17692
|
break;
|
|
17690
|
-
|
|
17691
|
-
|
|
17692
|
-
i++;
|
|
17693
|
+
case "ExportAllDeclaration":
|
|
17694
|
+
collectExportAll(node2);
|
|
17693
17695
|
break;
|
|
17694
|
-
}
|
|
17695
|
-
if (arg.startsWith("-") && arg !== "-") {
|
|
17696
|
-
continue;
|
|
17697
|
-
}
|
|
17698
|
-
scriptArg = arg;
|
|
17699
|
-
i++;
|
|
17700
|
-
break;
|
|
17701
|
-
}
|
|
17702
|
-
const scriptArgs = argv.slice(i);
|
|
17703
|
-
if (evalSource !== void 0) {
|
|
17704
|
-
const body = printResult ? `const __sbxResult = (function(){ return (${evalSource}
|
|
17705
|
-
); })();
|
|
17706
|
-
console.log(typeof __sbxResult === 'string' ? __sbxResult : require('util').inspect(__sbxResult));` : evalSource;
|
|
17707
|
-
const path = tempPath("eval", ctx.proc.pid);
|
|
17708
|
-
const stdinPath2 = await captureStdin(ctx);
|
|
17709
|
-
if (stdinPath2) temps.push(stdinPath2);
|
|
17710
|
-
ctx.vfs.writeFile(path, buildBootstrapForEval(body, ["/usr/bin/node", ...scriptArgs], stdinPath2), {
|
|
17711
|
-
privileged: true,
|
|
17712
|
-
mode: 384
|
|
17713
|
-
});
|
|
17714
|
-
temps.push(path);
|
|
17715
|
-
return execute(ctx, { script: path, argv: scriptArgs, stdinPath: stdinPath2, temps });
|
|
17716
17696
|
}
|
|
17717
|
-
|
|
17718
|
-
|
|
17719
|
-
|
|
17720
|
-
|
|
17721
|
-
|
|
17697
|
+
}
|
|
17698
|
+
rewriteReferences();
|
|
17699
|
+
const header = esm ? [
|
|
17700
|
+
`Object.defineProperty(${HELPERS.exports}, "__esModule", { value: true });`,
|
|
17701
|
+
...prelude,
|
|
17702
|
+
...[...exportGetters].map(
|
|
17703
|
+
([name, expression]) => `Object.defineProperty(${HELPERS.exports}, ${JSON.stringify(name)}, { enumerable: true, configurable: true, get: function () { return ${expression}; } });`
|
|
17704
|
+
)
|
|
17705
|
+
].join("\n") : "";
|
|
17706
|
+
return {
|
|
17707
|
+
code: header ? `${header}
|
|
17708
|
+
${applyEdits(source, edits)}` : applyEdits(source, edits),
|
|
17709
|
+
esm,
|
|
17710
|
+
topLevelAwait: hasTopLevelAwait(ast)
|
|
17711
|
+
};
|
|
17712
|
+
function collectImport(node2) {
|
|
17713
|
+
const specifier = node2.source.value;
|
|
17714
|
+
const specifiers = node2.specifiers ?? [];
|
|
17715
|
+
const id = namespaceFor(specifier);
|
|
17716
|
+
for (const entry of specifiers) {
|
|
17717
|
+
const local = entry.local.name ?? "";
|
|
17718
|
+
if (entry.type === "ImportDefaultSpecifier") {
|
|
17719
|
+
importBindings.set(local, `${id}.default`);
|
|
17720
|
+
} else if (entry.type === "ImportNamespaceSpecifier") {
|
|
17721
|
+
importBindings.set(local, id);
|
|
17722
|
+
} else {
|
|
17723
|
+
const imported = entry.imported;
|
|
17724
|
+
const name = imported.type === "Identifier" ? imported.name : imported.value;
|
|
17725
|
+
importBindings.set(local, `${id}[${JSON.stringify(name)}]`);
|
|
17722
17726
|
}
|
|
17723
|
-
const source = new TextDecoder().decode(await ctx.stdin.readAll());
|
|
17724
|
-
if (source.trim() === "") return 0;
|
|
17725
|
-
const path = tempPath("stdin-script", ctx.proc.pid);
|
|
17726
|
-
ctx.vfs.writeFile(path, buildBootstrapForEval(source, ["/usr/bin/node", ...scriptArgs], null), {
|
|
17727
|
-
privileged: true,
|
|
17728
|
-
mode: 384
|
|
17729
|
-
});
|
|
17730
|
-
temps.push(path);
|
|
17731
|
-
return execute(ctx, { script: path, argv: scriptArgs, temps });
|
|
17732
17727
|
}
|
|
17733
|
-
|
|
17734
|
-
|
|
17735
|
-
|
|
17736
|
-
|
|
17737
|
-
|
|
17738
|
-
|
|
17739
|
-
|
|
17740
|
-
|
|
17741
|
-
`
|
|
17742
|
-
);
|
|
17743
|
-
return 1;
|
|
17728
|
+
drop(node2);
|
|
17729
|
+
}
|
|
17730
|
+
function collectNamedExport(node2) {
|
|
17731
|
+
const declaration = node2.declaration;
|
|
17732
|
+
if (declaration) {
|
|
17733
|
+
for (const name of declaredNames(declaration)) exportGetters.set(name, name);
|
|
17734
|
+
edits.push({ start: node2.start, end: declaration.start, text: "" });
|
|
17735
|
+
return;
|
|
17744
17736
|
}
|
|
17745
|
-
const
|
|
17746
|
-
|
|
17747
|
-
const
|
|
17748
|
-
|
|
17749
|
-
const
|
|
17750
|
-
|
|
17751
|
-
|
|
17752
|
-
mode: 384
|
|
17753
|
-
});
|
|
17754
|
-
temps.push(sibling);
|
|
17755
|
-
return await execute(ctx, { script: sibling, argvPath: script, argv: scriptArgs, stdinPath, temps });
|
|
17756
|
-
} catch {
|
|
17757
|
-
return await execute(ctx, { script, argv: scriptArgs, stdinPath, temps });
|
|
17737
|
+
const source_ = node2.source;
|
|
17738
|
+
const id = source_ ? namespaceFor(source_.value) : null;
|
|
17739
|
+
for (const entry of node2.specifiers ?? []) {
|
|
17740
|
+
const local = nameOf(entry.local);
|
|
17741
|
+
const exported = nameOf(entry.exported);
|
|
17742
|
+
const read = id ? `${id}[${JSON.stringify(local)}]` : importBindings.get(local) ?? local;
|
|
17743
|
+
exportGetters.set(exported, read);
|
|
17758
17744
|
}
|
|
17745
|
+
drop(node2);
|
|
17759
17746
|
}
|
|
17760
|
-
|
|
17761
|
-
|
|
17762
|
-
|
|
17763
|
-
|
|
17764
|
-
|
|
17765
|
-
|
|
17766
|
-
|
|
17767
|
-
|
|
17768
|
-
|
|
17769
|
-
` : "";
|
|
17770
|
-
return `${BUFFER_COMPAT_SHIM}process.argv = ${JSON.stringify(argv)};
|
|
17771
|
-
${prelude}${source}
|
|
17772
|
-
`;
|
|
17773
|
-
}
|
|
17774
|
-
function resolveScript(ctx, operand) {
|
|
17775
|
-
const base2 = ctx.path(operand);
|
|
17776
|
-
const candidates = [base2, `${base2}.js`, `${base2}.mjs`, `${base2}.cjs`, `${base2}.json`];
|
|
17777
|
-
for (const candidate of candidates) {
|
|
17778
|
-
try {
|
|
17779
|
-
const st = ctx.vfs.stat(candidate, { cred: ctx.cred });
|
|
17780
|
-
if (st.isFile()) return ctx.vfs.realpath(candidate, ctx.cred);
|
|
17781
|
-
if (st.isDirectory()) {
|
|
17782
|
-
const manifest = join(candidate, "package.json");
|
|
17783
|
-
if (ctx.vfs.lexists(manifest)) {
|
|
17784
|
-
try {
|
|
17785
|
-
const main = JSON.parse(ctx.vfs.readText(manifest, ctx.cred)).main;
|
|
17786
|
-
if (main) {
|
|
17787
|
-
const mainPath = resolve(candidate, main);
|
|
17788
|
-
if (ctx.vfs.lexists(mainPath)) return ctx.vfs.realpath(mainPath, ctx.cred);
|
|
17789
|
-
if (ctx.vfs.lexists(mainPath + ".js")) return ctx.vfs.realpath(mainPath + ".js", ctx.cred);
|
|
17790
|
-
}
|
|
17791
|
-
} catch {
|
|
17792
|
-
}
|
|
17793
|
-
}
|
|
17794
|
-
for (const index of ["index.js", "index.mjs", "index.cjs"]) {
|
|
17795
|
-
const path = join(candidate, index);
|
|
17796
|
-
if (ctx.vfs.lexists(path)) return ctx.vfs.realpath(path, ctx.cred);
|
|
17797
|
-
}
|
|
17747
|
+
function collectDefaultExport(node2) {
|
|
17748
|
+
const declaration = node2.declaration;
|
|
17749
|
+
const isDeclaration = declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration";
|
|
17750
|
+
if (isDeclaration) {
|
|
17751
|
+
const named = declaration.id;
|
|
17752
|
+
if (named) {
|
|
17753
|
+
exportGetters.set("default", named.name);
|
|
17754
|
+
edits.push({ start: node2.start, end: declaration.start, text: "" });
|
|
17755
|
+
return;
|
|
17798
17756
|
}
|
|
17799
|
-
|
|
17757
|
+
const keyword = declaration.type === "FunctionDeclaration" ? "function" : "class";
|
|
17758
|
+
const keywordEnd = source.indexOf(keyword, declaration.start) + keyword.length;
|
|
17759
|
+
exportGetters.set("default", DEFAULT_LOCAL);
|
|
17760
|
+
edits.push({ start: node2.start, end: declaration.start, text: "" });
|
|
17761
|
+
edits.push({ start: keywordEnd, end: keywordEnd, text: ` ${DEFAULT_LOCAL}` });
|
|
17762
|
+
return;
|
|
17800
17763
|
}
|
|
17764
|
+
exportGetters.set("default", DEFAULT_LOCAL);
|
|
17765
|
+
edits.push({ start: node2.start, end: declaration.start, text: `var ${DEFAULT_LOCAL} = ` });
|
|
17766
|
+
edits.push({ start: node2.end, end: node2.end, text: ";" });
|
|
17801
17767
|
}
|
|
17802
|
-
|
|
17803
|
-
|
|
17804
|
-
|
|
17805
|
-
|
|
17806
|
-
|
|
17807
|
-
|
|
17808
|
-
|
|
17809
|
-
|
|
17810
|
-
|
|
17811
|
-
|
|
17812
|
-
|
|
17813
|
-
}
|
|
17814
|
-
|
|
17815
|
-
|
|
17816
|
-
|
|
17817
|
-
|
|
17818
|
-
|
|
17819
|
-
|
|
17820
|
-
|
|
17821
|
-
|
|
17822
|
-
|
|
17823
|
-
|
|
17824
|
-
|
|
17825
|
-
|
|
17826
|
-
|
|
17827
|
-
|
|
17828
|
-
|
|
17829
|
-
|
|
17830
|
-
|
|
17831
|
-
|
|
17832
|
-
|
|
17833
|
-
|
|
17834
|
-
|
|
17835
|
-
|
|
17836
|
-
|
|
17837
|
-
|
|
17838
|
-
|
|
17839
|
-
|
|
17840
|
-
|
|
17841
|
-
|
|
17842
|
-
|
|
17843
|
-
|
|
17844
|
-
|
|
17768
|
+
function collectExportAll(node2) {
|
|
17769
|
+
const id = namespaceFor(node2.source.value);
|
|
17770
|
+
const exported = node2.exported;
|
|
17771
|
+
if (exported) exportGetters.set(nameOf(exported), id);
|
|
17772
|
+
else prelude.push(`${HELPERS.exportAll}(${HELPERS.exports}, ${id});`);
|
|
17773
|
+
drop(node2);
|
|
17774
|
+
}
|
|
17775
|
+
function drop(node2) {
|
|
17776
|
+
edits.push({ start: node2.start, end: node2.end, text: "" });
|
|
17777
|
+
}
|
|
17778
|
+
function rewriteReferences() {
|
|
17779
|
+
const programScope = { names: new Set(importBindings.keys()), parent: null };
|
|
17780
|
+
visit(ast, programScope, true);
|
|
17781
|
+
function visit(node2, scope, isProgram = false) {
|
|
17782
|
+
let childScope = scope;
|
|
17783
|
+
let skip = NOTHING;
|
|
17784
|
+
switch (node2.type) {
|
|
17785
|
+
case "ImportDeclaration":
|
|
17786
|
+
case "ExportAllDeclaration":
|
|
17787
|
+
return;
|
|
17788
|
+
case "ExportNamedDeclaration":
|
|
17789
|
+
if (!node2.declaration) return;
|
|
17790
|
+
break;
|
|
17791
|
+
case "FunctionDeclaration":
|
|
17792
|
+
case "FunctionExpression":
|
|
17793
|
+
case "ArrowFunctionExpression": {
|
|
17794
|
+
const names = /* @__PURE__ */ new Set();
|
|
17795
|
+
for (const param of node2.params ?? []) collectPattern(param, names);
|
|
17796
|
+
const id = node2.id;
|
|
17797
|
+
if (id && node2.type === "FunctionExpression") names.add(id.name);
|
|
17798
|
+
const fnBody = node2.body;
|
|
17799
|
+
if (fnBody?.type === "BlockStatement") {
|
|
17800
|
+
for (const name of hoistedNames(fnBody.body)) names.add(name);
|
|
17801
|
+
}
|
|
17802
|
+
childScope = { names, parent: scope };
|
|
17803
|
+
break;
|
|
17804
|
+
}
|
|
17805
|
+
case "CatchClause": {
|
|
17806
|
+
const names = /* @__PURE__ */ new Set();
|
|
17807
|
+
if (node2.param) collectPattern(node2.param, names);
|
|
17808
|
+
childScope = { names, parent: scope };
|
|
17809
|
+
break;
|
|
17810
|
+
}
|
|
17811
|
+
case "ClassExpression": {
|
|
17812
|
+
const id = node2.id;
|
|
17813
|
+
if (id) childScope = { names: /* @__PURE__ */ new Set([id.name]), parent: scope };
|
|
17814
|
+
break;
|
|
17815
|
+
}
|
|
17816
|
+
case "BlockStatement":
|
|
17817
|
+
case "StaticBlock":
|
|
17818
|
+
if (!isProgram) {
|
|
17819
|
+
childScope = { names: blockNames(node2.body), parent: scope };
|
|
17820
|
+
}
|
|
17821
|
+
break;
|
|
17822
|
+
case "ForStatement":
|
|
17823
|
+
case "ForInStatement":
|
|
17824
|
+
case "ForOfStatement": {
|
|
17825
|
+
const head2 = node2.init ?? node2.left;
|
|
17826
|
+
if (head2?.type === "VariableDeclaration" && head2.kind !== "var") {
|
|
17827
|
+
const names = /* @__PURE__ */ new Set();
|
|
17828
|
+
for (const declarator of head2.declarations) {
|
|
17829
|
+
collectPattern(declarator.id, names);
|
|
17830
|
+
}
|
|
17831
|
+
childScope = { names, parent: scope };
|
|
17832
|
+
}
|
|
17833
|
+
break;
|
|
17834
|
+
}
|
|
17835
|
+
case "MetaProperty":
|
|
17836
|
+
edits.push({ start: node2.start, end: node2.end, text: HELPERS.meta });
|
|
17837
|
+
return;
|
|
17838
|
+
case "ImportExpression": {
|
|
17839
|
+
const argument = node2.source;
|
|
17840
|
+
edits.push({ start: node2.start, end: argument.start, text: `${HELPERS.dynamic}(` });
|
|
17841
|
+
visit(argument, childScope);
|
|
17842
|
+
edits.push({ start: argument.end, end: node2.end, text: ")" });
|
|
17843
|
+
return;
|
|
17844
|
+
}
|
|
17845
|
+
case "Identifier": {
|
|
17846
|
+
const replacement = lookup(node2.name, scope);
|
|
17847
|
+
if (replacement) edits.push({ start: node2.start, end: node2.end, text: replacement });
|
|
17848
|
+
return;
|
|
17849
|
+
}
|
|
17850
|
+
case "MemberExpression":
|
|
17851
|
+
case "MethodDefinition":
|
|
17852
|
+
case "PropertyDefinition":
|
|
17853
|
+
skip = node2.computed ? NOTHING : PROPERTY;
|
|
17854
|
+
break;
|
|
17855
|
+
case "Property": {
|
|
17856
|
+
if (node2.computed) break;
|
|
17857
|
+
if (node2.shorthand) {
|
|
17858
|
+
const value = node2.value;
|
|
17859
|
+
if (value.type === "Identifier") {
|
|
17860
|
+
const replacement = lookup(value.name, scope);
|
|
17861
|
+
if (replacement) {
|
|
17862
|
+
edits.push({ start: value.start, end: value.end, text: `${value.name}: ${replacement}` });
|
|
17863
|
+
return;
|
|
17864
|
+
}
|
|
17865
|
+
}
|
|
17866
|
+
break;
|
|
17867
|
+
}
|
|
17868
|
+
skip = PROPERTY;
|
|
17869
|
+
break;
|
|
17870
|
+
}
|
|
17871
|
+
case "LabeledStatement":
|
|
17872
|
+
case "BreakStatement":
|
|
17873
|
+
case "ContinueStatement":
|
|
17874
|
+
skip = LABEL;
|
|
17875
|
+
break;
|
|
17876
|
+
}
|
|
17877
|
+
for (const [key, value] of Object.entries(node2)) {
|
|
17878
|
+
if (key === "type" || key === "start" || key === "end" || skip.includes(key)) continue;
|
|
17879
|
+
if (Array.isArray(value)) {
|
|
17880
|
+
for (const item of value) if (isNode2(item)) visit(item, childScope);
|
|
17881
|
+
} else if (isNode2(value)) {
|
|
17882
|
+
visit(value, childScope);
|
|
17883
|
+
}
|
|
17884
|
+
}
|
|
17845
17885
|
}
|
|
17846
|
-
|
|
17847
|
-
|
|
17848
|
-
|
|
17886
|
+
function lookup(name, scope) {
|
|
17887
|
+
for (let current = scope; current; current = current.parent) {
|
|
17888
|
+
if (current.names.has(name)) {
|
|
17889
|
+
return current.parent === null ? importBindings.get(name) ?? null : null;
|
|
17890
|
+
}
|
|
17891
|
+
}
|
|
17892
|
+
return null;
|
|
17849
17893
|
}
|
|
17850
17894
|
}
|
|
17851
|
-
return 0;
|
|
17852
17895
|
}
|
|
17853
|
-
|
|
17854
|
-
|
|
17855
|
-
|
|
17856
|
-
|
|
17857
|
-
|
|
17858
|
-
|
|
17859
|
-
|
|
17896
|
+
var JSX_EXTENSION = /\.[jt]sx$/;
|
|
17897
|
+
var JsxParser = acorn.Parser.extend(jsx__default.default());
|
|
17898
|
+
var PARSE_OPTIONS = {
|
|
17899
|
+
ecmaVersion: "latest",
|
|
17900
|
+
sourceType: "module",
|
|
17901
|
+
allowAwaitOutsideFunction: true,
|
|
17902
|
+
allowHashBang: true,
|
|
17903
|
+
allowReturnOutsideFunction: true
|
|
17904
|
+
};
|
|
17905
|
+
function parseModule(source, filename) {
|
|
17906
|
+
const parser = JSX_EXTENSION.test(filename) ? JsxParser.parse.bind(JsxParser) : acorn.parse;
|
|
17907
|
+
return parser(source, PARSE_OPTIONS);
|
|
17908
|
+
}
|
|
17909
|
+
function containsImportExpression(node2) {
|
|
17910
|
+
if (Array.isArray(node2)) return node2.some(containsImportExpression);
|
|
17911
|
+
if (!isNode2(node2)) return false;
|
|
17912
|
+
if (node2.type === "ImportExpression") return true;
|
|
17913
|
+
for (const [key, value] of Object.entries(node2)) {
|
|
17914
|
+
if (key === "type" || key === "start" || key === "end") continue;
|
|
17915
|
+
if (containsImportExpression(value)) return true;
|
|
17860
17916
|
}
|
|
17917
|
+
return false;
|
|
17861
17918
|
}
|
|
17862
|
-
function
|
|
17863
|
-
|
|
17864
|
-
|
|
17865
|
-
|
|
17866
|
-
|
|
17867
|
-
|
|
17868
|
-
|
|
17869
|
-
|
|
17919
|
+
function containsImportMeta(node2) {
|
|
17920
|
+
if (Array.isArray(node2)) return node2.some(containsImportMeta);
|
|
17921
|
+
if (!isNode2(node2)) return false;
|
|
17922
|
+
if (node2.type === "MetaProperty") return true;
|
|
17923
|
+
for (const [key, value] of Object.entries(node2)) {
|
|
17924
|
+
if (key === "type" || key === "start" || key === "end") continue;
|
|
17925
|
+
if (containsImportMeta(value)) return true;
|
|
17926
|
+
}
|
|
17927
|
+
return false;
|
|
17870
17928
|
}
|
|
17871
|
-
|
|
17872
|
-
|
|
17873
|
-
|
|
17874
|
-
|
|
17875
|
-
|
|
17876
|
-
|
|
17877
|
-
|
|
17878
|
-
|
|
17879
|
-
|
|
17929
|
+
function hasTopLevelAwait(node2) {
|
|
17930
|
+
if (Array.isArray(node2)) return node2.some(hasTopLevelAwait);
|
|
17931
|
+
if (!isNode2(node2)) return false;
|
|
17932
|
+
if (node2.type === "FunctionDeclaration" || node2.type === "FunctionExpression" || node2.type === "ArrowFunctionExpression") {
|
|
17933
|
+
return false;
|
|
17934
|
+
}
|
|
17935
|
+
if (node2.type === "AwaitExpression") return true;
|
|
17936
|
+
if (node2.type === "ForOfStatement" && node2.await === true) return true;
|
|
17937
|
+
for (const [key, value] of Object.entries(node2)) {
|
|
17938
|
+
if (key === "type" || key === "start" || key === "end") continue;
|
|
17939
|
+
if (hasTopLevelAwait(value)) return true;
|
|
17940
|
+
}
|
|
17941
|
+
return false;
|
|
17942
|
+
}
|
|
17943
|
+
function declaredNames(declaration) {
|
|
17944
|
+
const names = /* @__PURE__ */ new Set();
|
|
17945
|
+
if (declaration.type === "VariableDeclaration") {
|
|
17946
|
+
for (const declarator of declaration.declarations) {
|
|
17947
|
+
collectPattern(declarator.id, names);
|
|
17880
17948
|
}
|
|
17881
|
-
|
|
17882
|
-
|
|
17883
|
-
|
|
17949
|
+
} else if (isNode2(declaration.id)) {
|
|
17950
|
+
names.add(declaration.id.name);
|
|
17951
|
+
}
|
|
17952
|
+
return [...names];
|
|
17953
|
+
}
|
|
17954
|
+
function nameOf(node2) {
|
|
17955
|
+
return node2.type === "Identifier" ? node2.name : node2.value;
|
|
17956
|
+
}
|
|
17957
|
+
function hoistedNames(body) {
|
|
17958
|
+
const names = blockNames(body);
|
|
17959
|
+
collectVars(body, names);
|
|
17960
|
+
return names;
|
|
17961
|
+
}
|
|
17962
|
+
function blockNames(body) {
|
|
17963
|
+
const names = /* @__PURE__ */ new Set();
|
|
17964
|
+
for (const node2 of body ?? []) {
|
|
17965
|
+
if (node2.type === "VariableDeclaration" && node2.kind !== "var") {
|
|
17966
|
+
for (const declarator of node2.declarations) {
|
|
17967
|
+
collectPattern(declarator.id, names);
|
|
17968
|
+
}
|
|
17969
|
+
} else if ((node2.type === "ClassDeclaration" || node2.type === "FunctionDeclaration") && isNode2(node2.id)) {
|
|
17970
|
+
names.add(node2.id.name);
|
|
17884
17971
|
}
|
|
17885
|
-
ctx.line(`nvm: only ${NODE_VERSION} is available in this container`);
|
|
17886
|
-
return 0;
|
|
17887
17972
|
}
|
|
17888
|
-
|
|
17889
|
-
function nodeCommands() {
|
|
17890
|
-
return [node, nodeVersionFile];
|
|
17973
|
+
return names;
|
|
17891
17974
|
}
|
|
17892
|
-
|
|
17893
|
-
|
|
17894
|
-
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17898
|
-
|
|
17899
|
-
|
|
17900
|
-
|
|
17901
|
-
|
|
17902
|
-
|
|
17903
|
-
|
|
17904
|
-
|
|
17905
|
-
|
|
17906
|
-
|
|
17907
|
-
|
|
17908
|
-
|
|
17909
|
-
|
|
17910
|
-
|
|
17911
|
-
|
|
17912
|
-
|
|
17913
|
-
|
|
17914
|
-
|
|
17915
|
-
|
|
17916
|
-
|
|
17917
|
-
|
|
17918
|
-
|
|
17919
|
-
|
|
17920
|
-
|
|
17921
|
-
|
|
17922
|
-
|
|
17923
|
-
|
|
17924
|
-
|
|
17925
|
-
|
|
17926
|
-
|
|
17927
|
-
|
|
17928
|
-
|
|
17975
|
+
function collectVars(nodes, names) {
|
|
17976
|
+
if (Array.isArray(nodes)) {
|
|
17977
|
+
for (const item of nodes) collectVars(item, names);
|
|
17978
|
+
return;
|
|
17979
|
+
}
|
|
17980
|
+
if (!isNode2(nodes)) return;
|
|
17981
|
+
const node2 = nodes;
|
|
17982
|
+
if (node2.type === "FunctionDeclaration" || node2.type === "FunctionExpression" || node2.type === "ArrowFunctionExpression") {
|
|
17983
|
+
if (isNode2(node2.id)) names.add(node2.id.name);
|
|
17984
|
+
return;
|
|
17985
|
+
}
|
|
17986
|
+
if (node2.type === "VariableDeclaration" && node2.kind === "var") {
|
|
17987
|
+
for (const declarator of node2.declarations) {
|
|
17988
|
+
collectPattern(declarator.id, names);
|
|
17989
|
+
}
|
|
17990
|
+
}
|
|
17991
|
+
for (const [key, value] of Object.entries(node2)) {
|
|
17992
|
+
if (key === "type" || key === "start" || key === "end") continue;
|
|
17993
|
+
collectVars(value, names);
|
|
17994
|
+
}
|
|
17995
|
+
}
|
|
17996
|
+
function collectPattern(node2, names) {
|
|
17997
|
+
if (!isNode2(node2)) return;
|
|
17998
|
+
switch (node2.type) {
|
|
17999
|
+
case "Identifier":
|
|
18000
|
+
names.add(node2.name);
|
|
18001
|
+
return;
|
|
18002
|
+
case "ObjectPattern":
|
|
18003
|
+
for (const property of node2.properties) {
|
|
18004
|
+
collectPattern(property.value ?? property.argument, names);
|
|
18005
|
+
}
|
|
18006
|
+
return;
|
|
18007
|
+
case "ArrayPattern":
|
|
18008
|
+
for (const element of node2.elements) collectPattern(element, names);
|
|
18009
|
+
return;
|
|
18010
|
+
case "AssignmentPattern":
|
|
18011
|
+
collectPattern(node2.left, names);
|
|
18012
|
+
return;
|
|
18013
|
+
case "RestElement":
|
|
18014
|
+
collectPattern(node2.argument, names);
|
|
18015
|
+
return;
|
|
18016
|
+
default:
|
|
18017
|
+
return;
|
|
18018
|
+
}
|
|
18019
|
+
}
|
|
18020
|
+
function applyEdits(source, edits) {
|
|
18021
|
+
const ordered = [...edits].sort((a, b) => b.start - a.start || b.end - a.end);
|
|
18022
|
+
let out = source;
|
|
18023
|
+
for (const edit of ordered) out = out.slice(0, edit.start) + edit.text + out.slice(edit.end);
|
|
18024
|
+
return out;
|
|
18025
|
+
}
|
|
18026
|
+
function isNode2(value) {
|
|
18027
|
+
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
18028
|
+
}
|
|
18029
|
+
var NOTHING = [];
|
|
18030
|
+
var PROPERTY = ["property", "key"];
|
|
18031
|
+
var LABEL = ["label"];
|
|
18032
|
+
|
|
18033
|
+
// src/node/node.ts
|
|
18034
|
+
var NODE_VERSION = "v22.12.0";
|
|
18035
|
+
new TextEncoder();
|
|
18036
|
+
var tempCounter = 0;
|
|
18037
|
+
function tempPath(kind, pid, ext = ".js") {
|
|
18038
|
+
return `/tmp/.sbx-${kind}-${pid}-${tempCounter++}${ext}`;
|
|
18039
|
+
}
|
|
18040
|
+
function withPrelude(source, prelude) {
|
|
18041
|
+
if (!source.startsWith("#!")) return prelude + source;
|
|
18042
|
+
const eol = source.indexOf("\n");
|
|
18043
|
+
if (eol < 0) return source + "\n" + prelude;
|
|
18044
|
+
return source.slice(0, eol + 1) + prelude + source.slice(eol + 1);
|
|
18045
|
+
}
|
|
18046
|
+
function siblingPath(script, pid) {
|
|
18047
|
+
const ext = extname(script) || ".js";
|
|
18048
|
+
return join(dirname(script), `.sbx-${pid}-${tempCounter++}-${basename(script, ext)}${ext}`);
|
|
18049
|
+
}
|
|
18050
|
+
var BUFFER_COMPAT_SHIM = `
|
|
18051
|
+
(function () {
|
|
18052
|
+
const seen = new Set();
|
|
18053
|
+
const widen = (B) => {
|
|
18054
|
+
if (!B || seen.has(B) || typeof B.isBuffer !== 'function') return;
|
|
18055
|
+
seen.add(B);
|
|
18056
|
+
const original = B.isBuffer.bind(B);
|
|
18057
|
+
B.isBuffer = (value) => original(value) || value instanceof Uint8Array;
|
|
18058
|
+
};
|
|
18059
|
+
try { widen(globalThis.Buffer); } catch (e) {}
|
|
18060
|
+
try { widen(require('buffer').Buffer); } catch (e) {}
|
|
18061
|
+
})();
|
|
18062
|
+
`;
|
|
18063
|
+
function buildPrelude(scriptPath, argv, stdinPath, preloads = []) {
|
|
18064
|
+
const argvLiteral = JSON.stringify(["/usr/bin/node", scriptPath, ...argv]);
|
|
18065
|
+
const pathLiteral = JSON.stringify(scriptPath);
|
|
18066
|
+
const stdinLiteral = JSON.stringify(stdinPath);
|
|
18067
|
+
return `${BUFFER_COMPAT_SHIM}
|
|
18068
|
+
process.argv = ${argvLiteral};
|
|
18069
|
+
try {
|
|
18070
|
+
__filename = ${pathLiteral};
|
|
18071
|
+
module.filename = ${pathLiteral};
|
|
18072
|
+
module.id = ${pathLiteral};
|
|
18073
|
+
if (require.main === module) require.main.filename = ${pathLiteral};
|
|
18074
|
+
} catch (e) {}
|
|
18075
|
+
${stdinPath === null ? "" : `(function () {
|
|
18076
|
+
const fs = require('fs');
|
|
18077
|
+
const { Readable } = require('stream');
|
|
18078
|
+
let data;
|
|
18079
|
+
try { data = fs.readFileSync(${stdinLiteral}); } catch (e) { data = Buffer.alloc(0); }
|
|
18080
|
+
const stream = Readable.from([data]);
|
|
18081
|
+
stream.isTTY = false;
|
|
18082
|
+
stream.fd = 0;
|
|
18083
|
+
stream.setRawMode = function () { return this; };
|
|
18084
|
+
try {
|
|
18085
|
+
Object.defineProperty(process, 'stdin', { value: stream, configurable: true, writable: true });
|
|
18086
|
+
} catch (e) { process.stdin = stream; }
|
|
18087
|
+
})();
|
|
18088
|
+
`}${preloadRequires(preloads)}`;
|
|
18089
|
+
}
|
|
18090
|
+
function preloadRequires(preloads) {
|
|
18091
|
+
return preloads.map((specifier) => `require(${JSON.stringify(specifier)});
|
|
18092
|
+
`).join("");
|
|
18093
|
+
}
|
|
18094
|
+
async function execute(ctx, invocation) {
|
|
18095
|
+
const { pod } = ctx.kernel;
|
|
18096
|
+
const live = ctx.stdin.interactive || ctx.stdin.isTTY;
|
|
18097
|
+
const tty = ctx.stdin.isTTY;
|
|
18098
|
+
let exitCode = 0;
|
|
18099
|
+
try {
|
|
18100
|
+
const proc = await pod.spawn("node", [invocation.script], {
|
|
18101
|
+
cwd: ctx.cwd,
|
|
18102
|
+
env: { ...invocation.env ?? ctx.env, PWD: ctx.cwd },
|
|
18103
|
+
argv: ["/usr/bin/node", invocation.argvPath ?? invocation.script, ...invocation.argv],
|
|
18104
|
+
...invocation.stdinPath ? { stdinPath: invocation.stdinPath } : {},
|
|
18105
|
+
/* An interactive caller's input was not captured to a file, so the
|
|
18106
|
+
* program's stdin has to stay open and be fed as it arrives — and be
|
|
18107
|
+
* reported as a terminal, since that is what decides whether a CLI
|
|
18108
|
+
* prompts or takes its defaults. */
|
|
18109
|
+
...live ? { interactiveStdin: true } : {},
|
|
18110
|
+
...tty ? { tty: true } : {}
|
|
18111
|
+
});
|
|
18112
|
+
proc.on("output", (chunk) => {
|
|
18113
|
+
try {
|
|
18114
|
+
ctx.write(chunk);
|
|
18115
|
+
} catch {
|
|
18116
|
+
}
|
|
18117
|
+
});
|
|
18118
|
+
proc.on("error", (chunk) => {
|
|
18119
|
+
try {
|
|
18120
|
+
ctx.stderr.write(chunk);
|
|
18121
|
+
} catch {
|
|
18122
|
+
}
|
|
18123
|
+
});
|
|
18124
|
+
proc.on("rawmode", (enabled) => {
|
|
18125
|
+
ctx.stdin.rawMode = enabled;
|
|
18126
|
+
});
|
|
18127
|
+
let forwarding = false;
|
|
18128
|
+
if (live) {
|
|
18129
|
+
forwarding = true;
|
|
18130
|
+
void (async () => {
|
|
18131
|
+
while (forwarding) {
|
|
18132
|
+
const chunk = await ctx.stdin.read();
|
|
18133
|
+
if (chunk === null) {
|
|
18134
|
+
proc.endInput?.();
|
|
18135
|
+
break;
|
|
18136
|
+
}
|
|
18137
|
+
try {
|
|
18138
|
+
proc.write(new TextDecoder().decode(chunk));
|
|
18139
|
+
} catch {
|
|
18140
|
+
break;
|
|
18141
|
+
}
|
|
18142
|
+
}
|
|
18143
|
+
})();
|
|
18144
|
+
}
|
|
18145
|
+
let onAbort;
|
|
18146
|
+
const aborted = new Promise((resolve3) => {
|
|
18147
|
+
onAbort = () => {
|
|
18148
|
+
try {
|
|
18149
|
+
proc.kill();
|
|
18150
|
+
} catch {
|
|
18151
|
+
}
|
|
18152
|
+
resolve3({ exitCode: 137 });
|
|
18153
|
+
};
|
|
18154
|
+
if (ctx.signal.aborted) onAbort();
|
|
18155
|
+
else ctx.signal.addEventListener("abort", onAbort, { once: true });
|
|
18156
|
+
});
|
|
18157
|
+
const result = await Promise.race([proc.completion, aborted]);
|
|
18158
|
+
forwarding = false;
|
|
18159
|
+
if (onAbort) ctx.signal.removeEventListener("abort", onAbort);
|
|
18160
|
+
exitCode = result.exitCode;
|
|
18161
|
+
} catch (e) {
|
|
18162
|
+
ctx.stderr.write(`node: ${e instanceof Error ? e.message : String(e)}
|
|
18163
|
+
`);
|
|
18164
|
+
exitCode = 1;
|
|
18165
|
+
} finally {
|
|
18166
|
+
for (const temp of invocation.temps) {
|
|
18167
|
+
try {
|
|
18168
|
+
ctx.vfs.unlink(temp);
|
|
18169
|
+
} catch {
|
|
18170
|
+
}
|
|
18171
|
+
}
|
|
18172
|
+
}
|
|
18173
|
+
return exitCode;
|
|
18174
|
+
}
|
|
18175
|
+
async function captureStdin(ctx) {
|
|
18176
|
+
if (ctx.stdin.isTTY || ctx.stdin.interactive) return null;
|
|
18177
|
+
const bytes2 = await ctx.stdin.readAll();
|
|
18178
|
+
if (bytes2.length === 0) return null;
|
|
18179
|
+
const path = tempPath("stdin", ctx.proc.pid, ".dat");
|
|
18180
|
+
ctx.vfs.writeFile(path, bytes2, { privileged: true, mode: 384 });
|
|
18181
|
+
return path;
|
|
18182
|
+
}
|
|
18183
|
+
var node = defineCommand({
|
|
18184
|
+
name: "node",
|
|
18185
|
+
path: "/usr/bin/node",
|
|
18186
|
+
aliases: ["nodejs"],
|
|
18187
|
+
summary: "run a JavaScript program with Node.js",
|
|
18188
|
+
usage: "node [options] [script.js] [arguments]",
|
|
18189
|
+
manual: `Runs JavaScript with a real Node.js API surface \u2014 fs, path, http,
|
|
18190
|
+
crypto, streams, worker_threads and npm packages \u2014 inside the container.
|
|
18191
|
+
The filesystem a script sees is the container's filesystem.`,
|
|
18192
|
+
async run(ctx) {
|
|
18193
|
+
const argv = ctx.args;
|
|
18194
|
+
const temps = [];
|
|
18195
|
+
let i = 0;
|
|
18196
|
+
let evalSource;
|
|
18197
|
+
let printResult = false;
|
|
18198
|
+
let scriptArg;
|
|
18199
|
+
const preloads = [];
|
|
18200
|
+
const envFiles = [];
|
|
18201
|
+
let testMode = false;
|
|
18202
|
+
let checkOnly = false;
|
|
18203
|
+
const testSettings = { namePatterns: [] };
|
|
18204
|
+
for (; i < argv.length; i++) {
|
|
18205
|
+
const arg = argv[i];
|
|
18206
|
+
if (arg === "-v" || arg === "--version") {
|
|
18207
|
+
ctx.line(NODE_VERSION);
|
|
18208
|
+
return 0;
|
|
18209
|
+
}
|
|
18210
|
+
if (arg === "-h" || arg === "--help") {
|
|
18211
|
+
printHelp(ctx);
|
|
18212
|
+
return 0;
|
|
18213
|
+
}
|
|
18214
|
+
if (arg === "-e" || arg === "--eval") {
|
|
18215
|
+
evalSource = argv[++i] ?? "";
|
|
18216
|
+
i++;
|
|
18217
|
+
break;
|
|
18218
|
+
}
|
|
18219
|
+
if (arg === "-p" || arg === "--print") {
|
|
18220
|
+
printResult = true;
|
|
18221
|
+
evalSource = argv[++i] ?? "";
|
|
18222
|
+
i++;
|
|
18223
|
+
break;
|
|
18224
|
+
}
|
|
18225
|
+
if (arg.startsWith("--eval=")) {
|
|
18226
|
+
evalSource = arg.slice("--eval=".length);
|
|
18227
|
+
i++;
|
|
18228
|
+
break;
|
|
18229
|
+
}
|
|
18230
|
+
if (arg.startsWith("--print=")) {
|
|
18231
|
+
printResult = true;
|
|
18232
|
+
evalSource = arg.slice("--print=".length);
|
|
18233
|
+
i++;
|
|
18234
|
+
break;
|
|
18235
|
+
}
|
|
18236
|
+
if (arg === "--") {
|
|
18237
|
+
i++;
|
|
18238
|
+
break;
|
|
18239
|
+
}
|
|
18240
|
+
const flag = arg.startsWith("--") ? arg.split("=", 1)[0] : arg;
|
|
18241
|
+
if (VALUE_FLAGS.has(flag)) {
|
|
18242
|
+
const value = arg.length > flag.length ? arg.slice(flag.length + 1) : argv[++i];
|
|
18243
|
+
if (value === void 0) {
|
|
18244
|
+
ctx.stderr.write(`node: ${flag} requires an argument
|
|
18245
|
+
`);
|
|
18246
|
+
return 9;
|
|
18247
|
+
}
|
|
18248
|
+
if (flag === "-r" || flag === "--require" || flag === "--import") preloads.push(value);
|
|
18249
|
+
else if (flag === "--env-file") envFiles.push({ path: value, optional: false });
|
|
18250
|
+
else if (flag === "--env-file-if-exists") envFiles.push({ path: value, optional: true });
|
|
18251
|
+
else if (flag === "--test-reporter") testSettings.reporter = value === "tap" ? "tap" : "spec";
|
|
18252
|
+
else if (flag === "--test-name-pattern") testSettings.namePatterns.push(value);
|
|
18253
|
+
else if (flag === "--loader" || flag === "--experimental-loader") {
|
|
18254
|
+
ctx.stderr.write(`node: ${flag} is not supported in this container; ${value} was not loaded
|
|
18255
|
+
`);
|
|
18256
|
+
}
|
|
18257
|
+
continue;
|
|
18258
|
+
}
|
|
18259
|
+
if (arg === "--test") {
|
|
18260
|
+
testMode = true;
|
|
18261
|
+
continue;
|
|
18262
|
+
}
|
|
18263
|
+
if (arg === "--test-only") {
|
|
18264
|
+
testSettings.only = true;
|
|
18265
|
+
continue;
|
|
18266
|
+
}
|
|
18267
|
+
if (arg === "-c" || arg === "--check") {
|
|
18268
|
+
checkOnly = true;
|
|
18269
|
+
continue;
|
|
18270
|
+
}
|
|
18271
|
+
if (flag === "--watch" || flag === "--watch-path" || flag === "--watch-preserve-output") {
|
|
18272
|
+
ctx.stderr.write(
|
|
18273
|
+
`node: ${flag} is not available in this container: file changes are not watched. Run the program again after changing it.
|
|
18274
|
+
`
|
|
18275
|
+
);
|
|
18276
|
+
return 9;
|
|
18277
|
+
}
|
|
18278
|
+
if (arg.startsWith("-") && arg !== "-") {
|
|
18279
|
+
continue;
|
|
18280
|
+
}
|
|
18281
|
+
scriptArg = arg;
|
|
18282
|
+
i++;
|
|
18283
|
+
break;
|
|
18284
|
+
}
|
|
18285
|
+
const scriptArgs = argv.slice(i);
|
|
18286
|
+
let env2;
|
|
18287
|
+
if (envFiles.length > 0) {
|
|
18288
|
+
const loaded = {};
|
|
18289
|
+
for (const file3 of envFiles) {
|
|
18290
|
+
let text2;
|
|
18291
|
+
try {
|
|
18292
|
+
text2 = ctx.vfs.readText(ctx.path(file3.path), ctx.cred);
|
|
18293
|
+
} catch {
|
|
18294
|
+
if (file3.optional) continue;
|
|
18295
|
+
ctx.stderr.write(`node: ${file3.path}: not found
|
|
18296
|
+
`);
|
|
18297
|
+
return 9;
|
|
18298
|
+
}
|
|
18299
|
+
Object.assign(loaded, parseEnvFile(text2));
|
|
18300
|
+
}
|
|
18301
|
+
env2 = { ...loaded, ...ctx.env };
|
|
18302
|
+
}
|
|
18303
|
+
const preloadSpecs = preloads.map((spec) => spec.startsWith(".") || spec.startsWith("/") ? ctx.path(spec) : spec);
|
|
18304
|
+
if (testMode) {
|
|
18305
|
+
return runTestFiles(ctx, scriptArg === void 0 ? scriptArgs : [scriptArg, ...scriptArgs], testSettings, preloads, env2 ?? ctx.env);
|
|
18306
|
+
}
|
|
18307
|
+
if (checkOnly && scriptArg !== void 0) {
|
|
18308
|
+
const script2 = resolveScript(ctx, scriptArg);
|
|
18309
|
+
if (!script2) {
|
|
18310
|
+
ctx.stderr.write(`node: cannot find module '${ctx.path(scriptArg)}'
|
|
18311
|
+
`);
|
|
18312
|
+
return 1;
|
|
18313
|
+
}
|
|
18314
|
+
return checkSyntax(ctx, script2);
|
|
18315
|
+
}
|
|
18316
|
+
if (evalSource !== void 0) {
|
|
18317
|
+
const body = printResult ? `const __sbxResult = (function(){ return (${evalSource}
|
|
18318
|
+
); })();
|
|
18319
|
+
console.log(typeof __sbxResult === 'string' ? __sbxResult : require('util').inspect(__sbxResult));` : evalSource;
|
|
18320
|
+
const path = tempPath("eval", ctx.proc.pid);
|
|
18321
|
+
const stdinPath2 = await captureStdin(ctx);
|
|
18322
|
+
if (stdinPath2) temps.push(stdinPath2);
|
|
18323
|
+
ctx.vfs.writeFile(path, buildBootstrapForEval(body, ["/usr/bin/node", ...scriptArgs], stdinPath2, preloadSpecs), {
|
|
18324
|
+
privileged: true,
|
|
18325
|
+
mode: 384
|
|
18326
|
+
});
|
|
18327
|
+
temps.push(path);
|
|
18328
|
+
return execute(ctx, { script: path, argv: scriptArgs, stdinPath: stdinPath2, temps, ...env2 ? { env: env2 } : {} });
|
|
18329
|
+
}
|
|
18330
|
+
if (scriptArg === void 0 || scriptArg === "-") {
|
|
18331
|
+
if (ctx.stdin.isTTY) {
|
|
18332
|
+
ctx.line(`Welcome to Node.js ${NODE_VERSION}.`);
|
|
18333
|
+
ctx.line('Type ".help" for more information.');
|
|
18334
|
+
return runRepl(ctx);
|
|
18335
|
+
}
|
|
18336
|
+
const source = new TextDecoder().decode(await ctx.stdin.readAll());
|
|
18337
|
+
if (source.trim() === "") return 0;
|
|
18338
|
+
const path = tempPath("stdin-script", ctx.proc.pid);
|
|
18339
|
+
ctx.vfs.writeFile(path, buildBootstrapForEval(source, ["/usr/bin/node", ...scriptArgs], null, preloadSpecs), {
|
|
18340
|
+
privileged: true,
|
|
18341
|
+
mode: 384
|
|
18342
|
+
});
|
|
18343
|
+
temps.push(path);
|
|
18344
|
+
return execute(ctx, { script: path, argv: scriptArgs, temps, ...env2 ? { env: env2 } : {} });
|
|
18345
|
+
}
|
|
18346
|
+
const script = resolveScript(ctx, scriptArg);
|
|
18347
|
+
if (!script) {
|
|
18348
|
+
ctx.stderr.write(
|
|
18349
|
+
`node:internal/modules/cjs/loader:1215
|
|
18350
|
+
throw err;
|
|
18351
|
+
^
|
|
18352
|
+
|
|
18353
|
+
Error: Cannot find module '${ctx.path(scriptArg)}'
|
|
18354
|
+
`
|
|
18355
|
+
);
|
|
18356
|
+
return 1;
|
|
18357
|
+
}
|
|
18358
|
+
const stdinPath = await captureStdin(ctx);
|
|
18359
|
+
if (stdinPath) temps.push(stdinPath);
|
|
18360
|
+
const sibling = siblingPath(script, ctx.proc.pid);
|
|
18361
|
+
try {
|
|
18362
|
+
const source = ctx.vfs.readText(script, ctx.cred);
|
|
18363
|
+
ctx.vfs.writeFile(sibling, withPrelude(source, buildPrelude(script, scriptArgs, stdinPath, preloadSpecs)), {
|
|
18364
|
+
privileged: true,
|
|
18365
|
+
mode: 384
|
|
18366
|
+
});
|
|
18367
|
+
temps.push(sibling);
|
|
18368
|
+
return await execute(ctx, {
|
|
18369
|
+
script: sibling,
|
|
18370
|
+
argvPath: script,
|
|
18371
|
+
argv: scriptArgs,
|
|
18372
|
+
stdinPath,
|
|
18373
|
+
temps,
|
|
18374
|
+
...env2 ? { env: env2 } : {}
|
|
18375
|
+
});
|
|
18376
|
+
} catch {
|
|
18377
|
+
return await execute(ctx, { script, argv: scriptArgs, stdinPath, temps, ...env2 ? { env: env2 } : {} });
|
|
18378
|
+
}
|
|
18379
|
+
}
|
|
18380
|
+
});
|
|
18381
|
+
function buildBootstrapForEval(source, argv, stdinPath, preloads = []) {
|
|
18382
|
+
const prelude = stdinPath ? `const fs = require('fs');
|
|
18383
|
+
const { Readable } = require('stream');
|
|
18384
|
+
let __sbxData; try { __sbxData = fs.readFileSync(${JSON.stringify(stdinPath)}); } catch (e) { __sbxData = Buffer.alloc(0); }
|
|
18385
|
+
const __sbxStdin = Readable.from([__sbxData]);
|
|
18386
|
+
__sbxStdin.isTTY = false;
|
|
18387
|
+
__sbxStdin.setRawMode = function () { return this; };
|
|
18388
|
+
try { Object.defineProperty(process, 'stdin', { value: __sbxStdin, configurable: true, writable: true }); } catch (e) { process.stdin = __sbxStdin; }
|
|
18389
|
+
` : "";
|
|
18390
|
+
return `${BUFFER_COMPAT_SHIM}process.argv = ${JSON.stringify(argv)};
|
|
18391
|
+
${prelude}${preloadRequires(preloads)}${source}
|
|
18392
|
+
`;
|
|
18393
|
+
}
|
|
18394
|
+
function resolveScript(ctx, operand) {
|
|
18395
|
+
const base2 = ctx.path(operand);
|
|
18396
|
+
const candidates = [base2, `${base2}.js`, `${base2}.mjs`, `${base2}.cjs`, `${base2}.json`];
|
|
18397
|
+
for (const candidate of candidates) {
|
|
18398
|
+
try {
|
|
18399
|
+
const st = ctx.vfs.stat(candidate, { cred: ctx.cred });
|
|
18400
|
+
if (st.isFile()) return ctx.vfs.realpath(candidate, ctx.cred);
|
|
18401
|
+
if (st.isDirectory()) {
|
|
18402
|
+
const manifest = join(candidate, "package.json");
|
|
18403
|
+
if (ctx.vfs.lexists(manifest)) {
|
|
18404
|
+
try {
|
|
18405
|
+
const main = JSON.parse(ctx.vfs.readText(manifest, ctx.cred)).main;
|
|
18406
|
+
if (main) {
|
|
18407
|
+
const mainPath = resolve(candidate, main);
|
|
18408
|
+
if (ctx.vfs.lexists(mainPath)) return ctx.vfs.realpath(mainPath, ctx.cred);
|
|
18409
|
+
if (ctx.vfs.lexists(mainPath + ".js")) return ctx.vfs.realpath(mainPath + ".js", ctx.cred);
|
|
18410
|
+
}
|
|
18411
|
+
} catch {
|
|
18412
|
+
}
|
|
18413
|
+
}
|
|
18414
|
+
for (const index of ["index.js", "index.mjs", "index.cjs"]) {
|
|
18415
|
+
const path = join(candidate, index);
|
|
18416
|
+
if (ctx.vfs.lexists(path)) return ctx.vfs.realpath(path, ctx.cred);
|
|
18417
|
+
}
|
|
18418
|
+
}
|
|
18419
|
+
} catch {
|
|
18420
|
+
}
|
|
18421
|
+
}
|
|
18422
|
+
return null;
|
|
18423
|
+
}
|
|
18424
|
+
async function runRepl(ctx) {
|
|
18425
|
+
const historyPath = join(ctx.env.HOME ?? "/root", ".node_repl_history");
|
|
18426
|
+
const statements = [];
|
|
18427
|
+
for (; ; ) {
|
|
18428
|
+
ctx.write("> ");
|
|
18429
|
+
const line = await ctx.stdin.readLine();
|
|
18430
|
+
if (line === null) {
|
|
18431
|
+
ctx.line("");
|
|
18432
|
+
break;
|
|
18433
|
+
}
|
|
18434
|
+
const trimmed = line.trim();
|
|
18435
|
+
if (trimmed === ".exit") break;
|
|
18436
|
+
if (trimmed === ".help") {
|
|
18437
|
+
ctx.line(".exit Exit the REPL");
|
|
18438
|
+
ctx.line(".help Print this help message");
|
|
18439
|
+
ctx.line(".clear Reset the session context");
|
|
18440
|
+
continue;
|
|
18441
|
+
}
|
|
18442
|
+
if (trimmed === ".clear") {
|
|
18443
|
+
statements.length = 0;
|
|
18444
|
+
continue;
|
|
18445
|
+
}
|
|
18446
|
+
if (trimmed === "") continue;
|
|
18447
|
+
const program = [...statements, `console.log(require('util').inspect((${trimmed})))`].join(";\n");
|
|
18448
|
+
const fallback = [...statements, trimmed].join(";\n");
|
|
18449
|
+
const path = tempPath("repl", ctx.proc.pid);
|
|
18450
|
+
ctx.vfs.writeFile(path, program, { privileged: true, mode: 384 });
|
|
18451
|
+
const result = await runQuiet(ctx, path);
|
|
18452
|
+
if (result.exitCode !== 0) {
|
|
18453
|
+
ctx.vfs.writeFile(path, fallback, { privileged: true, mode: 384 });
|
|
18454
|
+
const second = await runQuiet(ctx, path);
|
|
18455
|
+
ctx.write(second.stdout);
|
|
18456
|
+
if (second.exitCode === 0) statements.push(trimmed);
|
|
18457
|
+
else ctx.stderr.write(second.stderr);
|
|
18458
|
+
} else {
|
|
18459
|
+
ctx.write(result.stdout);
|
|
18460
|
+
statements.push(trimmed);
|
|
18461
|
+
}
|
|
18462
|
+
try {
|
|
18463
|
+
ctx.vfs.unlink(path);
|
|
18464
|
+
} catch {
|
|
18465
|
+
}
|
|
18466
|
+
try {
|
|
18467
|
+
ctx.vfs.appendFile(historyPath, trimmed + "\n", { cred: ctx.cred });
|
|
18468
|
+
} catch {
|
|
18469
|
+
}
|
|
18470
|
+
}
|
|
18471
|
+
return 0;
|
|
18472
|
+
}
|
|
18473
|
+
async function runQuiet(ctx, script) {
|
|
18474
|
+
try {
|
|
18475
|
+
const proc = await ctx.kernel.pod.spawn("node", [script], { cwd: ctx.cwd, env: ctx.env });
|
|
18476
|
+
return await proc.completion;
|
|
18477
|
+
} catch (e) {
|
|
18478
|
+
return { exitCode: 1, stdout: "", stderr: `${e instanceof Error ? e.message : String(e)}
|
|
18479
|
+
` };
|
|
18480
|
+
}
|
|
18481
|
+
}
|
|
18482
|
+
function printHelp(ctx) {
|
|
18483
|
+
ctx.line("Usage: node [options] [script.js] [arguments]");
|
|
18484
|
+
ctx.line(" node --test [files or globs]");
|
|
18485
|
+
ctx.line("");
|
|
18486
|
+
ctx.line("Options:");
|
|
18487
|
+
ctx.line(" -v, --version print Node.js version");
|
|
18488
|
+
ctx.line(" -e, --eval script evaluate script");
|
|
18489
|
+
ctx.line(" -p, --print evaluate script and print result");
|
|
18490
|
+
ctx.line(" -c, --check check syntax without running");
|
|
18491
|
+
ctx.line(" -r, --require module load a module before the program");
|
|
18492
|
+
ctx.line(" --import module load a module before the program");
|
|
18493
|
+
ctx.line(" --env-file file load environment variables from a file");
|
|
18494
|
+
ctx.line(" --test run test files with node:test");
|
|
18495
|
+
ctx.line(" --test-reporter spec|tap choose the test report format");
|
|
18496
|
+
ctx.line(" --test-name-pattern regex run only tests whose name matches");
|
|
18497
|
+
ctx.line(" -h, --help print this message");
|
|
18498
|
+
}
|
|
18499
|
+
var VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
18500
|
+
"-r",
|
|
18501
|
+
"--require",
|
|
18502
|
+
"--import",
|
|
18503
|
+
"--loader",
|
|
18504
|
+
"--experimental-loader",
|
|
18505
|
+
"--env-file",
|
|
18506
|
+
"--env-file-if-exists",
|
|
18507
|
+
"--input-type",
|
|
18508
|
+
"--title",
|
|
18509
|
+
"-C",
|
|
18510
|
+
"--conditions",
|
|
18511
|
+
"--test-reporter",
|
|
18512
|
+
"--test-reporter-destination",
|
|
18513
|
+
"--test-name-pattern",
|
|
18514
|
+
"--test-skip-pattern",
|
|
18515
|
+
"--test-concurrency",
|
|
18516
|
+
"--test-timeout",
|
|
18517
|
+
"--test-shard",
|
|
18518
|
+
"--disable-warning",
|
|
18519
|
+
"--redirect-warnings",
|
|
18520
|
+
"--stack-trace-limit",
|
|
18521
|
+
"--inspect-port",
|
|
18522
|
+
"--report-dir",
|
|
18523
|
+
"--report-filename"
|
|
18524
|
+
]);
|
|
18525
|
+
function parseEnvFile(text2) {
|
|
18526
|
+
const out = {};
|
|
18527
|
+
for (const raw of text2.split(/\r?\n/)) {
|
|
18528
|
+
const line = raw.trim();
|
|
18529
|
+
if (!line || line.startsWith("#")) continue;
|
|
18530
|
+
const match2 = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_.-]*)\s*=\s*(.*)$/.exec(line);
|
|
18531
|
+
if (!match2) continue;
|
|
18532
|
+
let value = match2[2];
|
|
18533
|
+
const quote3 = value[0];
|
|
18534
|
+
if ((quote3 === '"' || quote3 === "'" || quote3 === "`") && value.length >= 2 && value.endsWith(quote3)) {
|
|
18535
|
+
value = value.slice(1, -1);
|
|
18536
|
+
if (quote3 === '"') value = value.replace(/\\n/g, "\n");
|
|
18537
|
+
} else {
|
|
18538
|
+
const comment = value.indexOf(" #");
|
|
18539
|
+
if (comment >= 0) value = value.slice(0, comment);
|
|
18540
|
+
value = value.trim();
|
|
18541
|
+
}
|
|
18542
|
+
out[match2[1]] = value;
|
|
18543
|
+
}
|
|
18544
|
+
return out;
|
|
18545
|
+
}
|
|
18546
|
+
var AsyncFunction = Object.getPrototypeOf(async function() {
|
|
18547
|
+
}).constructor;
|
|
18548
|
+
function checkSyntax(ctx, script) {
|
|
18549
|
+
let source = ctx.vfs.readText(script, ctx.cred);
|
|
18550
|
+
if (source.startsWith("#!")) source = `//${source.slice(2)}`;
|
|
18551
|
+
try {
|
|
18552
|
+
const esm = script.endsWith(".mjs") || !script.endsWith(".cjs") && looksLikeEsm(source);
|
|
18553
|
+
const transformed = esm ? transformEsm(source, script) : null;
|
|
18554
|
+
new AsyncFunction("exports", "require", "module", "__filename", "__dirname", transformed?.code ?? source);
|
|
18555
|
+
return 0;
|
|
18556
|
+
} catch (error) {
|
|
18557
|
+
if (!(error instanceof SyntaxError)) throw error;
|
|
18558
|
+
ctx.stderr.write(`${script}
|
|
18559
|
+
|
|
18560
|
+
${error.name}: ${error.message}
|
|
18561
|
+
|
|
18562
|
+
Node.js ${NODE_VERSION}
|
|
18563
|
+
`);
|
|
18564
|
+
return 1;
|
|
18565
|
+
}
|
|
18566
|
+
}
|
|
18567
|
+
var TEST_FILE_NAME = /^(?:test|test-.+|.+[.\-_]test)\.(?:c|m)?js$/;
|
|
18568
|
+
var SCRIPT_FILE = /\.(?:c|m)?js$/;
|
|
18569
|
+
function globToRegExp(pattern) {
|
|
18570
|
+
let out = "";
|
|
18571
|
+
for (let index = 0; index < pattern.length; index += 1) {
|
|
18572
|
+
const ch = pattern[index];
|
|
18573
|
+
if (ch === "*") {
|
|
18574
|
+
if (pattern[index + 1] === "*") {
|
|
18575
|
+
index += 1;
|
|
18576
|
+
if (pattern[index + 1] === "/") index += 1;
|
|
18577
|
+
out += "(?:.*/)?";
|
|
18578
|
+
} else out += "[^/]*";
|
|
18579
|
+
} else if (ch === "?") out += "[^/]";
|
|
18580
|
+
else out += ch.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
18581
|
+
}
|
|
18582
|
+
return new RegExp(`^${out}$`);
|
|
18583
|
+
}
|
|
18584
|
+
function discoverTestFiles(ctx, patterns) {
|
|
18585
|
+
const files = /* @__PURE__ */ new Set();
|
|
18586
|
+
const missing = [];
|
|
18587
|
+
const walk = (dir3, visit, underTestDir = false) => {
|
|
18588
|
+
let names;
|
|
18589
|
+
try {
|
|
18590
|
+
names = ctx.vfs.readdir(dir3, ctx.cred);
|
|
18591
|
+
} catch {
|
|
18592
|
+
return;
|
|
18593
|
+
}
|
|
18594
|
+
for (const name of [...names].sort()) {
|
|
18595
|
+
if (name === "node_modules" || name.startsWith(".")) continue;
|
|
18596
|
+
const path = join(dir3, name);
|
|
18597
|
+
let isDirectory;
|
|
18598
|
+
try {
|
|
18599
|
+
isDirectory = ctx.vfs.stat(path, { cred: ctx.cred }).isDirectory();
|
|
18600
|
+
} catch {
|
|
18601
|
+
continue;
|
|
18602
|
+
}
|
|
18603
|
+
if (isDirectory) walk(path, visit, underTestDir || name === "test");
|
|
18604
|
+
else visit(path, name, underTestDir);
|
|
18605
|
+
}
|
|
18606
|
+
};
|
|
18607
|
+
const byName = (path, name, underTestDir) => {
|
|
18608
|
+
if (SCRIPT_FILE.test(name) && (underTestDir || TEST_FILE_NAME.test(name))) files.add(path);
|
|
18609
|
+
};
|
|
18610
|
+
if (patterns.length === 0) walk(ctx.cwd, byName);
|
|
18611
|
+
for (const pattern of patterns) {
|
|
18612
|
+
const target = ctx.path(pattern);
|
|
18613
|
+
let stat2 = null;
|
|
18614
|
+
try {
|
|
18615
|
+
stat2 = ctx.vfs.stat(target, { cred: ctx.cred });
|
|
18616
|
+
} catch {
|
|
18617
|
+
stat2 = null;
|
|
18618
|
+
}
|
|
18619
|
+
if (stat2?.isFile()) {
|
|
18620
|
+
files.add(target);
|
|
18621
|
+
continue;
|
|
18622
|
+
}
|
|
18623
|
+
if (stat2?.isDirectory()) {
|
|
18624
|
+
walk(target, byName, basename(target) === "test");
|
|
18625
|
+
continue;
|
|
18626
|
+
}
|
|
18627
|
+
if (/[*?]/.test(pattern)) {
|
|
18628
|
+
const matcher = globToRegExp(target);
|
|
18629
|
+
const before = files.size;
|
|
18630
|
+
walk(ctx.cwd, (path) => {
|
|
18631
|
+
if (matcher.test(path)) files.add(path);
|
|
18632
|
+
});
|
|
18633
|
+
if (files.size > before) continue;
|
|
18634
|
+
}
|
|
18635
|
+
missing.push(pattern);
|
|
18636
|
+
}
|
|
18637
|
+
return { files: [...files].sort(), missing };
|
|
18638
|
+
}
|
|
18639
|
+
async function runTestFiles(ctx, args, settings, preloads, env2) {
|
|
18640
|
+
const patterns = [];
|
|
18641
|
+
for (const arg of args) {
|
|
18642
|
+
if (arg.startsWith("--test-reporter=")) settings.reporter = arg.endsWith("=tap") ? "tap" : "spec";
|
|
18643
|
+
else if (arg.startsWith("--test-name-pattern=")) settings.namePatterns.push(arg.slice("--test-name-pattern=".length));
|
|
18644
|
+
else if (arg === "--test-only") settings.only = true;
|
|
18645
|
+
else if (!arg.startsWith("-")) patterns.push(arg);
|
|
18646
|
+
}
|
|
18647
|
+
const { files, missing } = discoverTestFiles(ctx, patterns);
|
|
18648
|
+
if (missing.length > 0) {
|
|
18649
|
+
for (const pattern of missing) ctx.stderr.write(`Could not find '${ctx.path(pattern)}'
|
|
18650
|
+
`);
|
|
18651
|
+
return 1;
|
|
18652
|
+
}
|
|
18653
|
+
if (files.length === 0) {
|
|
18654
|
+
ctx.stderr.write(
|
|
18655
|
+
"node --test: no test files found. Test files are named *.test.js, *-test.js, *_test.js, test-*.js or test.js (also .mjs and .cjs), or live in a test/ directory; node_modules is not searched.\n"
|
|
18656
|
+
);
|
|
18657
|
+
return 0;
|
|
18658
|
+
}
|
|
18659
|
+
const childEnv = { ...env2, SANDBOXEDJS_NODE_TEST: JSON.stringify(settings) };
|
|
18660
|
+
let failed = 0;
|
|
18661
|
+
for (const file3 of files) {
|
|
18662
|
+
const child = ctx.kernel.spawn(["node", ...preloads.flatMap((spec) => ["-r", spec]), file3], {
|
|
18663
|
+
cwd: ctx.cwd,
|
|
18664
|
+
env: childEnv,
|
|
18665
|
+
cred: ctx.cred,
|
|
18666
|
+
ppid: ctx.proc.pid,
|
|
18667
|
+
stdout: ctx.stdout,
|
|
18668
|
+
stderr: ctx.stderr
|
|
18669
|
+
});
|
|
18670
|
+
if (await child.wait() !== 0) failed += 1;
|
|
18671
|
+
}
|
|
18672
|
+
if (files.length > 1) {
|
|
18673
|
+
ctx.line(settings.reporter === "tap" ? `# files ${files.length} failed ${failed}` : `\u2139 files ${files.length}, failed ${failed}`);
|
|
18674
|
+
}
|
|
18675
|
+
return failed > 0 ? 1 : 0;
|
|
18676
|
+
}
|
|
18677
|
+
var nodeVersionFile = defineCommand({
|
|
18678
|
+
name: "nvm",
|
|
18679
|
+
path: "/usr/local/bin/nvm",
|
|
18680
|
+
summary: "node version manager (single-version stub)",
|
|
18681
|
+
run(ctx) {
|
|
18682
|
+
const sub = ctx.args[0];
|
|
18683
|
+
if (sub === "current" || sub === "version") {
|
|
18684
|
+
ctx.line(NODE_VERSION);
|
|
18685
|
+
return 0;
|
|
18686
|
+
}
|
|
18687
|
+
if (sub === "ls" || sub === "list") {
|
|
18688
|
+
ctx.line(`-> ${NODE_VERSION}`);
|
|
18689
|
+
return 0;
|
|
18690
|
+
}
|
|
18691
|
+
ctx.line(`nvm: only ${NODE_VERSION} is available in this container`);
|
|
18692
|
+
return 0;
|
|
18693
|
+
}
|
|
18694
|
+
});
|
|
18695
|
+
function nodeCommands() {
|
|
18696
|
+
return [node, nodeVersionFile];
|
|
18697
|
+
}
|
|
18698
|
+
|
|
18699
|
+
// src/python/python.ts
|
|
18700
|
+
init_path();
|
|
18701
|
+
|
|
18702
|
+
// src/python/host-abi.ts
|
|
18703
|
+
var SBX_HOST_ABI_VERSION = 1;
|
|
18704
|
+
var SBX_REQUEST_HEADER_BYTES = 16;
|
|
18705
|
+
var SBX_RESPONSE_HEADER_BYTES = 20;
|
|
18706
|
+
var Op = {
|
|
18707
|
+
handshake: 0,
|
|
18708
|
+
openat: 1,
|
|
18709
|
+
close: 2,
|
|
18710
|
+
read: 3,
|
|
18711
|
+
write: 4,
|
|
18712
|
+
pread: 5,
|
|
18713
|
+
pwrite: 6,
|
|
18714
|
+
lseek: 7,
|
|
18715
|
+
fstat: 8,
|
|
18716
|
+
statat: 9,
|
|
18717
|
+
ftruncate: 10,
|
|
18718
|
+
renameat: 11,
|
|
18719
|
+
unlinkat: 12,
|
|
18720
|
+
mkdirat: 13,
|
|
18721
|
+
readlinkat: 14,
|
|
18722
|
+
symlinkat: 15,
|
|
18723
|
+
getdents: 16,
|
|
18724
|
+
fsync: 17,
|
|
18725
|
+
dup: 256,
|
|
18726
|
+
dup2: 257,
|
|
18727
|
+
get_flags: 258,
|
|
18728
|
+
set_flags: 259,
|
|
18729
|
+
pipe: 512,
|
|
18730
|
+
poll: 768,
|
|
18731
|
+
clock_gettime: 1024,
|
|
18732
|
+
sleep: 1025,
|
|
18733
|
+
getpid: 1280,
|
|
18734
|
+
getcwd: 1281,
|
|
17929
18735
|
chdir: 1282,
|
|
17930
18736
|
environ: 1283,
|
|
17931
18737
|
getrandom: 1536,
|
|
@@ -18363,7 +19169,7 @@ var wheels_default = {
|
|
|
18363
19169
|
|
|
18364
19170
|
// package.json
|
|
18365
19171
|
var package_default = {
|
|
18366
|
-
version: "0.1.
|
|
19172
|
+
version: "0.1.74"};
|
|
18367
19173
|
|
|
18368
19174
|
// src/python/config.ts
|
|
18369
19175
|
function runtimeModuleUrl() {
|
|
@@ -22334,7 +23140,7 @@ var pyodideModule = null;
|
|
|
22334
23140
|
var indexUrl;
|
|
22335
23141
|
var moduleUrl;
|
|
22336
23142
|
var DEFAULT_BROWSER_INDEX_URL = "https://cdn.jsdelivr.net/pyodide/v0.28.3/full/";
|
|
22337
|
-
var
|
|
23143
|
+
var isNode3 = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
22338
23144
|
function configureCPython(options = {}) {
|
|
22339
23145
|
if (options.indexURL !== void 0) indexUrl = options.indexURL;
|
|
22340
23146
|
if (options.moduleURL !== void 0) {
|
|
@@ -22350,7 +23156,7 @@ function importPyodide() {
|
|
|
22350
23156
|
/* webpackIgnore: true */
|
|
22351
23157
|
moduleUrl
|
|
22352
23158
|
);
|
|
22353
|
-
} else if (
|
|
23159
|
+
} else if (isNode3) {
|
|
22354
23160
|
pyodideModule = nodeOnlyModule("pyodide");
|
|
22355
23161
|
} else {
|
|
22356
23162
|
pyodideModule = import(
|
|
@@ -22364,7 +23170,7 @@ function importPyodide() {
|
|
|
22364
23170
|
}
|
|
22365
23171
|
async function resolveIndexUrl() {
|
|
22366
23172
|
if (indexUrl) return indexUrl;
|
|
22367
|
-
if (!
|
|
23173
|
+
if (!isNode3) return DEFAULT_BROWSER_INDEX_URL;
|
|
22368
23174
|
try {
|
|
22369
23175
|
const { createRequire } = await nodeBuiltin("module");
|
|
22370
23176
|
const path = await nodeBuiltin("path");
|
|
@@ -24303,7 +25109,7 @@ function renameShadowedExports(source) {
|
|
|
24303
25109
|
(node2) => node2.type.startsWith("Import") || node2.type.startsWith("Export")
|
|
24304
25110
|
);
|
|
24305
25111
|
if (!isModule) return null;
|
|
24306
|
-
const programScope = { bindsExports:
|
|
25112
|
+
const programScope = { bindsExports: hoistedNames2(body).has(NAME), parent: null };
|
|
24307
25113
|
if (!programScope.bindsExports) return null;
|
|
24308
25114
|
const targets = [];
|
|
24309
25115
|
let bail = false;
|
|
@@ -24319,24 +25125,24 @@ function renameShadowedExports(source) {
|
|
|
24319
25125
|
function visit(node2, scope) {
|
|
24320
25126
|
if (bail) return;
|
|
24321
25127
|
let childScope = scope;
|
|
24322
|
-
let skip =
|
|
25128
|
+
let skip = NOTHING2;
|
|
24323
25129
|
switch (node2.type) {
|
|
24324
25130
|
case "FunctionDeclaration":
|
|
24325
25131
|
case "FunctionExpression":
|
|
24326
25132
|
case "ArrowFunctionExpression": {
|
|
24327
25133
|
const names = /* @__PURE__ */ new Set();
|
|
24328
|
-
for (const param of node2.params ?? [])
|
|
25134
|
+
for (const param of node2.params ?? []) collectPattern2(param, names);
|
|
24329
25135
|
if (isExports(node2.id) && node2.type === "FunctionExpression") names.add(NAME);
|
|
24330
25136
|
const fnBody = node2.body;
|
|
24331
25137
|
if (fnBody?.type === "BlockStatement") {
|
|
24332
|
-
for (const name of
|
|
25138
|
+
for (const name of hoistedNames2(fnBody.body)) names.add(name);
|
|
24333
25139
|
}
|
|
24334
25140
|
childScope = { bindsExports: names.has(NAME), parent: scope };
|
|
24335
25141
|
break;
|
|
24336
25142
|
}
|
|
24337
25143
|
case "CatchClause": {
|
|
24338
25144
|
const names = /* @__PURE__ */ new Set();
|
|
24339
|
-
if (node2.param)
|
|
25145
|
+
if (node2.param) collectPattern2(node2.param, names);
|
|
24340
25146
|
childScope = { bindsExports: names.has(NAME), parent: scope };
|
|
24341
25147
|
break;
|
|
24342
25148
|
}
|
|
@@ -24350,7 +25156,7 @@ function renameShadowedExports(source) {
|
|
|
24350
25156
|
case "StaticBlock":
|
|
24351
25157
|
if (node2 !== ast.body) {
|
|
24352
25158
|
childScope = {
|
|
24353
|
-
bindsExports:
|
|
25159
|
+
bindsExports: blockNames2(node2.body).has(NAME),
|
|
24354
25160
|
parent: scope
|
|
24355
25161
|
};
|
|
24356
25162
|
}
|
|
@@ -24362,7 +25168,7 @@ function renameShadowedExports(source) {
|
|
|
24362
25168
|
if (head2?.type === "VariableDeclaration" && head2.kind !== "var") {
|
|
24363
25169
|
const names = /* @__PURE__ */ new Set();
|
|
24364
25170
|
for (const declarator of head2.declarations) {
|
|
24365
|
-
|
|
25171
|
+
collectPattern2(declarator.id, names);
|
|
24366
25172
|
}
|
|
24367
25173
|
childScope = { bindsExports: names.has(NAME), parent: scope };
|
|
24368
25174
|
}
|
|
@@ -24386,7 +25192,7 @@ function renameShadowedExports(source) {
|
|
|
24386
25192
|
case "MemberExpression":
|
|
24387
25193
|
case "MethodDefinition":
|
|
24388
25194
|
case "PropertyDefinition":
|
|
24389
|
-
skip = node2.computed ?
|
|
25195
|
+
skip = node2.computed ? NOTHING2 : PROPERTY2;
|
|
24390
25196
|
break;
|
|
24391
25197
|
case "Property":
|
|
24392
25198
|
if (node2.computed) break;
|
|
@@ -24397,19 +25203,19 @@ function renameShadowedExports(source) {
|
|
|
24397
25203
|
}
|
|
24398
25204
|
return;
|
|
24399
25205
|
}
|
|
24400
|
-
skip =
|
|
25206
|
+
skip = PROPERTY2;
|
|
24401
25207
|
break;
|
|
24402
25208
|
case "LabeledStatement":
|
|
24403
25209
|
case "BreakStatement":
|
|
24404
25210
|
case "ContinueStatement":
|
|
24405
|
-
skip =
|
|
25211
|
+
skip = LABEL2;
|
|
24406
25212
|
break;
|
|
24407
25213
|
}
|
|
24408
25214
|
for (const [key, value] of Object.entries(node2)) {
|
|
24409
25215
|
if (key === "type" || key === "start" || key === "end" || skip.includes(key)) continue;
|
|
24410
25216
|
if (Array.isArray(value)) {
|
|
24411
|
-
for (const item of value) if (
|
|
24412
|
-
} else if (
|
|
25217
|
+
for (const item of value) if (isNode4(item)) visit(item, childScope);
|
|
25218
|
+
} else if (isNode4(value)) {
|
|
24413
25219
|
visit(value, childScope);
|
|
24414
25220
|
}
|
|
24415
25221
|
}
|
|
@@ -24421,73 +25227,73 @@ function resolvesToProgram(scope) {
|
|
|
24421
25227
|
}
|
|
24422
25228
|
return false;
|
|
24423
25229
|
}
|
|
24424
|
-
function
|
|
24425
|
-
const names =
|
|
24426
|
-
|
|
25230
|
+
function hoistedNames2(body) {
|
|
25231
|
+
const names = blockNames2(body);
|
|
25232
|
+
collectVars2(body, names);
|
|
24427
25233
|
return names;
|
|
24428
25234
|
}
|
|
24429
|
-
function
|
|
25235
|
+
function blockNames2(body) {
|
|
24430
25236
|
const names = /* @__PURE__ */ new Set();
|
|
24431
25237
|
for (const node2 of body ?? []) {
|
|
24432
25238
|
if (node2.type === "VariableDeclaration" && node2.kind !== "var") {
|
|
24433
25239
|
for (const declarator of node2.declarations) {
|
|
24434
|
-
|
|
25240
|
+
collectPattern2(declarator.id, names);
|
|
24435
25241
|
}
|
|
24436
|
-
} else if (node2.type === "ClassDeclaration" &&
|
|
25242
|
+
} else if (node2.type === "ClassDeclaration" && isNode4(node2.id)) {
|
|
24437
25243
|
names.add(node2.id.name);
|
|
24438
|
-
} else if (node2.type === "FunctionDeclaration" &&
|
|
25244
|
+
} else if (node2.type === "FunctionDeclaration" && isNode4(node2.id)) {
|
|
24439
25245
|
names.add(node2.id.name);
|
|
24440
25246
|
}
|
|
24441
25247
|
}
|
|
24442
25248
|
return names;
|
|
24443
25249
|
}
|
|
24444
|
-
function
|
|
25250
|
+
function collectVars2(nodes, names) {
|
|
24445
25251
|
if (Array.isArray(nodes)) {
|
|
24446
|
-
for (const item of nodes)
|
|
25252
|
+
for (const item of nodes) collectVars2(item, names);
|
|
24447
25253
|
return;
|
|
24448
25254
|
}
|
|
24449
|
-
if (!
|
|
25255
|
+
if (!isNode4(nodes)) return;
|
|
24450
25256
|
const node2 = nodes;
|
|
24451
25257
|
if (node2.type === "FunctionDeclaration" || node2.type === "FunctionExpression" || node2.type === "ArrowFunctionExpression") {
|
|
24452
|
-
if (
|
|
25258
|
+
if (isNode4(node2.id)) names.add(node2.id.name);
|
|
24453
25259
|
return;
|
|
24454
25260
|
}
|
|
24455
25261
|
if (node2.type === "VariableDeclaration" && node2.kind === "var") {
|
|
24456
25262
|
for (const declarator of node2.declarations) {
|
|
24457
|
-
|
|
25263
|
+
collectPattern2(declarator.id, names);
|
|
24458
25264
|
}
|
|
24459
25265
|
}
|
|
24460
25266
|
for (const [key, value] of Object.entries(node2)) {
|
|
24461
25267
|
if (key === "type" || key === "start" || key === "end") continue;
|
|
24462
|
-
|
|
25268
|
+
collectVars2(value, names);
|
|
24463
25269
|
}
|
|
24464
25270
|
}
|
|
24465
|
-
function
|
|
24466
|
-
if (!
|
|
25271
|
+
function collectPattern2(node2, names) {
|
|
25272
|
+
if (!isNode4(node2)) return;
|
|
24467
25273
|
switch (node2.type) {
|
|
24468
25274
|
case "Identifier":
|
|
24469
25275
|
names.add(node2.name);
|
|
24470
25276
|
return;
|
|
24471
25277
|
case "ObjectPattern":
|
|
24472
25278
|
for (const property of node2.properties) {
|
|
24473
|
-
|
|
25279
|
+
collectPattern2(property.value ?? property.argument, names);
|
|
24474
25280
|
}
|
|
24475
25281
|
return;
|
|
24476
25282
|
case "ArrayPattern":
|
|
24477
|
-
for (const element of node2.elements)
|
|
25283
|
+
for (const element of node2.elements) collectPattern2(element, names);
|
|
24478
25284
|
return;
|
|
24479
25285
|
case "AssignmentPattern":
|
|
24480
|
-
|
|
25286
|
+
collectPattern2(node2.left, names);
|
|
24481
25287
|
return;
|
|
24482
25288
|
case "RestElement":
|
|
24483
|
-
|
|
25289
|
+
collectPattern2(node2.argument, names);
|
|
24484
25290
|
return;
|
|
24485
25291
|
default:
|
|
24486
25292
|
return;
|
|
24487
25293
|
}
|
|
24488
25294
|
}
|
|
24489
25295
|
function isExports(value) {
|
|
24490
|
-
return
|
|
25296
|
+
return isNode4(value) && value.type === "Identifier" && value.name === NAME;
|
|
24491
25297
|
}
|
|
24492
25298
|
function freshName(source) {
|
|
24493
25299
|
let name = "__sandboxedjs_exports";
|
|
@@ -24495,12 +25301,12 @@ function freshName(source) {
|
|
|
24495
25301
|
while (source.includes(name)) name = `__sandboxedjs_exports${++suffix}`;
|
|
24496
25302
|
return name;
|
|
24497
25303
|
}
|
|
24498
|
-
function
|
|
25304
|
+
function isNode4(value) {
|
|
24499
25305
|
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
24500
25306
|
}
|
|
24501
|
-
var
|
|
24502
|
-
var
|
|
24503
|
-
var
|
|
25307
|
+
var NOTHING2 = [];
|
|
25308
|
+
var PROPERTY2 = ["property", "key"];
|
|
25309
|
+
var LABEL2 = ["label"];
|
|
24504
25310
|
|
|
24505
25311
|
// src/pkg/index.ts
|
|
24506
25312
|
init_path();
|
|
@@ -25246,752 +26052,356 @@ var ContainerFs = class {
|
|
|
25246
26052
|
this.vfs.symlink(target, clean(link));
|
|
25247
26053
|
}
|
|
25248
26054
|
async readlink(path) {
|
|
25249
|
-
return this.vfs.readlink(clean(path));
|
|
25250
|
-
}
|
|
25251
|
-
async realpath(path) {
|
|
25252
|
-
return this.vfs.realpath(clean(path));
|
|
25253
|
-
}
|
|
25254
|
-
async chmod(path, mode) {
|
|
25255
|
-
this.vfs.chmod(clean(path), mode);
|
|
25256
|
-
}
|
|
25257
|
-
async chown(path, uid, gid) {
|
|
25258
|
-
this.vfs.chown(clean(path), uid, gid, ROOT_CRED);
|
|
25259
|
-
}
|
|
25260
|
-
/** Every path beneath `root`, depth-first. */
|
|
25261
|
-
async walk(root = "/") {
|
|
25262
|
-
return [...this.vfs.walk(clean(root))];
|
|
25263
|
-
}
|
|
25264
|
-
/** Total bytes and file counts, as `df` reports them. */
|
|
25265
|
-
async usage(root = "/") {
|
|
25266
|
-
return this.vfs.usage(clean(root));
|
|
25267
|
-
}
|
|
25268
|
-
/** Read many files at once, keyed by path. */
|
|
25269
|
-
async readAll(paths) {
|
|
25270
|
-
const out = {};
|
|
25271
|
-
for (const path of paths) out[path] = this.vfs.readText(clean(path));
|
|
25272
|
-
return out;
|
|
25273
|
-
}
|
|
25274
|
-
/** Write a whole map of files, creating parents. */
|
|
25275
|
-
async writeAll(files, opts = {}) {
|
|
25276
|
-
for (const [key, value] of Object.entries(files)) {
|
|
25277
|
-
await this.writeFile(resolve(opts.cwd ?? "/", key), value);
|
|
25278
|
-
}
|
|
25279
|
-
}
|
|
25280
|
-
};
|
|
25281
|
-
|
|
25282
|
-
// src/container/session.ts
|
|
25283
|
-
var Session = class {
|
|
25284
|
-
constructor(kernel, init) {
|
|
25285
|
-
this.kernel = kernel;
|
|
25286
|
-
this.proc = kernel.procs.create({
|
|
25287
|
-
argv: ["-sh"],
|
|
25288
|
-
cwd: init.cwd,
|
|
25289
|
-
env: init.env,
|
|
25290
|
-
cred: init.cred,
|
|
25291
|
-
ppid: 1,
|
|
25292
|
-
kind: "shell",
|
|
25293
|
-
tty: "pts/0"
|
|
25294
|
-
});
|
|
25295
|
-
this.shell = new Shell({
|
|
25296
|
-
kernel,
|
|
25297
|
-
proc: this.proc,
|
|
25298
|
-
cwd: init.cwd,
|
|
25299
|
-
env: init.env,
|
|
25300
|
-
cred: init.cred,
|
|
25301
|
-
scriptName: "sh",
|
|
25302
|
-
options: { interactive: true }
|
|
25303
|
-
});
|
|
25304
|
-
this.hooks = init.hooks ?? {};
|
|
25305
|
-
}
|
|
25306
|
-
kernel;
|
|
25307
|
-
shell;
|
|
25308
|
-
proc;
|
|
25309
|
-
closed = false;
|
|
25310
|
-
hooks;
|
|
25311
|
-
get cwd() {
|
|
25312
|
-
return this.shell.cwd;
|
|
25313
|
-
}
|
|
25314
|
-
get env() {
|
|
25315
|
-
return this.shell.vars.environment();
|
|
25316
|
-
}
|
|
25317
|
-
get history() {
|
|
25318
|
-
return this.shell.history;
|
|
25319
|
-
}
|
|
25320
|
-
/** Run a command line, keeping every side effect for the next call. */
|
|
25321
|
-
async run(command, opts = {}) {
|
|
25322
|
-
if (this.closed) throw new Error("session is closed");
|
|
25323
|
-
const combined = [];
|
|
25324
|
-
const decoder9 = new TextDecoder();
|
|
25325
|
-
const stdout = new BufferSink((chunk) => {
|
|
25326
|
-
const text2 = decoder9.decode(chunk, { stream: true });
|
|
25327
|
-
combined.push(text2);
|
|
25328
|
-
opts.onStdout?.(text2);
|
|
25329
|
-
this.hooks.onStdout?.(text2);
|
|
25330
|
-
});
|
|
25331
|
-
const stderr = new BufferSink((chunk) => {
|
|
25332
|
-
const text2 = decoder9.decode(chunk, { stream: true });
|
|
25333
|
-
combined.push(text2);
|
|
25334
|
-
opts.onStderr?.(text2);
|
|
25335
|
-
this.hooks.onStderr?.(text2);
|
|
25336
|
-
});
|
|
25337
|
-
if (opts.tty) {
|
|
25338
|
-
stdout.isTTY = true;
|
|
25339
|
-
stderr.isTTY = true;
|
|
25340
|
-
stdout.columns = opts.columns ?? 80;
|
|
25341
|
-
stdout.rows = opts.rows ?? 24;
|
|
25342
|
-
}
|
|
25343
|
-
const stdin = opts.stdin === void 0 ? new NullInput() : typeof opts.stdin === "string" || opts.stdin instanceof Uint8Array ? Pipe.from(opts.stdin) : opts.stdin;
|
|
25344
|
-
this.shell.history.push(command);
|
|
25345
|
-
let timer;
|
|
25346
|
-
if (opts.timeoutMs !== void 0) {
|
|
25347
|
-
timer = setTimeout(() => this.proc.deliver("SIGKILL"), opts.timeoutMs);
|
|
25348
|
-
}
|
|
25349
|
-
let exitCode;
|
|
25350
|
-
try {
|
|
25351
|
-
exitCode = await this.shell.execute(command, { stdin, stdout, stderr });
|
|
25352
|
-
} finally {
|
|
25353
|
-
if (timer) clearTimeout(timer);
|
|
25354
|
-
}
|
|
25355
|
-
return { exitCode, stdout: stdout.text(), stderr: stderr.text(), output: combined.join("") };
|
|
25356
|
-
}
|
|
25357
|
-
/** Stream a long-running command; resolves when it exits. */
|
|
25358
|
-
async stream(command, handlers = {}) {
|
|
25359
|
-
const result = await this.run(command, handlers);
|
|
25360
|
-
return result.exitCode;
|
|
25361
|
-
}
|
|
25362
|
-
/** Feed the session an arbitrary output stream, for terminal integration. */
|
|
25363
|
-
async pipeTo(command, stdout, stderr, stdin) {
|
|
25364
|
-
return this.shell.execute(command, { stdin: stdin ?? new NullInput(), stdout, stderr });
|
|
25365
|
-
}
|
|
25366
|
-
/** True when the last command asked the shell to exit. */
|
|
25367
|
-
get isExiting() {
|
|
25368
|
-
return this.shell.isExiting;
|
|
25369
|
-
}
|
|
25370
|
-
close() {
|
|
25371
|
-
if (this.closed) return;
|
|
25372
|
-
this.closed = true;
|
|
25373
|
-
this.proc.exit(0);
|
|
25374
|
-
this.kernel.procs.remove(this.proc.pid);
|
|
25375
|
-
}
|
|
25376
|
-
};
|
|
25377
|
-
|
|
25378
|
-
// src/node/node-child-process-bridge.ts
|
|
25379
|
-
var KernelChildProcess = class {
|
|
25380
|
-
pid;
|
|
25381
|
-
command;
|
|
25382
|
-
args;
|
|
25383
|
-
parentPid;
|
|
25384
|
-
state = "running";
|
|
25385
|
-
exitCode;
|
|
25386
|
-
stdout = "";
|
|
25387
|
-
stderr = "";
|
|
25388
|
-
listeners = /* @__PURE__ */ new Map();
|
|
25389
|
-
kernel;
|
|
25390
|
-
cred;
|
|
25391
|
-
cwd;
|
|
25392
|
-
env;
|
|
25393
|
-
stdin = new Pipe();
|
|
25394
|
-
process;
|
|
25395
|
-
started = false;
|
|
25396
|
-
cancelled = false;
|
|
25397
|
-
constructor(kernel, cred, config2, pid) {
|
|
25398
|
-
this.stdin.interactive = true;
|
|
25399
|
-
if (config2.inheritStdio) this.stdin.isTTY = true;
|
|
25400
|
-
if (config2.stdinIgnored) this.stdin.end();
|
|
25401
|
-
this.stdin.onRawMode = (enabled) => this.emit("rawmode", enabled);
|
|
25402
|
-
this.kernel = kernel;
|
|
25403
|
-
this.cred = cred;
|
|
25404
|
-
this.pid = pid;
|
|
25405
|
-
this.command = config2.command;
|
|
25406
|
-
this.args = config2.args?.slice() ?? [];
|
|
25407
|
-
this.parentPid = config2.parentPid;
|
|
25408
|
-
this.cwd = config2.cwd ?? "/";
|
|
25409
|
-
this.env = { ...config2.env };
|
|
25410
|
-
}
|
|
25411
|
-
on(event, listener) {
|
|
25412
|
-
let listeners = this.listeners.get(event);
|
|
25413
|
-
if (!listeners) {
|
|
25414
|
-
listeners = /* @__PURE__ */ new Set();
|
|
25415
|
-
this.listeners.set(event, listeners);
|
|
25416
|
-
}
|
|
25417
|
-
listeners.add(listener);
|
|
25418
|
-
return this;
|
|
25419
|
-
}
|
|
25420
|
-
emit(event, ...args) {
|
|
25421
|
-
for (const listener of this.listeners.get(event) ?? []) listener(...args);
|
|
25422
|
-
}
|
|
25423
|
-
exec() {
|
|
25424
|
-
if (this.started) return;
|
|
25425
|
-
this.started = true;
|
|
25426
|
-
queueMicrotask(() => {
|
|
25427
|
-
if (this.cancelled) {
|
|
25428
|
-
this.finish(143);
|
|
25429
|
-
return;
|
|
25430
|
-
}
|
|
25431
|
-
const stdout = new ChildOutput(this, "stdout");
|
|
25432
|
-
const stderr = new ChildOutput(this, "stderr");
|
|
25433
|
-
try {
|
|
25434
|
-
this.process = this.kernel.spawn([this.command, ...this.args], {
|
|
25435
|
-
cwd: this.cwd,
|
|
25436
|
-
env: this.env,
|
|
25437
|
-
cred: this.cred,
|
|
25438
|
-
stdin: this.stdin,
|
|
25439
|
-
stdout,
|
|
25440
|
-
stderr,
|
|
25441
|
-
ppid: 1
|
|
25442
|
-
});
|
|
25443
|
-
void this.process.wait().then((code) => {
|
|
25444
|
-
stdout.end();
|
|
25445
|
-
stderr.end();
|
|
25446
|
-
this.finish(code);
|
|
25447
|
-
});
|
|
25448
|
-
} catch (error) {
|
|
25449
|
-
stderr.write(error instanceof Error ? error.message : String(error));
|
|
25450
|
-
stderr.end();
|
|
25451
|
-
stdout.end();
|
|
25452
|
-
this.finish(1);
|
|
25453
|
-
}
|
|
25454
|
-
});
|
|
25455
|
-
}
|
|
25456
|
-
sendStdin(data) {
|
|
25457
|
-
try {
|
|
25458
|
-
this.stdin.write(data);
|
|
25459
|
-
} catch {
|
|
25460
|
-
}
|
|
25461
|
-
}
|
|
25462
|
-
/** Signal EOF, so a child reading stdin to the end can finish. */
|
|
25463
|
-
endStdin() {
|
|
25464
|
-
try {
|
|
25465
|
-
this.stdin.end();
|
|
25466
|
-
} catch {
|
|
25467
|
-
}
|
|
25468
|
-
}
|
|
25469
|
-
kill(signal = "SIGTERM") {
|
|
25470
|
-
if (this.process) {
|
|
25471
|
-
this.process.deliver(signal);
|
|
25472
|
-
return;
|
|
25473
|
-
}
|
|
25474
|
-
this.cancelled = true;
|
|
26055
|
+
return this.vfs.readlink(clean(path));
|
|
25475
26056
|
}
|
|
25476
|
-
|
|
25477
|
-
|
|
25478
|
-
this.state = "exited";
|
|
25479
|
-
this.exitCode = code;
|
|
25480
|
-
this.emit("exit", code);
|
|
26057
|
+
async realpath(path) {
|
|
26058
|
+
return this.vfs.realpath(clean(path));
|
|
25481
26059
|
}
|
|
25482
|
-
|
|
25483
|
-
this
|
|
25484
|
-
this.emit(stream, text2);
|
|
26060
|
+
async chmod(path, mode) {
|
|
26061
|
+
this.vfs.chmod(clean(path), mode);
|
|
25485
26062
|
}
|
|
25486
|
-
|
|
25487
|
-
|
|
25488
|
-
constructor(child, stream) {
|
|
25489
|
-
this.child = child;
|
|
25490
|
-
this.stream = stream;
|
|
26063
|
+
async chown(path, uid, gid) {
|
|
26064
|
+
this.vfs.chown(clean(path), uid, gid, ROOT_CRED);
|
|
25491
26065
|
}
|
|
25492
|
-
|
|
25493
|
-
|
|
25494
|
-
|
|
25495
|
-
closedState = false;
|
|
25496
|
-
decoder = new TextDecoder();
|
|
25497
|
-
get closed() {
|
|
25498
|
-
return this.closedState;
|
|
26066
|
+
/** Every path beneath `root`, depth-first. */
|
|
26067
|
+
async walk(root = "/") {
|
|
26068
|
+
return [...this.vfs.walk(clean(root))];
|
|
25499
26069
|
}
|
|
25500
|
-
|
|
25501
|
-
|
|
25502
|
-
|
|
25503
|
-
if (text2) this.child.append(this.stream, text2);
|
|
26070
|
+
/** Total bytes and file counts, as `df` reports them. */
|
|
26071
|
+
async usage(root = "/") {
|
|
26072
|
+
return this.vfs.usage(clean(root));
|
|
25504
26073
|
}
|
|
25505
|
-
|
|
25506
|
-
|
|
25507
|
-
|
|
25508
|
-
const
|
|
25509
|
-
|
|
26074
|
+
/** Read many files at once, keyed by path. */
|
|
26075
|
+
async readAll(paths) {
|
|
26076
|
+
const out = {};
|
|
26077
|
+
for (const path of paths) out[path] = this.vfs.readText(clean(path));
|
|
26078
|
+
return out;
|
|
25510
26079
|
}
|
|
25511
|
-
|
|
25512
|
-
|
|
25513
|
-
|
|
25514
|
-
|
|
25515
|
-
const originalSpawn = manager.spawn;
|
|
25516
|
-
manager.spawn = (config2) => {
|
|
25517
|
-
const resolved = kernel.resolveExecutable(config2.command, config2.cwd ?? "/", config2.env ?? {}, cred);
|
|
25518
|
-
if (resolved?.kind === "builtin") {
|
|
25519
|
-
return new KernelChildProcess(kernel, cred, config2, nextBridgePid++);
|
|
26080
|
+
/** Write a whole map of files, creating parents. */
|
|
26081
|
+
async writeAll(files, opts = {}) {
|
|
26082
|
+
for (const [key, value] of Object.entries(files)) {
|
|
26083
|
+
await this.writeFile(resolve(opts.cwd ?? "/", key), value);
|
|
25520
26084
|
}
|
|
25521
|
-
return originalSpawn.call(manager, config2);
|
|
25522
|
-
};
|
|
25523
|
-
return () => {
|
|
25524
|
-
if (manager.spawn === originalSpawn) return;
|
|
25525
|
-
manager.spawn = originalSpawn;
|
|
25526
|
-
};
|
|
25527
|
-
}
|
|
25528
|
-
|
|
25529
|
-
// src/node/host-module-tracker.ts
|
|
25530
|
-
var HostModuleTracker = class {
|
|
25531
|
-
active = 0;
|
|
25532
|
-
disposed = false;
|
|
25533
|
-
dispose() {
|
|
25534
|
-
this.disposed = true;
|
|
25535
|
-
}
|
|
25536
|
-
wrapped = /* @__PURE__ */ new WeakMap();
|
|
25537
|
-
originals = /* @__PURE__ */ new WeakMap();
|
|
25538
|
-
pending = () => this.active;
|
|
25539
|
-
unwrap = (value) => value && (typeof value === "object" || typeof value === "function") ? this.originals.get(value) ?? value : value;
|
|
25540
|
-
wrap(value) {
|
|
25541
|
-
if (value === null || typeof value !== "object" && typeof value !== "function") return value;
|
|
25542
|
-
const object = value;
|
|
25543
|
-
if (Array.isArray(value) || ArrayBuffer.isView(value) || value instanceof ArrayBuffer) return value;
|
|
25544
|
-
if (this.wrapped.has(object)) return this.wrapped.get(object);
|
|
25545
|
-
const tracker = this;
|
|
25546
|
-
const proxy = new Proxy(object, {
|
|
25547
|
-
// CommonJS native loaders re-export by assigning exports back onto the
|
|
25548
|
-
// binding object. Never store a process-owned proxy in a shared module.
|
|
25549
|
-
set(target, key, member) {
|
|
25550
|
-
return Reflect.set(target, key, tracker.unwrap(member), target);
|
|
25551
|
-
},
|
|
25552
|
-
defineProperty(target, key, descriptor) {
|
|
25553
|
-
return Reflect.defineProperty(target, key, "value" in descriptor ? { ...descriptor, value: tracker.unwrap(descriptor.value) } : descriptor);
|
|
25554
|
-
},
|
|
25555
|
-
get(target, key) {
|
|
25556
|
-
const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
|
|
25557
|
-
const member = Reflect.get(target, key, target);
|
|
25558
|
-
if (descriptor && !descriptor.configurable && "value" in descriptor && !descriptor.writable) return member;
|
|
25559
|
-
return typeof member === "function" ? tracker.wrap(member) : member;
|
|
25560
|
-
},
|
|
25561
|
-
apply(target, receiver, args) {
|
|
25562
|
-
const result = Reflect.apply(target, tracker.unwrap(receiver), args.map(tracker.unwrap));
|
|
25563
|
-
if (result && typeof result.then === "function") {
|
|
25564
|
-
tracker.active++;
|
|
25565
|
-
return Promise.resolve(result).then(
|
|
25566
|
-
(value2) => {
|
|
25567
|
-
tracker.active--;
|
|
25568
|
-
return tracker.disposed ? new Promise(() => {
|
|
25569
|
-
}) : tracker.wrap(value2);
|
|
25570
|
-
},
|
|
25571
|
-
(error) => {
|
|
25572
|
-
tracker.active--;
|
|
25573
|
-
if (tracker.disposed) return new Promise(() => {
|
|
25574
|
-
});
|
|
25575
|
-
throw error;
|
|
25576
|
-
}
|
|
25577
|
-
);
|
|
25578
|
-
}
|
|
25579
|
-
return tracker.wrap(result);
|
|
25580
|
-
},
|
|
25581
|
-
construct(target, args, newTarget) {
|
|
25582
|
-
return tracker.wrap(Reflect.construct(target, args.map(tracker.unwrap), tracker.unwrap(newTarget)));
|
|
25583
|
-
}
|
|
25584
|
-
});
|
|
25585
|
-
this.wrapped.set(object, proxy);
|
|
25586
|
-
this.originals.set(proxy, object);
|
|
25587
|
-
return proxy;
|
|
25588
26085
|
}
|
|
25589
26086
|
};
|
|
25590
26087
|
|
|
25591
|
-
// src/
|
|
25592
|
-
|
|
25593
|
-
|
|
25594
|
-
|
|
25595
|
-
|
|
25596
|
-
|
|
25597
|
-
|
|
25598
|
-
|
|
25599
|
-
|
|
25600
|
-
|
|
25601
|
-
|
|
25602
|
-
|
|
25603
|
-
|
|
25604
|
-
|
|
25605
|
-
|
|
25606
|
-
|
|
25607
|
-
|
|
25608
|
-
|
|
25609
|
-
|
|
25610
|
-
|
|
25611
|
-
|
|
25612
|
-
|
|
25613
|
-
};
|
|
25614
|
-
var DEFAULT_LOCAL = "__sbxDefault";
|
|
25615
|
-
var MAYBE_ESM = /(^|[\s;}(])(?:import|export)(?:[\s({[*"']|$)|\bimport\s*\.\s*meta\b/;
|
|
25616
|
-
function looksLikeEsm(source) {
|
|
25617
|
-
return MAYBE_ESM.test(source);
|
|
25618
|
-
}
|
|
25619
|
-
function transformEsm(source, filename = "module.js") {
|
|
25620
|
-
if (!looksLikeEsm(source)) return null;
|
|
25621
|
-
let ast;
|
|
25622
|
-
try {
|
|
25623
|
-
ast = parseModule(source, filename);
|
|
25624
|
-
} catch {
|
|
25625
|
-
return null;
|
|
25626
|
-
}
|
|
25627
|
-
const body = ast.body;
|
|
25628
|
-
const hasModuleSyntax = body.some(
|
|
25629
|
-
(node2) => node2.type.startsWith("Import") || node2.type.startsWith("Export")
|
|
25630
|
-
);
|
|
25631
|
-
const usesImportMeta = !hasModuleSyntax && containsImportMeta(ast);
|
|
25632
|
-
const esm = hasModuleSyntax || usesImportMeta;
|
|
25633
|
-
if (!esm && !containsImportExpression(ast)) return null;
|
|
25634
|
-
const edits = [];
|
|
25635
|
-
const prelude = [];
|
|
25636
|
-
const importBindings = /* @__PURE__ */ new Map();
|
|
25637
|
-
const exportGetters = /* @__PURE__ */ new Map();
|
|
25638
|
-
let namespaceCount = 0;
|
|
25639
|
-
const namespaceFor = (specifier) => {
|
|
25640
|
-
const id = `__sbxNs${namespaceCount++}`;
|
|
25641
|
-
prelude.push(`var ${id} = ${HELPERS.import}(${JSON.stringify(specifier)});`);
|
|
25642
|
-
return id;
|
|
25643
|
-
};
|
|
25644
|
-
for (const node2 of body) {
|
|
25645
|
-
if (node2.type === "ImportDeclaration") collectImport(node2);
|
|
26088
|
+
// src/container/session.ts
|
|
26089
|
+
var Session = class {
|
|
26090
|
+
constructor(kernel, init) {
|
|
26091
|
+
this.kernel = kernel;
|
|
26092
|
+
this.proc = kernel.procs.create({
|
|
26093
|
+
argv: ["-sh"],
|
|
26094
|
+
cwd: init.cwd,
|
|
26095
|
+
env: init.env,
|
|
26096
|
+
cred: init.cred,
|
|
26097
|
+
ppid: 1,
|
|
26098
|
+
kind: "shell",
|
|
26099
|
+
tty: "pts/0"
|
|
26100
|
+
});
|
|
26101
|
+
this.shell = new Shell({
|
|
26102
|
+
kernel,
|
|
26103
|
+
proc: this.proc,
|
|
26104
|
+
cwd: init.cwd,
|
|
26105
|
+
env: init.env,
|
|
26106
|
+
cred: init.cred,
|
|
26107
|
+
scriptName: "sh",
|
|
26108
|
+
options: { interactive: true }
|
|
26109
|
+
});
|
|
26110
|
+
this.hooks = init.hooks ?? {};
|
|
25646
26111
|
}
|
|
25647
|
-
|
|
25648
|
-
|
|
25649
|
-
|
|
25650
|
-
|
|
25651
|
-
|
|
25652
|
-
|
|
25653
|
-
|
|
25654
|
-
break;
|
|
25655
|
-
case "ExportAllDeclaration":
|
|
25656
|
-
collectExportAll(node2);
|
|
25657
|
-
break;
|
|
25658
|
-
}
|
|
26112
|
+
kernel;
|
|
26113
|
+
shell;
|
|
26114
|
+
proc;
|
|
26115
|
+
closed = false;
|
|
26116
|
+
hooks;
|
|
26117
|
+
get cwd() {
|
|
26118
|
+
return this.shell.cwd;
|
|
25659
26119
|
}
|
|
25660
|
-
|
|
25661
|
-
|
|
25662
|
-
`Object.defineProperty(${HELPERS.exports}, "__esModule", { value: true });`,
|
|
25663
|
-
...prelude,
|
|
25664
|
-
...[...exportGetters].map(
|
|
25665
|
-
([name, expression]) => `Object.defineProperty(${HELPERS.exports}, ${JSON.stringify(name)}, { enumerable: true, configurable: true, get: function () { return ${expression}; } });`
|
|
25666
|
-
)
|
|
25667
|
-
].join("\n") : "";
|
|
25668
|
-
return {
|
|
25669
|
-
code: header ? `${header}
|
|
25670
|
-
${applyEdits(source, edits)}` : applyEdits(source, edits),
|
|
25671
|
-
esm,
|
|
25672
|
-
topLevelAwait: hasTopLevelAwait(ast)
|
|
25673
|
-
};
|
|
25674
|
-
function collectImport(node2) {
|
|
25675
|
-
const specifier = node2.source.value;
|
|
25676
|
-
const specifiers = node2.specifiers ?? [];
|
|
25677
|
-
const id = namespaceFor(specifier);
|
|
25678
|
-
for (const entry of specifiers) {
|
|
25679
|
-
const local = entry.local.name ?? "";
|
|
25680
|
-
if (entry.type === "ImportDefaultSpecifier") {
|
|
25681
|
-
importBindings.set(local, `${id}.default`);
|
|
25682
|
-
} else if (entry.type === "ImportNamespaceSpecifier") {
|
|
25683
|
-
importBindings.set(local, id);
|
|
25684
|
-
} else {
|
|
25685
|
-
const imported = entry.imported;
|
|
25686
|
-
const name = imported.type === "Identifier" ? imported.name : imported.value;
|
|
25687
|
-
importBindings.set(local, `${id}[${JSON.stringify(name)}]`);
|
|
25688
|
-
}
|
|
25689
|
-
}
|
|
25690
|
-
drop(node2);
|
|
26120
|
+
get env() {
|
|
26121
|
+
return this.shell.vars.environment();
|
|
25691
26122
|
}
|
|
25692
|
-
|
|
25693
|
-
|
|
25694
|
-
|
|
25695
|
-
|
|
25696
|
-
|
|
25697
|
-
|
|
26123
|
+
get history() {
|
|
26124
|
+
return this.shell.history;
|
|
26125
|
+
}
|
|
26126
|
+
/** Run a command line, keeping every side effect for the next call. */
|
|
26127
|
+
async run(command, opts = {}) {
|
|
26128
|
+
if (this.closed) throw new Error("session is closed");
|
|
26129
|
+
const combined = [];
|
|
26130
|
+
const decoder9 = new TextDecoder();
|
|
26131
|
+
const stdout = new BufferSink((chunk) => {
|
|
26132
|
+
const text2 = decoder9.decode(chunk, { stream: true });
|
|
26133
|
+
combined.push(text2);
|
|
26134
|
+
opts.onStdout?.(text2);
|
|
26135
|
+
this.hooks.onStdout?.(text2);
|
|
26136
|
+
});
|
|
26137
|
+
const stderr = new BufferSink((chunk) => {
|
|
26138
|
+
const text2 = decoder9.decode(chunk, { stream: true });
|
|
26139
|
+
combined.push(text2);
|
|
26140
|
+
opts.onStderr?.(text2);
|
|
26141
|
+
this.hooks.onStderr?.(text2);
|
|
26142
|
+
});
|
|
26143
|
+
const outGate = new DetachableOutput(stdout, (text2) => this.hooks.onStdout?.(text2));
|
|
26144
|
+
const errGate = new DetachableOutput(stderr, (text2) => this.hooks.onStderr?.(text2));
|
|
26145
|
+
if (opts.tty) {
|
|
26146
|
+
outGate.isTTY = true;
|
|
26147
|
+
errGate.isTTY = true;
|
|
26148
|
+
outGate.columns = opts.columns ?? 80;
|
|
26149
|
+
outGate.rows = opts.rows ?? 24;
|
|
25698
26150
|
}
|
|
25699
|
-
const
|
|
25700
|
-
|
|
25701
|
-
|
|
25702
|
-
|
|
25703
|
-
|
|
25704
|
-
const read = id ? `${id}[${JSON.stringify(local)}]` : importBindings.get(local) ?? local;
|
|
25705
|
-
exportGetters.set(exported, read);
|
|
26151
|
+
const stdin = opts.stdin === void 0 ? new NullInput() : typeof opts.stdin === "string" || opts.stdin instanceof Uint8Array ? Pipe.from(opts.stdin) : opts.stdin;
|
|
26152
|
+
this.shell.history.push(command);
|
|
26153
|
+
let timer;
|
|
26154
|
+
if (opts.timeoutMs !== void 0) {
|
|
26155
|
+
timer = setTimeout(() => this.proc.deliver("SIGKILL"), opts.timeoutMs);
|
|
25706
26156
|
}
|
|
25707
|
-
|
|
25708
|
-
|
|
25709
|
-
|
|
25710
|
-
|
|
25711
|
-
|
|
25712
|
-
|
|
25713
|
-
|
|
25714
|
-
if (named) {
|
|
25715
|
-
exportGetters.set("default", named.name);
|
|
25716
|
-
edits.push({ start: node2.start, end: declaration.start, text: "" });
|
|
25717
|
-
return;
|
|
25718
|
-
}
|
|
25719
|
-
const keyword = declaration.type === "FunctionDeclaration" ? "function" : "class";
|
|
25720
|
-
const keywordEnd = source.indexOf(keyword, declaration.start) + keyword.length;
|
|
25721
|
-
exportGetters.set("default", DEFAULT_LOCAL);
|
|
25722
|
-
edits.push({ start: node2.start, end: declaration.start, text: "" });
|
|
25723
|
-
edits.push({ start: keywordEnd, end: keywordEnd, text: ` ${DEFAULT_LOCAL}` });
|
|
25724
|
-
return;
|
|
26157
|
+
let exitCode;
|
|
26158
|
+
try {
|
|
26159
|
+
exitCode = await this.shell.execute(command, { stdin, stdout: outGate, stderr: errGate });
|
|
26160
|
+
} finally {
|
|
26161
|
+
if (timer) clearTimeout(timer);
|
|
26162
|
+
outGate.detach();
|
|
26163
|
+
errGate.detach();
|
|
25725
26164
|
}
|
|
25726
|
-
|
|
25727
|
-
edits.push({ start: node2.start, end: declaration.start, text: `var ${DEFAULT_LOCAL} = ` });
|
|
25728
|
-
edits.push({ start: node2.end, end: node2.end, text: ";" });
|
|
26165
|
+
return { exitCode, stdout: stdout.text(), stderr: stderr.text(), output: combined.join("") };
|
|
25729
26166
|
}
|
|
25730
|
-
|
|
25731
|
-
|
|
25732
|
-
const
|
|
25733
|
-
|
|
25734
|
-
else prelude.push(`${HELPERS.exportAll}(${HELPERS.exports}, ${id});`);
|
|
25735
|
-
drop(node2);
|
|
26167
|
+
/** Stream a long-running command; resolves when it exits. */
|
|
26168
|
+
async stream(command, handlers = {}) {
|
|
26169
|
+
const result = await this.run(command, handlers);
|
|
26170
|
+
return result.exitCode;
|
|
25736
26171
|
}
|
|
25737
|
-
|
|
25738
|
-
|
|
26172
|
+
/** Feed the session an arbitrary output stream, for terminal integration. */
|
|
26173
|
+
async pipeTo(command, stdout, stderr, stdin) {
|
|
26174
|
+
return this.shell.execute(command, { stdin: stdin ?? new NullInput(), stdout, stderr });
|
|
25739
26175
|
}
|
|
25740
|
-
|
|
25741
|
-
|
|
25742
|
-
|
|
25743
|
-
|
|
25744
|
-
|
|
25745
|
-
|
|
25746
|
-
|
|
25747
|
-
|
|
25748
|
-
|
|
25749
|
-
return;
|
|
25750
|
-
case "ExportNamedDeclaration":
|
|
25751
|
-
if (!node2.declaration) return;
|
|
25752
|
-
break;
|
|
25753
|
-
case "FunctionDeclaration":
|
|
25754
|
-
case "FunctionExpression":
|
|
25755
|
-
case "ArrowFunctionExpression": {
|
|
25756
|
-
const names = /* @__PURE__ */ new Set();
|
|
25757
|
-
for (const param of node2.params ?? []) collectPattern2(param, names);
|
|
25758
|
-
const id = node2.id;
|
|
25759
|
-
if (id && node2.type === "FunctionExpression") names.add(id.name);
|
|
25760
|
-
const fnBody = node2.body;
|
|
25761
|
-
if (fnBody?.type === "BlockStatement") {
|
|
25762
|
-
for (const name of hoistedNames2(fnBody.body)) names.add(name);
|
|
25763
|
-
}
|
|
25764
|
-
childScope = { names, parent: scope };
|
|
25765
|
-
break;
|
|
25766
|
-
}
|
|
25767
|
-
case "CatchClause": {
|
|
25768
|
-
const names = /* @__PURE__ */ new Set();
|
|
25769
|
-
if (node2.param) collectPattern2(node2.param, names);
|
|
25770
|
-
childScope = { names, parent: scope };
|
|
25771
|
-
break;
|
|
25772
|
-
}
|
|
25773
|
-
case "ClassExpression": {
|
|
25774
|
-
const id = node2.id;
|
|
25775
|
-
if (id) childScope = { names: /* @__PURE__ */ new Set([id.name]), parent: scope };
|
|
25776
|
-
break;
|
|
25777
|
-
}
|
|
25778
|
-
case "BlockStatement":
|
|
25779
|
-
case "StaticBlock":
|
|
25780
|
-
if (!isProgram) {
|
|
25781
|
-
childScope = { names: blockNames2(node2.body), parent: scope };
|
|
25782
|
-
}
|
|
25783
|
-
break;
|
|
25784
|
-
case "ForStatement":
|
|
25785
|
-
case "ForInStatement":
|
|
25786
|
-
case "ForOfStatement": {
|
|
25787
|
-
const head2 = node2.init ?? node2.left;
|
|
25788
|
-
if (head2?.type === "VariableDeclaration" && head2.kind !== "var") {
|
|
25789
|
-
const names = /* @__PURE__ */ new Set();
|
|
25790
|
-
for (const declarator of head2.declarations) {
|
|
25791
|
-
collectPattern2(declarator.id, names);
|
|
25792
|
-
}
|
|
25793
|
-
childScope = { names, parent: scope };
|
|
25794
|
-
}
|
|
25795
|
-
break;
|
|
25796
|
-
}
|
|
25797
|
-
case "MetaProperty":
|
|
25798
|
-
edits.push({ start: node2.start, end: node2.end, text: HELPERS.meta });
|
|
25799
|
-
return;
|
|
25800
|
-
case "ImportExpression": {
|
|
25801
|
-
const argument = node2.source;
|
|
25802
|
-
edits.push({ start: node2.start, end: argument.start, text: `${HELPERS.dynamic}(` });
|
|
25803
|
-
visit(argument, childScope);
|
|
25804
|
-
edits.push({ start: argument.end, end: node2.end, text: ")" });
|
|
25805
|
-
return;
|
|
25806
|
-
}
|
|
25807
|
-
case "Identifier": {
|
|
25808
|
-
const replacement = lookup(node2.name, scope);
|
|
25809
|
-
if (replacement) edits.push({ start: node2.start, end: node2.end, text: replacement });
|
|
25810
|
-
return;
|
|
25811
|
-
}
|
|
25812
|
-
case "MemberExpression":
|
|
25813
|
-
case "MethodDefinition":
|
|
25814
|
-
case "PropertyDefinition":
|
|
25815
|
-
skip = node2.computed ? NOTHING2 : PROPERTY2;
|
|
25816
|
-
break;
|
|
25817
|
-
case "Property": {
|
|
25818
|
-
if (node2.computed) break;
|
|
25819
|
-
if (node2.shorthand) {
|
|
25820
|
-
const value = node2.value;
|
|
25821
|
-
if (value.type === "Identifier") {
|
|
25822
|
-
const replacement = lookup(value.name, scope);
|
|
25823
|
-
if (replacement) {
|
|
25824
|
-
edits.push({ start: value.start, end: value.end, text: `${value.name}: ${replacement}` });
|
|
25825
|
-
return;
|
|
25826
|
-
}
|
|
25827
|
-
}
|
|
25828
|
-
break;
|
|
25829
|
-
}
|
|
25830
|
-
skip = PROPERTY2;
|
|
25831
|
-
break;
|
|
25832
|
-
}
|
|
25833
|
-
case "LabeledStatement":
|
|
25834
|
-
case "BreakStatement":
|
|
25835
|
-
case "ContinueStatement":
|
|
25836
|
-
skip = LABEL2;
|
|
25837
|
-
break;
|
|
25838
|
-
}
|
|
25839
|
-
for (const [key, value] of Object.entries(node2)) {
|
|
25840
|
-
if (key === "type" || key === "start" || key === "end" || skip.includes(key)) continue;
|
|
25841
|
-
if (Array.isArray(value)) {
|
|
25842
|
-
for (const item of value) if (isNode4(item)) visit(item, childScope);
|
|
25843
|
-
} else if (isNode4(value)) {
|
|
25844
|
-
visit(value, childScope);
|
|
25845
|
-
}
|
|
25846
|
-
}
|
|
25847
|
-
}
|
|
25848
|
-
function lookup(name, scope) {
|
|
25849
|
-
for (let current = scope; current; current = current.parent) {
|
|
25850
|
-
if (current.names.has(name)) {
|
|
25851
|
-
return current.parent === null ? importBindings.get(name) ?? null : null;
|
|
25852
|
-
}
|
|
25853
|
-
}
|
|
25854
|
-
return null;
|
|
25855
|
-
}
|
|
26176
|
+
/** True when the last command asked the shell to exit. */
|
|
26177
|
+
get isExiting() {
|
|
26178
|
+
return this.shell.isExiting;
|
|
26179
|
+
}
|
|
26180
|
+
close() {
|
|
26181
|
+
if (this.closed) return;
|
|
26182
|
+
this.closed = true;
|
|
26183
|
+
this.proc.exit(0);
|
|
26184
|
+
this.kernel.procs.remove(this.proc.pid);
|
|
25856
26185
|
}
|
|
25857
|
-
}
|
|
25858
|
-
var JSX_EXTENSION = /\.[jt]sx$/;
|
|
25859
|
-
var JsxParser = acorn.Parser.extend(jsx__default.default());
|
|
25860
|
-
var PARSE_OPTIONS = {
|
|
25861
|
-
ecmaVersion: "latest",
|
|
25862
|
-
sourceType: "module",
|
|
25863
|
-
allowAwaitOutsideFunction: true,
|
|
25864
|
-
allowHashBang: true,
|
|
25865
|
-
allowReturnOutsideFunction: true
|
|
25866
26186
|
};
|
|
25867
|
-
|
|
25868
|
-
|
|
25869
|
-
|
|
25870
|
-
|
|
25871
|
-
|
|
25872
|
-
|
|
25873
|
-
|
|
25874
|
-
|
|
25875
|
-
|
|
25876
|
-
|
|
25877
|
-
|
|
26187
|
+
|
|
26188
|
+
// src/node/node-child-process-bridge.ts
|
|
26189
|
+
var KernelChildProcess = class {
|
|
26190
|
+
pid;
|
|
26191
|
+
command;
|
|
26192
|
+
args;
|
|
26193
|
+
parentPid;
|
|
26194
|
+
state = "running";
|
|
26195
|
+
exitCode;
|
|
26196
|
+
stdout = "";
|
|
26197
|
+
stderr = "";
|
|
26198
|
+
listeners = /* @__PURE__ */ new Map();
|
|
26199
|
+
kernel;
|
|
26200
|
+
cred;
|
|
26201
|
+
cwd;
|
|
26202
|
+
env;
|
|
26203
|
+
stdin = new Pipe();
|
|
26204
|
+
process;
|
|
26205
|
+
started = false;
|
|
26206
|
+
cancelled = false;
|
|
26207
|
+
constructor(kernel, cred, config2, pid) {
|
|
26208
|
+
this.stdin.interactive = true;
|
|
26209
|
+
if (config2.inheritStdio) this.stdin.isTTY = true;
|
|
26210
|
+
if (config2.stdinIgnored) this.stdin.end();
|
|
26211
|
+
this.stdin.onRawMode = (enabled) => this.emit("rawmode", enabled);
|
|
26212
|
+
this.kernel = kernel;
|
|
26213
|
+
this.cred = cred;
|
|
26214
|
+
this.pid = pid;
|
|
26215
|
+
this.command = config2.command;
|
|
26216
|
+
this.args = config2.args?.slice() ?? [];
|
|
26217
|
+
this.parentPid = config2.parentPid;
|
|
26218
|
+
this.cwd = config2.cwd ?? "/";
|
|
26219
|
+
this.env = { ...config2.env };
|
|
26220
|
+
}
|
|
26221
|
+
on(event, listener) {
|
|
26222
|
+
let listeners = this.listeners.get(event);
|
|
26223
|
+
if (!listeners) {
|
|
26224
|
+
listeners = /* @__PURE__ */ new Set();
|
|
26225
|
+
this.listeners.set(event, listeners);
|
|
26226
|
+
}
|
|
26227
|
+
listeners.add(listener);
|
|
26228
|
+
return this;
|
|
25878
26229
|
}
|
|
25879
|
-
|
|
25880
|
-
|
|
25881
|
-
function containsImportMeta(node2) {
|
|
25882
|
-
if (Array.isArray(node2)) return node2.some(containsImportMeta);
|
|
25883
|
-
if (!isNode4(node2)) return false;
|
|
25884
|
-
if (node2.type === "MetaProperty") return true;
|
|
25885
|
-
for (const [key, value] of Object.entries(node2)) {
|
|
25886
|
-
if (key === "type" || key === "start" || key === "end") continue;
|
|
25887
|
-
if (containsImportMeta(value)) return true;
|
|
26230
|
+
emit(event, ...args) {
|
|
26231
|
+
for (const listener of this.listeners.get(event) ?? []) listener(...args);
|
|
25888
26232
|
}
|
|
25889
|
-
|
|
25890
|
-
|
|
25891
|
-
|
|
25892
|
-
|
|
25893
|
-
|
|
25894
|
-
|
|
25895
|
-
|
|
26233
|
+
exec() {
|
|
26234
|
+
if (this.started) return;
|
|
26235
|
+
this.started = true;
|
|
26236
|
+
queueMicrotask(() => {
|
|
26237
|
+
if (this.cancelled) {
|
|
26238
|
+
this.finish(143);
|
|
26239
|
+
return;
|
|
26240
|
+
}
|
|
26241
|
+
const stdout = new ChildOutput(this, "stdout");
|
|
26242
|
+
const stderr = new ChildOutput(this, "stderr");
|
|
26243
|
+
try {
|
|
26244
|
+
this.process = this.kernel.spawn([this.command, ...this.args], {
|
|
26245
|
+
cwd: this.cwd,
|
|
26246
|
+
env: this.env,
|
|
26247
|
+
cred: this.cred,
|
|
26248
|
+
stdin: this.stdin,
|
|
26249
|
+
stdout,
|
|
26250
|
+
stderr,
|
|
26251
|
+
ppid: 1
|
|
26252
|
+
});
|
|
26253
|
+
void this.process.wait().then((code) => {
|
|
26254
|
+
stdout.end();
|
|
26255
|
+
stderr.end();
|
|
26256
|
+
this.finish(code);
|
|
26257
|
+
});
|
|
26258
|
+
} catch (error) {
|
|
26259
|
+
stderr.write(error instanceof Error ? error.message : String(error));
|
|
26260
|
+
stderr.end();
|
|
26261
|
+
stdout.end();
|
|
26262
|
+
this.finish(1);
|
|
26263
|
+
}
|
|
26264
|
+
});
|
|
25896
26265
|
}
|
|
25897
|
-
|
|
25898
|
-
|
|
25899
|
-
|
|
25900
|
-
|
|
25901
|
-
|
|
26266
|
+
sendStdin(data) {
|
|
26267
|
+
try {
|
|
26268
|
+
this.stdin.write(data);
|
|
26269
|
+
} catch {
|
|
26270
|
+
}
|
|
25902
26271
|
}
|
|
25903
|
-
|
|
25904
|
-
|
|
25905
|
-
|
|
25906
|
-
|
|
25907
|
-
|
|
25908
|
-
for (const declarator of declaration.declarations) {
|
|
25909
|
-
collectPattern2(declarator.id, names);
|
|
26272
|
+
/** Signal EOF, so a child reading stdin to the end can finish. */
|
|
26273
|
+
endStdin() {
|
|
26274
|
+
try {
|
|
26275
|
+
this.stdin.end();
|
|
26276
|
+
} catch {
|
|
25910
26277
|
}
|
|
25911
|
-
} else if (isNode4(declaration.id)) {
|
|
25912
|
-
names.add(declaration.id.name);
|
|
25913
26278
|
}
|
|
25914
|
-
|
|
25915
|
-
|
|
25916
|
-
|
|
25917
|
-
|
|
25918
|
-
}
|
|
25919
|
-
function hoistedNames2(body) {
|
|
25920
|
-
const names = blockNames2(body);
|
|
25921
|
-
collectVars2(body, names);
|
|
25922
|
-
return names;
|
|
25923
|
-
}
|
|
25924
|
-
function blockNames2(body) {
|
|
25925
|
-
const names = /* @__PURE__ */ new Set();
|
|
25926
|
-
for (const node2 of body ?? []) {
|
|
25927
|
-
if (node2.type === "VariableDeclaration" && node2.kind !== "var") {
|
|
25928
|
-
for (const declarator of node2.declarations) {
|
|
25929
|
-
collectPattern2(declarator.id, names);
|
|
25930
|
-
}
|
|
25931
|
-
} else if ((node2.type === "ClassDeclaration" || node2.type === "FunctionDeclaration") && isNode4(node2.id)) {
|
|
25932
|
-
names.add(node2.id.name);
|
|
26279
|
+
kill(signal = "SIGTERM") {
|
|
26280
|
+
if (this.process) {
|
|
26281
|
+
this.process.deliver(signal);
|
|
26282
|
+
return;
|
|
25933
26283
|
}
|
|
26284
|
+
this.cancelled = true;
|
|
25934
26285
|
}
|
|
25935
|
-
|
|
25936
|
-
|
|
25937
|
-
|
|
25938
|
-
|
|
25939
|
-
|
|
25940
|
-
return;
|
|
26286
|
+
finish(code) {
|
|
26287
|
+
if (this.state === "exited") return;
|
|
26288
|
+
this.state = "exited";
|
|
26289
|
+
this.exitCode = code;
|
|
26290
|
+
this.emit("exit", code);
|
|
25941
26291
|
}
|
|
25942
|
-
|
|
25943
|
-
|
|
25944
|
-
|
|
25945
|
-
if (isNode4(node2.id)) names.add(node2.id.name);
|
|
25946
|
-
return;
|
|
26292
|
+
append(stream, text2) {
|
|
26293
|
+
this[stream] += text2;
|
|
26294
|
+
this.emit(stream, text2);
|
|
25947
26295
|
}
|
|
25948
|
-
|
|
25949
|
-
|
|
25950
|
-
|
|
25951
|
-
|
|
26296
|
+
};
|
|
26297
|
+
var ChildOutput = class {
|
|
26298
|
+
constructor(child, stream) {
|
|
26299
|
+
this.child = child;
|
|
26300
|
+
this.stream = stream;
|
|
25952
26301
|
}
|
|
25953
|
-
|
|
25954
|
-
|
|
25955
|
-
|
|
26302
|
+
child;
|
|
26303
|
+
stream;
|
|
26304
|
+
isTTY = false;
|
|
26305
|
+
closedState = false;
|
|
26306
|
+
decoder = new TextDecoder();
|
|
26307
|
+
get closed() {
|
|
26308
|
+
return this.closedState;
|
|
26309
|
+
}
|
|
26310
|
+
write(data) {
|
|
26311
|
+
if (this.closedState) return;
|
|
26312
|
+
const text2 = typeof data === "string" ? data : this.decoder.decode(data, { stream: true });
|
|
26313
|
+
if (text2) this.child.append(this.stream, text2);
|
|
26314
|
+
}
|
|
26315
|
+
end() {
|
|
26316
|
+
if (this.closedState) return;
|
|
26317
|
+
this.closedState = true;
|
|
26318
|
+
const tail2 = this.decoder.decode();
|
|
26319
|
+
if (tail2) this.child.append(this.stream, tail2);
|
|
25956
26320
|
}
|
|
26321
|
+
};
|
|
26322
|
+
var nextBridgePid = 1073741824;
|
|
26323
|
+
function installNodeChildProcessBridge(pod, kernel, cred) {
|
|
26324
|
+
const manager = pod.processManager;
|
|
26325
|
+
const originalSpawn = manager.spawn;
|
|
26326
|
+
manager.spawn = (config2) => {
|
|
26327
|
+
const resolved = kernel.resolveExecutable(config2.command, config2.cwd ?? "/", config2.env ?? {}, cred);
|
|
26328
|
+
if (resolved?.kind === "builtin") {
|
|
26329
|
+
return new KernelChildProcess(kernel, cred, config2, nextBridgePid++);
|
|
26330
|
+
}
|
|
26331
|
+
return originalSpawn.call(manager, config2);
|
|
26332
|
+
};
|
|
26333
|
+
return () => {
|
|
26334
|
+
if (manager.spawn === originalSpawn) return;
|
|
26335
|
+
manager.spawn = originalSpawn;
|
|
26336
|
+
};
|
|
25957
26337
|
}
|
|
25958
|
-
|
|
25959
|
-
|
|
25960
|
-
|
|
25961
|
-
|
|
25962
|
-
|
|
25963
|
-
|
|
25964
|
-
|
|
25965
|
-
|
|
25966
|
-
|
|
26338
|
+
|
|
26339
|
+
// src/node/host-module-tracker.ts
|
|
26340
|
+
var HostModuleTracker = class {
|
|
26341
|
+
active = 0;
|
|
26342
|
+
disposed = false;
|
|
26343
|
+
dispose() {
|
|
26344
|
+
this.disposed = true;
|
|
26345
|
+
}
|
|
26346
|
+
wrapped = /* @__PURE__ */ new WeakMap();
|
|
26347
|
+
originals = /* @__PURE__ */ new WeakMap();
|
|
26348
|
+
pending = () => this.active;
|
|
26349
|
+
unwrap = (value) => value && (typeof value === "object" || typeof value === "function") ? this.originals.get(value) ?? value : value;
|
|
26350
|
+
wrap(value) {
|
|
26351
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") return value;
|
|
26352
|
+
const object = value;
|
|
26353
|
+
if (Array.isArray(value) || ArrayBuffer.isView(value) || value instanceof ArrayBuffer) return value;
|
|
26354
|
+
if (this.wrapped.has(object)) return this.wrapped.get(object);
|
|
26355
|
+
const tracker = this;
|
|
26356
|
+
const proxy = new Proxy(object, {
|
|
26357
|
+
// CommonJS native loaders re-export by assigning exports back onto the
|
|
26358
|
+
// binding object. Never store a process-owned proxy in a shared module.
|
|
26359
|
+
set(target, key, member) {
|
|
26360
|
+
return Reflect.set(target, key, tracker.unwrap(member), target);
|
|
26361
|
+
},
|
|
26362
|
+
defineProperty(target, key, descriptor) {
|
|
26363
|
+
return Reflect.defineProperty(target, key, "value" in descriptor ? { ...descriptor, value: tracker.unwrap(descriptor.value) } : descriptor);
|
|
26364
|
+
},
|
|
26365
|
+
get(target, key) {
|
|
26366
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
|
|
26367
|
+
const member = Reflect.get(target, key, target);
|
|
26368
|
+
if (descriptor && !descriptor.configurable && "value" in descriptor && !descriptor.writable) return member;
|
|
26369
|
+
return typeof member === "function" ? tracker.wrap(member) : member;
|
|
26370
|
+
},
|
|
26371
|
+
apply(target, receiver, args) {
|
|
26372
|
+
const result = Reflect.apply(target, tracker.unwrap(receiver), args.map(tracker.unwrap));
|
|
26373
|
+
if (result && typeof result.then === "function") {
|
|
26374
|
+
tracker.active++;
|
|
26375
|
+
return Promise.resolve(result).then(
|
|
26376
|
+
(value2) => {
|
|
26377
|
+
tracker.active--;
|
|
26378
|
+
return tracker.disposed ? new Promise(() => {
|
|
26379
|
+
}) : tracker.wrap(value2);
|
|
26380
|
+
},
|
|
26381
|
+
(error) => {
|
|
26382
|
+
tracker.active--;
|
|
26383
|
+
if (tracker.disposed) return new Promise(() => {
|
|
26384
|
+
});
|
|
26385
|
+
throw error;
|
|
26386
|
+
}
|
|
26387
|
+
);
|
|
26388
|
+
}
|
|
26389
|
+
return tracker.wrap(result);
|
|
26390
|
+
},
|
|
26391
|
+
construct(target, args, newTarget) {
|
|
26392
|
+
return tracker.wrap(Reflect.construct(target, args.map(tracker.unwrap), tracker.unwrap(newTarget)));
|
|
25967
26393
|
}
|
|
25968
|
-
|
|
25969
|
-
|
|
25970
|
-
|
|
25971
|
-
|
|
25972
|
-
case "AssignmentPattern":
|
|
25973
|
-
collectPattern2(node2.left, names);
|
|
25974
|
-
return;
|
|
25975
|
-
case "RestElement":
|
|
25976
|
-
collectPattern2(node2.argument, names);
|
|
25977
|
-
return;
|
|
25978
|
-
default:
|
|
25979
|
-
return;
|
|
26394
|
+
});
|
|
26395
|
+
this.wrapped.set(object, proxy);
|
|
26396
|
+
this.originals.set(proxy, object);
|
|
26397
|
+
return proxy;
|
|
25980
26398
|
}
|
|
25981
|
-
}
|
|
25982
|
-
|
|
25983
|
-
|
|
25984
|
-
|
|
25985
|
-
for (const edit of ordered) out = out.slice(0, edit.start) + edit.text + out.slice(edit.end);
|
|
25986
|
-
return out;
|
|
25987
|
-
}
|
|
25988
|
-
function isNode4(value) {
|
|
25989
|
-
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
25990
|
-
}
|
|
25991
|
-
var NOTHING2 = [];
|
|
25992
|
-
var PROPERTY2 = ["property", "key"];
|
|
25993
|
-
var LABEL2 = ["label"];
|
|
26399
|
+
};
|
|
26400
|
+
|
|
26401
|
+
// src/node/commonjs-engine.ts
|
|
26402
|
+
init_path();
|
|
25994
26403
|
var EXTENSIONS = [".js", ".mjs", ".cjs", ".json", ".node"];
|
|
26404
|
+
var PREFIX_ONLY_BUILTINS = /* @__PURE__ */ new Set(["test", "test/reporters", "sea", "sqlite"]);
|
|
25995
26405
|
var CONDITION_SETS = {
|
|
25996
26406
|
import: [["node", "import", "module", "default"], ["node", "require", "default"], ["default"]],
|
|
25997
26407
|
require: [["node", "require", "default"], ["node", "import", "module", "default"], ["default"]]
|
|
@@ -26331,7 +26741,8 @@ ${code}
|
|
|
26331
26741
|
}
|
|
26332
26742
|
builtin(specifier, importer) {
|
|
26333
26743
|
const name = specifier.replace(/^node:/, "");
|
|
26334
|
-
|
|
26744
|
+
const prefixOnly = PREFIX_ONLY_BUILTINS.has(name) && !specifier.startsWith("node:");
|
|
26745
|
+
if (prefixOnly || !Object.prototype.hasOwnProperty.call(this.builtins, name)) {
|
|
26335
26746
|
return Object.prototype.hasOwnProperty.call(this.overrides, specifier) ? { found: true, value: this.overrides[specifier] } : { found: false, value: void 0 };
|
|
26336
26747
|
}
|
|
26337
26748
|
if (name === "module" && importer) {
|
|
@@ -27601,21 +28012,23 @@ function resolveTarget(input, overrides, defaultProtocol) {
|
|
|
27601
28012
|
};
|
|
27602
28013
|
}
|
|
27603
28014
|
function isLoopback(hostname) {
|
|
27604
|
-
return
|
|
28015
|
+
return isLoopbackHostname(hostname);
|
|
27605
28016
|
}
|
|
27606
28017
|
var VirtualClientRequest = class extends streamModule4__default.default.Writable {
|
|
27607
|
-
constructor(target, router, fetchImpl, trackRequest) {
|
|
28018
|
+
constructor(target, router, fetchImpl, trackRequest, loopback = void 0) {
|
|
27608
28019
|
super();
|
|
27609
28020
|
this.target = target;
|
|
27610
28021
|
this.router = router;
|
|
27611
28022
|
this.fetchImpl = fetchImpl;
|
|
27612
28023
|
this.trackRequest = trackRequest;
|
|
28024
|
+
this.loopback = loopback;
|
|
27613
28025
|
for (const [name, value] of Object.entries(target.headers)) this.setHeader(name, value);
|
|
27614
28026
|
}
|
|
27615
28027
|
target;
|
|
27616
28028
|
router;
|
|
27617
28029
|
fetchImpl;
|
|
27618
28030
|
trackRequest;
|
|
28031
|
+
loopback;
|
|
27619
28032
|
socket = socketStub();
|
|
27620
28033
|
connection = this.socket;
|
|
27621
28034
|
chunks = [];
|
|
@@ -27729,7 +28142,9 @@ var VirtualClientRequest = class extends streamModule4__default.default.Writable
|
|
|
27729
28142
|
} catch (error) {
|
|
27730
28143
|
clearTimeout(this.timer);
|
|
27731
28144
|
if (this.destroyedByUser) return;
|
|
27732
|
-
const
|
|
28145
|
+
const thrown = error instanceof Error ? error : new Error(String(error));
|
|
28146
|
+
const cause = thrown.cause;
|
|
28147
|
+
const failure2 = cause instanceof Error && "code" in cause ? cause : thrown;
|
|
27733
28148
|
if (!("code" in failure2)) Object.assign(failure2, { code: "ECONNREFUSED" });
|
|
27734
28149
|
this.emit("error", failure2);
|
|
27735
28150
|
} finally {
|
|
@@ -27737,18 +28152,21 @@ var VirtualClientRequest = class extends streamModule4__default.default.Writable
|
|
|
27737
28152
|
}
|
|
27738
28153
|
}
|
|
27739
28154
|
async viaRouter(body) {
|
|
27740
|
-
|
|
28155
|
+
const init = {
|
|
28156
|
+
method: this.target.method,
|
|
28157
|
+
path: this.target.path,
|
|
28158
|
+
headers: this.getHeaders(),
|
|
28159
|
+
body: body.length ? new Uint8Array(body) : null
|
|
28160
|
+
};
|
|
28161
|
+
const local = this.router.activePortsIncludes(this.target.port);
|
|
28162
|
+
const remote = local || !this.loopback ? null : await this.loopback(this.target.port, init);
|
|
28163
|
+
if (!local && !remote) {
|
|
27741
28164
|
throw Object.assign(
|
|
27742
28165
|
new Error(`connect ECONNREFUSED ${this.target.hostname}:${this.target.port}`),
|
|
27743
28166
|
{ code: "ECONNREFUSED", errno: -61, syscall: "connect", address: this.target.hostname, port: this.target.port }
|
|
27744
28167
|
);
|
|
27745
28168
|
}
|
|
27746
|
-
const result = await this.router.request(this.target.port,
|
|
27747
|
-
method: this.target.method,
|
|
27748
|
-
path: this.target.path,
|
|
27749
|
-
headers: this.getHeaders(),
|
|
27750
|
-
body: body.length ? new Uint8Array(body) : null
|
|
27751
|
-
});
|
|
28169
|
+
const result = remote ?? await this.router.request(this.target.port, init);
|
|
27752
28170
|
const body_ = result.body;
|
|
27753
28171
|
const bytes2 = typeof body_ === "string" ? new TextEncoder().encode(body_) : body_ instanceof ArrayBuffer ? new Uint8Array(body_) : body_ ?? new Uint8Array();
|
|
27754
28172
|
const status = result.statusCode ?? 200;
|
|
@@ -27788,7 +28206,13 @@ function createHttpModule(router, owner, options = {}, defaultProtocol = "http:"
|
|
|
27788
28206
|
const request = (input, second, third) => {
|
|
27789
28207
|
const overrides = second && typeof second === "object" && !(second instanceof Function) ? second : void 0;
|
|
27790
28208
|
const callback = [second, third].find((value) => typeof value === "function");
|
|
27791
|
-
const req = new VirtualClientRequest(
|
|
28209
|
+
const req = new VirtualClientRequest(
|
|
28210
|
+
resolveTarget(input, overrides, defaultProtocol),
|
|
28211
|
+
router,
|
|
28212
|
+
options.fetch,
|
|
28213
|
+
options.trackRequest,
|
|
28214
|
+
options.loopback
|
|
28215
|
+
);
|
|
27792
28216
|
if (callback) req.on("response", callback);
|
|
27793
28217
|
return req;
|
|
27794
28218
|
};
|
|
@@ -27815,6 +28239,62 @@ function createHttpModule(router, owner, options = {}, defaultProtocol = "http:"
|
|
|
27815
28239
|
}
|
|
27816
28240
|
};
|
|
27817
28241
|
}
|
|
28242
|
+
function createVirtualFetch(router, options = {}) {
|
|
28243
|
+
return (async (input, init) => {
|
|
28244
|
+
const request = new Request(input, init);
|
|
28245
|
+
const url = new URL(request.url);
|
|
28246
|
+
const release = options.trackRequest?.();
|
|
28247
|
+
try {
|
|
28248
|
+
if (!isLoopback(url.hostname)) {
|
|
28249
|
+
if (!options.fetch) {
|
|
28250
|
+
throw Object.assign(new TypeError("fetch failed"), {
|
|
28251
|
+
cause: Object.assign(new Error(`getaddrinfo ENOTFOUND ${url.hostname}`), { code: "ENOTFOUND" })
|
|
28252
|
+
});
|
|
28253
|
+
}
|
|
28254
|
+
return await options.fetch(request);
|
|
28255
|
+
}
|
|
28256
|
+
const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
|
|
28257
|
+
const headers = {};
|
|
28258
|
+
request.headers.forEach((value, key) => {
|
|
28259
|
+
headers[key] = value;
|
|
28260
|
+
});
|
|
28261
|
+
const bodyless = request.method === "GET" || request.method === "HEAD";
|
|
28262
|
+
const loopbackRequest = {
|
|
28263
|
+
method: request.method,
|
|
28264
|
+
path: `${url.pathname}${url.search}`,
|
|
28265
|
+
headers,
|
|
28266
|
+
body: bodyless ? null : new Uint8Array(await request.arrayBuffer())
|
|
28267
|
+
};
|
|
28268
|
+
const result = router.activePortsIncludes(port) ? await router.request(port, loopbackRequest) : await options.loopback?.(port, loopbackRequest) ?? null;
|
|
28269
|
+
if (!result) {
|
|
28270
|
+
throw Object.assign(new TypeError("fetch failed"), {
|
|
28271
|
+
cause: Object.assign(new Error(`connect ECONNREFUSED ${url.hostname}:${port}`), {
|
|
28272
|
+
code: "ECONNREFUSED",
|
|
28273
|
+
errno: -61,
|
|
28274
|
+
syscall: "connect",
|
|
28275
|
+
address: url.hostname,
|
|
28276
|
+
port
|
|
28277
|
+
})
|
|
28278
|
+
});
|
|
28279
|
+
}
|
|
28280
|
+
const status = result.statusCode ?? 200;
|
|
28281
|
+
const responseHeaders = new Headers();
|
|
28282
|
+
for (const [name, value] of Object.entries(result.headers ?? {})) {
|
|
28283
|
+
for (const part of Array.isArray(value) ? value : [value]) responseHeaders.append(name, String(part));
|
|
28284
|
+
}
|
|
28285
|
+
const raw = result.body;
|
|
28286
|
+
const bytes2 = typeof raw === "string" ? new TextEncoder().encode(raw) : raw instanceof ArrayBuffer ? new Uint8Array(raw) : raw ?? new Uint8Array();
|
|
28287
|
+
const nullBody = status === 204 || status === 205 || status === 304 || request.method === "HEAD";
|
|
28288
|
+
return new Response(nullBody ? null : new Uint8Array(bytes2), {
|
|
28289
|
+
status,
|
|
28290
|
+
statusText: result.statusMessage ?? STATUS_CODES[status] ?? "",
|
|
28291
|
+
headers: responseHeaders
|
|
28292
|
+
});
|
|
28293
|
+
} finally {
|
|
28294
|
+
release?.();
|
|
28295
|
+
}
|
|
28296
|
+
});
|
|
28297
|
+
}
|
|
27818
28298
|
function validateHeaderName(name) {
|
|
27819
28299
|
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" });
|
|
27820
28300
|
}
|
|
@@ -27834,6 +28314,492 @@ function socketStub() {
|
|
|
27834
28314
|
}
|
|
27835
28315
|
var METHODS = ["ACL", "BIND", "CHECKOUT", "CONNECT", "COPY", "DELETE", "GET", "HEAD", "LINK", "LOCK", "M-SEARCH", "MERGE", "MKACTIVITY", "MKCALENDAR", "MKCOL", "MOVE", "NOTIFY", "OPTIONS", "PATCH", "POST", "PROPFIND", "PROPPATCH", "PURGE", "PUT", "REBIND", "REPORT", "SEARCH", "SOURCE", "SUBSCRIBE", "TRACE", "UNBIND", "UNLINK", "UNLOCK", "UNSUBSCRIBE"];
|
|
27836
28316
|
var STATUS_CODES = { 100: "Continue", 200: "OK", 201: "Created", 202: "Accepted", 204: "No Content", 206: "Partial Content", 301: "Moved Permanently", 302: "Found", 304: "Not Modified", 307: "Temporary Redirect", 308: "Permanent Redirect", 400: "Bad Request", 401: "Unauthorized", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 409: "Conflict", 413: "Payload Too Large", 415: "Unsupported Media Type", 422: "Unprocessable Entity", 429: "Too Many Requests", 500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway", 503: "Service Unavailable" };
|
|
28317
|
+
|
|
28318
|
+
// src/node/test-module.ts
|
|
28319
|
+
function parseArguments(args) {
|
|
28320
|
+
let name = "<anonymous>";
|
|
28321
|
+
let options = {};
|
|
28322
|
+
let fn;
|
|
28323
|
+
for (const arg of args) {
|
|
28324
|
+
if (typeof arg === "string") name = arg;
|
|
28325
|
+
else if (typeof arg === "function") {
|
|
28326
|
+
fn = arg;
|
|
28327
|
+
if (name === "<anonymous>" && arg.name) name = arg.name;
|
|
28328
|
+
} else if (arg && typeof arg === "object") options = arg;
|
|
28329
|
+
}
|
|
28330
|
+
return { name, options, fn };
|
|
28331
|
+
}
|
|
28332
|
+
function errorText(error) {
|
|
28333
|
+
if (error instanceof Error) {
|
|
28334
|
+
const stack = error.stack ?? `${error.name}: ${error.message}`;
|
|
28335
|
+
return stack.includes(error.message) ? stack : `${error.name}: ${error.message}
|
|
28336
|
+
${stack}`;
|
|
28337
|
+
}
|
|
28338
|
+
return String(error);
|
|
28339
|
+
}
|
|
28340
|
+
function indent(text2, spaces) {
|
|
28341
|
+
const pad2 = " ".repeat(spaces);
|
|
28342
|
+
return text2.split("\n").map((line) => line ? pad2 + line : line).join("\n");
|
|
28343
|
+
}
|
|
28344
|
+
function duration(started) {
|
|
28345
|
+
return (performance.now() - started).toFixed(6).replace(/\.?0+$/, "");
|
|
28346
|
+
}
|
|
28347
|
+
function invoke(host2, fn, context, timeout) {
|
|
28348
|
+
const body = new Promise((resolve3, reject) => {
|
|
28349
|
+
if (fn.length >= 2) {
|
|
28350
|
+
let settled = false;
|
|
28351
|
+
const done = (error) => {
|
|
28352
|
+
if (settled) return;
|
|
28353
|
+
settled = true;
|
|
28354
|
+
if (error) reject(error);
|
|
28355
|
+
else resolve3();
|
|
28356
|
+
};
|
|
28357
|
+
try {
|
|
28358
|
+
const returned = fn(context, done);
|
|
28359
|
+
if (returned && typeof returned.then === "function") {
|
|
28360
|
+
reject(new Error("passed a callback but also returned a Promise"));
|
|
28361
|
+
}
|
|
28362
|
+
} catch (error) {
|
|
28363
|
+
done(error);
|
|
28364
|
+
}
|
|
28365
|
+
return;
|
|
28366
|
+
}
|
|
28367
|
+
try {
|
|
28368
|
+
Promise.resolve(fn(context)).then(() => resolve3(), reject);
|
|
28369
|
+
} catch (error) {
|
|
28370
|
+
reject(error);
|
|
28371
|
+
}
|
|
28372
|
+
});
|
|
28373
|
+
if (timeout === void 0 || !Number.isFinite(timeout)) return body;
|
|
28374
|
+
return new Promise((resolve3, reject) => {
|
|
28375
|
+
const timer = host2.setTimeout(() => reject(new Error(`test timed out after ${timeout}ms`)), timeout);
|
|
28376
|
+
body.then(
|
|
28377
|
+
() => {
|
|
28378
|
+
host2.clearTimeout(timer);
|
|
28379
|
+
resolve3();
|
|
28380
|
+
},
|
|
28381
|
+
(error) => {
|
|
28382
|
+
host2.clearTimeout(timer);
|
|
28383
|
+
reject(error);
|
|
28384
|
+
}
|
|
28385
|
+
);
|
|
28386
|
+
});
|
|
28387
|
+
}
|
|
28388
|
+
function createMockTracker() {
|
|
28389
|
+
const restorers = [];
|
|
28390
|
+
const fn = (original = () => void 0, implementation = original) => {
|
|
28391
|
+
let current = implementation;
|
|
28392
|
+
const once = /* @__PURE__ */ new Map();
|
|
28393
|
+
const calls = [];
|
|
28394
|
+
const mocked = function(...args) {
|
|
28395
|
+
const index = calls.length;
|
|
28396
|
+
const chosen = once.get(index) ?? current;
|
|
28397
|
+
once.delete(index);
|
|
28398
|
+
const call = { arguments: args, result: void 0, error: void 0, this: this };
|
|
28399
|
+
calls.push(call);
|
|
28400
|
+
try {
|
|
28401
|
+
call.result = chosen.apply(this, args);
|
|
28402
|
+
return call.result;
|
|
28403
|
+
} catch (error) {
|
|
28404
|
+
call.error = error;
|
|
28405
|
+
throw error;
|
|
28406
|
+
}
|
|
28407
|
+
};
|
|
28408
|
+
Object.defineProperty(mocked, "mock", {
|
|
28409
|
+
value: {
|
|
28410
|
+
calls,
|
|
28411
|
+
callCount: () => calls.length,
|
|
28412
|
+
resetCalls: () => {
|
|
28413
|
+
calls.length = 0;
|
|
28414
|
+
},
|
|
28415
|
+
mockImplementation: (next) => {
|
|
28416
|
+
current = next;
|
|
28417
|
+
},
|
|
28418
|
+
mockImplementationOnce: (next, onCall) => {
|
|
28419
|
+
once.set(onCall ?? calls.length, next);
|
|
28420
|
+
},
|
|
28421
|
+
restore: () => {
|
|
28422
|
+
current = original;
|
|
28423
|
+
}
|
|
28424
|
+
}
|
|
28425
|
+
});
|
|
28426
|
+
return mocked;
|
|
28427
|
+
};
|
|
28428
|
+
const method = (object, name, implementation) => {
|
|
28429
|
+
const original = object[name];
|
|
28430
|
+
if (typeof original !== "function") {
|
|
28431
|
+
throw new TypeError(`The property '${name}' is not a function and cannot be mocked`);
|
|
28432
|
+
}
|
|
28433
|
+
const mocked = fn(original, implementation ?? original);
|
|
28434
|
+
object[name] = mocked;
|
|
28435
|
+
const restore = () => {
|
|
28436
|
+
object[name] = original;
|
|
28437
|
+
};
|
|
28438
|
+
mocked.mock.restore = restore;
|
|
28439
|
+
restorers.push(restore);
|
|
28440
|
+
return mocked;
|
|
28441
|
+
};
|
|
28442
|
+
return {
|
|
28443
|
+
fn,
|
|
28444
|
+
method,
|
|
28445
|
+
reset: () => {
|
|
28446
|
+
for (const restore of restorers.splice(0)) restore();
|
|
28447
|
+
},
|
|
28448
|
+
restoreAll: () => {
|
|
28449
|
+
for (const restore of restorers.splice(0)) restore();
|
|
28450
|
+
}
|
|
28451
|
+
};
|
|
28452
|
+
}
|
|
28453
|
+
function createTestModule(host2) {
|
|
28454
|
+
const root = {
|
|
28455
|
+
kind: "suite",
|
|
28456
|
+
name: "",
|
|
28457
|
+
options: {},
|
|
28458
|
+
parent: null,
|
|
28459
|
+
children: [],
|
|
28460
|
+
hooks: { before: [], after: [], beforeEach: [], afterEach: [] }
|
|
28461
|
+
};
|
|
28462
|
+
let collecting = root;
|
|
28463
|
+
let scheduled = false;
|
|
28464
|
+
let running = null;
|
|
28465
|
+
const mock = createMockTracker();
|
|
28466
|
+
const counts = { tests: 0, suites: 0, pass: 0, fail: 0, cancelled: 0, skipped: 0, todo: 0 };
|
|
28467
|
+
const failures = [];
|
|
28468
|
+
let tapIndex = 0;
|
|
28469
|
+
let onlyWarned = false;
|
|
28470
|
+
const settings = () => host2.settings();
|
|
28471
|
+
const tap = () => settings().reporter === "tap";
|
|
28472
|
+
const schedule = () => {
|
|
28473
|
+
if (scheduled) return;
|
|
28474
|
+
scheduled = true;
|
|
28475
|
+
host2.setTimeout(() => {
|
|
28476
|
+
running = runAll();
|
|
28477
|
+
}, 0);
|
|
28478
|
+
};
|
|
28479
|
+
const fullName = (node2) => {
|
|
28480
|
+
const parts = [];
|
|
28481
|
+
let cursor = node2;
|
|
28482
|
+
while (cursor && cursor !== root) {
|
|
28483
|
+
parts.unshift(cursor.name);
|
|
28484
|
+
cursor = cursor.parent;
|
|
28485
|
+
}
|
|
28486
|
+
return parts.join(" ");
|
|
28487
|
+
};
|
|
28488
|
+
const matchesPattern2 = (name) => {
|
|
28489
|
+
const patterns = settings().namePatterns ?? [];
|
|
28490
|
+
if (patterns.length === 0) return true;
|
|
28491
|
+
return patterns.some((pattern) => {
|
|
28492
|
+
try {
|
|
28493
|
+
return new RegExp(pattern).test(name);
|
|
28494
|
+
} catch {
|
|
28495
|
+
return name.includes(pattern);
|
|
28496
|
+
}
|
|
28497
|
+
});
|
|
28498
|
+
};
|
|
28499
|
+
const hasOnly = (node2) => Boolean(node2.options.only) || node2.kind === "suite" && node2.children.some(hasOnly);
|
|
28500
|
+
const report = (depth, outcome, name, started, detail) => {
|
|
28501
|
+
if (tap()) {
|
|
28502
|
+
tapIndex += 1;
|
|
28503
|
+
const ok2 = outcome === "fail" ? "not ok" : "ok";
|
|
28504
|
+
const directive = outcome === "skip" ? " # SKIP" : outcome === "todo" ? " # TODO" : outcome === "cancelled" ? " # CANCELLED" : "";
|
|
28505
|
+
host2.write(`${ok2} ${tapIndex} - ${name}${directive}
|
|
28506
|
+
`);
|
|
28507
|
+
host2.write(` ---
|
|
28508
|
+
duration_ms: ${duration(started)}
|
|
28509
|
+
`);
|
|
28510
|
+
if (detail) host2.write(` error: |-
|
|
28511
|
+
${indent(detail, 4)}
|
|
28512
|
+
`);
|
|
28513
|
+
host2.write(" ...\n");
|
|
28514
|
+
return;
|
|
28515
|
+
}
|
|
28516
|
+
const pad2 = " ".repeat(depth);
|
|
28517
|
+
const mark = outcome === "pass" ? "\u2714" : outcome === "fail" ? "\u2716" : outcome === "cancelled" ? "\u2716" : "\uFE63";
|
|
28518
|
+
const suffix = outcome === "skip" ? " # SKIP" : outcome === "todo" ? " # TODO" : "";
|
|
28519
|
+
host2.write(`${pad2}${mark} ${name} (${duration(started)}ms)${suffix}
|
|
28520
|
+
`);
|
|
28521
|
+
if (detail) host2.write(`${indent(detail, depth * 2 + 2)}
|
|
28522
|
+
`);
|
|
28523
|
+
};
|
|
28524
|
+
const record = (outcome, name, error) => {
|
|
28525
|
+
counts.tests += 1;
|
|
28526
|
+
if (outcome === "pass") counts.pass += 1;
|
|
28527
|
+
else if (outcome === "fail") {
|
|
28528
|
+
counts.fail += 1;
|
|
28529
|
+
failures.push({ name, error });
|
|
28530
|
+
} else if (outcome === "cancelled") {
|
|
28531
|
+
counts.cancelled += 1;
|
|
28532
|
+
failures.push({ name, error });
|
|
28533
|
+
} else if (outcome === "skip") counts.skipped += 1;
|
|
28534
|
+
else counts.todo += 1;
|
|
28535
|
+
};
|
|
28536
|
+
const ancestors = (suite) => {
|
|
28537
|
+
const chain = [];
|
|
28538
|
+
for (let cursor = suite; cursor; cursor = cursor.parent) chain.unshift(cursor);
|
|
28539
|
+
return chain;
|
|
28540
|
+
};
|
|
28541
|
+
const runTest = async (name, display, options, fn, depth, suite, extraHooks, runOnly) => {
|
|
28542
|
+
const started = performance.now();
|
|
28543
|
+
if (!matchesPattern2(display)) return true;
|
|
28544
|
+
if (runOnly && !options.only) return true;
|
|
28545
|
+
if (options.skip) {
|
|
28546
|
+
record("skip", display);
|
|
28547
|
+
report(depth, "skip", name, started);
|
|
28548
|
+
return true;
|
|
28549
|
+
}
|
|
28550
|
+
if (!fn) {
|
|
28551
|
+
const outcome = options.todo ? "todo" : "skip";
|
|
28552
|
+
record(outcome, display);
|
|
28553
|
+
report(depth, outcome, name, started);
|
|
28554
|
+
return true;
|
|
28555
|
+
}
|
|
28556
|
+
const controller = new AbortController();
|
|
28557
|
+
const subtests = [];
|
|
28558
|
+
const ownHooks = { before: [], after: [], beforeEach: [], afterEach: [] };
|
|
28559
|
+
let skipped = false;
|
|
28560
|
+
let todo = options.todo ?? false;
|
|
28561
|
+
const context = {
|
|
28562
|
+
name,
|
|
28563
|
+
fullName: display,
|
|
28564
|
+
signal: controller.signal,
|
|
28565
|
+
mock,
|
|
28566
|
+
test: (...args) => {
|
|
28567
|
+
const sub = parseArguments(args);
|
|
28568
|
+
const promise = runTest(
|
|
28569
|
+
sub.name,
|
|
28570
|
+
`${display} ${sub.name}`,
|
|
28571
|
+
sub.options,
|
|
28572
|
+
sub.fn,
|
|
28573
|
+
depth + 1,
|
|
28574
|
+
suite,
|
|
28575
|
+
ownHooks,
|
|
28576
|
+
false
|
|
28577
|
+
);
|
|
28578
|
+
subtests.push(promise);
|
|
28579
|
+
return promise.then(() => void 0);
|
|
28580
|
+
},
|
|
28581
|
+
skip: (message) => {
|
|
28582
|
+
skipped = message ?? true;
|
|
28583
|
+
},
|
|
28584
|
+
todo: (message) => {
|
|
28585
|
+
todo = message ?? true;
|
|
28586
|
+
},
|
|
28587
|
+
diagnostic: (message) => {
|
|
28588
|
+
host2.write(tap() ? `# ${message}
|
|
28589
|
+
` : `${" ".repeat(depth + 1)}\u2139 ${message}
|
|
28590
|
+
`);
|
|
28591
|
+
},
|
|
28592
|
+
plan: () => {
|
|
28593
|
+
},
|
|
28594
|
+
before: (hook2) => ownHooks.before.push(hook2),
|
|
28595
|
+
after: (hook2) => ownHooks.after.push(hook2),
|
|
28596
|
+
beforeEach: (hook2) => ownHooks.beforeEach.push(hook2),
|
|
28597
|
+
afterEach: (hook2) => ownHooks.afterEach.push(hook2)
|
|
28598
|
+
};
|
|
28599
|
+
let error;
|
|
28600
|
+
try {
|
|
28601
|
+
const chain = ancestors(suite);
|
|
28602
|
+
for (const level of chain) for (const hook2 of level.hooks.beforeEach) await invoke(host2, hook2, context, void 0);
|
|
28603
|
+
for (const hook2 of extraHooks.beforeEach) await invoke(host2, hook2, context, void 0);
|
|
28604
|
+
await invoke(host2, fn, context, options.timeout);
|
|
28605
|
+
const results = await Promise.all(subtests);
|
|
28606
|
+
for (const hook2 of ownHooks.after) await invoke(host2, hook2, context, void 0);
|
|
28607
|
+
if (results.includes(false)) error = new Error(`${results.filter((ok2) => !ok2).length} subtest(s) failed`);
|
|
28608
|
+
for (const hook2 of extraHooks.afterEach) await invoke(host2, hook2, context, void 0);
|
|
28609
|
+
for (const level of [...chain].reverse()) for (const hook2 of level.hooks.afterEach) await invoke(host2, hook2, context, void 0);
|
|
28610
|
+
} catch (caught) {
|
|
28611
|
+
error = caught;
|
|
28612
|
+
} finally {
|
|
28613
|
+
controller.abort();
|
|
28614
|
+
}
|
|
28615
|
+
if (skipped) {
|
|
28616
|
+
record("skip", display);
|
|
28617
|
+
report(depth, "skip", name, started);
|
|
28618
|
+
return true;
|
|
28619
|
+
}
|
|
28620
|
+
if (error !== void 0) {
|
|
28621
|
+
if (todo) {
|
|
28622
|
+
record("todo", display);
|
|
28623
|
+
report(depth, "todo", name, started);
|
|
28624
|
+
return true;
|
|
28625
|
+
}
|
|
28626
|
+
record("fail", display, error);
|
|
28627
|
+
report(depth, "fail", name, started, errorText(error));
|
|
28628
|
+
return false;
|
|
28629
|
+
}
|
|
28630
|
+
record(todo ? "todo" : "pass", display);
|
|
28631
|
+
report(depth, todo ? "todo" : "pass", name, started);
|
|
28632
|
+
return true;
|
|
28633
|
+
};
|
|
28634
|
+
const runSuite = async (suite, depth, runOnly) => {
|
|
28635
|
+
const started = performance.now();
|
|
28636
|
+
const display = fullName(suite);
|
|
28637
|
+
const isRoot = suite === root;
|
|
28638
|
+
if (!isRoot) {
|
|
28639
|
+
counts.suites += 1;
|
|
28640
|
+
if (tap()) host2.write(`# Subtest: ${suite.name}
|
|
28641
|
+
`);
|
|
28642
|
+
else host2.write(`${" ".repeat(depth)}\u25B6 ${suite.name}
|
|
28643
|
+
`);
|
|
28644
|
+
if (suite.options.skip) {
|
|
28645
|
+
for (const child of suite.children) if (child.kind === "test") record("skip", fullName(child));
|
|
28646
|
+
report(depth, "skip", suite.name, started);
|
|
28647
|
+
return true;
|
|
28648
|
+
}
|
|
28649
|
+
}
|
|
28650
|
+
const context = { name: suite.name, signal: new AbortController().signal };
|
|
28651
|
+
let ok2 = true;
|
|
28652
|
+
try {
|
|
28653
|
+
for (const hook2 of suite.hooks.before) await invoke(host2, hook2, context, void 0);
|
|
28654
|
+
} catch (error) {
|
|
28655
|
+
for (const child of suite.children) {
|
|
28656
|
+
if (child.kind === "test") {
|
|
28657
|
+
record("cancelled", fullName(child), error);
|
|
28658
|
+
report(depth + (isRoot ? 0 : 1), "cancelled", child.name, started, errorText(error));
|
|
28659
|
+
}
|
|
28660
|
+
}
|
|
28661
|
+
if (!isRoot) report(depth, "fail", suite.name, started);
|
|
28662
|
+
return false;
|
|
28663
|
+
}
|
|
28664
|
+
const only = runOnly || settings().only === true && suite.children.some(hasOnly);
|
|
28665
|
+
for (const child of suite.children) {
|
|
28666
|
+
const childDepth = depth + (isRoot ? 0 : 1);
|
|
28667
|
+
if (child.kind === "suite") {
|
|
28668
|
+
if (only && !hasOnly(child) && !child.options.only) continue;
|
|
28669
|
+
ok2 = await runSuite(child, childDepth, only && !child.options.only) && ok2;
|
|
28670
|
+
} else {
|
|
28671
|
+
ok2 = await runTest(
|
|
28672
|
+
child.name,
|
|
28673
|
+
fullName(child),
|
|
28674
|
+
child.options,
|
|
28675
|
+
child.fn,
|
|
28676
|
+
childDepth,
|
|
28677
|
+
suite,
|
|
28678
|
+
{ before: [], after: [], beforeEach: [], afterEach: [] },
|
|
28679
|
+
only
|
|
28680
|
+
) && ok2;
|
|
28681
|
+
}
|
|
28682
|
+
}
|
|
28683
|
+
try {
|
|
28684
|
+
for (const hook2 of suite.hooks.after) await invoke(host2, hook2, context, void 0);
|
|
28685
|
+
} catch (error) {
|
|
28686
|
+
ok2 = false;
|
|
28687
|
+
failures.push({ name: `${display || "<root>"} (after hook)`, error });
|
|
28688
|
+
host2.write(`${indent(`\u2716 after hook failed
|
|
28689
|
+
${errorText(error)}`, depth * 2)}
|
|
28690
|
+
`);
|
|
28691
|
+
}
|
|
28692
|
+
if (!isRoot) {
|
|
28693
|
+
if (tap()) host2.write(`${ok2 ? "ok" : "not ok"} ${++tapIndex} - ${suite.name}
|
|
28694
|
+
`);
|
|
28695
|
+
else host2.write(`${" ".repeat(depth)}${ok2 ? "\u25B6" : "\u2716"} ${suite.name} (${duration(started)}ms)
|
|
28696
|
+
`);
|
|
28697
|
+
}
|
|
28698
|
+
return ok2;
|
|
28699
|
+
};
|
|
28700
|
+
const runAll = async () => {
|
|
28701
|
+
const release = host2.keepAlive();
|
|
28702
|
+
const started = performance.now();
|
|
28703
|
+
if (tap()) host2.write("TAP version 13\n");
|
|
28704
|
+
if (!settings().only && !onlyWarned && root.children.some(hasOnly)) {
|
|
28705
|
+
onlyWarned = true;
|
|
28706
|
+
host2.write("\u2139 'only' and 'runOnly' require the --test-only command-line option.\n");
|
|
28707
|
+
}
|
|
28708
|
+
let ok2 = true;
|
|
28709
|
+
try {
|
|
28710
|
+
ok2 = await runSuite(root, 0, false);
|
|
28711
|
+
} catch (error) {
|
|
28712
|
+
ok2 = false;
|
|
28713
|
+
failures.push({ name: "<test runner>", error });
|
|
28714
|
+
}
|
|
28715
|
+
mock.restoreAll();
|
|
28716
|
+
if (tap()) {
|
|
28717
|
+
host2.write(`1..${tapIndex}
|
|
28718
|
+
`);
|
|
28719
|
+
for (const [key, value] of Object.entries(counts)) host2.write(`# ${key} ${value}
|
|
28720
|
+
`);
|
|
28721
|
+
host2.write(`# duration_ms ${duration(started)}
|
|
28722
|
+
`);
|
|
28723
|
+
} else {
|
|
28724
|
+
for (const [key, value] of Object.entries(counts)) host2.write(`\u2139 ${key} ${value}
|
|
28725
|
+
`);
|
|
28726
|
+
host2.write(`\u2139 duration_ms ${duration(started)}
|
|
28727
|
+
`);
|
|
28728
|
+
if (failures.length > 0) {
|
|
28729
|
+
host2.write("\n\u2716 failing tests:\n\n");
|
|
28730
|
+
for (const failure2 of failures) host2.write(`test at ${failure2.name}
|
|
28731
|
+
${indent(errorText(failure2.error), 2)}
|
|
28732
|
+
|
|
28733
|
+
`);
|
|
28734
|
+
}
|
|
28735
|
+
}
|
|
28736
|
+
release();
|
|
28737
|
+
host2.exit(ok2 && counts.fail === 0 && counts.cancelled === 0 ? 0 : 1);
|
|
28738
|
+
};
|
|
28739
|
+
const declareTest = (extra) => (...args) => {
|
|
28740
|
+
const { name, options, fn } = parseArguments(args);
|
|
28741
|
+
if (running && collecting === root && scheduled) {
|
|
28742
|
+
host2.write(`\u2716 test "${name}" was declared after the run started and did not run
|
|
28743
|
+
`);
|
|
28744
|
+
return Promise.resolve();
|
|
28745
|
+
}
|
|
28746
|
+
collecting.children.push({ kind: "test", name, options: { ...options, ...extra }, parent: collecting, fn });
|
|
28747
|
+
schedule();
|
|
28748
|
+
return Promise.resolve();
|
|
28749
|
+
};
|
|
28750
|
+
const declareSuite = (extra) => (...args) => {
|
|
28751
|
+
const { name, options, fn } = parseArguments(args);
|
|
28752
|
+
const suite = {
|
|
28753
|
+
kind: "suite",
|
|
28754
|
+
name,
|
|
28755
|
+
options: { ...options, ...extra },
|
|
28756
|
+
parent: collecting,
|
|
28757
|
+
children: [],
|
|
28758
|
+
hooks: { before: [], after: [], beforeEach: [], afterEach: [] }
|
|
28759
|
+
};
|
|
28760
|
+
collecting.children.push(suite);
|
|
28761
|
+
schedule();
|
|
28762
|
+
const previous = collecting;
|
|
28763
|
+
collecting = suite;
|
|
28764
|
+
try {
|
|
28765
|
+
fn?.({ name, signal: new AbortController().signal });
|
|
28766
|
+
} finally {
|
|
28767
|
+
collecting = previous;
|
|
28768
|
+
}
|
|
28769
|
+
return Promise.resolve();
|
|
28770
|
+
};
|
|
28771
|
+
const withModifiers = (make) => {
|
|
28772
|
+
const base2 = make({});
|
|
28773
|
+
base2.skip = make({ skip: true });
|
|
28774
|
+
base2.todo = make({ todo: true });
|
|
28775
|
+
base2.only = make({ only: true });
|
|
28776
|
+
return base2;
|
|
28777
|
+
};
|
|
28778
|
+
const test = withModifiers(declareTest);
|
|
28779
|
+
const describe2 = withModifiers(declareSuite);
|
|
28780
|
+
const hook = (kind) => (fn) => {
|
|
28781
|
+
collecting.hooks[kind].push(fn);
|
|
28782
|
+
schedule();
|
|
28783
|
+
};
|
|
28784
|
+
Object.assign(test, {
|
|
28785
|
+
test,
|
|
28786
|
+
it: test,
|
|
28787
|
+
describe: describe2,
|
|
28788
|
+
suite: describe2,
|
|
28789
|
+
before: hook("before"),
|
|
28790
|
+
after: hook("after"),
|
|
28791
|
+
beforeEach: hook("beforeEach"),
|
|
28792
|
+
afterEach: hook("afterEach"),
|
|
28793
|
+
mock,
|
|
28794
|
+
run: () => {
|
|
28795
|
+
throw Object.assign(new Error("node:test run() is not available in this container; use `node --test`"), {
|
|
28796
|
+
code: "ERR_FEATURE_UNAVAILABLE_ON_PLATFORM"
|
|
28797
|
+
});
|
|
28798
|
+
}
|
|
28799
|
+
});
|
|
28800
|
+
Object.defineProperty(test, "default", { value: test, enumerable: false });
|
|
28801
|
+
return test;
|
|
28802
|
+
}
|
|
27837
28803
|
var hashes = { md5: legacy$1.md5, sha1: legacy$1.sha1, "sha-1": legacy$1.sha1, sha224: sha256.sha224, "sha-224": sha256.sha224, sha256: sha256.sha256, "sha-256": sha256.sha256, sha384: sha512.sha384, "sha-384": sha512.sha384, sha512: sha512.sha512, "sha-512": sha512.sha512 };
|
|
27838
28804
|
function createCryptoModule() {
|
|
27839
28805
|
const cryptoObject = globalThis.crypto;
|
|
@@ -28790,7 +29756,7 @@ function createCoreModules(options) {
|
|
|
28790
29756
|
});
|
|
28791
29757
|
const stderrWrite = options.stderr ?? (() => {
|
|
28792
29758
|
});
|
|
28793
|
-
const timers = createTrackedTimers();
|
|
29759
|
+
const timers = createTrackedTimers((error) => reportUncaught(error));
|
|
28794
29760
|
const processObject = Object.assign(new EventEmitter4__default.default(), processShim__default.default, {
|
|
28795
29761
|
argv: options.argv?.slice() ?? ["/usr/bin/node"],
|
|
28796
29762
|
argv0: "node",
|
|
@@ -28820,16 +29786,65 @@ function createCoreModules(options) {
|
|
|
28820
29786
|
uptime: () => performance.now() / 1e3,
|
|
28821
29787
|
memoryUsage: () => ({ rss: 0, heapTotal: 0, heapUsed: 0, external: 0, arrayBuffers: 0 }),
|
|
28822
29788
|
cpuUsage: () => ({ user: 0, system: 0 }),
|
|
28823
|
-
|
|
28824
|
-
|
|
28825
|
-
|
|
28826
|
-
|
|
29789
|
+
/* A bare `process.exit()` ends with `process.exitCode`, as in Node. */
|
|
29790
|
+
exit: (code) => {
|
|
29791
|
+
const status = normalizeExitCode(code ?? processObject.exitCode);
|
|
29792
|
+
exitCode = status;
|
|
29793
|
+
processObject.exitCode = status;
|
|
29794
|
+
emitExit(status);
|
|
29795
|
+
options.onExit?.(status);
|
|
29796
|
+
},
|
|
29797
|
+
nextTick: (fn, ...args) => {
|
|
29798
|
+
queueMicrotask(() => {
|
|
29799
|
+
try {
|
|
29800
|
+
fn(...args);
|
|
29801
|
+
} catch (error) {
|
|
29802
|
+
reportUncaught(error);
|
|
29803
|
+
}
|
|
29804
|
+
});
|
|
28827
29805
|
},
|
|
28828
29806
|
kill: () => true
|
|
28829
29807
|
});
|
|
29808
|
+
for (const method of EVENT_EMITTER_METHODS) {
|
|
29809
|
+
const implementation = EventEmitter4__default.default.prototype[method];
|
|
29810
|
+
if (typeof implementation === "function") processObject[method] = implementation;
|
|
29811
|
+
}
|
|
28830
29812
|
const tty = options.tty === true;
|
|
28831
29813
|
processObject.stdout = makeOutputStream(stdoutWrite, 1, tty);
|
|
28832
29814
|
processObject.stderr = makeOutputStream(stderrWrite, 2, tty);
|
|
29815
|
+
let exiting = false;
|
|
29816
|
+
const emitExit = (status) => {
|
|
29817
|
+
if (exiting) return;
|
|
29818
|
+
exiting = true;
|
|
29819
|
+
try {
|
|
29820
|
+
processObject.emit("exit", status);
|
|
29821
|
+
} catch {
|
|
29822
|
+
}
|
|
29823
|
+
};
|
|
29824
|
+
const reportUncaught = (error, origin = "uncaughtException") => {
|
|
29825
|
+
if (!exiting && processObject.listenerCount(origin) > 0) {
|
|
29826
|
+
try {
|
|
29827
|
+
processObject.emit(origin, error, origin === "uncaughtException" ? origin : void 0);
|
|
29828
|
+
return;
|
|
29829
|
+
} catch (handlerError) {
|
|
29830
|
+
error = handlerError;
|
|
29831
|
+
}
|
|
29832
|
+
}
|
|
29833
|
+
stderrWrite(formatUncaught(error));
|
|
29834
|
+
try {
|
|
29835
|
+
processObject.exit(1);
|
|
29836
|
+
} catch {
|
|
29837
|
+
}
|
|
29838
|
+
};
|
|
29839
|
+
const defer = (fn) => {
|
|
29840
|
+
queueMicrotask(() => {
|
|
29841
|
+
try {
|
|
29842
|
+
fn();
|
|
29843
|
+
} catch (error) {
|
|
29844
|
+
reportUncaught(error);
|
|
29845
|
+
}
|
|
29846
|
+
});
|
|
29847
|
+
};
|
|
28833
29848
|
const stdin = options.interactiveStdin ? new streamModule4__default.default.PassThrough() : new streamModule4__default.default.Readable({ read() {
|
|
28834
29849
|
this.push(null);
|
|
28835
29850
|
} });
|
|
@@ -28849,7 +29864,7 @@ function createCoreModules(options) {
|
|
|
28849
29864
|
});
|
|
28850
29865
|
processObject.stdin = stdin;
|
|
28851
29866
|
Reflect.deleteProperty(processObject, "browser");
|
|
28852
|
-
const fs = createFsModule(volume, () => cwd, options.stdinPath);
|
|
29867
|
+
const fs = createFsModule(volume, () => cwd, options.stdinPath, defer);
|
|
28853
29868
|
const path = createPathModule(() => cwd);
|
|
28854
29869
|
const consoleObject = new Console(stdoutWrite, stderrWrite);
|
|
28855
29870
|
const os = createOsModule();
|
|
@@ -28862,20 +29877,24 @@ function createCoreModules(options) {
|
|
|
28862
29877
|
}
|
|
28863
29878
|
};
|
|
28864
29879
|
let inFlightRequests = 0;
|
|
29880
|
+
const trackRequest = () => {
|
|
29881
|
+
inFlightRequests++;
|
|
29882
|
+
return () => {
|
|
29883
|
+
inFlightRequests--;
|
|
29884
|
+
};
|
|
29885
|
+
};
|
|
29886
|
+
const ambientFetch = options.http?.fetch ?? (typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : void 0);
|
|
29887
|
+
const outboundFetch = options.http?.policy && ambientFetch ? policedFetch(options.http.policy, ambientFetch) : ambientFetch;
|
|
28865
29888
|
const httpOptions = {
|
|
28866
|
-
...
|
|
28867
|
-
|
|
28868
|
-
|
|
28869
|
-
return () => {
|
|
28870
|
-
inFlightRequests--;
|
|
28871
|
-
};
|
|
28872
|
-
}
|
|
29889
|
+
...outboundFetch ? { fetch: outboundFetch } : {},
|
|
29890
|
+
...options.http?.loopback ? { loopback: options.http.loopback } : {},
|
|
29891
|
+
trackRequest
|
|
28873
29892
|
};
|
|
28874
29893
|
const http = options.http ? createHttpModule(options.http.router, options.http.owner, httpOptions, "http:") : createUnsupportedModule("http");
|
|
28875
29894
|
const https = options.http ? createHttpModule(options.http.router, options.http.owner, httpOptions, "https:") : createUnsupportedModule("https");
|
|
28876
29895
|
const childProcess = options.spawnChild ? createChildProcessModule(options.spawnChild, () => cwd, options.syncSpawn, () => ({ ...processObject.env })) : createUnsupportedModule("child_process");
|
|
28877
29896
|
const readline = createReadlineModule(() => processObject.stdin, () => processObject.stdout);
|
|
28878
|
-
const dns = createDnsModule();
|
|
29897
|
+
const dns = createDnsModule(defer);
|
|
28879
29898
|
const builtins = {
|
|
28880
29899
|
assert: assert_module_default,
|
|
28881
29900
|
"assert/strict": assert_module_default.strict ?? assert_module_default,
|
|
@@ -28911,7 +29930,27 @@ function createCoreModules(options) {
|
|
|
28911
29930
|
url: url_module_default,
|
|
28912
29931
|
util: util_module_default,
|
|
28913
29932
|
"util/types": util_module_default.types ?? {},
|
|
28914
|
-
zlib: zlib_module_default
|
|
29933
|
+
zlib: zlib_module_default,
|
|
29934
|
+
test: createTestModule({
|
|
29935
|
+
write: stdoutWrite,
|
|
29936
|
+
setTimeout: (fn, ms) => timers.api.setTimeout(fn, ms),
|
|
29937
|
+
clearTimeout: (handle) => timers.api.clearTimeout(handle),
|
|
29938
|
+
/* A pending interval is what keeps a process alive in this runtime; a test
|
|
29939
|
+
* awaiting nothing but promises would otherwise be judged finished. */
|
|
29940
|
+
keepAlive: () => {
|
|
29941
|
+
const handle = timers.api.setInterval(() => {
|
|
29942
|
+
}, 1 << 30);
|
|
29943
|
+
return () => timers.api.clearInterval(handle);
|
|
29944
|
+
},
|
|
29945
|
+
exit: (code) => {
|
|
29946
|
+
processObject.exitCode = code;
|
|
29947
|
+
try {
|
|
29948
|
+
processObject.exit(code);
|
|
29949
|
+
} catch {
|
|
29950
|
+
}
|
|
29951
|
+
},
|
|
29952
|
+
settings: () => parseTestSettings(env2.SANDBOXEDJS_NODE_TEST)
|
|
29953
|
+
})
|
|
28915
29954
|
};
|
|
28916
29955
|
for (const name of stubNames) builtins[name] = createUnsupportedModule(name);
|
|
28917
29956
|
builtins.net = createNetModule();
|
|
@@ -28919,8 +29958,26 @@ function createCoreModules(options) {
|
|
|
28919
29958
|
Buffer: Buffer2,
|
|
28920
29959
|
console: consoleObject,
|
|
28921
29960
|
process: processObject,
|
|
28922
|
-
...timers.api
|
|
29961
|
+
...timers.api,
|
|
29962
|
+
queueMicrotask: (fn) => queueMicrotask(() => {
|
|
29963
|
+
try {
|
|
29964
|
+
fn();
|
|
29965
|
+
} catch (error) {
|
|
29966
|
+
reportUncaught(error);
|
|
29967
|
+
}
|
|
29968
|
+
})
|
|
28923
29969
|
};
|
|
29970
|
+
if (options.http) {
|
|
29971
|
+
globals.fetch = createVirtualFetch(options.http.router, {
|
|
29972
|
+
...outboundFetch ? { fetch: outboundFetch } : {},
|
|
29973
|
+
...options.http.loopback ? { loopback: options.http.loopback } : {},
|
|
29974
|
+
trackRequest
|
|
29975
|
+
});
|
|
29976
|
+
const NativeWebSocket = globalThis.WebSocket;
|
|
29977
|
+
if (options.http.policy && NativeWebSocket) {
|
|
29978
|
+
globals.WebSocket = policedWebSocket(NativeWebSocket, options.http.policy);
|
|
29979
|
+
}
|
|
29980
|
+
}
|
|
28924
29981
|
const globalOverlay = new Proxy(globalThis, {
|
|
28925
29982
|
get: (target, key) => typeof key === "string" && key in globals ? globals[key] : key === "global" || key === "globalThis" ? globalOverlay : Reflect.get(target, key),
|
|
28926
29983
|
has: (target, key) => typeof key === "string" && key in globals || Reflect.has(target, key)
|
|
@@ -28936,6 +29993,10 @@ function createCoreModules(options) {
|
|
|
28936
29993
|
/** Client requests sent but not yet read to completion. */
|
|
28937
29994
|
pendingRequests: () => inFlightRequests,
|
|
28938
29995
|
cancelTimers: timers.cancelAll,
|
|
29996
|
+
reportUncaught: (error) => reportUncaught(error),
|
|
29997
|
+
reportUnhandledRejection: (reason) => reportUncaught(reason, "unhandledRejection"),
|
|
29998
|
+
exitStatus: () => normalizeExitCode(processObject.exitCode),
|
|
29999
|
+
emitExit,
|
|
28939
30000
|
writeStdin: (data) => {
|
|
28940
30001
|
if (options.interactiveStdin) stdin.write(data);
|
|
28941
30002
|
},
|
|
@@ -28997,7 +30058,7 @@ function createPathModule(cwd) {
|
|
|
28997
30058
|
path.default = path;
|
|
28998
30059
|
return path;
|
|
28999
30060
|
}
|
|
29000
|
-
function createFsModule(volume, cwd, stdinPath) {
|
|
30061
|
+
function createFsModule(volume, cwd, stdinPath, defer = queueMicrotask) {
|
|
29001
30062
|
const fds = /* @__PURE__ */ new Map();
|
|
29002
30063
|
let nextFd = 3;
|
|
29003
30064
|
if (stdinPath) fds.set(0, { path: stdinPath, position: 0, flags: "r" });
|
|
@@ -29037,12 +30098,15 @@ function createFsModule(volume, cwd, stdinPath) {
|
|
|
29037
30098
|
volume.rmdirSync(path);
|
|
29038
30099
|
};
|
|
29039
30100
|
const callback = (operation, cb) => {
|
|
29040
|
-
|
|
30101
|
+
defer(() => {
|
|
30102
|
+
let value;
|
|
29041
30103
|
try {
|
|
29042
|
-
|
|
30104
|
+
value = operation();
|
|
29043
30105
|
} catch (error) {
|
|
29044
30106
|
cb(error);
|
|
30107
|
+
return;
|
|
29045
30108
|
}
|
|
30109
|
+
cb(null, value);
|
|
29046
30110
|
});
|
|
29047
30111
|
};
|
|
29048
30112
|
const fs = {
|
|
@@ -29172,7 +30236,7 @@ function createFsModule(volume, cwd, stdinPath) {
|
|
|
29172
30236
|
const slice = whole.subarray(start2, Math.max(start2, end));
|
|
29173
30237
|
const stream = streamModule4__default.default.Readable.from([settings.encoding ? slice.toString(settings.encoding) : slice]);
|
|
29174
30238
|
Object.assign(stream, { path: target, bytesRead: slice.length, close: () => stream.destroy() });
|
|
29175
|
-
|
|
30239
|
+
defer(() => {
|
|
29176
30240
|
stream.emit("open", 0);
|
|
29177
30241
|
stream.emit("ready");
|
|
29178
30242
|
});
|
|
@@ -29240,7 +30304,7 @@ function createFsModule(volume, cwd, stdinPath) {
|
|
|
29240
30304
|
}
|
|
29241
30305
|
fs.realpath.native = fs.realpath;
|
|
29242
30306
|
fs.exists = (path, cb) => {
|
|
29243
|
-
|
|
30307
|
+
defer(() => cb(fs.existsSync(path)));
|
|
29244
30308
|
};
|
|
29245
30309
|
fs.promises = {
|
|
29246
30310
|
...Object.fromEntries(
|
|
@@ -29362,7 +30426,7 @@ var Console = class {
|
|
|
29362
30426
|
timeLog = (_label = "default") => {
|
|
29363
30427
|
};
|
|
29364
30428
|
};
|
|
29365
|
-
function createDnsModule() {
|
|
30429
|
+
function createDnsModule(defer = queueMicrotask) {
|
|
29366
30430
|
const LOOPBACK = {
|
|
29367
30431
|
localhost: { address: "127.0.0.1", family: 4 },
|
|
29368
30432
|
"127.0.0.1": { address: "127.0.0.1", family: 4 },
|
|
@@ -29382,7 +30446,7 @@ function createDnsModule() {
|
|
|
29382
30446
|
const lookup = (hostname, options, callback) => {
|
|
29383
30447
|
const done = typeof options === "function" ? options : callback;
|
|
29384
30448
|
const all = typeof options === "object" && options !== null && options.all;
|
|
29385
|
-
|
|
30449
|
+
defer(() => {
|
|
29386
30450
|
try {
|
|
29387
30451
|
const entry = lookupSync(hostname);
|
|
29388
30452
|
done?.(null, all ? [entry] : entry.address, entry.family);
|
|
@@ -29540,7 +30604,16 @@ var ERRNO_CONSTANTS = {
|
|
|
29540
30604
|
EWOULDBLOCK: 11,
|
|
29541
30605
|
EXDEV: 18
|
|
29542
30606
|
};
|
|
29543
|
-
function createTrackedTimers() {
|
|
30607
|
+
function createTrackedTimers(onError = (error) => {
|
|
30608
|
+
throw error;
|
|
30609
|
+
}) {
|
|
30610
|
+
const run2 = (fn, args) => {
|
|
30611
|
+
try {
|
|
30612
|
+
fn(...args);
|
|
30613
|
+
} catch (error) {
|
|
30614
|
+
onError(error);
|
|
30615
|
+
}
|
|
30616
|
+
};
|
|
29544
30617
|
const live = /* @__PURE__ */ new Set();
|
|
29545
30618
|
const unrefed = /* @__PURE__ */ new Set();
|
|
29546
30619
|
const states = /* @__PURE__ */ new WeakMap();
|
|
@@ -29583,7 +30656,7 @@ function createTrackedTimers() {
|
|
|
29583
30656
|
const native = setTimeout(
|
|
29584
30657
|
(...inner) => {
|
|
29585
30658
|
complete(handle);
|
|
29586
|
-
fn
|
|
30659
|
+
run2(fn, inner);
|
|
29587
30660
|
},
|
|
29588
30661
|
delay,
|
|
29589
30662
|
...args
|
|
@@ -29591,14 +30664,14 @@ function createTrackedTimers() {
|
|
|
29591
30664
|
handle = track(native);
|
|
29592
30665
|
return handle;
|
|
29593
30666
|
};
|
|
29594
|
-
const setIntervalTracked = (fn, delay, ...args) => track(setInterval(fn, delay, ...args));
|
|
30667
|
+
const setIntervalTracked = (fn, delay, ...args) => track(setInterval((...inner) => run2(fn, inner), delay, ...args));
|
|
29595
30668
|
const hostSetImmediate = globalThis.setImmediate;
|
|
29596
30669
|
const setImmediateTracked = (fn, ...args) => {
|
|
29597
30670
|
if (!hostSetImmediate) return setTimeoutTracked(fn, 0, ...args);
|
|
29598
30671
|
let handle;
|
|
29599
30672
|
const native = hostSetImmediate((...inner) => {
|
|
29600
30673
|
complete(handle);
|
|
29601
|
-
fn
|
|
30674
|
+
run2(fn, inner);
|
|
29602
30675
|
}, ...args);
|
|
29603
30676
|
handle = track(native);
|
|
29604
30677
|
return handle;
|
|
@@ -29781,6 +30854,43 @@ function createNetModule() {
|
|
|
29781
30854
|
isIP: (value) => isIPv4(value) ? 4 : isIPv6(value) ? 6 : 0
|
|
29782
30855
|
});
|
|
29783
30856
|
}
|
|
30857
|
+
function parseTestSettings(raw) {
|
|
30858
|
+
if (!raw) return {};
|
|
30859
|
+
try {
|
|
30860
|
+
const parsed = JSON.parse(raw);
|
|
30861
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
30862
|
+
} catch {
|
|
30863
|
+
return {};
|
|
30864
|
+
}
|
|
30865
|
+
}
|
|
30866
|
+
var EVENT_EMITTER_METHODS = [
|
|
30867
|
+
"on",
|
|
30868
|
+
"addListener",
|
|
30869
|
+
"once",
|
|
30870
|
+
"off",
|
|
30871
|
+
"removeListener",
|
|
30872
|
+
"removeAllListeners",
|
|
30873
|
+
"emit",
|
|
30874
|
+
"prependListener",
|
|
30875
|
+
"prependOnceListener",
|
|
30876
|
+
"listeners",
|
|
30877
|
+
"rawListeners",
|
|
30878
|
+
"listenerCount",
|
|
30879
|
+
"eventNames",
|
|
30880
|
+
"setMaxListeners",
|
|
30881
|
+
"getMaxListeners"
|
|
30882
|
+
];
|
|
30883
|
+
function normalizeExitCode(value) {
|
|
30884
|
+
const code = typeof value === "string" && value.trim() !== "" ? Number(value) : value;
|
|
30885
|
+
return typeof code === "number" && Number.isInteger(code) ? code & 255 : 0;
|
|
30886
|
+
}
|
|
30887
|
+
function formatUncaught(error) {
|
|
30888
|
+
const text2 = error instanceof Error ? error.stack ?? `${error.name}: ${error.message}` : `Uncaught ${typeof error === "string" ? JSON.stringify(error) : String(error)}`;
|
|
30889
|
+
return `${text2}
|
|
30890
|
+
|
|
30891
|
+
Node.js v22.12.0
|
|
30892
|
+
`;
|
|
30893
|
+
}
|
|
29784
30894
|
var stubNames = ["cluster", "dgram", "diagnostics_channel", "domain", "http2", "inspector", "net", "tls", "v8", "vm", "worker_threads"];
|
|
29785
30895
|
var builtinNames2 = [
|
|
29786
30896
|
"assert",
|
|
@@ -29818,6 +30928,7 @@ var builtinNames2 = [
|
|
|
29818
30928
|
"util",
|
|
29819
30929
|
"util/types",
|
|
29820
30930
|
"zlib",
|
|
30931
|
+
"test",
|
|
29821
30932
|
...stubNames
|
|
29822
30933
|
];
|
|
29823
30934
|
|
|
@@ -30639,16 +31750,20 @@ async function loadNodeRolldownMemfsBinding() {
|
|
|
30639
31750
|
return null;
|
|
30640
31751
|
}
|
|
30641
31752
|
const fromBinding = createRequire(join3(packageDir, "package.json"));
|
|
30642
|
-
let
|
|
31753
|
+
let runtimeModuleUrl2;
|
|
30643
31754
|
let fsModuleUrl;
|
|
30644
|
-
let createContext2;
|
|
30645
31755
|
try {
|
|
30646
|
-
|
|
31756
|
+
runtimeModuleUrl2 = resolveSubpath(node2, fromBinding, "@napi-rs/wasm-runtime", ".");
|
|
30647
31757
|
fsModuleUrl = resolveSubpath(node2, fromBinding, "@napi-rs/wasm-runtime", "./fs");
|
|
30648
|
-
({ createContext: createContext2 } = fromBinding("@emnapi/runtime"));
|
|
30649
31758
|
} catch {
|
|
30650
31759
|
return null;
|
|
30651
31760
|
}
|
|
31761
|
+
const runtime = await import(
|
|
31762
|
+
/* @vite-ignore */
|
|
31763
|
+
/* webpackIgnore: true */
|
|
31764
|
+
runtimeModuleUrl2
|
|
31765
|
+
);
|
|
31766
|
+
const createContext2 = runtime.createContext;
|
|
30652
31767
|
const { memfs } = await import(
|
|
30653
31768
|
/* @vite-ignore */
|
|
30654
31769
|
/* webpackIgnore: true */
|
|
@@ -30680,7 +31795,7 @@ async function loadNodeRolldownMemfsBinding() {
|
|
|
30680
31795
|
onCreateWorker() {
|
|
30681
31796
|
const worker = new Worker2(workerPath, {
|
|
30682
31797
|
env: process.env,
|
|
30683
|
-
workerData: { runtimeAnchor, fsModuleUrl },
|
|
31798
|
+
workerData: { runtimeAnchor, runtimeModuleUrl: runtimeModuleUrl2, fsModuleUrl },
|
|
30684
31799
|
/*
|
|
30685
31800
|
* Deliberately no `execArgv`.
|
|
30686
31801
|
*
|
|
@@ -31123,6 +32238,8 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
31123
32238
|
rolldownBinding;
|
|
31124
32239
|
/** Backs outbound `http`/`https` client requests from inside the sandbox. */
|
|
31125
32240
|
fetch;
|
|
32241
|
+
/** What guest programs may reach outside the container. */
|
|
32242
|
+
networkPolicy;
|
|
31126
32243
|
constructor(options) {
|
|
31127
32244
|
ensureProcessGlobal();
|
|
31128
32245
|
this.sockets = new VirtualTcpNetwork((port) => this.router.activePortsIncludes(port));
|
|
@@ -31140,6 +32257,7 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
31140
32257
|
this.router.onListen = (port) => notify(port, `http://localhost:${port}`);
|
|
31141
32258
|
}
|
|
31142
32259
|
if (options.fetch) this.fetch = options.fetch;
|
|
32260
|
+
if (options.network) this.networkPolicy = { ...options.network };
|
|
31143
32261
|
this.packages = new CleanPackageInstaller(this.volume, {
|
|
31144
32262
|
cwd: this.workdir,
|
|
31145
32263
|
...options.registry ? { registry: options.registry } : {},
|
|
@@ -31150,6 +32268,10 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
31150
32268
|
static async boot(options = {}) {
|
|
31151
32269
|
return new _LocalRuntimePod(options);
|
|
31152
32270
|
}
|
|
32271
|
+
/** Apply a container's outbound policy to programs started from now on. */
|
|
32272
|
+
setNetworkPolicy(policy) {
|
|
32273
|
+
this.networkPolicy = { ...policy };
|
|
32274
|
+
}
|
|
31153
32275
|
async spawn(command, args = [], options = {}) {
|
|
31154
32276
|
this.assertActive();
|
|
31155
32277
|
if (command !== "node" && command !== "nodejs") throw commandError(command);
|
|
@@ -31162,7 +32284,6 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
31162
32284
|
await this.prepareRolldown(cwd, env2);
|
|
31163
32285
|
if (proc.isKilled()) return 137;
|
|
31164
32286
|
const untrack = trackProcess(proc);
|
|
31165
|
-
let requestedExit = 0;
|
|
31166
32287
|
let engine;
|
|
31167
32288
|
const core = createCoreModules({
|
|
31168
32289
|
volume: this.volume,
|
|
@@ -31176,11 +32297,15 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
31176
32297
|
* thrown from a later callback it would escape into whichever library
|
|
31177
32298
|
* scheduled that callback and look like an unrelated crash. */
|
|
31178
32299
|
onExit: (code) => {
|
|
31179
|
-
requestedExit = code;
|
|
31180
32300
|
proc.exitNow(code);
|
|
31181
32301
|
if (engine?.isEvaluating) throw new ProcessExit(code);
|
|
31182
32302
|
},
|
|
31183
|
-
http: {
|
|
32303
|
+
http: {
|
|
32304
|
+
router: this.router,
|
|
32305
|
+
owner,
|
|
32306
|
+
...this.fetch ? { fetch: this.fetch } : {},
|
|
32307
|
+
...this.networkPolicy ? { policy: this.networkPolicy } : {}
|
|
32308
|
+
},
|
|
31184
32309
|
spawnChild: (config2) => this.processManager.spawn(config2),
|
|
31185
32310
|
...typeof options.stdinPath === "string" ? { stdinPath: options.stdinPath } : {},
|
|
31186
32311
|
...options.interactiveStdin ? { interactiveStdin: true } : {},
|
|
@@ -31204,7 +32329,9 @@ var LocalRuntimePod = class _LocalRuntimePod {
|
|
|
31204
32329
|
try {
|
|
31205
32330
|
await Promise.race([engine.run(script), proc.waitForKill()]);
|
|
31206
32331
|
await this.settle(owner, core.pendingHandles, core.readingStdin, () => core.pendingRequests() + hostWork.pending(), () => proc.isKilled());
|
|
31207
|
-
|
|
32332
|
+
const status = core.exitStatus();
|
|
32333
|
+
core.emitExit(status);
|
|
32334
|
+
return status;
|
|
31208
32335
|
} finally {
|
|
31209
32336
|
hostWork.dispose();
|
|
31210
32337
|
core.cancelTimers();
|
|
@@ -31707,6 +32834,9 @@ var WorkerRuntimePod = class _WorkerRuntimePod extends LocalRuntimePod {
|
|
|
31707
32834
|
case "http-response":
|
|
31708
32835
|
this.settleProxied(Number(message.id), message.response);
|
|
31709
32836
|
return;
|
|
32837
|
+
case "loopback-request":
|
|
32838
|
+
void this.answerLoopback(worker, message);
|
|
32839
|
+
return;
|
|
31710
32840
|
case "ws-data":
|
|
31711
32841
|
this.upgraded.get(Number(message.id))?.write(new Uint8Array(message.data));
|
|
31712
32842
|
return;
|
|
@@ -31742,7 +32872,8 @@ var WorkerRuntimePod = class _WorkerRuntimePod extends LocalRuntimePod {
|
|
|
31742
32872
|
aliases: this.aliases,
|
|
31743
32873
|
...typeof options.stdinPath === "string" ? { stdinPath: options.stdinPath } : {},
|
|
31744
32874
|
...options.interactiveStdin ? { interactiveStdin: true } : {},
|
|
31745
|
-
...options.tty ? { tty: true } : {}
|
|
32875
|
+
...options.tty ? { tty: true } : {},
|
|
32876
|
+
...this.networkPolicy ? { network: this.networkPolicy } : {}
|
|
31746
32877
|
});
|
|
31747
32878
|
process2.begin();
|
|
31748
32879
|
return process2;
|
|
@@ -31878,6 +33009,38 @@ var WorkerRuntimePod = class _WorkerRuntimePod extends LocalRuntimePod {
|
|
|
31878
33009
|
init: { method: request.method, path: request.url, headers: request.headers }
|
|
31879
33010
|
});
|
|
31880
33011
|
}
|
|
33012
|
+
/**
|
|
33013
|
+
* Answer a program that is calling a server in this container.
|
|
33014
|
+
*
|
|
33015
|
+
* A guest's router holds only the servers on its own thread, so a request to
|
|
33016
|
+
* a port some other process opened comes here, where every server in the
|
|
33017
|
+
* container is registered. `null` means nothing listens, which the guest
|
|
33018
|
+
* reports as a refused connection.
|
|
33019
|
+
*/
|
|
33020
|
+
async answerLoopback(worker, message) {
|
|
33021
|
+
const port = Number(message.port);
|
|
33022
|
+
let response = null;
|
|
33023
|
+
if (this.router.activePortsIncludes(port)) {
|
|
33024
|
+
try {
|
|
33025
|
+
const result = await this.router.request(port, message.request);
|
|
33026
|
+
const body = result.body;
|
|
33027
|
+
response = {
|
|
33028
|
+
statusCode: result.statusCode,
|
|
33029
|
+
statusMessage: result.statusMessage,
|
|
33030
|
+
headers: result.headers,
|
|
33031
|
+
body: typeof body === "string" ? new TextEncoder().encode(body) : body instanceof ArrayBuffer ? new Uint8Array(body) : body ?? new Uint8Array()
|
|
33032
|
+
};
|
|
33033
|
+
} catch (error) {
|
|
33034
|
+
response = {
|
|
33035
|
+
statusCode: 502,
|
|
33036
|
+
statusMessage: "Bad Gateway",
|
|
33037
|
+
headers: {},
|
|
33038
|
+
body: new TextEncoder().encode(error instanceof Error ? error.message : String(error))
|
|
33039
|
+
};
|
|
33040
|
+
}
|
|
33041
|
+
}
|
|
33042
|
+
worker.postMessage({ type: "loopback-response", id: message.id, response });
|
|
33043
|
+
}
|
|
31881
33044
|
settleProxied(id, response) {
|
|
31882
33045
|
const resolve3 = this.waiting.get(id);
|
|
31883
33046
|
if (!resolve3) return;
|
|
@@ -31968,13 +33131,19 @@ var Container = class _Container {
|
|
|
31968
33131
|
// ── boot ──────────────────────────────────────────────────────────────────
|
|
31969
33132
|
static async create(opts = {}) {
|
|
31970
33133
|
if (opts.python) configurePython(opts.python);
|
|
33134
|
+
const network = {
|
|
33135
|
+
allowOutbound: opts.network?.allowOutbound ?? false,
|
|
33136
|
+
allowedHosts: opts.network?.allowedHosts ?? null
|
|
33137
|
+
};
|
|
31971
33138
|
const podOptions = {
|
|
31972
33139
|
workdir: opts.cwd ?? "/",
|
|
31973
33140
|
env: opts.env ?? {},
|
|
33141
|
+
network,
|
|
31974
33142
|
...opts.onServerReady ? { onServerReady: opts.onServerReady } : {}
|
|
31975
33143
|
};
|
|
31976
33144
|
const workerOptions = { ...podOptions, ...opts.workerUrl ? { workerUrl: opts.workerUrl } : {} };
|
|
31977
33145
|
const pod = opts.pod ?? (opts.isolation === "realm" ? null : opts.isolation === "worker" ? await WorkerRuntimePod.boot(workerOptions) : await WorkerRuntimePod.tryBoot(workerOptions, opts.onRuntimeFallback)) ?? await LocalRuntimePod.boot(podOptions);
|
|
33146
|
+
if (opts.pod) opts.pod.setNetworkPolicy?.(network);
|
|
31978
33147
|
const kernel = new Kernel({
|
|
31979
33148
|
pod,
|
|
31980
33149
|
hostname: opts.hostname ?? "sandbox",
|
|
@@ -32069,7 +33238,7 @@ var Container = class _Container {
|
|
|
32069
33238
|
async exec(command, opts = {}) {
|
|
32070
33239
|
this.assertActive();
|
|
32071
33240
|
const started = Date.now();
|
|
32072
|
-
const { io, stdout, stderr, combined } = this.makeStdio(opts);
|
|
33241
|
+
const { io, stdout, stderr, combined, detach } = this.makeStdio(opts);
|
|
32073
33242
|
const cred = opts.user ? this.kernel.users.credFor(opts.user) : this.defaults.cred;
|
|
32074
33243
|
const env2 = { ...this.defaults.env, ...opts.env };
|
|
32075
33244
|
const cwd = opts.cwd ? resolve(this.defaults.cwd, opts.cwd) : this.defaults.cwd;
|
|
@@ -32098,6 +33267,7 @@ var Container = class _Container {
|
|
|
32098
33267
|
]);
|
|
32099
33268
|
} finally {
|
|
32100
33269
|
if (timer) clearTimeout(timer);
|
|
33270
|
+
detach();
|
|
32101
33271
|
proc.exit(0);
|
|
32102
33272
|
this.kernel.procs.remove(proc.pid);
|
|
32103
33273
|
}
|
|
@@ -32114,7 +33284,7 @@ var Container = class _Container {
|
|
|
32114
33284
|
async run(argv, opts = {}) {
|
|
32115
33285
|
this.assertActive();
|
|
32116
33286
|
const started = Date.now();
|
|
32117
|
-
const { io, stdout, stderr, combined } = this.makeStdio(opts);
|
|
33287
|
+
const { io, stdout, stderr, combined, detach } = this.makeStdio(opts);
|
|
32118
33288
|
const cred = opts.user ? this.kernel.users.credFor(opts.user) : this.defaults.cred;
|
|
32119
33289
|
const cwd = opts.cwd ? resolve(this.defaults.cwd, opts.cwd) : this.defaults.cwd;
|
|
32120
33290
|
const result = await this.kernel.run(argv, {
|
|
@@ -32126,6 +33296,7 @@ var Container = class _Container {
|
|
|
32126
33296
|
stderr: io.stderr,
|
|
32127
33297
|
...opts.timeoutMs ?? this.defaults.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs ?? this.defaults.timeoutMs } : {}
|
|
32128
33298
|
});
|
|
33299
|
+
detach();
|
|
32129
33300
|
return {
|
|
32130
33301
|
exitCode: result.exitCode,
|
|
32131
33302
|
stdout: stdout.text(),
|
|
@@ -32216,6 +33387,14 @@ var Container = class _Container {
|
|
|
32216
33387
|
if (!this.defaultSession) this.defaultSession = this.session();
|
|
32217
33388
|
return this.defaultSession;
|
|
32218
33389
|
}
|
|
33390
|
+
/**
|
|
33391
|
+
* The streams one call collects into.
|
|
33392
|
+
*
|
|
33393
|
+
* They are detachable because a background job started by the command keeps
|
|
33394
|
+
* writing after the call has returned. Nothing reads the result any more by
|
|
33395
|
+
* then, so without `detach` a chatty server would grow the buffer for as long
|
|
33396
|
+
* as it ran; afterwards its output still reaches the container-wide taps.
|
|
33397
|
+
*/
|
|
32219
33398
|
makeStdio(opts) {
|
|
32220
33399
|
const combined = [];
|
|
32221
33400
|
const decoder9 = new TextDecoder();
|
|
@@ -32231,14 +33410,25 @@ var Container = class _Container {
|
|
|
32231
33410
|
opts.onStderr?.(text2);
|
|
32232
33411
|
this.hooks.onStderr?.(text2);
|
|
32233
33412
|
});
|
|
33413
|
+
const outGate = new DetachableOutput(stdout, (text2) => this.hooks.onStdout?.(text2));
|
|
33414
|
+
const errGate = new DetachableOutput(stderr, (text2) => this.hooks.onStderr?.(text2));
|
|
32234
33415
|
if (opts.tty) {
|
|
32235
|
-
|
|
32236
|
-
|
|
32237
|
-
|
|
32238
|
-
|
|
33416
|
+
outGate.isTTY = true;
|
|
33417
|
+
errGate.isTTY = true;
|
|
33418
|
+
outGate.columns = opts.columns ?? 80;
|
|
33419
|
+
outGate.rows = opts.rows ?? 24;
|
|
32239
33420
|
}
|
|
32240
33421
|
const stdin = opts.stdin === void 0 ? new NullInput() : Pipe.from(opts.stdin);
|
|
32241
|
-
return {
|
|
33422
|
+
return {
|
|
33423
|
+
io: { stdin, stdout: outGate, stderr: errGate },
|
|
33424
|
+
stdout,
|
|
33425
|
+
stderr,
|
|
33426
|
+
combined,
|
|
33427
|
+
detach: () => {
|
|
33428
|
+
outGate.detach();
|
|
33429
|
+
errGate.detach();
|
|
33430
|
+
}
|
|
33431
|
+
};
|
|
32242
33432
|
}
|
|
32243
33433
|
// ── networking ────────────────────────────────────────────────────────────
|
|
32244
33434
|
/** Send an HTTP request to a server running inside the container. */
|