@nodetool-ai/sandbox-runtime 0.0.0-stage → 0.8.9-bootstrap.0
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 +24 -2
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/host-access-gate.d.ts +24 -0
- package/dist/host-access-gate.d.ts.map +1 -0
- package/dist/host-access-gate.js +31 -0
- package/dist/host-access-gate.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +318 -0
- package/dist/index.js.map +1 -0
- package/dist/js-sandbox-worker/engine.d.ts +4 -0
- package/dist/js-sandbox-worker/engine.d.ts.map +1 -0
- package/dist/js-sandbox-worker/engine.js +82 -0
- package/dist/js-sandbox-worker/engine.js.map +1 -0
- package/dist/js-sandbox-worker/host.d.ts +136 -0
- package/dist/js-sandbox-worker/host.d.ts.map +1 -0
- package/dist/js-sandbox-worker/host.js +482 -0
- package/dist/js-sandbox-worker/host.js.map +1 -0
- package/dist/js-sandbox-worker/interpreter.d.ts +276 -0
- package/dist/js-sandbox-worker/interpreter.d.ts.map +1 -0
- package/dist/js-sandbox-worker/interpreter.js +1318 -0
- package/dist/js-sandbox-worker/interpreter.js.map +1 -0
- package/dist/js-sandbox-worker/protocol.d.ts +168 -0
- package/dist/js-sandbox-worker/protocol.d.ts.map +1 -0
- package/dist/js-sandbox-worker/protocol.js +217 -0
- package/dist/js-sandbox-worker/protocol.js.map +1 -0
- package/dist/js-sandbox-worker/worker-entry.d.ts +26 -0
- package/dist/js-sandbox-worker/worker-entry.d.ts.map +1 -0
- package/dist/js-sandbox-worker/worker-entry.js +308 -0
- package/dist/js-sandbox-worker/worker-entry.js.map +1 -0
- package/dist/limits.d.ts +77 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/limits.js +56 -0
- package/dist/limits.js.map +1 -0
- package/dist/sandbox-bootstrap-modules.d.ts +54 -0
- package/dist/sandbox-bootstrap-modules.d.ts.map +1 -0
- package/dist/sandbox-bootstrap-modules.js +104 -0
- package/dist/sandbox-bootstrap-modules.js.map +1 -0
- package/dist/sandbox-bytes.d.ts +43 -0
- package/dist/sandbox-bytes.d.ts.map +1 -0
- package/dist/sandbox-bytes.js +61 -0
- package/dist/sandbox-bytes.js.map +1 -0
- package/dist/sandbox-canvas-api.d.ts +30 -0
- package/dist/sandbox-canvas-api.d.ts.map +1 -0
- package/dist/sandbox-canvas-api.js +81 -0
- package/dist/sandbox-canvas-api.js.map +1 -0
- package/dist/sandbox-constants.d.ts +5 -0
- package/dist/sandbox-constants.d.ts.map +1 -0
- package/dist/sandbox-constants.js +13 -0
- package/dist/sandbox-constants.js.map +1 -0
- package/dist/sandbox-json-transport.d.ts +107 -0
- package/dist/sandbox-json-transport.d.ts.map +1 -0
- package/dist/sandbox-json-transport.js +324 -0
- package/dist/sandbox-json-transport.js.map +1 -0
- package/dist/timeline-capture.d.ts +21 -0
- package/dist/timeline-capture.d.ts.map +1 -0
- package/dist/timeline-capture.js +564 -0
- package/dist/timeline-capture.js.map +1 -0
- package/dist/utils/type-guards.d.ts +26 -0
- package/dist/utils/type-guards.d.ts.map +1 -0
- package/dist/utils/type-guards.js +44 -0
- package/dist/utils/type-guards.js.map +1 -0
- package/package.json +138 -4
- package/vendor/README.md +17 -0
- package/vendor/quickjs/LICENSE +21 -0
- package/vendor/quickjs/PROVENANCE.json +8 -0
- package/vendor/quickjs/adapter/fetch.d.ts +56 -0
- package/vendor/quickjs/adapter/fetch.js +140 -0
- package/vendor/quickjs/createTimeInterval.d.ts +9 -0
- package/vendor/quickjs/createTimeInterval.js +22 -0
- package/vendor/quickjs/createVirtualFileSystem.d.ts +13 -0
- package/vendor/quickjs/createVirtualFileSystem.js +191 -0
- package/vendor/quickjs/index.d.ts +77 -0
- package/vendor/quickjs/index.js +77 -0
- package/vendor/quickjs/loadAsyncQuickJs.d.ts +12 -0
- package/vendor/quickjs/loadAsyncQuickJs.js +66 -0
- package/vendor/quickjs/loadQuickJs.d.ts +12 -0
- package/vendor/quickjs/loadQuickJs.js +73 -0
- package/vendor/quickjs/modules/assert.d.ts +2 -0
- package/vendor/quickjs/modules/assert.js +47 -0
- package/vendor/quickjs/modules/buffer.d.ts +2 -0
- package/vendor/quickjs/modules/buffer.js +106 -0
- package/vendor/quickjs/modules/build/test-lib.js +2 -0
- package/vendor/quickjs/modules/events.d.ts +2 -0
- package/vendor/quickjs/modules/events.js +4 -0
- package/vendor/quickjs/modules/fs.d.ts +2 -0
- package/vendor/quickjs/modules/fs.js +76 -0
- package/vendor/quickjs/modules/fs_promises.d.ts +2 -0
- package/vendor/quickjs/modules/fs_promises.js +328 -0
- package/vendor/quickjs/modules/module.d.ts +2 -0
- package/vendor/quickjs/modules/module.js +33 -0
- package/vendor/quickjs/modules/nodeCompatibility/headers.d.ts +2 -0
- package/vendor/quickjs/modules/nodeCompatibility/headers.js +58 -0
- package/vendor/quickjs/modules/nodeCompatibility/request.d.ts +2 -0
- package/vendor/quickjs/modules/nodeCompatibility/request.js +5 -0
- package/vendor/quickjs/modules/nodeCompatibility/response.d.ts +2 -0
- package/vendor/quickjs/modules/nodeCompatibility/response.js +5 -0
- package/vendor/quickjs/modules/path.d.ts +2 -0
- package/vendor/quickjs/modules/path.js +504 -0
- package/vendor/quickjs/modules/process.d.ts +2 -0
- package/vendor/quickjs/modules/process.js +309 -0
- package/vendor/quickjs/modules/punycode.d.ts +2 -0
- package/vendor/quickjs/modules/punycode.js +443 -0
- package/vendor/quickjs/modules/querystring.d.ts +2 -0
- package/vendor/quickjs/modules/querystring.js +15 -0
- package/vendor/quickjs/modules/string_decoder.d.ts +2 -0
- package/vendor/quickjs/modules/string_decoder.js +223 -0
- package/vendor/quickjs/modules/timers.d.ts +2 -0
- package/vendor/quickjs/modules/timers.js +10 -0
- package/vendor/quickjs/modules/timers_promises.d.ts +2 -0
- package/vendor/quickjs/modules/timers_promises.js +40 -0
- package/vendor/quickjs/modules/url.d.ts +2 -0
- package/vendor/quickjs/modules/url.js +104 -0
- package/vendor/quickjs/modules/util.d.ts +2 -0
- package/vendor/quickjs/modules/util.js +233 -0
- package/vendor/quickjs/package.json +3 -0
- package/vendor/quickjs/sandbox/asyncVersion/createAsyncEvalCodeFunction.d.ts +4 -0
- package/vendor/quickjs/sandbox/asyncVersion/createAsyncEvalCodeFunction.js +76 -0
- package/vendor/quickjs/sandbox/asyncVersion/createAsyncValidateCodeFunction.d.ts +3 -0
- package/vendor/quickjs/sandbox/asyncVersion/createAsyncValidateCodeFunction.js +22 -0
- package/vendor/quickjs/sandbox/asyncVersion/executeAsyncSandboxFunction.d.ts +12 -0
- package/vendor/quickjs/sandbox/asyncVersion/executeAsyncSandboxFunction.js +9 -0
- package/vendor/quickjs/sandbox/asyncVersion/getAsyncModuleLoader.d.ts +4 -0
- package/vendor/quickjs/sandbox/asyncVersion/getAsyncModuleLoader.js +30 -0
- package/vendor/quickjs/sandbox/asyncVersion/modulePathNormalizerAsync.d.ts +2 -0
- package/vendor/quickjs/sandbox/asyncVersion/modulePathNormalizerAsync.js +12 -0
- package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncNodeCompatibility.d.ts +3 -0
- package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncNodeCompatibility.js +11 -0
- package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncSandbox.d.ts +4 -0
- package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncSandbox.js +10 -0
- package/vendor/quickjs/sandbox/expose/expose.d.ts +3 -0
- package/vendor/quickjs/sandbox/expose/expose.js +155 -0
- package/vendor/quickjs/sandbox/expose/isES2015Class.d.ts +1 -0
- package/vendor/quickjs/sandbox/expose/isES2015Class.js +4 -0
- package/vendor/quickjs/sandbox/expose/isObject.d.ts +1 -0
- package/vendor/quickjs/sandbox/expose/isObject.js +4 -0
- package/vendor/quickjs/sandbox/expose/pendingHostPromises.d.ts +6 -0
- package/vendor/quickjs/sandbox/expose/pendingHostPromises.js +40 -0
- package/vendor/quickjs/sandbox/getMaxIntervalAmount.d.ts +8 -0
- package/vendor/quickjs/sandbox/getMaxIntervalAmount.js +12 -0
- package/vendor/quickjs/sandbox/getMaxTimeoutAmount.d.ts +8 -0
- package/vendor/quickjs/sandbox/getMaxTimeoutAmount.js +12 -0
- package/vendor/quickjs/sandbox/handleEvalError.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleEvalError.js +21 -0
- package/vendor/quickjs/sandbox/handleToNative/handleToNative.d.ts +9 -0
- package/vendor/quickjs/sandbox/handleToNative/handleToNative.js +153 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/index.d.ts +10 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/index.js +36 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeArrayBuffer.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeArrayBuffer.js +4 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeBuffer.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeBuffer.js +16 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeDate.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeDate.js +16 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeError.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeError.js +18 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeHeaders.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeHeaders.js +17 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeMap.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeMap.js +18 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeSet.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeSet.js +16 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeURLSearchParams.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeURLSearchParams.js +17 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeUrl.d.ts +2 -0
- package/vendor/quickjs/sandbox/handleToNative/serializer/serializeUrl.js +17 -0
- package/vendor/quickjs/sandbox/helper.d.ts +2 -0
- package/vendor/quickjs/sandbox/helper.js +14 -0
- package/vendor/quickjs/sandbox/provide/provideConsole.d.ts +6 -0
- package/vendor/quickjs/sandbox/provide/provideConsole.js +53 -0
- package/vendor/quickjs/sandbox/provide/provideEnv.d.ts +3 -0
- package/vendor/quickjs/sandbox/provide/provideEnv.js +10 -0
- package/vendor/quickjs/sandbox/provide/provideFs.d.ts +4 -0
- package/vendor/quickjs/sandbox/provide/provideFs.js +159 -0
- package/vendor/quickjs/sandbox/provide/provideHttp.d.ts +9 -0
- package/vendor/quickjs/sandbox/provide/provideHttp.js +42 -0
- package/vendor/quickjs/sandbox/provide/provideTimingFunctions.d.ts +7 -0
- package/vendor/quickjs/sandbox/provide/provideTimingFunctions.js +119 -0
- package/vendor/quickjs/sandbox/setupFileSystem.d.ts +3 -0
- package/vendor/quickjs/sandbox/setupFileSystem.js +13 -0
- package/vendor/quickjs/sandbox/syncVersion/createEvalCodeFunction.d.ts +4 -0
- package/vendor/quickjs/sandbox/syncVersion/createEvalCodeFunction.js +76 -0
- package/vendor/quickjs/sandbox/syncVersion/createValidateCodeFunction.d.ts +3 -0
- package/vendor/quickjs/sandbox/syncVersion/createValidateCodeFunction.js +22 -0
- package/vendor/quickjs/sandbox/syncVersion/executeSandboxFunction.d.ts +12 -0
- package/vendor/quickjs/sandbox/syncVersion/executeSandboxFunction.js +9 -0
- package/vendor/quickjs/sandbox/syncVersion/getModuleLoader.d.ts +4 -0
- package/vendor/quickjs/sandbox/syncVersion/getModuleLoader.js +30 -0
- package/vendor/quickjs/sandbox/syncVersion/modulePathNormalizer.d.ts +2 -0
- package/vendor/quickjs/sandbox/syncVersion/modulePathNormalizer.js +12 -0
- package/vendor/quickjs/sandbox/syncVersion/prepareNodeCompatibility.d.ts +3 -0
- package/vendor/quickjs/sandbox/syncVersion/prepareNodeCompatibility.js +11 -0
- package/vendor/quickjs/sandbox/syncVersion/prepareSandbox.d.ts +4 -0
- package/vendor/quickjs/sandbox/syncVersion/prepareSandbox.js +10 -0
- package/vendor/quickjs/types/CodeFunctionInput.d.ts +12 -0
- package/vendor/quickjs/types/CodeFunctionInput.js +1 -0
- package/vendor/quickjs/types/ErrorResponse.d.ts +9 -0
- package/vendor/quickjs/types/ErrorResponse.js +1 -0
- package/vendor/quickjs/types/LoadQuickJsOptions.d.ts +3 -0
- package/vendor/quickjs/types/LoadQuickJsOptions.js +1 -0
- package/vendor/quickjs/types/OkResponse.d.ts +4 -0
- package/vendor/quickjs/types/OkResponse.js +1 -0
- package/vendor/quickjs/types/OkResponseCheck.d.ts +3 -0
- package/vendor/quickjs/types/OkResponseCheck.js +1 -0
- package/vendor/quickjs/types/Prettify.d.ts +3 -0
- package/vendor/quickjs/types/Prettify.js +1 -0
- package/vendor/quickjs/types/RuntimeOptions.d.ts +87 -0
- package/vendor/quickjs/types/RuntimeOptions.js +1 -0
- package/vendor/quickjs/types/SandboxEvalCode.d.ts +5 -0
- package/vendor/quickjs/types/SandboxEvalCode.js +1 -0
- package/vendor/quickjs/types/SandboxFunction.d.ts +16 -0
- package/vendor/quickjs/types/SandboxFunction.js +1 -0
- package/vendor/quickjs/types/SandboxOptions.d.ts +152 -0
- package/vendor/quickjs/types/SandboxOptions.js +1 -0
- package/vendor/quickjs/types/SandboxValidateCode.d.ts +9 -0
- package/vendor/quickjs/types/SandboxValidateCode.js +1 -0
- package/vendor/quickjs/types/Serializer.d.ts +2 -0
- package/vendor/quickjs/types/Serializer.js +1 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main-thread side of the off-thread QuickJS sandbox.
|
|
3
|
+
*
|
|
4
|
+
* It resolves the worker entry for whichever environment the process is in,
|
|
5
|
+
* keeps a small warm pool, and serves every bridge call the guest makes as an
|
|
6
|
+
* RPC over the port. Cancellation is `worker.terminate()`, immediately: it is
|
|
7
|
+
* equally instant for a spinning guest and a parked one, and the logs and
|
|
8
|
+
* emitted values already live in the main-thread accumulators — port FIFO
|
|
9
|
+
* delivered every RPC the guest made before the abort. The deadline backstop
|
|
10
|
+
* terminates a worker that answers nothing at all.
|
|
11
|
+
*
|
|
12
|
+
* This is the one module in `js-sandbox-worker/` that reaches for Node, and it
|
|
13
|
+
* does so through `importNodeBuiltin`, so importing it off Node resolves
|
|
14
|
+
* nothing and the caller falls back in-process.
|
|
15
|
+
*/
|
|
16
|
+
import { SANDBOX_DISPATCHER_BINDINGS, type HostToWorkerMessage, type ResultMessage, type RunMessage, type WorkerToHostMessage } from "./protocol.js";
|
|
17
|
+
/** Workers alive at once. A fifth concurrent run waits for a free one. */
|
|
18
|
+
export declare const MAX_SANDBOX_WORKERS = 4;
|
|
19
|
+
/** Slack on top of the run's own budget before the backstop fires. */
|
|
20
|
+
export declare const DEADLINE_MARGIN_MS = 5000;
|
|
21
|
+
export type WorkerEntry = {
|
|
22
|
+
/** A compiled entry: hand the file URL straight to `new Worker()`. */
|
|
23
|
+
readonly kind: "file";
|
|
24
|
+
readonly href: string;
|
|
25
|
+
} | {
|
|
26
|
+
/**
|
|
27
|
+
* A TypeScript entry (tsx dev, vitest). The worker starts from an eval'd
|
|
28
|
+
* bootstrap that registers tsx's transform and then imports the entry —
|
|
29
|
+
* tsx's own `--import` hook deliberately skips worker threads, and
|
|
30
|
+
* Node's built-in strip-only loader rejects the syntax the workspace
|
|
31
|
+
* packages use, so the explicit `tsx/esm/api` registration is the one
|
|
32
|
+
* path that works.
|
|
33
|
+
*/
|
|
34
|
+
readonly kind: "bootstrap";
|
|
35
|
+
readonly href: string;
|
|
36
|
+
/** File URL of `tsx/esm/api`, resolved from this package. */
|
|
37
|
+
readonly tsxApiHref: string;
|
|
38
|
+
readonly execArgv: readonly string[];
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* The worker entry for this environment, or `null` when there is none.
|
|
42
|
+
*
|
|
43
|
+
* Three shapes, decided by where this module itself was loaded from:
|
|
44
|
+
*
|
|
45
|
+
* | `import.meta.url` ends in | Entry | Mechanism |
|
|
46
|
+
* |---|---|---|
|
|
47
|
+
* | `.ts` (tsx, vitest) | sibling `worker-entry.ts` | explicit `execArgv` loading tsx |
|
|
48
|
+
* | `.js` (compiled `dist/`) | sibling `worker-entry.js` | plain `new Worker(url)` |
|
|
49
|
+
* | `server.mjs` (esbuild bundle) | `js-sandbox-worker/worker-entry.js` next to it | plain `new Worker(url)` |
|
|
50
|
+
*
|
|
51
|
+
* The `.ts` entry wins whenever this module is a `.ts` file, which is what
|
|
52
|
+
* keeps a stale `dist/` from being loaded under tsx. `execArgv` is passed
|
|
53
|
+
* explicitly rather than inherited: a vitest worker does not necessarily carry
|
|
54
|
+
* the loader flags its parent was started with.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveWorkerEntry(): Promise<WorkerEntry | null>;
|
|
57
|
+
/** The slice of a worker this module uses, so a test can supply a stub. */
|
|
58
|
+
export interface SandboxWorkerHandle {
|
|
59
|
+
postMessage(message: HostToWorkerMessage): void;
|
|
60
|
+
/** Route one message to the active run. Replaces any previous sink. */
|
|
61
|
+
onMessage(handler: (message: WorkerToHostMessage) => void): void;
|
|
62
|
+
/** Called when the thread dies — an `error` event or an unexpected `exit`. */
|
|
63
|
+
onDeath(handler: (error: Error) => void): void;
|
|
64
|
+
terminate(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Hold and release the process for this worker. A leased worker refs, so a
|
|
67
|
+
* run in flight cannot be cut short by the event loop draining; an idle
|
|
68
|
+
* pooled worker unrefs, so a warm pool never keeps the process alive on its
|
|
69
|
+
* own. Optional: a handle with no thread behind it has nothing to manage.
|
|
70
|
+
*/
|
|
71
|
+
ref?(): void;
|
|
72
|
+
unref?(): void;
|
|
73
|
+
}
|
|
74
|
+
export type SandboxWorkerFactory = () => Promise<SandboxWorkerHandle | null>;
|
|
75
|
+
/** Spawn a real `worker_threads` worker at the resolved entry. */
|
|
76
|
+
export declare const defaultSandboxWorkerFactory: SandboxWorkerFactory;
|
|
77
|
+
type Lease = {
|
|
78
|
+
readonly handle: SandboxWorkerHandle;
|
|
79
|
+
/** Return the worker to the pool, or drop it when the thread is gone. */
|
|
80
|
+
release(discard: boolean): void;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Warm workers, one run in flight each.
|
|
84
|
+
*
|
|
85
|
+
* Workers are spawned lazily up to the cap and reused after every run: a fresh
|
|
86
|
+
* QuickJS engine costs a WASM instantiation, so the pool is what keeps a short
|
|
87
|
+
* run short. A worker that was terminated is dropped rather than reused, and
|
|
88
|
+
* the next acquire spawns its replacement.
|
|
89
|
+
*/
|
|
90
|
+
export declare class SandboxWorkerPool {
|
|
91
|
+
private readonly factory;
|
|
92
|
+
private readonly max;
|
|
93
|
+
private readonly idle;
|
|
94
|
+
private readonly waiting;
|
|
95
|
+
private live;
|
|
96
|
+
constructor(factory?: SandboxWorkerFactory, max?: number);
|
|
97
|
+
acquire(): Promise<Lease | null>;
|
|
98
|
+
/** Terminate every idle worker. In-flight runs keep the ones they hold. */
|
|
99
|
+
destroy(): void;
|
|
100
|
+
private take;
|
|
101
|
+
private spawnChain;
|
|
102
|
+
private give;
|
|
103
|
+
}
|
|
104
|
+
/** The process-wide pool. A test passes its own instead. */
|
|
105
|
+
export declare function defaultSandboxWorkerPool(): SandboxWorkerPool;
|
|
106
|
+
export interface RunInWorkerOptions {
|
|
107
|
+
/** The run payload, minus its `type` tag. */
|
|
108
|
+
readonly run: Omit<RunMessage, "type">;
|
|
109
|
+
/**
|
|
110
|
+
* The main-side bridge table an RPC path is looked up in: the same record
|
|
111
|
+
* `deriveBridgeShape` was given, plus the dispatchers and function globals.
|
|
112
|
+
* A path resolves member by member and must land on a function.
|
|
113
|
+
*/
|
|
114
|
+
readonly dispatch: Readonly<Record<string, unknown>>;
|
|
115
|
+
readonly onLog: (line: string) => void;
|
|
116
|
+
readonly onProgress: (percent: number, message?: string) => void;
|
|
117
|
+
readonly signal?: AbortSignal;
|
|
118
|
+
/** Suspended-time credit; pushed to the worker whenever it moves. */
|
|
119
|
+
readonly suspendedMs?: () => number;
|
|
120
|
+
/** Synchronous `stream.open` answer, re-read after every bridge call. */
|
|
121
|
+
readonly isStreamOpen?: (handle: string) => boolean;
|
|
122
|
+
readonly pool?: SandboxWorkerPool;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Run one guest program on a pooled worker and return how it settled.
|
|
126
|
+
*
|
|
127
|
+
* The result is always a `ResultMessage`: the guest's own outcome, a cancelled
|
|
128
|
+
* result synthesized when the abort terminated the thread, or a failed result carrying
|
|
129
|
+
* whatever killed the thread. The caller maps a `failure: "worker"` message
|
|
130
|
+
* through `describeEngineFailure`. Returns `null` when no worker could be
|
|
131
|
+
* acquired at all, which is the caller's signal to run in-process.
|
|
132
|
+
*/
|
|
133
|
+
export declare function runInWorker(options: RunInWorkerOptions): Promise<ResultMessage | null>;
|
|
134
|
+
/** Guest binding names for the dispatchers, re-exported for the caller. */
|
|
135
|
+
export { SANDBOX_DISPATCHER_BINDINGS };
|
|
136
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/js-sandbox-worker/host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main-thread side of the off-thread QuickJS sandbox.
|
|
3
|
+
*
|
|
4
|
+
* It resolves the worker entry for whichever environment the process is in,
|
|
5
|
+
* keeps a small warm pool, and serves every bridge call the guest makes as an
|
|
6
|
+
* RPC over the port. Cancellation is `worker.terminate()`, immediately: it is
|
|
7
|
+
* equally instant for a spinning guest and a parked one, and the logs and
|
|
8
|
+
* emitted values already live in the main-thread accumulators — port FIFO
|
|
9
|
+
* delivered every RPC the guest made before the abort. The deadline backstop
|
|
10
|
+
* terminates a worker that answers nothing at all.
|
|
11
|
+
*
|
|
12
|
+
* This is the one module in `js-sandbox-worker/` that reaches for Node, and it
|
|
13
|
+
* does so through `importNodeBuiltin`, so importing it off Node resolves
|
|
14
|
+
* nothing and the caller falls back in-process.
|
|
15
|
+
*/
|
|
16
|
+
import { createLogger, importNodeBuiltin } from "@nodetool-ai/config";
|
|
17
|
+
import { isWorkerToHostMessage, SANDBOX_DISPATCHER_BINDINGS } from "./protocol.js";
|
|
18
|
+
import { isFunction, isObjectLike } from "../utils/type-guards.js";
|
|
19
|
+
/** Workers alive at once. A fifth concurrent run waits for a free one. */
|
|
20
|
+
export const MAX_SANDBOX_WORKERS = 4;
|
|
21
|
+
/** Slack on top of the run's own budget before the backstop fires. */
|
|
22
|
+
export const DEADLINE_MARGIN_MS = 5_000;
|
|
23
|
+
const log = createLogger("nodetool.agents.sandbox-host");
|
|
24
|
+
const SLOW_WORKER_ACQUIRE_MS = 1_000;
|
|
25
|
+
const SLOW_WORKER_ROUND_TRIP_MS = 1_000;
|
|
26
|
+
/**
|
|
27
|
+
* The worker entry for this environment, or `null` when there is none.
|
|
28
|
+
*
|
|
29
|
+
* Three shapes, decided by where this module itself was loaded from:
|
|
30
|
+
*
|
|
31
|
+
* | `import.meta.url` ends in | Entry | Mechanism |
|
|
32
|
+
* |---|---|---|
|
|
33
|
+
* | `.ts` (tsx, vitest) | sibling `worker-entry.ts` | explicit `execArgv` loading tsx |
|
|
34
|
+
* | `.js` (compiled `dist/`) | sibling `worker-entry.js` | plain `new Worker(url)` |
|
|
35
|
+
* | `server.mjs` (esbuild bundle) | `js-sandbox-worker/worker-entry.js` next to it | plain `new Worker(url)` |
|
|
36
|
+
*
|
|
37
|
+
* The `.ts` entry wins whenever this module is a `.ts` file, which is what
|
|
38
|
+
* keeps a stale `dist/` from being loaded under tsx. `execArgv` is passed
|
|
39
|
+
* explicitly rather than inherited: a vitest worker does not necessarily carry
|
|
40
|
+
* the loader flags its parent was started with.
|
|
41
|
+
*/
|
|
42
|
+
export async function resolveWorkerEntry() {
|
|
43
|
+
const fs = await importNodeBuiltin("node:fs");
|
|
44
|
+
if (fs === null)
|
|
45
|
+
return null;
|
|
46
|
+
const url = await importNodeBuiltin("node:url");
|
|
47
|
+
if (url === null)
|
|
48
|
+
return null;
|
|
49
|
+
const self = import.meta.url;
|
|
50
|
+
const exists = (candidate) => {
|
|
51
|
+
try {
|
|
52
|
+
return fs.existsSync(url.fileURLToPath(candidate));
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
if (self.endsWith("server.mjs")) {
|
|
59
|
+
const bundled = new URL("js-sandbox-worker/worker-entry.js", self);
|
|
60
|
+
return exists(bundled) ? { kind: "file", href: bundled.href } : null;
|
|
61
|
+
}
|
|
62
|
+
if (self.endsWith(".ts")) {
|
|
63
|
+
const source = new URL("worker-entry.ts", self);
|
|
64
|
+
if (!exists(source))
|
|
65
|
+
return null;
|
|
66
|
+
const tsxApiHref = await resolveTsxApi(url);
|
|
67
|
+
if (tsxApiHref === null)
|
|
68
|
+
return null;
|
|
69
|
+
return {
|
|
70
|
+
kind: "bootstrap",
|
|
71
|
+
href: source.href,
|
|
72
|
+
tsxApiHref,
|
|
73
|
+
// `nodetool-dev` is what makes the workspace `exports` maps resolve to
|
|
74
|
+
// source instead of `dist/`, the same condition the dev server runs
|
|
75
|
+
// under. Passed explicitly: a vitest worker does not carry the flags its
|
|
76
|
+
// parent was started with.
|
|
77
|
+
execArgv: ["--conditions=nodetool-dev"]
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const compiled = new URL("worker-entry.js", self);
|
|
81
|
+
return exists(compiled) ? { kind: "file", href: compiled.href } : null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Where `tsx/esm/api` lives, as a file URL.
|
|
85
|
+
*
|
|
86
|
+
* tsx is resolved from this package rather than assumed on the path, and a
|
|
87
|
+
* resolution failure returns `null` so the caller falls back in-process
|
|
88
|
+
* instead of spawning a worker that cannot parse its own entry.
|
|
89
|
+
*/
|
|
90
|
+
async function resolveTsxApi(url) {
|
|
91
|
+
const nodeModule = await importNodeBuiltin("node:module");
|
|
92
|
+
if (nodeModule === null)
|
|
93
|
+
return null;
|
|
94
|
+
try {
|
|
95
|
+
const api = nodeModule.createRequire(import.meta.url).resolve("tsx/esm/api");
|
|
96
|
+
return url.pathToFileURL(api).href;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The eval'd bootstrap for a TypeScript entry. CJS on purpose: an eval worker
|
|
104
|
+
* is CJS, and the two dynamic imports are what carry it into ESM.
|
|
105
|
+
*/
|
|
106
|
+
const TS_BOOTSTRAP = `
|
|
107
|
+
const { workerData } = require("node:worker_threads");
|
|
108
|
+
import(workerData.tsxApiHref)
|
|
109
|
+
.then((tsx) => { tsx.register(); return import(workerData.entryHref); })
|
|
110
|
+
.catch((error) => { throw error; });
|
|
111
|
+
`;
|
|
112
|
+
/** Spawn a real `worker_threads` worker at the resolved entry. */
|
|
113
|
+
export const defaultSandboxWorkerFactory = async () => {
|
|
114
|
+
const threads = await importNodeBuiltin("node:worker_threads");
|
|
115
|
+
if (threads === null)
|
|
116
|
+
return null;
|
|
117
|
+
const entry = await resolveWorkerEntry();
|
|
118
|
+
if (entry === null)
|
|
119
|
+
return null;
|
|
120
|
+
const worker = entry.kind === "file"
|
|
121
|
+
? new threads.Worker(new URL(entry.href), {})
|
|
122
|
+
: new threads.Worker(TS_BOOTSTRAP, {
|
|
123
|
+
eval: true,
|
|
124
|
+
workerData: { tsxApiHref: entry.tsxApiHref, entryHref: entry.href },
|
|
125
|
+
execArgv: [...entry.execArgv]
|
|
126
|
+
});
|
|
127
|
+
let sink;
|
|
128
|
+
let death;
|
|
129
|
+
let dead = false;
|
|
130
|
+
const die = (error) => {
|
|
131
|
+
if (dead)
|
|
132
|
+
return;
|
|
133
|
+
dead = true;
|
|
134
|
+
death?.(error);
|
|
135
|
+
};
|
|
136
|
+
worker.on("message", (raw) => {
|
|
137
|
+
if (isWorkerToHostMessage(raw))
|
|
138
|
+
sink?.(raw);
|
|
139
|
+
});
|
|
140
|
+
worker.on("error", (raw) => {
|
|
141
|
+
const error = raw;
|
|
142
|
+
die(error instanceof Error ? error : new Error(String(error)));
|
|
143
|
+
});
|
|
144
|
+
worker.on("exit", (code) => {
|
|
145
|
+
die(new Error(`the sandbox worker exited with code ${String(code)}`));
|
|
146
|
+
});
|
|
147
|
+
// A pooled worker must never hold the process open on its own — and this has
|
|
148
|
+
// to come *after* the listeners above. Attaching a `message` listener starts
|
|
149
|
+
// the worker's public port, which re-refs it, so unreffing first is silently
|
|
150
|
+
// undone: a CLI run that left a worker pooled then hung until its 45-minute
|
|
151
|
+
// CI job timeout instead of exiting.
|
|
152
|
+
worker.unref();
|
|
153
|
+
return {
|
|
154
|
+
postMessage: (message) => worker.postMessage(message),
|
|
155
|
+
onMessage: (handler) => {
|
|
156
|
+
sink = handler;
|
|
157
|
+
},
|
|
158
|
+
onDeath: (handler) => {
|
|
159
|
+
death = handler;
|
|
160
|
+
if (dead)
|
|
161
|
+
handler(new Error("the sandbox worker is already dead"));
|
|
162
|
+
},
|
|
163
|
+
terminate: () => {
|
|
164
|
+
dead = true;
|
|
165
|
+
void worker.terminate();
|
|
166
|
+
},
|
|
167
|
+
ref: () => worker.ref(),
|
|
168
|
+
unref: () => worker.unref()
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Warm workers, one run in flight each.
|
|
173
|
+
*
|
|
174
|
+
* Workers are spawned lazily up to the cap and reused after every run: a fresh
|
|
175
|
+
* QuickJS engine costs a WASM instantiation, so the pool is what keeps a short
|
|
176
|
+
* run short. A worker that was terminated is dropped rather than reused, and
|
|
177
|
+
* the next acquire spawns its replacement.
|
|
178
|
+
*/
|
|
179
|
+
export class SandboxWorkerPool {
|
|
180
|
+
factory;
|
|
181
|
+
max;
|
|
182
|
+
idle = [];
|
|
183
|
+
waiting = [];
|
|
184
|
+
live = 0;
|
|
185
|
+
constructor(factory = defaultSandboxWorkerFactory, max = MAX_SANDBOX_WORKERS) {
|
|
186
|
+
this.factory = factory;
|
|
187
|
+
this.max = max;
|
|
188
|
+
}
|
|
189
|
+
async acquire() {
|
|
190
|
+
const handle = await this.take();
|
|
191
|
+
if (handle === null)
|
|
192
|
+
return null;
|
|
193
|
+
// Leased: hold the process until the run gives it back.
|
|
194
|
+
handle.ref?.();
|
|
195
|
+
return {
|
|
196
|
+
handle,
|
|
197
|
+
release: (discard) => this.give(handle, discard)
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/** Terminate every idle worker. In-flight runs keep the ones they hold. */
|
|
201
|
+
destroy() {
|
|
202
|
+
while (this.idle.length > 0) {
|
|
203
|
+
const handle = this.idle.pop();
|
|
204
|
+
this.live--;
|
|
205
|
+
handle?.terminate();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
async take() {
|
|
209
|
+
const idle = this.idle.pop();
|
|
210
|
+
if (idle !== undefined)
|
|
211
|
+
return idle;
|
|
212
|
+
if (this.live < this.max) {
|
|
213
|
+
this.live++;
|
|
214
|
+
let handle;
|
|
215
|
+
try {
|
|
216
|
+
// One spawn at a time. A burst of runs would otherwise start several
|
|
217
|
+
// workers in parallel, and under tsx each spawn recompiles the whole
|
|
218
|
+
// sandbox graph — four contending compiles turn a 500 ms warm-up into
|
|
219
|
+
// several seconds. Serialized, the first worker comes up while the
|
|
220
|
+
// rest of the burst queues behind it, then drains at per-run cost.
|
|
221
|
+
this.spawnChain = this.spawnChain
|
|
222
|
+
.catch(() => undefined)
|
|
223
|
+
.then(() => this.factory());
|
|
224
|
+
handle = await this.spawnChain;
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
handle = null;
|
|
228
|
+
}
|
|
229
|
+
if (handle === null)
|
|
230
|
+
this.live--;
|
|
231
|
+
return handle;
|
|
232
|
+
}
|
|
233
|
+
return new Promise((resolve) => {
|
|
234
|
+
this.waiting.push(resolve);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
spawnChain = Promise.resolve(null);
|
|
238
|
+
give(handle, discard) {
|
|
239
|
+
if (discard) {
|
|
240
|
+
this.live--;
|
|
241
|
+
handle.terminate();
|
|
242
|
+
// A waiter must not be stranded behind a worker that no longer exists;
|
|
243
|
+
// wake it so it spawns the replacement itself.
|
|
244
|
+
const waiter = this.waiting.shift();
|
|
245
|
+
if (waiter !== undefined) {
|
|
246
|
+
this.live++;
|
|
247
|
+
void this.factory()
|
|
248
|
+
.then((replacement) => {
|
|
249
|
+
if (replacement === null)
|
|
250
|
+
this.live--;
|
|
251
|
+
waiter(replacement);
|
|
252
|
+
})
|
|
253
|
+
.catch(() => {
|
|
254
|
+
this.live--;
|
|
255
|
+
waiter(null);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const waiter = this.waiting.shift();
|
|
261
|
+
if (waiter !== undefined) {
|
|
262
|
+
// Straight into the next run, so it stays leased and stays ref'd.
|
|
263
|
+
waiter(handle);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
// Idle again: stop holding the process open.
|
|
267
|
+
handle.unref?.();
|
|
268
|
+
this.idle.push(handle);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
let sharedPool;
|
|
272
|
+
/** The process-wide pool. A test passes its own instead. */
|
|
273
|
+
export function defaultSandboxWorkerPool() {
|
|
274
|
+
if (sharedPool === undefined)
|
|
275
|
+
sharedPool = new SandboxWorkerPool();
|
|
276
|
+
return sharedPool;
|
|
277
|
+
}
|
|
278
|
+
function failure(runId, error) {
|
|
279
|
+
return {
|
|
280
|
+
type: "result",
|
|
281
|
+
runId,
|
|
282
|
+
evalOk: false,
|
|
283
|
+
errorName: error instanceof Error ? error.name : "Error",
|
|
284
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
285
|
+
failure: "worker"
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
function cancelled(runId) {
|
|
289
|
+
return {
|
|
290
|
+
type: "result",
|
|
291
|
+
runId,
|
|
292
|
+
evalOk: false,
|
|
293
|
+
errorName: "ExecutionCancelled",
|
|
294
|
+
errorMessage: "Execution cancelled",
|
|
295
|
+
failure: "cancelled"
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Resolve an RPC path against the dispatch table and call it.
|
|
300
|
+
*
|
|
301
|
+
* The path is data from the worker, so every hop is checked: a path that does
|
|
302
|
+
* not land on a function is an error the guest sees, not a host crash.
|
|
303
|
+
*/
|
|
304
|
+
async function dispatchRpc(table, path, args) {
|
|
305
|
+
let current = table;
|
|
306
|
+
for (const segment of path) {
|
|
307
|
+
if (!isObjectLike(current)) {
|
|
308
|
+
throw new Error(`no sandbox bridge at ${path.join(".")}`);
|
|
309
|
+
}
|
|
310
|
+
current = current[segment];
|
|
311
|
+
}
|
|
312
|
+
if (!isFunction(current)) {
|
|
313
|
+
throw new Error(`no sandbox bridge at ${path.join(".")}`);
|
|
314
|
+
}
|
|
315
|
+
return current(...args);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Run one guest program on a pooled worker and return how it settled.
|
|
319
|
+
*
|
|
320
|
+
* The result is always a `ResultMessage`: the guest's own outcome, a cancelled
|
|
321
|
+
* result synthesized when the abort terminated the thread, or a failed result carrying
|
|
322
|
+
* whatever killed the thread. The caller maps a `failure: "worker"` message
|
|
323
|
+
* through `describeEngineFailure`. Returns `null` when no worker could be
|
|
324
|
+
* acquired at all, which is the caller's signal to run in-process.
|
|
325
|
+
*/
|
|
326
|
+
export async function runInWorker(options) {
|
|
327
|
+
const runStartedAt = performance.now();
|
|
328
|
+
const pool = options.pool ?? defaultSandboxWorkerPool();
|
|
329
|
+
const acquireStartedAt = performance.now();
|
|
330
|
+
const lease = await pool.acquire();
|
|
331
|
+
const acquireMs = performance.now() - acquireStartedAt;
|
|
332
|
+
if (acquireMs >= SLOW_WORKER_ACQUIRE_MS) {
|
|
333
|
+
log.warn("Slow sandbox worker acquisition", {
|
|
334
|
+
runId: options.run.runId,
|
|
335
|
+
acquireMs
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
if (lease === null)
|
|
339
|
+
return null;
|
|
340
|
+
const { handle } = lease;
|
|
341
|
+
const runId = options.run.runId;
|
|
342
|
+
const openHandles = Object.keys(options.run.streamOpenSeed ?? {});
|
|
343
|
+
let closed = new Set(openHandles.filter((name) => options.run.streamOpenSeed?.[name] !== true));
|
|
344
|
+
let lastSuspendedMs = 0;
|
|
345
|
+
let settled = false;
|
|
346
|
+
let discard = false;
|
|
347
|
+
let deadlineTimer;
|
|
348
|
+
let abortListener;
|
|
349
|
+
const result = await new Promise((resolve) => {
|
|
350
|
+
const settle = (result, dropWorker) => {
|
|
351
|
+
if (settled)
|
|
352
|
+
return;
|
|
353
|
+
settled = true;
|
|
354
|
+
discard = discard || dropWorker;
|
|
355
|
+
if (deadlineTimer !== undefined)
|
|
356
|
+
clearTimeout(deadlineTimer);
|
|
357
|
+
if (abortListener !== undefined) {
|
|
358
|
+
options.signal?.removeEventListener("abort", abortListener);
|
|
359
|
+
}
|
|
360
|
+
handle.onMessage(() => { });
|
|
361
|
+
handle.onDeath(() => { });
|
|
362
|
+
lease.release(discard);
|
|
363
|
+
resolve(result);
|
|
364
|
+
};
|
|
365
|
+
// Pushes that ride along with every reply: a suspend credit the interrupt
|
|
366
|
+
// handler reads, and the close-only stream mirror. Both land while the
|
|
367
|
+
// guest is parked on the RPC it just made.
|
|
368
|
+
const pushSideChannels = () => {
|
|
369
|
+
if (settled)
|
|
370
|
+
return;
|
|
371
|
+
if (options.suspendedMs !== undefined) {
|
|
372
|
+
const suspendedMs = options.suspendedMs();
|
|
373
|
+
if (suspendedMs !== lastSuspendedMs) {
|
|
374
|
+
lastSuspendedMs = suspendedMs;
|
|
375
|
+
handle.postMessage({ type: "suspend-update", runId, suspendedMs });
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
if (options.isStreamOpen !== undefined) {
|
|
379
|
+
for (const name of openHandles) {
|
|
380
|
+
if (closed.has(name) || options.isStreamOpen(name))
|
|
381
|
+
continue;
|
|
382
|
+
closed = new Set([...closed, name]);
|
|
383
|
+
handle.postMessage({ type: "stream-closed", runId, handle: name });
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
handle.onDeath((error) => settle(failure(runId, error), true));
|
|
388
|
+
handle.onMessage((message) => {
|
|
389
|
+
if (settled)
|
|
390
|
+
return;
|
|
391
|
+
switch (message.type) {
|
|
392
|
+
case "log":
|
|
393
|
+
options.onLog(message.line);
|
|
394
|
+
return;
|
|
395
|
+
case "progress":
|
|
396
|
+
options.onProgress(message.percent, message.message);
|
|
397
|
+
return;
|
|
398
|
+
case "result":
|
|
399
|
+
settle(message, message.failure === "worker");
|
|
400
|
+
return;
|
|
401
|
+
case "rpc": {
|
|
402
|
+
const { id, path, args } = message;
|
|
403
|
+
void (async () => {
|
|
404
|
+
try {
|
|
405
|
+
const value = await dispatchRpc(options.dispatch, path, args);
|
|
406
|
+
if (settled)
|
|
407
|
+
return;
|
|
408
|
+
handle.postMessage({ type: "rpc-reply", id, ok: true, value });
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
if (settled)
|
|
412
|
+
return;
|
|
413
|
+
handle.postMessage({
|
|
414
|
+
type: "rpc-reply",
|
|
415
|
+
id,
|
|
416
|
+
ok: false,
|
|
417
|
+
name: error instanceof Error ? error.name : "Error",
|
|
418
|
+
message: error instanceof Error ? error.message : String(error)
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
pushSideChannels();
|
|
422
|
+
})();
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
if (options.signal !== undefined) {
|
|
427
|
+
abortListener = () => {
|
|
428
|
+
if (settled)
|
|
429
|
+
return;
|
|
430
|
+
// Kill the thread. Nothing gentler is worth having: the logs and
|
|
431
|
+
// emitted values already live in the main-thread accumulators (port
|
|
432
|
+
// FIFO delivered every RPC the guest made before this), a cancelled
|
|
433
|
+
// action leaving no partial `state` mutation is the cleaner contract,
|
|
434
|
+
// and `terminate()` is equally instant for a guest that spins and one
|
|
435
|
+
// that awaits. The pool replaces the worker lazily.
|
|
436
|
+
settle(cancelled(runId), true);
|
|
437
|
+
};
|
|
438
|
+
if (options.signal.aborted) {
|
|
439
|
+
abortListener();
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
options.signal.addEventListener("abort", abortListener, { once: true });
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
// Backstop for a worker that answers nothing at all — a wedged thread never
|
|
446
|
+
// reaches its own deadline, so the main thread keeps one of its own.
|
|
447
|
+
//
|
|
448
|
+
// The suspend allowance only widens it when the run can actually suspend,
|
|
449
|
+
// the way the engine's own abort is sized in `js-sandbox.ts` and
|
|
450
|
+
// `interpreter.ts`. Adding it unconditionally put a ~30 minute floor
|
|
451
|
+
// (`DEFAULT_SUSPEND_ALLOWANCE_MS`) under every run, so a wedged worker —
|
|
452
|
+
// a guest that OOMs marshaling a host value, say — outlived its
|
|
453
|
+
// `timeoutMs` by half an hour instead of failing.
|
|
454
|
+
const backstop = options.run.timeoutMs +
|
|
455
|
+
(options.run.hasClock ? Math.max(0, options.run.suspendAllowanceMs) : 0) +
|
|
456
|
+
DEADLINE_MARGIN_MS;
|
|
457
|
+
deadlineTimer = setTimeout(() => {
|
|
458
|
+
settle(failure(runId, new Error(`the sandbox worker did not answer within ${backstop} ms and was terminated`)), true);
|
|
459
|
+
}, backstop);
|
|
460
|
+
try {
|
|
461
|
+
handle.postMessage({ type: "run", ...options.run });
|
|
462
|
+
}
|
|
463
|
+
catch (error) {
|
|
464
|
+
// A `DataCloneError` here is the pre-scan having missed something; the
|
|
465
|
+
// worker never started, so the thread is still reusable.
|
|
466
|
+
settle(failure(runId, error), false);
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
const totalMs = performance.now() - runStartedAt;
|
|
470
|
+
if (totalMs >= SLOW_WORKER_ROUND_TRIP_MS) {
|
|
471
|
+
log.warn("Slow sandbox worker round trip", {
|
|
472
|
+
runId,
|
|
473
|
+
acquireMs,
|
|
474
|
+
workerRoundTripMs: Math.max(0, totalMs - acquireMs),
|
|
475
|
+
totalMs
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
return result;
|
|
479
|
+
}
|
|
480
|
+
/** Guest binding names for the dispatchers, re-exported for the caller. */
|
|
481
|
+
export { SANDBOX_DISPATCHER_BINDINGS };
|
|
482
|
+
//# sourceMappingURL=host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/js-sandbox-worker/host.ts"],"names":[],"mappings":"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"}
|