sandboxedjs 0.1.29 → 0.1.31
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/LICENSE +1 -7
- package/README.md +137 -92
- package/bin/sandboxedjs-serve.mjs +24 -0
- package/dist/browser-host.cjs +112 -0
- package/dist/browser-host.cjs.map +1 -0
- package/dist/browser-host.d.cts +25 -0
- package/dist/browser-host.d.ts +25 -0
- package/dist/browser-host.js +109 -0
- package/dist/browser-host.js.map +1 -0
- package/dist/index.cjs +464 -178
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +139 -16
- package/dist/index.d.ts +139 -16
- package/dist/index.js +462 -179
- package/dist/index.js.map +1 -1
- package/dist/service-worker.js +112 -0
- package/dist/service-worker.js.map +1 -0
- package/dist/worker-entry.js +140 -116
- package/dist/worker-entry.js.map +1 -1
- package/package.json +9 -3
package/dist/index.d.cts
CHANGED
|
@@ -6,7 +6,7 @@ interface ChildHandle {
|
|
|
6
6
|
pid: number;
|
|
7
7
|
state: "starting" | "running" | "exited";
|
|
8
8
|
exitCode: number | undefined;
|
|
9
|
-
on(event: "stdout" | "stderr" | "exit", listener: (...args: any[]) => void): unknown;
|
|
9
|
+
on(event: "stdout" | "stderr" | "exit" | "rawmode", listener: (...args: any[]) => void): unknown;
|
|
10
10
|
exec(): void;
|
|
11
11
|
sendStdin(data: string): void;
|
|
12
12
|
/**
|
|
@@ -25,6 +25,14 @@ interface ChildSpawnConfig {
|
|
|
25
25
|
cwd?: string;
|
|
26
26
|
env?: Record<string, string>;
|
|
27
27
|
parentPid?: number;
|
|
28
|
+
/**
|
|
29
|
+
* The child was given the parent's streams (`stdio: "inherit"`).
|
|
30
|
+
*
|
|
31
|
+
* Its input is then the parent's terminal rather than a pipe that will end,
|
|
32
|
+
* which is the difference between a program that waits for what the user
|
|
33
|
+
* types and one that reads to end-of-input and stops.
|
|
34
|
+
*/
|
|
35
|
+
inheritStdio?: boolean;
|
|
28
36
|
}
|
|
29
37
|
type SpawnChild = (config: ChildSpawnConfig) => ChildHandle;
|
|
30
38
|
/**
|
|
@@ -40,6 +48,7 @@ type SyncSpawn = (request: {
|
|
|
40
48
|
cwd: string;
|
|
41
49
|
env?: Record<string, string>;
|
|
42
50
|
input?: string;
|
|
51
|
+
inheritStdio?: boolean;
|
|
43
52
|
}) => {
|
|
44
53
|
status: number | null;
|
|
45
54
|
stdout: string;
|
|
@@ -50,7 +59,7 @@ type SyncSpawn = (request: {
|
|
|
50
59
|
message: string;
|
|
51
60
|
};
|
|
52
61
|
};
|
|
53
|
-
declare function createChildProcessModule(spawnChild: SpawnChild, defaultCwd: () => string, syncSpawn?: SyncSpawn): Record<string, unknown>;
|
|
62
|
+
declare function createChildProcessModule(spawnChild: SpawnChild, defaultCwd: () => string, syncSpawn?: SyncSpawn, defaultEnv?: () => Record<string, string>): Record<string, unknown>;
|
|
54
63
|
|
|
55
64
|
/**
|
|
56
65
|
* Clean-room contracts between SandboxedJS and its JavaScript runtime.
|
|
@@ -433,7 +442,10 @@ declare class Pipe implements InputStream, OutputStream {
|
|
|
433
442
|
* whole line on every keystroke — so the terminal must stop echoing, or
|
|
434
443
|
* every character appears twice.
|
|
435
444
|
*/
|
|
436
|
-
|
|
445
|
+
private raw;
|
|
446
|
+
onRawMode?: (enabled: boolean) => void;
|
|
447
|
+
get rawMode(): boolean;
|
|
448
|
+
set rawMode(enabled: boolean);
|
|
437
449
|
columns: number | undefined;
|
|
438
450
|
rows: number | undefined;
|
|
439
451
|
get closed(): boolean;
|
|
@@ -1382,6 +1394,8 @@ declare class Shell {
|
|
|
1382
1394
|
constructor(init: ShellInit);
|
|
1383
1395
|
/** Parse and run a script fragment. Returns the last exit status. */
|
|
1384
1396
|
execute(source: string, io: ShellIO): Promise<number>;
|
|
1397
|
+
/** Signal the current terminal pipeline without terminating the interactive shell. */
|
|
1398
|
+
interruptForeground(signal: string, stdin: InputStream): void;
|
|
1385
1399
|
get isExiting(): boolean;
|
|
1386
1400
|
/** True when `source` is not yet a complete command (for REPL continuation). */
|
|
1387
1401
|
static isIncomplete(source: string): boolean;
|
|
@@ -1665,12 +1679,15 @@ interface ContainerOptions {
|
|
|
1665
1679
|
/**
|
|
1666
1680
|
* Where guest programs run.
|
|
1667
1681
|
*
|
|
1668
|
-
* `"
|
|
1669
|
-
*
|
|
1670
|
-
*
|
|
1671
|
-
* `"realm"`
|
|
1682
|
+
* `"auto"` (the default) tries the worker runtime and reports any fallback.
|
|
1683
|
+
* `"worker"` requires a working guest worker and shared-memory channel: boot
|
|
1684
|
+
* rejects with the cause if either is unavailable, rather than letting
|
|
1685
|
+
* synchronous child-process calls fail later. `"realm"` opts out explicitly.
|
|
1686
|
+
* Processes requiring host-native modules can still run in the host realm.
|
|
1672
1687
|
*/
|
|
1673
|
-
isolation?: "worker" | "realm";
|
|
1688
|
+
isolation?: "auto" | "worker" | "realm";
|
|
1689
|
+
/** Receives the reason for an automatic fallback; defaults to console.warn. */
|
|
1690
|
+
onRuntimeFallback?: (error: Error) => void;
|
|
1674
1691
|
/**
|
|
1675
1692
|
* Where to load the guest worker bundle from.
|
|
1676
1693
|
*
|
|
@@ -2457,6 +2474,7 @@ declare class VirtualHttpServer extends EventEmitter {
|
|
|
2457
2474
|
readonly owner: string;
|
|
2458
2475
|
listening: boolean;
|
|
2459
2476
|
private portValue;
|
|
2477
|
+
private referenced;
|
|
2460
2478
|
constructor(router: VirtualHttpRouter, owner: string, listener?: (req: VirtualIncomingMessage, res: VirtualServerResponse) => void);
|
|
2461
2479
|
listen(...args: any[]): this;
|
|
2462
2480
|
close(callback?: (error?: Error) => void): this;
|
|
@@ -2467,17 +2485,20 @@ declare class VirtualHttpServer extends EventEmitter {
|
|
|
2467
2485
|
} | null;
|
|
2468
2486
|
ref(): this;
|
|
2469
2487
|
unref(): this;
|
|
2488
|
+
hasRef(): boolean;
|
|
2470
2489
|
setTimeout(_milliseconds: number, callback?: () => void): this;
|
|
2471
2490
|
}
|
|
2472
2491
|
declare class VirtualHttpRouter {
|
|
2473
2492
|
private readonly servers;
|
|
2474
2493
|
/** Notified when a server begins listening, for `onServerReady`. */
|
|
2475
2494
|
onListen: ((port: number) => void) | undefined;
|
|
2495
|
+
onClose: ((port: number) => void) | undefined;
|
|
2476
2496
|
register(port: number, server: VirtualHttpServer, owner: string): void;
|
|
2477
2497
|
unregister(port: number, server: VirtualHttpServer): void;
|
|
2478
2498
|
/** Whether anything in this container is listening on `port`. */
|
|
2479
2499
|
activePortsIncludes(port: number): boolean;
|
|
2480
2500
|
activePorts(owner?: string): number[];
|
|
2501
|
+
referencedPorts(owner: string): number[];
|
|
2481
2502
|
closeOwner(owner: string): void;
|
|
2482
2503
|
closeAll(): void;
|
|
2483
2504
|
request(port: number, init?: VirtualRequestInit): Promise<RuntimeHttpResponse>;
|
|
@@ -2734,6 +2755,7 @@ declare class LocalRuntimePod implements RuntimePod {
|
|
|
2734
2755
|
spawn(config: ChildSpawnConfig): ChildHandle;
|
|
2735
2756
|
};
|
|
2736
2757
|
private disposed;
|
|
2758
|
+
private readonly running;
|
|
2737
2759
|
protected readonly workdir: string;
|
|
2738
2760
|
protected readonly env: Record<string, string>;
|
|
2739
2761
|
protected readonly aliases: Record<string, string>;
|
|
@@ -2777,6 +2799,62 @@ declare class LocalRuntimePod implements RuntimePod {
|
|
|
2777
2799
|
private assertActive;
|
|
2778
2800
|
}
|
|
2779
2801
|
|
|
2802
|
+
/**
|
|
2803
|
+
* A pod that evaluates each guest program on its own thread.
|
|
2804
|
+
*
|
|
2805
|
+
* Everything shared stays here: the volume, the HTTP router, the package
|
|
2806
|
+
* installer and the process table. Only the program's own evaluation moves,
|
|
2807
|
+
* and it reaches back for the rest through a {@link SyncChannelServer}.
|
|
2808
|
+
*
|
|
2809
|
+
* That arrangement is forced rather than chosen. A synchronous call has to
|
|
2810
|
+
* block the caller while the work it is waiting on still makes progress, so
|
|
2811
|
+
* the blocking side cannot be the side that owns the resources — otherwise a
|
|
2812
|
+
* child process needing the filesystem would have to call into a thread that
|
|
2813
|
+
* is frozen waiting for that child. The guest blocks; the host never does.
|
|
2814
|
+
*
|
|
2815
|
+
* It inherits from {@link LocalRuntimePod} because every other part of the
|
|
2816
|
+
* contract is identical, and overriding one method is a smaller and more
|
|
2817
|
+
* honest claim than reimplementing nine. Both are held to the same contract
|
|
2818
|
+
* suite (`test/pod-contract.ts`).
|
|
2819
|
+
*/
|
|
2820
|
+
|
|
2821
|
+
interface WorkerRuntimeOptions extends LocalRuntimeOptions {
|
|
2822
|
+
/** Where the guest bundle lives; defaults to the copy shipped beside this one. */
|
|
2823
|
+
workerUrl?: string | URL;
|
|
2824
|
+
}
|
|
2825
|
+
declare class WorkerRuntimePod extends LocalRuntimePod {
|
|
2826
|
+
private readonly workerUrl;
|
|
2827
|
+
/** Live workers, so teardown can stop them all. */
|
|
2828
|
+
private readonly live;
|
|
2829
|
+
protected constructor(options: WorkerRuntimeOptions);
|
|
2830
|
+
/** Boot without silently dropping synchronous child-process support. */
|
|
2831
|
+
static boot(options?: WorkerRuntimeOptions): Promise<WorkerRuntimePod>;
|
|
2832
|
+
/** Compatibility mode, with an observable explanation for every fallback. */
|
|
2833
|
+
static tryBoot(options?: WorkerRuntimeOptions, onFallback?: (error: Error) => void): Promise<WorkerRuntimePod | null>;
|
|
2834
|
+
spawn(command: string, args?: string[], options?: Record<string, unknown>): Promise<RuntimeProcess>;
|
|
2835
|
+
private spawnInWorker;
|
|
2836
|
+
/** Start an asynchronous child on the host's behalf and relay its events. */
|
|
2837
|
+
private startChild;
|
|
2838
|
+
/** Run a child to completion and collect it, for the guest's `spawnSync`. */
|
|
2839
|
+
private runChildToCompletion;
|
|
2840
|
+
private readonly proxies;
|
|
2841
|
+
private readonly waiting;
|
|
2842
|
+
private nextRequestId;
|
|
2843
|
+
/**
|
|
2844
|
+
* Register a stand-in for a server that is actually running in the Worker.
|
|
2845
|
+
*
|
|
2846
|
+
* The router only knows how to reach servers on this thread, so each bound
|
|
2847
|
+
* port gets a local server whose whole job is to forward and wait.
|
|
2848
|
+
*/
|
|
2849
|
+
private proxyPort;
|
|
2850
|
+
private forward;
|
|
2851
|
+
private settleProxied;
|
|
2852
|
+
private closeProxies;
|
|
2853
|
+
teardown(): void;
|
|
2854
|
+
/** Does anything under `cwd` need a module only the host can supply? */
|
|
2855
|
+
private needsHostModules;
|
|
2856
|
+
}
|
|
2857
|
+
|
|
2780
2858
|
interface RegistryManifest {
|
|
2781
2859
|
name: string;
|
|
2782
2860
|
version: string;
|
|
@@ -2837,8 +2915,8 @@ declare function extractNpmTarball(volume: RuntimeVolume, compressed: Uint8Array
|
|
|
2837
2915
|
* own dependency cache, where no such file exists. That is the same trap
|
|
2838
2916
|
* Rolldown's WASI binding falls into, and it surfaces just as obliquely.
|
|
2839
2917
|
*
|
|
2840
|
-
* So this never assumes it worked.
|
|
2841
|
-
*
|
|
2918
|
+
* So this never assumes it worked. Strict boot surfaces the failure; automatic mode reports
|
|
2919
|
+
* the cause before choosing the in-realm pod.
|
|
2842
2920
|
*/
|
|
2843
2921
|
interface RuntimeWorker {
|
|
2844
2922
|
postMessage(message: unknown): void;
|
|
@@ -2859,14 +2937,59 @@ declare function startRuntimeWorker(options?: {
|
|
|
2859
2937
|
timeoutMs?: number;
|
|
2860
2938
|
}): Promise<RuntimeWorker>;
|
|
2861
2939
|
|
|
2940
|
+
declare function syncChannelSupported(): boolean;
|
|
2941
|
+
|
|
2862
2942
|
/**
|
|
2863
|
-
*
|
|
2943
|
+
* Wiring a container's HTTP servers up to real URLs in the page.
|
|
2864
2944
|
*
|
|
2865
|
-
*
|
|
2866
|
-
*
|
|
2867
|
-
*
|
|
2945
|
+
* The service worker does the routing; this is the half that lives in the page
|
|
2946
|
+
* and actually knows about the container.
|
|
2947
|
+
*
|
|
2948
|
+
* **Read the origin note before using this.** A preview served this way runs on
|
|
2949
|
+
* *your* origin, so scripts inside it can reach `window.parent`, your cookies
|
|
2950
|
+
* and your `localStorage` — the sandbox contains the program's *filesystem and
|
|
2951
|
+
* process table*, not the page it serves. For code you did not write, either
|
|
2952
|
+
* host the preview on a separate origin, or use {@link renderInto}, which puts
|
|
2953
|
+
* the response in an iframe with no origin at all.
|
|
2868
2954
|
*/
|
|
2869
|
-
|
|
2955
|
+
|
|
2956
|
+
interface PreviewOptions {
|
|
2957
|
+
/** Where the worker script lives; defaults to the copy shipped beside the bundle. */
|
|
2958
|
+
scriptUrl?: string | URL;
|
|
2959
|
+
/** Registration scope. Must be able to see the paths a preview will request. */
|
|
2960
|
+
scope?: string;
|
|
2961
|
+
}
|
|
2962
|
+
interface Preview {
|
|
2963
|
+
/** The URL an iframe should be pointed at to see `port`. */
|
|
2964
|
+
urlFor(port: number): string;
|
|
2965
|
+
/** Stop answering requests and unregister the worker. */
|
|
2966
|
+
dispose(): Promise<void>;
|
|
2967
|
+
}
|
|
2968
|
+
/**
|
|
2969
|
+
* Register the preview worker and start answering its requests from `box`.
|
|
2970
|
+
*
|
|
2971
|
+
* Resolves to null where service workers are unavailable — a non-secure origin,
|
|
2972
|
+
* a browser with them disabled, or any non-browser host. Callers should treat
|
|
2973
|
+
* that as "no preview URLs here" and fall back to `box.request`.
|
|
2974
|
+
*/
|
|
2975
|
+
declare function createPreview(box: Container, options?: PreviewOptions): Promise<Preview | null>;
|
|
2976
|
+
/**
|
|
2977
|
+
* Show one response from the container inside an element, without letting it
|
|
2978
|
+
* touch the page.
|
|
2979
|
+
*
|
|
2980
|
+
* The iframe is sandboxed with `allow-scripts` and deliberately *without*
|
|
2981
|
+
* `allow-same-origin`, which puts the document in an opaque origin: its scripts
|
|
2982
|
+
* run, and they can reach neither this page's DOM nor its cookies and storage.
|
|
2983
|
+
* That combination is what makes it safe to render output you do not trust.
|
|
2984
|
+
*
|
|
2985
|
+
* The trade-off is that only this one response exists — a page that asks for
|
|
2986
|
+
* `/main.js` gets nothing, because there is no origin to serve it from. For a
|
|
2987
|
+
* whole site, use {@link createPreview}, and read its note about origins first.
|
|
2988
|
+
*/
|
|
2989
|
+
declare function renderInto(box: Container, element: HTMLElement, options?: {
|
|
2990
|
+
port: number;
|
|
2991
|
+
path?: string;
|
|
2992
|
+
}): Promise<HTMLIFrameElement>;
|
|
2870
2993
|
|
|
2871
2994
|
/**
|
|
2872
2995
|
* sandboxedjs — a Linux-like container that runs entirely inside Node.js.
|
|
@@ -2886,4 +3009,4 @@ declare function syncChannelSupported(): boolean;
|
|
|
2886
3009
|
* ```
|
|
2887
3010
|
*/
|
|
2888
3011
|
|
|
2889
|
-
export { ArithError, BufferSink, type CPythonOptions, CallbackSink, type ChildHandle, type ChildSpawnConfig, type CleanInstallerOptions, CleanPackageInstaller, type Command, CommandRegistry, CommonJsEngine, type CommonJsEngineOptions, type CommonJsModule, Container, ContainerFs, type ContainerOptions, type ContextInit, type CoreModulesOptions, type Cred, type DirEntry, ERRNO, type Env, type ErrnoCode, type EsmTransformResult, type ExecContext, type ExecOptions, type ExecResult, type FileData, FileInput, FileOutput, type GroupEntry, type HttpResponse, IncompleteInputError, type InputStream, type InstallOptions, type Job, KERNEL_NAME, KERNEL_RELEASE, Kernel, type KernelOptions, type ListeningPort, type LocalRuntimeOptions, LocalRuntimePod, MemoryVolume, type MountEntry, NODE_VERSION, NPM_VERSION, type NetInterface, type NetworkOptions, NetworkStack, NullInput, NullOutput, OS_RELEASE, type OutputStream, PYTHON_VERSION, type PasswdEntry, Pipe, Process, type ProcessKind, type ProcessOptions, type ProcessState, ProcessTable, type PythonOptions, ROOT_CRED, type ResolvedExecutable, type RootfsOptions, type RunOptions, type RunResult, type RuntimePackageInstaller, type RuntimePod, type RuntimeProcess, type RuntimeProcessManager, type RuntimeProcessResult, type RuntimeVolume, SIGNALS, SIGNAL_NAMES, Session, type SessionInit, type SessionResult, type SessionRunOptions, Shell, ShellExit, type ShellIO, type ShellInit, Lexer as ShellLexer, type ShellOptions, ShellSyntaxError, type SpawnChild, type SpawnHandle, Stats, type Stdio, SysError, TeeOutput, Terminal, type TerminalOptions, UserDatabase, Variables, Vfs, VirtualHttpRouter, VirtualHttpServer, VirtualIncomingMessage, type VirtualNode, type VirtualProvider, VirtualServerResponse, WASM_ALIASES, type WriteOptions, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configureCPython, configurePython, createChildProcessModule, createContainer, createContext, createCoreModules, createContainer as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, extractNpmTarball, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isCPythonAvailable, isPythonAvailable, isSysError, looksLikeEsm, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path as posixPath, resetPidCounter, shellQuote, startRuntimeWorker, strerror, syncChannelSupported, transformEsm, unameInfo };
|
|
3012
|
+
export { ArithError, BufferSink, type CPythonOptions, CallbackSink, type ChildHandle, type ChildSpawnConfig, type CleanInstallerOptions, CleanPackageInstaller, type Command, CommandRegistry, CommonJsEngine, type CommonJsEngineOptions, type CommonJsModule, Container, ContainerFs, type ContainerOptions, type ContextInit, type CoreModulesOptions, type Cred, type DirEntry, ERRNO, type Env, type ErrnoCode, type EsmTransformResult, type ExecContext, type ExecOptions, type ExecResult, type FileData, FileInput, FileOutput, type GroupEntry, type HttpResponse, IncompleteInputError, type InputStream, type InstallOptions, type Job, KERNEL_NAME, KERNEL_RELEASE, Kernel, type KernelOptions, type ListeningPort, type LocalRuntimeOptions, LocalRuntimePod, MemoryVolume, type MountEntry, NODE_VERSION, NPM_VERSION, type NetInterface, type NetworkOptions, NetworkStack, NullInput, NullOutput, OS_RELEASE, type OutputStream, PYTHON_VERSION, type PasswdEntry, Pipe, type Preview, type PreviewOptions, Process, type ProcessKind, type ProcessOptions, type ProcessState, ProcessTable, type PythonOptions, ROOT_CRED, type ResolvedExecutable, type RootfsOptions, type RunOptions, type RunResult, type RuntimePackageInstaller, type RuntimePod, type RuntimeProcess, type RuntimeProcessManager, type RuntimeProcessResult, type RuntimeVolume, SIGNALS, SIGNAL_NAMES, Session, type SessionInit, type SessionResult, type SessionRunOptions, Shell, ShellExit, type ShellIO, type ShellInit, Lexer as ShellLexer, type ShellOptions, ShellSyntaxError, type SpawnChild, type SpawnHandle, Stats, type Stdio, SysError, TeeOutput, Terminal, type TerminalOptions, UserDatabase, Variables, Vfs, VirtualHttpRouter, VirtualHttpServer, VirtualIncomingMessage, type VirtualNode, type VirtualProvider, VirtualServerResponse, WASM_ALIASES, type WorkerRuntimeOptions, WorkerRuntimePod, type WriteOptions, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configureCPython, configurePython, createChildProcessModule, createContainer, createContext, createCoreModules, createPreview, createContainer as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, extractNpmTarball, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isCPythonAvailable, isPythonAvailable, isSysError, looksLikeEsm, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path as posixPath, renderInto, resetPidCounter, shellQuote, startRuntimeWorker, strerror, syncChannelSupported, transformEsm, unameInfo };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ interface ChildHandle {
|
|
|
6
6
|
pid: number;
|
|
7
7
|
state: "starting" | "running" | "exited";
|
|
8
8
|
exitCode: number | undefined;
|
|
9
|
-
on(event: "stdout" | "stderr" | "exit", listener: (...args: any[]) => void): unknown;
|
|
9
|
+
on(event: "stdout" | "stderr" | "exit" | "rawmode", listener: (...args: any[]) => void): unknown;
|
|
10
10
|
exec(): void;
|
|
11
11
|
sendStdin(data: string): void;
|
|
12
12
|
/**
|
|
@@ -25,6 +25,14 @@ interface ChildSpawnConfig {
|
|
|
25
25
|
cwd?: string;
|
|
26
26
|
env?: Record<string, string>;
|
|
27
27
|
parentPid?: number;
|
|
28
|
+
/**
|
|
29
|
+
* The child was given the parent's streams (`stdio: "inherit"`).
|
|
30
|
+
*
|
|
31
|
+
* Its input is then the parent's terminal rather than a pipe that will end,
|
|
32
|
+
* which is the difference between a program that waits for what the user
|
|
33
|
+
* types and one that reads to end-of-input and stops.
|
|
34
|
+
*/
|
|
35
|
+
inheritStdio?: boolean;
|
|
28
36
|
}
|
|
29
37
|
type SpawnChild = (config: ChildSpawnConfig) => ChildHandle;
|
|
30
38
|
/**
|
|
@@ -40,6 +48,7 @@ type SyncSpawn = (request: {
|
|
|
40
48
|
cwd: string;
|
|
41
49
|
env?: Record<string, string>;
|
|
42
50
|
input?: string;
|
|
51
|
+
inheritStdio?: boolean;
|
|
43
52
|
}) => {
|
|
44
53
|
status: number | null;
|
|
45
54
|
stdout: string;
|
|
@@ -50,7 +59,7 @@ type SyncSpawn = (request: {
|
|
|
50
59
|
message: string;
|
|
51
60
|
};
|
|
52
61
|
};
|
|
53
|
-
declare function createChildProcessModule(spawnChild: SpawnChild, defaultCwd: () => string, syncSpawn?: SyncSpawn): Record<string, unknown>;
|
|
62
|
+
declare function createChildProcessModule(spawnChild: SpawnChild, defaultCwd: () => string, syncSpawn?: SyncSpawn, defaultEnv?: () => Record<string, string>): Record<string, unknown>;
|
|
54
63
|
|
|
55
64
|
/**
|
|
56
65
|
* Clean-room contracts between SandboxedJS and its JavaScript runtime.
|
|
@@ -433,7 +442,10 @@ declare class Pipe implements InputStream, OutputStream {
|
|
|
433
442
|
* whole line on every keystroke — so the terminal must stop echoing, or
|
|
434
443
|
* every character appears twice.
|
|
435
444
|
*/
|
|
436
|
-
|
|
445
|
+
private raw;
|
|
446
|
+
onRawMode?: (enabled: boolean) => void;
|
|
447
|
+
get rawMode(): boolean;
|
|
448
|
+
set rawMode(enabled: boolean);
|
|
437
449
|
columns: number | undefined;
|
|
438
450
|
rows: number | undefined;
|
|
439
451
|
get closed(): boolean;
|
|
@@ -1382,6 +1394,8 @@ declare class Shell {
|
|
|
1382
1394
|
constructor(init: ShellInit);
|
|
1383
1395
|
/** Parse and run a script fragment. Returns the last exit status. */
|
|
1384
1396
|
execute(source: string, io: ShellIO): Promise<number>;
|
|
1397
|
+
/** Signal the current terminal pipeline without terminating the interactive shell. */
|
|
1398
|
+
interruptForeground(signal: string, stdin: InputStream): void;
|
|
1385
1399
|
get isExiting(): boolean;
|
|
1386
1400
|
/** True when `source` is not yet a complete command (for REPL continuation). */
|
|
1387
1401
|
static isIncomplete(source: string): boolean;
|
|
@@ -1665,12 +1679,15 @@ interface ContainerOptions {
|
|
|
1665
1679
|
/**
|
|
1666
1680
|
* Where guest programs run.
|
|
1667
1681
|
*
|
|
1668
|
-
* `"
|
|
1669
|
-
*
|
|
1670
|
-
*
|
|
1671
|
-
* `"realm"`
|
|
1682
|
+
* `"auto"` (the default) tries the worker runtime and reports any fallback.
|
|
1683
|
+
* `"worker"` requires a working guest worker and shared-memory channel: boot
|
|
1684
|
+
* rejects with the cause if either is unavailable, rather than letting
|
|
1685
|
+
* synchronous child-process calls fail later. `"realm"` opts out explicitly.
|
|
1686
|
+
* Processes requiring host-native modules can still run in the host realm.
|
|
1672
1687
|
*/
|
|
1673
|
-
isolation?: "worker" | "realm";
|
|
1688
|
+
isolation?: "auto" | "worker" | "realm";
|
|
1689
|
+
/** Receives the reason for an automatic fallback; defaults to console.warn. */
|
|
1690
|
+
onRuntimeFallback?: (error: Error) => void;
|
|
1674
1691
|
/**
|
|
1675
1692
|
* Where to load the guest worker bundle from.
|
|
1676
1693
|
*
|
|
@@ -2457,6 +2474,7 @@ declare class VirtualHttpServer extends EventEmitter {
|
|
|
2457
2474
|
readonly owner: string;
|
|
2458
2475
|
listening: boolean;
|
|
2459
2476
|
private portValue;
|
|
2477
|
+
private referenced;
|
|
2460
2478
|
constructor(router: VirtualHttpRouter, owner: string, listener?: (req: VirtualIncomingMessage, res: VirtualServerResponse) => void);
|
|
2461
2479
|
listen(...args: any[]): this;
|
|
2462
2480
|
close(callback?: (error?: Error) => void): this;
|
|
@@ -2467,17 +2485,20 @@ declare class VirtualHttpServer extends EventEmitter {
|
|
|
2467
2485
|
} | null;
|
|
2468
2486
|
ref(): this;
|
|
2469
2487
|
unref(): this;
|
|
2488
|
+
hasRef(): boolean;
|
|
2470
2489
|
setTimeout(_milliseconds: number, callback?: () => void): this;
|
|
2471
2490
|
}
|
|
2472
2491
|
declare class VirtualHttpRouter {
|
|
2473
2492
|
private readonly servers;
|
|
2474
2493
|
/** Notified when a server begins listening, for `onServerReady`. */
|
|
2475
2494
|
onListen: ((port: number) => void) | undefined;
|
|
2495
|
+
onClose: ((port: number) => void) | undefined;
|
|
2476
2496
|
register(port: number, server: VirtualHttpServer, owner: string): void;
|
|
2477
2497
|
unregister(port: number, server: VirtualHttpServer): void;
|
|
2478
2498
|
/** Whether anything in this container is listening on `port`. */
|
|
2479
2499
|
activePortsIncludes(port: number): boolean;
|
|
2480
2500
|
activePorts(owner?: string): number[];
|
|
2501
|
+
referencedPorts(owner: string): number[];
|
|
2481
2502
|
closeOwner(owner: string): void;
|
|
2482
2503
|
closeAll(): void;
|
|
2483
2504
|
request(port: number, init?: VirtualRequestInit): Promise<RuntimeHttpResponse>;
|
|
@@ -2734,6 +2755,7 @@ declare class LocalRuntimePod implements RuntimePod {
|
|
|
2734
2755
|
spawn(config: ChildSpawnConfig): ChildHandle;
|
|
2735
2756
|
};
|
|
2736
2757
|
private disposed;
|
|
2758
|
+
private readonly running;
|
|
2737
2759
|
protected readonly workdir: string;
|
|
2738
2760
|
protected readonly env: Record<string, string>;
|
|
2739
2761
|
protected readonly aliases: Record<string, string>;
|
|
@@ -2777,6 +2799,62 @@ declare class LocalRuntimePod implements RuntimePod {
|
|
|
2777
2799
|
private assertActive;
|
|
2778
2800
|
}
|
|
2779
2801
|
|
|
2802
|
+
/**
|
|
2803
|
+
* A pod that evaluates each guest program on its own thread.
|
|
2804
|
+
*
|
|
2805
|
+
* Everything shared stays here: the volume, the HTTP router, the package
|
|
2806
|
+
* installer and the process table. Only the program's own evaluation moves,
|
|
2807
|
+
* and it reaches back for the rest through a {@link SyncChannelServer}.
|
|
2808
|
+
*
|
|
2809
|
+
* That arrangement is forced rather than chosen. A synchronous call has to
|
|
2810
|
+
* block the caller while the work it is waiting on still makes progress, so
|
|
2811
|
+
* the blocking side cannot be the side that owns the resources — otherwise a
|
|
2812
|
+
* child process needing the filesystem would have to call into a thread that
|
|
2813
|
+
* is frozen waiting for that child. The guest blocks; the host never does.
|
|
2814
|
+
*
|
|
2815
|
+
* It inherits from {@link LocalRuntimePod} because every other part of the
|
|
2816
|
+
* contract is identical, and overriding one method is a smaller and more
|
|
2817
|
+
* honest claim than reimplementing nine. Both are held to the same contract
|
|
2818
|
+
* suite (`test/pod-contract.ts`).
|
|
2819
|
+
*/
|
|
2820
|
+
|
|
2821
|
+
interface WorkerRuntimeOptions extends LocalRuntimeOptions {
|
|
2822
|
+
/** Where the guest bundle lives; defaults to the copy shipped beside this one. */
|
|
2823
|
+
workerUrl?: string | URL;
|
|
2824
|
+
}
|
|
2825
|
+
declare class WorkerRuntimePod extends LocalRuntimePod {
|
|
2826
|
+
private readonly workerUrl;
|
|
2827
|
+
/** Live workers, so teardown can stop them all. */
|
|
2828
|
+
private readonly live;
|
|
2829
|
+
protected constructor(options: WorkerRuntimeOptions);
|
|
2830
|
+
/** Boot without silently dropping synchronous child-process support. */
|
|
2831
|
+
static boot(options?: WorkerRuntimeOptions): Promise<WorkerRuntimePod>;
|
|
2832
|
+
/** Compatibility mode, with an observable explanation for every fallback. */
|
|
2833
|
+
static tryBoot(options?: WorkerRuntimeOptions, onFallback?: (error: Error) => void): Promise<WorkerRuntimePod | null>;
|
|
2834
|
+
spawn(command: string, args?: string[], options?: Record<string, unknown>): Promise<RuntimeProcess>;
|
|
2835
|
+
private spawnInWorker;
|
|
2836
|
+
/** Start an asynchronous child on the host's behalf and relay its events. */
|
|
2837
|
+
private startChild;
|
|
2838
|
+
/** Run a child to completion and collect it, for the guest's `spawnSync`. */
|
|
2839
|
+
private runChildToCompletion;
|
|
2840
|
+
private readonly proxies;
|
|
2841
|
+
private readonly waiting;
|
|
2842
|
+
private nextRequestId;
|
|
2843
|
+
/**
|
|
2844
|
+
* Register a stand-in for a server that is actually running in the Worker.
|
|
2845
|
+
*
|
|
2846
|
+
* The router only knows how to reach servers on this thread, so each bound
|
|
2847
|
+
* port gets a local server whose whole job is to forward and wait.
|
|
2848
|
+
*/
|
|
2849
|
+
private proxyPort;
|
|
2850
|
+
private forward;
|
|
2851
|
+
private settleProxied;
|
|
2852
|
+
private closeProxies;
|
|
2853
|
+
teardown(): void;
|
|
2854
|
+
/** Does anything under `cwd` need a module only the host can supply? */
|
|
2855
|
+
private needsHostModules;
|
|
2856
|
+
}
|
|
2857
|
+
|
|
2780
2858
|
interface RegistryManifest {
|
|
2781
2859
|
name: string;
|
|
2782
2860
|
version: string;
|
|
@@ -2837,8 +2915,8 @@ declare function extractNpmTarball(volume: RuntimeVolume, compressed: Uint8Array
|
|
|
2837
2915
|
* own dependency cache, where no such file exists. That is the same trap
|
|
2838
2916
|
* Rolldown's WASI binding falls into, and it surfaces just as obliquely.
|
|
2839
2917
|
*
|
|
2840
|
-
* So this never assumes it worked.
|
|
2841
|
-
*
|
|
2918
|
+
* So this never assumes it worked. Strict boot surfaces the failure; automatic mode reports
|
|
2919
|
+
* the cause before choosing the in-realm pod.
|
|
2842
2920
|
*/
|
|
2843
2921
|
interface RuntimeWorker {
|
|
2844
2922
|
postMessage(message: unknown): void;
|
|
@@ -2859,14 +2937,59 @@ declare function startRuntimeWorker(options?: {
|
|
|
2859
2937
|
timeoutMs?: number;
|
|
2860
2938
|
}): Promise<RuntimeWorker>;
|
|
2861
2939
|
|
|
2940
|
+
declare function syncChannelSupported(): boolean;
|
|
2941
|
+
|
|
2862
2942
|
/**
|
|
2863
|
-
*
|
|
2943
|
+
* Wiring a container's HTTP servers up to real URLs in the page.
|
|
2864
2944
|
*
|
|
2865
|
-
*
|
|
2866
|
-
*
|
|
2867
|
-
*
|
|
2945
|
+
* The service worker does the routing; this is the half that lives in the page
|
|
2946
|
+
* and actually knows about the container.
|
|
2947
|
+
*
|
|
2948
|
+
* **Read the origin note before using this.** A preview served this way runs on
|
|
2949
|
+
* *your* origin, so scripts inside it can reach `window.parent`, your cookies
|
|
2950
|
+
* and your `localStorage` — the sandbox contains the program's *filesystem and
|
|
2951
|
+
* process table*, not the page it serves. For code you did not write, either
|
|
2952
|
+
* host the preview on a separate origin, or use {@link renderInto}, which puts
|
|
2953
|
+
* the response in an iframe with no origin at all.
|
|
2868
2954
|
*/
|
|
2869
|
-
|
|
2955
|
+
|
|
2956
|
+
interface PreviewOptions {
|
|
2957
|
+
/** Where the worker script lives; defaults to the copy shipped beside the bundle. */
|
|
2958
|
+
scriptUrl?: string | URL;
|
|
2959
|
+
/** Registration scope. Must be able to see the paths a preview will request. */
|
|
2960
|
+
scope?: string;
|
|
2961
|
+
}
|
|
2962
|
+
interface Preview {
|
|
2963
|
+
/** The URL an iframe should be pointed at to see `port`. */
|
|
2964
|
+
urlFor(port: number): string;
|
|
2965
|
+
/** Stop answering requests and unregister the worker. */
|
|
2966
|
+
dispose(): Promise<void>;
|
|
2967
|
+
}
|
|
2968
|
+
/**
|
|
2969
|
+
* Register the preview worker and start answering its requests from `box`.
|
|
2970
|
+
*
|
|
2971
|
+
* Resolves to null where service workers are unavailable — a non-secure origin,
|
|
2972
|
+
* a browser with them disabled, or any non-browser host. Callers should treat
|
|
2973
|
+
* that as "no preview URLs here" and fall back to `box.request`.
|
|
2974
|
+
*/
|
|
2975
|
+
declare function createPreview(box: Container, options?: PreviewOptions): Promise<Preview | null>;
|
|
2976
|
+
/**
|
|
2977
|
+
* Show one response from the container inside an element, without letting it
|
|
2978
|
+
* touch the page.
|
|
2979
|
+
*
|
|
2980
|
+
* The iframe is sandboxed with `allow-scripts` and deliberately *without*
|
|
2981
|
+
* `allow-same-origin`, which puts the document in an opaque origin: its scripts
|
|
2982
|
+
* run, and they can reach neither this page's DOM nor its cookies and storage.
|
|
2983
|
+
* That combination is what makes it safe to render output you do not trust.
|
|
2984
|
+
*
|
|
2985
|
+
* The trade-off is that only this one response exists — a page that asks for
|
|
2986
|
+
* `/main.js` gets nothing, because there is no origin to serve it from. For a
|
|
2987
|
+
* whole site, use {@link createPreview}, and read its note about origins first.
|
|
2988
|
+
*/
|
|
2989
|
+
declare function renderInto(box: Container, element: HTMLElement, options?: {
|
|
2990
|
+
port: number;
|
|
2991
|
+
path?: string;
|
|
2992
|
+
}): Promise<HTMLIFrameElement>;
|
|
2870
2993
|
|
|
2871
2994
|
/**
|
|
2872
2995
|
* sandboxedjs — a Linux-like container that runs entirely inside Node.js.
|
|
@@ -2886,4 +3009,4 @@ declare function syncChannelSupported(): boolean;
|
|
|
2886
3009
|
* ```
|
|
2887
3010
|
*/
|
|
2888
3011
|
|
|
2889
|
-
export { ArithError, BufferSink, type CPythonOptions, CallbackSink, type ChildHandle, type ChildSpawnConfig, type CleanInstallerOptions, CleanPackageInstaller, type Command, CommandRegistry, CommonJsEngine, type CommonJsEngineOptions, type CommonJsModule, Container, ContainerFs, type ContainerOptions, type ContextInit, type CoreModulesOptions, type Cred, type DirEntry, ERRNO, type Env, type ErrnoCode, type EsmTransformResult, type ExecContext, type ExecOptions, type ExecResult, type FileData, FileInput, FileOutput, type GroupEntry, type HttpResponse, IncompleteInputError, type InputStream, type InstallOptions, type Job, KERNEL_NAME, KERNEL_RELEASE, Kernel, type KernelOptions, type ListeningPort, type LocalRuntimeOptions, LocalRuntimePod, MemoryVolume, type MountEntry, NODE_VERSION, NPM_VERSION, type NetInterface, type NetworkOptions, NetworkStack, NullInput, NullOutput, OS_RELEASE, type OutputStream, PYTHON_VERSION, type PasswdEntry, Pipe, Process, type ProcessKind, type ProcessOptions, type ProcessState, ProcessTable, type PythonOptions, ROOT_CRED, type ResolvedExecutable, type RootfsOptions, type RunOptions, type RunResult, type RuntimePackageInstaller, type RuntimePod, type RuntimeProcess, type RuntimeProcessManager, type RuntimeProcessResult, type RuntimeVolume, SIGNALS, SIGNAL_NAMES, Session, type SessionInit, type SessionResult, type SessionRunOptions, Shell, ShellExit, type ShellIO, type ShellInit, Lexer as ShellLexer, type ShellOptions, ShellSyntaxError, type SpawnChild, type SpawnHandle, Stats, type Stdio, SysError, TeeOutput, Terminal, type TerminalOptions, UserDatabase, Variables, Vfs, VirtualHttpRouter, VirtualHttpServer, VirtualIncomingMessage, type VirtualNode, type VirtualProvider, VirtualServerResponse, WASM_ALIASES, type WriteOptions, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configureCPython, configurePython, createChildProcessModule, createContainer, createContext, createCoreModules, createContainer as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, extractNpmTarball, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isCPythonAvailable, isPythonAvailable, isSysError, looksLikeEsm, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path as posixPath, resetPidCounter, shellQuote, startRuntimeWorker, strerror, syncChannelSupported, transformEsm, unameInfo };
|
|
3012
|
+
export { ArithError, BufferSink, type CPythonOptions, CallbackSink, type ChildHandle, type ChildSpawnConfig, type CleanInstallerOptions, CleanPackageInstaller, type Command, CommandRegistry, CommonJsEngine, type CommonJsEngineOptions, type CommonJsModule, Container, ContainerFs, type ContainerOptions, type ContextInit, type CoreModulesOptions, type Cred, type DirEntry, ERRNO, type Env, type ErrnoCode, type EsmTransformResult, type ExecContext, type ExecOptions, type ExecResult, type FileData, FileInput, FileOutput, type GroupEntry, type HttpResponse, IncompleteInputError, type InputStream, type InstallOptions, type Job, KERNEL_NAME, KERNEL_RELEASE, Kernel, type KernelOptions, type ListeningPort, type LocalRuntimeOptions, LocalRuntimePod, MemoryVolume, type MountEntry, NODE_VERSION, NPM_VERSION, type NetInterface, type NetworkOptions, NetworkStack, NullInput, NullOutput, OS_RELEASE, type OutputStream, PYTHON_VERSION, type PasswdEntry, Pipe, type Preview, type PreviewOptions, Process, type ProcessKind, type ProcessOptions, type ProcessState, ProcessTable, type PythonOptions, ROOT_CRED, type ResolvedExecutable, type RootfsOptions, type RunOptions, type RunResult, type RuntimePackageInstaller, type RuntimePod, type RuntimeProcess, type RuntimeProcessManager, type RuntimeProcessResult, type RuntimeVolume, SIGNALS, SIGNAL_NAMES, Session, type SessionInit, type SessionResult, type SessionRunOptions, Shell, ShellExit, type ShellIO, type ShellInit, Lexer as ShellLexer, type ShellOptions, ShellSyntaxError, type SpawnChild, type SpawnHandle, Stats, type Stdio, SysError, TeeOutput, Terminal, type TerminalOptions, UserDatabase, Variables, Vfs, VirtualHttpRouter, VirtualHttpServer, VirtualIncomingMessage, type VirtualNode, type VirtualProvider, VirtualServerResponse, WASM_ALIASES, type WorkerRuntimeOptions, WorkerRuntimePod, type WriteOptions, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configureCPython, configurePython, createChildProcessModule, createContainer, createContext, createCoreModules, createPreview, createContainer as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, extractNpmTarball, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isCPythonAvailable, isPythonAvailable, isSysError, looksLikeEsm, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path as posixPath, renderInto, resetPidCounter, shellQuote, startRuntimeWorker, strerror, syncChannelSupported, transformEsm, unameInfo };
|