Repository navigation
0.20.1 — The types tell the truth: passes on every target
Patch release: the declared types now tell the truth on every target.
Fixed: passes is returned everywhere the type declares it
RenderHtmlResult.passes (the layout-pass count) was declared in @formepdf/html's types but returned by only one of the six result constructions — node renderHtml. The browser and worker entries, and renderHtmlWithLayout on all three targets, returned undefined while type-checking fine. Found building a Cloudflare Workers template against the published package.
The hole went three layers down: three hand-written per-target result objects (one updated when passes was added), a WASM binding that never carried the field on the layout path, and the engine computing the value in render_with_layout and discarding it. All three layers are fixed, and the structure that allowed the drift is gone:
- One shared construction (
result.js) now builds every result object for all three entries — a new field is added in exactly one place. - Declared type ↔ runtime shape is enforced in both directions: the expected key sets are derived from
keyof RenderHtmlResult(a type change that the runtime doesn't match failsnpm test's typecheck), and per-target tests assert the exact key set in the real runtime — plain Node, real workerd via@cloudflare/vitest-pool-workers, and real headless Chromium. - Fails-first was demonstrated against the registry: the published 0.20.0 layout path fails the new shape test.
Engine
- New
render_with_layout_and_passes()—render_with_layout()unchanged (now a thin wrapper).
Output is byte-identical to 0.20.0 across the fixture wall, the cross-target determinism gate, and the 15-template compat corpus (zero warnings-baseline diff). All packages in lockstep at 0.20.1: npm (@formepdf/*), crates.io (forme-pdf), PyPI (formepdf), Go (v0.20.1).