sandboxedjs 0.1.25 → 0.1.27
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 +42 -11
- package/dist/index.cjs +1769 -459
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -12
- package/dist/index.d.ts +68 -12
- package/dist/index.js +1765 -452
- package/dist/index.js.map +1 -1
- package/package.json +2 -5
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import EventEmitter from 'events';
|
|
1
|
+
import EventEmitter from 'events/events.js';
|
|
2
2
|
import streamModule from 'stream-browserify';
|
|
3
3
|
|
|
4
4
|
/** The handle a pod's process manager returns. */
|
|
@@ -81,7 +81,12 @@ interface RuntimeProcessResult {
|
|
|
81
81
|
}
|
|
82
82
|
interface RuntimeProcess {
|
|
83
83
|
readonly completion: Promise<RuntimeProcessResult>;
|
|
84
|
-
|
|
84
|
+
/**
|
|
85
|
+
* `output` and `error` carry stdout and stderr; `exit` the code. `rawmode`
|
|
86
|
+
* reports the program turning terminal raw mode on or off, which a terminal
|
|
87
|
+
* needs so that it stops echoing input the program is drawing itself.
|
|
88
|
+
*/
|
|
89
|
+
on(event: "output" | "error" | "exit" | "rawmode", listener: (...args: any[]) => void): this;
|
|
85
90
|
write(data: string): void;
|
|
86
91
|
kill(signal?: string): void;
|
|
87
92
|
}
|
|
@@ -191,7 +196,7 @@ interface DirEntry {
|
|
|
191
196
|
/**
|
|
192
197
|
* The container's virtual filesystem.
|
|
193
198
|
*
|
|
194
|
-
* Real file content lives in
|
|
199
|
+
* Real file content lives in the RuntimePod's `MemoryVolume`, deliberately the
|
|
195
200
|
* *same* volume the Node.js worker processes see — so a file written by `echo`
|
|
196
201
|
* is readable by `require('fs')` inside a spawned script, and vice versa.
|
|
197
202
|
*
|
|
@@ -390,6 +395,14 @@ declare class Pipe implements InputStream, OutputStream {
|
|
|
390
395
|
isTTY: boolean;
|
|
391
396
|
/** Set on pipes owned by an outside caller, who may never call `end()`. */
|
|
392
397
|
interactive: boolean;
|
|
398
|
+
/**
|
|
399
|
+
* Set while the running program has put the terminal in raw mode.
|
|
400
|
+
*
|
|
401
|
+
* A program in raw mode draws its own input — a prompt library redraws the
|
|
402
|
+
* whole line on every keystroke — so the terminal must stop echoing, or
|
|
403
|
+
* every character appears twice.
|
|
404
|
+
*/
|
|
405
|
+
rawMode: boolean;
|
|
393
406
|
columns: number | undefined;
|
|
394
407
|
rows: number | undefined;
|
|
395
408
|
get closed(): boolean;
|
|
@@ -733,7 +746,7 @@ declare function createContext(init: ContextInit): ExecContext;
|
|
|
733
746
|
* The container's network stack.
|
|
734
747
|
*
|
|
735
748
|
* There is no real socket layer: HTTP servers started inside the container are
|
|
736
|
-
* registered with
|
|
749
|
+
* registered with the RuntimePod's request proxy, and this module is the routing and
|
|
737
750
|
* name-resolution layer on top — interfaces for `ip`/`ifconfig`, a hosts file
|
|
738
751
|
* resolver, a listening-port table for `ss`/`netstat`, and an outbound policy
|
|
739
752
|
* that decides whether `curl https://example.com` is allowed to touch the real
|
|
@@ -792,7 +805,7 @@ declare class NetworkStack {
|
|
|
792
805
|
registerListener(port: number, info: Omit<ListeningPort, "port" | "since">): void;
|
|
793
806
|
unregisterListener(port: number): void;
|
|
794
807
|
listening(): ListeningPort[];
|
|
795
|
-
/** Ports
|
|
808
|
+
/** Ports the pod's proxy has registered for this instance. */
|
|
796
809
|
private knownPodPorts;
|
|
797
810
|
/** True when something inside the container answers on `port`. */
|
|
798
811
|
isPortOpen(port: number, timeoutMs?: number): Promise<boolean>;
|
|
@@ -1719,7 +1732,7 @@ declare class Container {
|
|
|
1719
1732
|
/**
|
|
1720
1733
|
* Deliver a request whose body is bytes, without letting them become text.
|
|
1721
1734
|
*
|
|
1722
|
-
*
|
|
1735
|
+
* A RuntimePod's public `request()` may run the body through `toString("utf8")` on
|
|
1723
1736
|
* its way in, so anything above `0x7f` is replaced: a five-byte payload
|
|
1724
1737
|
* containing `0x89` and `0xff` arrives as nine. That silently destroys every
|
|
1725
1738
|
* upload — an image or a video reaches the server the wrong size and no
|
|
@@ -1759,7 +1772,7 @@ declare class Container {
|
|
|
1759
1772
|
get cwd(): string;
|
|
1760
1773
|
get env(): Record<string, string>;
|
|
1761
1774
|
private assertActive;
|
|
1762
|
-
/** Tear down every process and release the
|
|
1775
|
+
/** Tear down every process and release the runtime pod. */
|
|
1763
1776
|
dispose(): void;
|
|
1764
1777
|
get isDisposed(): boolean;
|
|
1765
1778
|
}
|
|
@@ -2101,17 +2114,16 @@ interface RootfsOptions {
|
|
|
2101
2114
|
declare function buildRootfs(vfs: Vfs, opts?: RootfsOptions): void;
|
|
2102
2115
|
|
|
2103
2116
|
/**
|
|
2104
|
-
* The Node.js
|
|
2117
|
+
* The Node.js command adapter, backed by the clean-room RuntimePod.
|
|
2105
2118
|
*
|
|
2106
|
-
*
|
|
2119
|
+
* The pod runs the script over the *same* memory volume
|
|
2107
2120
|
* the container's filesystem uses, so `require('fs')` inside a script sees the
|
|
2108
2121
|
* files `echo` and `tar` created, and anything the script writes is visible to
|
|
2109
2122
|
* the shell afterwards.
|
|
2110
2123
|
*
|
|
2111
|
-
* Two
|
|
2124
|
+
* Two details of the underlying `spawn` are handled here:
|
|
2112
2125
|
* - only `node` resolves as a command, so everything else is dispatched by our
|
|
2113
|
-
* own kernel rather than being handed to
|
|
2114
|
-
* unknown command);
|
|
2126
|
+
* own kernel rather than being handed to the Node process runner;
|
|
2115
2127
|
* - the worker's stdin has no end-of-stream signal, so when a pipeline feeds
|
|
2116
2128
|
* a script we materialise stdin as a file and install a real stdin stream
|
|
2117
2129
|
* over it before the script loads.
|
|
@@ -2262,6 +2274,16 @@ declare class CommonJsEngine {
|
|
|
2262
2274
|
main: CommonJsModule | null;
|
|
2263
2275
|
/** `package.json` per directory; resolution reads them constantly. */
|
|
2264
2276
|
private readonly manifests;
|
|
2277
|
+
private evaluationDepth;
|
|
2278
|
+
/**
|
|
2279
|
+
* Is a module body running synchronously right now?
|
|
2280
|
+
*
|
|
2281
|
+
* `process.exit` unwinds by throwing, and that is only safe while one of
|
|
2282
|
+
* this engine's own frames is on the stack to catch it. Thrown from a later
|
|
2283
|
+
* callback — a stream handler, a timer — it would escape into whichever
|
|
2284
|
+
* library called that callback and surface as an unrelated crash.
|
|
2285
|
+
*/
|
|
2286
|
+
get isEvaluating(): boolean;
|
|
2265
2287
|
constructor(volume: RuntimeVolume, options?: Omit<CommonJsEngineOptions, "volume">);
|
|
2266
2288
|
/**
|
|
2267
2289
|
* Evaluate an entry point.
|
|
@@ -2426,12 +2448,31 @@ interface CoreModulesOptions {
|
|
|
2426
2448
|
spawnChild?: SpawnChild;
|
|
2427
2449
|
/** File holding the process's standard input, exposed as descriptor 0. */
|
|
2428
2450
|
stdinPath?: string;
|
|
2451
|
+
/** Keep `process.stdin` open and fed by {@link writeStdin} rather than ending it. */
|
|
2452
|
+
interactiveStdin?: boolean;
|
|
2453
|
+
/** Report the standard streams as a terminal, which is what makes CLIs prompt. */
|
|
2454
|
+
tty?: boolean;
|
|
2455
|
+
/** Called when the program turns raw mode on or off. */
|
|
2456
|
+
onRawMode?: (enabled: boolean) => void;
|
|
2429
2457
|
}
|
|
2430
2458
|
/** Build the core-module table injected into each isolated JS worker. */
|
|
2431
2459
|
declare function createCoreModules(options: CoreModulesOptions): {
|
|
2432
2460
|
builtins: Record<string, unknown>;
|
|
2433
2461
|
globals: Record<string, unknown>;
|
|
2434
2462
|
process: Record<string, any>;
|
|
2463
|
+
/** Deliver a chunk of input to an interactive `process.stdin`. */
|
|
2464
|
+
writeStdin(data: string): void;
|
|
2465
|
+
/** Signal end-of-input to an interactive `process.stdin`. */
|
|
2466
|
+
endStdin(): void;
|
|
2467
|
+
/**
|
|
2468
|
+
* Is the program waiting on input?
|
|
2469
|
+
*
|
|
2470
|
+
* Node keeps a process alive for an open stdin only while something is
|
|
2471
|
+
* actually reading it, and that distinction matters here: a CLI sitting on a
|
|
2472
|
+
* prompt has no timers pending and would otherwise look finished, while a
|
|
2473
|
+
* program that never touches stdin must still be allowed to exit.
|
|
2474
|
+
*/
|
|
2475
|
+
readingStdin(): boolean;
|
|
2435
2476
|
/**
|
|
2436
2477
|
* How many timers this process still has outstanding.
|
|
2437
2478
|
*
|
|
@@ -2442,6 +2483,8 @@ declare function createCoreModules(options: CoreModulesOptions): {
|
|
|
2442
2483
|
* script that has simply finished.
|
|
2443
2484
|
*/
|
|
2444
2485
|
pendingHandles(): number;
|
|
2486
|
+
/** Active timers which called `unref()` and therefore only merit startup grace. */
|
|
2487
|
+
pendingUnrefed(): number;
|
|
2445
2488
|
};
|
|
2446
2489
|
|
|
2447
2490
|
interface EsmTransformResult {
|
|
@@ -2528,9 +2571,18 @@ declare class LocalRuntimePod implements RuntimePod {
|
|
|
2528
2571
|
private readonly aliases;
|
|
2529
2572
|
private readonly modules;
|
|
2530
2573
|
private readonly esbuild;
|
|
2574
|
+
private rolldownBinding;
|
|
2531
2575
|
private constructor();
|
|
2532
2576
|
static boot(options?: LocalRuntimeOptions): Promise<LocalRuntimePod>;
|
|
2533
2577
|
spawn(command: string, args?: string[], options?: Record<string, unknown>): Promise<RuntimeProcess>;
|
|
2578
|
+
/**
|
|
2579
|
+
* Rolldown's JavaScript API synchronously requires its compiled binding.
|
|
2580
|
+
* When a project contains Rolldown, preload the official WASI build in the
|
|
2581
|
+
* host and expose it through the module override table before evaluation.
|
|
2582
|
+
* Keeping this demand-driven avoids adding WASM startup cost to ordinary
|
|
2583
|
+
* shells and Node programs.
|
|
2584
|
+
*/
|
|
2585
|
+
private prepareRolldown;
|
|
2534
2586
|
/**
|
|
2535
2587
|
* Wait until the process has either started serving or genuinely run out of
|
|
2536
2588
|
* work.
|
|
@@ -2565,6 +2617,10 @@ interface RegistryManifest {
|
|
|
2565
2617
|
};
|
|
2566
2618
|
dependencies?: Record<string, string>;
|
|
2567
2619
|
optionalDependencies?: Record<string, string>;
|
|
2620
|
+
os?: string[];
|
|
2621
|
+
cpu?: string[];
|
|
2622
|
+
libc?: string[];
|
|
2623
|
+
main?: string;
|
|
2568
2624
|
bin?: string | Record<string, string>;
|
|
2569
2625
|
}
|
|
2570
2626
|
interface CleanInstallerOptions {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import EventEmitter from 'events';
|
|
1
|
+
import EventEmitter from 'events/events.js';
|
|
2
2
|
import streamModule from 'stream-browserify';
|
|
3
3
|
|
|
4
4
|
/** The handle a pod's process manager returns. */
|
|
@@ -81,7 +81,12 @@ interface RuntimeProcessResult {
|
|
|
81
81
|
}
|
|
82
82
|
interface RuntimeProcess {
|
|
83
83
|
readonly completion: Promise<RuntimeProcessResult>;
|
|
84
|
-
|
|
84
|
+
/**
|
|
85
|
+
* `output` and `error` carry stdout and stderr; `exit` the code. `rawmode`
|
|
86
|
+
* reports the program turning terminal raw mode on or off, which a terminal
|
|
87
|
+
* needs so that it stops echoing input the program is drawing itself.
|
|
88
|
+
*/
|
|
89
|
+
on(event: "output" | "error" | "exit" | "rawmode", listener: (...args: any[]) => void): this;
|
|
85
90
|
write(data: string): void;
|
|
86
91
|
kill(signal?: string): void;
|
|
87
92
|
}
|
|
@@ -191,7 +196,7 @@ interface DirEntry {
|
|
|
191
196
|
/**
|
|
192
197
|
* The container's virtual filesystem.
|
|
193
198
|
*
|
|
194
|
-
* Real file content lives in
|
|
199
|
+
* Real file content lives in the RuntimePod's `MemoryVolume`, deliberately the
|
|
195
200
|
* *same* volume the Node.js worker processes see — so a file written by `echo`
|
|
196
201
|
* is readable by `require('fs')` inside a spawned script, and vice versa.
|
|
197
202
|
*
|
|
@@ -390,6 +395,14 @@ declare class Pipe implements InputStream, OutputStream {
|
|
|
390
395
|
isTTY: boolean;
|
|
391
396
|
/** Set on pipes owned by an outside caller, who may never call `end()`. */
|
|
392
397
|
interactive: boolean;
|
|
398
|
+
/**
|
|
399
|
+
* Set while the running program has put the terminal in raw mode.
|
|
400
|
+
*
|
|
401
|
+
* A program in raw mode draws its own input — a prompt library redraws the
|
|
402
|
+
* whole line on every keystroke — so the terminal must stop echoing, or
|
|
403
|
+
* every character appears twice.
|
|
404
|
+
*/
|
|
405
|
+
rawMode: boolean;
|
|
393
406
|
columns: number | undefined;
|
|
394
407
|
rows: number | undefined;
|
|
395
408
|
get closed(): boolean;
|
|
@@ -733,7 +746,7 @@ declare function createContext(init: ContextInit): ExecContext;
|
|
|
733
746
|
* The container's network stack.
|
|
734
747
|
*
|
|
735
748
|
* There is no real socket layer: HTTP servers started inside the container are
|
|
736
|
-
* registered with
|
|
749
|
+
* registered with the RuntimePod's request proxy, and this module is the routing and
|
|
737
750
|
* name-resolution layer on top — interfaces for `ip`/`ifconfig`, a hosts file
|
|
738
751
|
* resolver, a listening-port table for `ss`/`netstat`, and an outbound policy
|
|
739
752
|
* that decides whether `curl https://example.com` is allowed to touch the real
|
|
@@ -792,7 +805,7 @@ declare class NetworkStack {
|
|
|
792
805
|
registerListener(port: number, info: Omit<ListeningPort, "port" | "since">): void;
|
|
793
806
|
unregisterListener(port: number): void;
|
|
794
807
|
listening(): ListeningPort[];
|
|
795
|
-
/** Ports
|
|
808
|
+
/** Ports the pod's proxy has registered for this instance. */
|
|
796
809
|
private knownPodPorts;
|
|
797
810
|
/** True when something inside the container answers on `port`. */
|
|
798
811
|
isPortOpen(port: number, timeoutMs?: number): Promise<boolean>;
|
|
@@ -1719,7 +1732,7 @@ declare class Container {
|
|
|
1719
1732
|
/**
|
|
1720
1733
|
* Deliver a request whose body is bytes, without letting them become text.
|
|
1721
1734
|
*
|
|
1722
|
-
*
|
|
1735
|
+
* A RuntimePod's public `request()` may run the body through `toString("utf8")` on
|
|
1723
1736
|
* its way in, so anything above `0x7f` is replaced: a five-byte payload
|
|
1724
1737
|
* containing `0x89` and `0xff` arrives as nine. That silently destroys every
|
|
1725
1738
|
* upload — an image or a video reaches the server the wrong size and no
|
|
@@ -1759,7 +1772,7 @@ declare class Container {
|
|
|
1759
1772
|
get cwd(): string;
|
|
1760
1773
|
get env(): Record<string, string>;
|
|
1761
1774
|
private assertActive;
|
|
1762
|
-
/** Tear down every process and release the
|
|
1775
|
+
/** Tear down every process and release the runtime pod. */
|
|
1763
1776
|
dispose(): void;
|
|
1764
1777
|
get isDisposed(): boolean;
|
|
1765
1778
|
}
|
|
@@ -2101,17 +2114,16 @@ interface RootfsOptions {
|
|
|
2101
2114
|
declare function buildRootfs(vfs: Vfs, opts?: RootfsOptions): void;
|
|
2102
2115
|
|
|
2103
2116
|
/**
|
|
2104
|
-
* The Node.js
|
|
2117
|
+
* The Node.js command adapter, backed by the clean-room RuntimePod.
|
|
2105
2118
|
*
|
|
2106
|
-
*
|
|
2119
|
+
* The pod runs the script over the *same* memory volume
|
|
2107
2120
|
* the container's filesystem uses, so `require('fs')` inside a script sees the
|
|
2108
2121
|
* files `echo` and `tar` created, and anything the script writes is visible to
|
|
2109
2122
|
* the shell afterwards.
|
|
2110
2123
|
*
|
|
2111
|
-
* Two
|
|
2124
|
+
* Two details of the underlying `spawn` are handled here:
|
|
2112
2125
|
* - only `node` resolves as a command, so everything else is dispatched by our
|
|
2113
|
-
* own kernel rather than being handed to
|
|
2114
|
-
* unknown command);
|
|
2126
|
+
* own kernel rather than being handed to the Node process runner;
|
|
2115
2127
|
* - the worker's stdin has no end-of-stream signal, so when a pipeline feeds
|
|
2116
2128
|
* a script we materialise stdin as a file and install a real stdin stream
|
|
2117
2129
|
* over it before the script loads.
|
|
@@ -2262,6 +2274,16 @@ declare class CommonJsEngine {
|
|
|
2262
2274
|
main: CommonJsModule | null;
|
|
2263
2275
|
/** `package.json` per directory; resolution reads them constantly. */
|
|
2264
2276
|
private readonly manifests;
|
|
2277
|
+
private evaluationDepth;
|
|
2278
|
+
/**
|
|
2279
|
+
* Is a module body running synchronously right now?
|
|
2280
|
+
*
|
|
2281
|
+
* `process.exit` unwinds by throwing, and that is only safe while one of
|
|
2282
|
+
* this engine's own frames is on the stack to catch it. Thrown from a later
|
|
2283
|
+
* callback — a stream handler, a timer — it would escape into whichever
|
|
2284
|
+
* library called that callback and surface as an unrelated crash.
|
|
2285
|
+
*/
|
|
2286
|
+
get isEvaluating(): boolean;
|
|
2265
2287
|
constructor(volume: RuntimeVolume, options?: Omit<CommonJsEngineOptions, "volume">);
|
|
2266
2288
|
/**
|
|
2267
2289
|
* Evaluate an entry point.
|
|
@@ -2426,12 +2448,31 @@ interface CoreModulesOptions {
|
|
|
2426
2448
|
spawnChild?: SpawnChild;
|
|
2427
2449
|
/** File holding the process's standard input, exposed as descriptor 0. */
|
|
2428
2450
|
stdinPath?: string;
|
|
2451
|
+
/** Keep `process.stdin` open and fed by {@link writeStdin} rather than ending it. */
|
|
2452
|
+
interactiveStdin?: boolean;
|
|
2453
|
+
/** Report the standard streams as a terminal, which is what makes CLIs prompt. */
|
|
2454
|
+
tty?: boolean;
|
|
2455
|
+
/** Called when the program turns raw mode on or off. */
|
|
2456
|
+
onRawMode?: (enabled: boolean) => void;
|
|
2429
2457
|
}
|
|
2430
2458
|
/** Build the core-module table injected into each isolated JS worker. */
|
|
2431
2459
|
declare function createCoreModules(options: CoreModulesOptions): {
|
|
2432
2460
|
builtins: Record<string, unknown>;
|
|
2433
2461
|
globals: Record<string, unknown>;
|
|
2434
2462
|
process: Record<string, any>;
|
|
2463
|
+
/** Deliver a chunk of input to an interactive `process.stdin`. */
|
|
2464
|
+
writeStdin(data: string): void;
|
|
2465
|
+
/** Signal end-of-input to an interactive `process.stdin`. */
|
|
2466
|
+
endStdin(): void;
|
|
2467
|
+
/**
|
|
2468
|
+
* Is the program waiting on input?
|
|
2469
|
+
*
|
|
2470
|
+
* Node keeps a process alive for an open stdin only while something is
|
|
2471
|
+
* actually reading it, and that distinction matters here: a CLI sitting on a
|
|
2472
|
+
* prompt has no timers pending and would otherwise look finished, while a
|
|
2473
|
+
* program that never touches stdin must still be allowed to exit.
|
|
2474
|
+
*/
|
|
2475
|
+
readingStdin(): boolean;
|
|
2435
2476
|
/**
|
|
2436
2477
|
* How many timers this process still has outstanding.
|
|
2437
2478
|
*
|
|
@@ -2442,6 +2483,8 @@ declare function createCoreModules(options: CoreModulesOptions): {
|
|
|
2442
2483
|
* script that has simply finished.
|
|
2443
2484
|
*/
|
|
2444
2485
|
pendingHandles(): number;
|
|
2486
|
+
/** Active timers which called `unref()` and therefore only merit startup grace. */
|
|
2487
|
+
pendingUnrefed(): number;
|
|
2445
2488
|
};
|
|
2446
2489
|
|
|
2447
2490
|
interface EsmTransformResult {
|
|
@@ -2528,9 +2571,18 @@ declare class LocalRuntimePod implements RuntimePod {
|
|
|
2528
2571
|
private readonly aliases;
|
|
2529
2572
|
private readonly modules;
|
|
2530
2573
|
private readonly esbuild;
|
|
2574
|
+
private rolldownBinding;
|
|
2531
2575
|
private constructor();
|
|
2532
2576
|
static boot(options?: LocalRuntimeOptions): Promise<LocalRuntimePod>;
|
|
2533
2577
|
spawn(command: string, args?: string[], options?: Record<string, unknown>): Promise<RuntimeProcess>;
|
|
2578
|
+
/**
|
|
2579
|
+
* Rolldown's JavaScript API synchronously requires its compiled binding.
|
|
2580
|
+
* When a project contains Rolldown, preload the official WASI build in the
|
|
2581
|
+
* host and expose it through the module override table before evaluation.
|
|
2582
|
+
* Keeping this demand-driven avoids adding WASM startup cost to ordinary
|
|
2583
|
+
* shells and Node programs.
|
|
2584
|
+
*/
|
|
2585
|
+
private prepareRolldown;
|
|
2534
2586
|
/**
|
|
2535
2587
|
* Wait until the process has either started serving or genuinely run out of
|
|
2536
2588
|
* work.
|
|
@@ -2565,6 +2617,10 @@ interface RegistryManifest {
|
|
|
2565
2617
|
};
|
|
2566
2618
|
dependencies?: Record<string, string>;
|
|
2567
2619
|
optionalDependencies?: Record<string, string>;
|
|
2620
|
+
os?: string[];
|
|
2621
|
+
cpu?: string[];
|
|
2622
|
+
libc?: string[];
|
|
2623
|
+
main?: string;
|
|
2568
2624
|
bin?: string | Record<string, string>;
|
|
2569
2625
|
}
|
|
2570
2626
|
interface CleanInstallerOptions {
|