Add opt-in Tier-0 no-eval compiled validation fast path - #36
Merged
Conversation
safeParseCompiled compiles a schema into a closure tree at construction time (no eval / no new Function / no codegen), so it runs where JIT tiers cannot: strict-CSP pages and edge runtimes (Cloudflare Workers, Deno Deploy, Vercel Edge). It removes the interpreter's megamorphic per-node dispatch and per-value dataset allocation, winning ~1.1-2.4x on container schemas across both V8 and JSC, while staying byte-identical to safeParse on success and error paths. The interpreter remains the SSoT; this is an opt-in parallel path. Piped, async, and non-specialized nodes fall back to ~run (defense-in-depth against an accept-invalid bypass), an invariant locked by a test. A bare top-level primitive should use safeParse directly (documented entry overhead). - packages/tskm/src/compile.ts: closure compiler, getCompiledValidate (WeakMap keyed off the schema value), safeParseCompiled - packages/tskm/src/index.ts: opt-in exports - packages/tskm/test/compile.test.ts: byte-identical conformance + piped/refined child bypass guards + fast-path-only-for-bare-leaf invariant (Stryker oracle) - bench/validator: full-materializing per-fixture sink, no-regression gate, 30-schema interleaved shared-IC guard (zero V8 deopts) - test/workerd/smoke.ts: no-eval property proven by execution under node --disallow-code-generation-from-strings Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
commit: |
The compiled validator specialized schemas by their public `type` string, so a foreign schema with a colliding `type` (e.g. "string"), no pipe and a stricter `~run` was specialized and had its `~run` bypassed, accepting input the interpreter rejects. Dispatch on factory identity (`schema.reference`) instead in both `compile()` and `primitiveCode()`; non-native schemas fall back to their own `~run`. Document the `reference` trust boundary and pin the routing with a type-string collision battery plus a contract test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
compile.ts was auto-included in the mutation `mutate` set, but the existing tests only covered the security-critical routing, leaving its specialized walkers at ~39% and dragging the package under the 80% break threshold (70.85%). Add a comprehensive interpreter-parity battery (`toStrictEqual` vs the interpreter as a differential oracle) covering every specialized path: the 3/5-key strip unrolls, the wide/general primitive object, the array item-inline codes, faithful-optional drop and defaults, rest modes, declared `__proto__`, the abort knobs, per-slot type-order permutations, and custom-message branches. Package score 70.85 -> 83.58. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an opt-in Tier-0 no-eval compiled validation fast path (
safeParseCompiled/getCompiledValidate). It compiles a schema into a closure tree at construction time — noeval, nonew Function, no codegen — so it runs where JIT tiers cannot: strict-CSP pages and edge runtimes (Cloudflare Workers, Deno Deploy, Vercel Edge). It removes the interpreter's megamorphic per-node dispatch and per-value dataset allocation.The interpreter stays the source of truth; this is an opt-in parallel path. Piped, async, and non-specialized nodes fall back to
~run, byte-identical tosafeParseon success and error paths.Performance vs interpreter (full-materializing per-fixture sink, median of 5)
Bare top-level primitives are a documented non-target (use
safeParsedirectly). A 30-schema interleaved shared-IC guard shows zero V8 deopts and no regression on either engine.Edge / CSP
Proven by execution (not by grep) under
node --disallow-code-generation-from-strings— the same constraint Cloudflare Workers enforce. The compiled validator builds and runs with zeroeval/Function. Seetest/workerd/smoke.ts.Conformance
packages/tskm/test/compile.test.tsasserts byte-identical results (toStrictEqual) on success AND error paths, including piped-child-in-container cases that guard against an accept-invalid bypass, plus a fast-path-only-for-bare-leaf invariant. It doubles as a Stryker oracle (verified it kills the bypass mutant).Notes
evaltier (the higher ceiling) is intentionally out of scope (Tier-0 only).main.🤖 Generated with Claude Code