| name | engine-call-contract |
| description | How every call into the text engine is shaped, and where each entry point's names live. Use before adding, moving, or removing anything on a published surface, before adding an error path or a result type to an engine call, and when deciding whether a failure belongs to the caller or to this package. |
The engine call contract
Two rules decide almost every API question in this package. Both were arrived at by getting them wrong first.
A call answers, or it throws where it was written
An engine call is synchronous and takes no resource that could be missing: a font is required at construction,
text and spans are validated there, and constraints are checked by the call itself. Nothing is left to wait for and
nothing is left for a caller to get wrong, so there is no failure to hand back.
- Return the answer.
layout() returns metrics. glyphs() returns the inspection. No { ok } union, no
nullable, no out-of-band error to consult afterwards.
- Throw for input the language let them express but which has no meaning.
{ mode: 'at-most', size: NaN } is
well-typed and means nothing; there is no width it could stand for, so there is nothing to return, clamp, or
guess. Throw from the call, name the axis or the span or the offset, and let the stack point at the caller.
Silently accepting it turns a wiring bug into wrong text on screen, which is worse than an exception.
- Never return or proactively scan for a failure the caller cannot cause. A result union for an engine defect makes every caller write
if (result.ok) forever -- inside a flexbox measure callback, many times per layout -- to guard a branch that
only means this package is broken. A deep runtime validator adds the same ceremony inside Glyph. Prove package-owned
invariants at their producer; if corruption is encountered naturally, let the operation throw.
- Never enter a broken state that outlives the call. A rejected frame must not leave the engine refusing work,
recompiling an invalid frame at frame rate, or holding a latch a caller has to clear. Report once, stop, and keep
the rest of the scene live: transforms, visibility, and render order belong to the last accepted publication and
never entered the frame that was refused.