Initial Commit
This commit is contained in:
66
packages/devtools/tooling/sandbox/src/spawn-engine/runner.md
Normal file
66
packages/devtools/tooling/sandbox/src/spawn-engine/runner.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Runner (spawn-engine child entry)
|
||||
|
||||
## Purpose
|
||||
|
||||
`runner.ts` is the child-process entry point invoked by `SpawnEngine`. The parent process spawns it via `node:child_process.spawn`, writes a JSON `RunnerInput` envelope to its stdin (closing the pipe to signal end-of-input), and reads a JSON `RunnerOutput` envelope from its stdout. The runner runs inside a fresh OS process with a sanitised environment — that process boundary is the security guarantee, not anything the runner itself does.
|
||||
|
||||
The runner exports `runRunner(input)` as a pure function so the parent can also test the evaluation pipeline without spawning a child. The `main()` entry point reads stdin, parses JSON, calls `runRunner`, and writes stdout — exposed for tests that want to drive the full I/O surface.
|
||||
|
||||
## Features
|
||||
|
||||
- Pure `runRunner(input): RunnerOutput` for in-process testing.
|
||||
- `readStdinAll()` async stdin slurper.
|
||||
- `main()` orchestrator.
|
||||
- Auto-invokes `main()` when the file is launched directly (matched by
|
||||
filename ending in `runner.{js,ts,cjs,mjs}`).
|
||||
- `stringify(value)` JSON-safe fallback used by the captured console.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
The runner is normally invoked by `SpawnEngine`; consumers do not call it
|
||||
directly. To test in isolation:
|
||||
|
||||
```ts
|
||||
import { runRunner } from "@suaveplan/sandbox/runner";
|
||||
|
||||
const out = runRunner({
|
||||
code: "1 + 1",
|
||||
context: {},
|
||||
modules: [],
|
||||
maxOutputSize: 1024,
|
||||
});
|
||||
console.log(out.result); // 2
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Drive the full stdin/stdout pipeline against the runner file by spawning a
|
||||
real child:
|
||||
|
||||
```ts
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
const child = spawn(process.execPath, ["./dist/spawn-engine/runner.js"], {
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
});
|
||||
child.stdin.write(JSON.stringify({ code: "1 + 1", context: {}, modules: [], maxOutputSize: 1024 }));
|
||||
child.stdin.end();
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `RunnerInput` — `{ code, context, modules, maxOutputSize }`.
|
||||
- `RunnerOutput` — `{ success, result, error, logs, memoryUsed }`.
|
||||
- `runRunner(input: RunnerInput): RunnerOutput`.
|
||||
- `readStdinAll(): Promise<string>`.
|
||||
- `main(): Promise<void>`.
|
||||
- `stringify(value: unknown): string`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The runner builds a function scope via
|
||||
`Reflect.construct(Function, [...keys, source])` — this is the controlled
|
||||
boundary the runner owns; the parent is the one that decides whether to
|
||||
spawn it. Strict mode is enforced via the prologue. The
|
||||
auto-invoke guard checks `process.argv[1]` against a filename regex so
|
||||
re-importing the runner from a test never triggers the main loop.
|
||||
Reference in New Issue
Block a user