/** * TS emitter leg — Phase 1 PR-3a. * * Wires `runTsEmitter` against the production TS codegen * (`emitNativeKernBodyTS`). The flow: * * 1. Lower fixture-only IR (`__trace`, `return`, `throw`) into KERN-native * shapes via [[lowerFixtureToKernIR]]. Production emitters know nothing * about fixture probes. * 2. Wrap the lowered IR in a synthetic `handler lang="kern"` so the * body-statement code path is exercised. * 3. Run `emitNativeKernBodyTS` with `traceHooks.eachIterNext: true` — * a narrowly scoped opt-in flag that injects a `__kernTrace(...)` call * at the canonical event location (after destructuring, before body). * 4. Wrap the emitted body in a `try` that catches two sentinel error * classes — `__KernReturn` and `__KernThrow` — converting them to * `CompletionRecord`s. A normal fall-through is `{kind:'normal'}`. * 5. Execute in a fresh `vm.Context`. Bindings from `env.bindings` are * injected as globals. The trace sink (`__kernTrace`) and sentinel * classes are also globals. * 6. Return the observed [[Trace]] for comparison against the reference. * * Scoping discipline (per agon brainstorm constraint): trace-hook injection * stays limited to `each`. Generalising the hook surface is an explicit * spec revision, not a creep. */ import type { IRNode } from '../../types.js'; import type { SemanticEnv } from './index.js'; import type { Trace } from './trace.js'; interface FixtureForLeg { ir: IRNode; } /** * TS-target lowering — wraps the shared target-aware lowering. * Kept exported under the original name so existing tests + the harness * stay backward-compatible. */ export declare function lowerFixtureToKernIR(node: IRNode): IRNode; /** * Best-effort error-name extraction for vm-context throws. `err instanceof * Error` is unreliable across the vm boundary (the inner realm has its * own `Error` prototype), so we fall back to a duck-typed property check. */ declare function canonicalizeErrorName(err: unknown): string; /** * Run the TS leg of the differential harness. PR-3a entry point. * * Always uses an `async` wrapper IIFE so emitted `for await (...)` syntax * compiles. Sync fixtures pay no runtime cost; the wrapper resolves * immediately. The reference runner stays sync — async semantics in our * spec are observably identical to sync, so we await once at the boundary. * * Error model: ONLY the `__KernReturn`/`__KernThrow` sentinels — which are * caught inside the IIFE and resolved as proper [[CompletionRecord]]s — * count as fixture-comparable throws. Any error that escapes the IIFE * (emitter bug, SyntaxError from malformed emitted code, hung async, * unexpected runtime exception) is RE-THROWN from this function so the * harness records it as `leg-error`, NOT as a fixture-comparable * completion. The previous "swallow everything" pattern made emitter * regressions falsely pass. * * Timeout: a second explicit `Promise.race` deadline covers async paths * that `vm.runInContext`'s sync-only timeout can't see (e.g. `for await` * over a never-resolving iterator). A timeout escalates to `leg-error` * via a re-thrown TsLegTimeoutError. * * @throws TsLegError / TsLegTimeoutError when the leg itself cannot * report a meaningful trace. The harness translates these into * `leg-error` verdicts. */ export declare function runTsEmitterLeg(fixture: FixtureForLeg, env: SemanticEnv): Promise; export declare class TsLegError extends Error { constructor(message: string); } export declare class TsLegTimeoutError extends TsLegError { constructor(ms: number); } export { canonicalizeErrorName };