Skip to content

Interface: ValidationRegistry

API / @xmachines/play-dom / ValidationRegistry

Defined in: @xmachines/json-render-dom

Registry of validated fields for one rendered tree.

Properties

PropertyModifierTypeDescriptionDefined in
clearpublic(path) => voidForget a field’s recorded state; the registration itself survives.-
customFunctionsreadonlyRecord<string, ValidationFunction>Custom validation functions available to every check.-
dropReleased?public() => voidEnd a pass. The registry forgets the state of each field whose last registration went away and that did not register again. It also forgets the state of a field that only new owners hold now: an element that goes and another element that registers the path in the same pass start the field fresh, as in the framework renderers, whatever the order of the two. What a new owner wrote in the pass stays, as if the field started fresh at the change: a touch of the new owner gives no result of the old one. A write of the old owner in the pass goes. An owner that registers again in place keeps the state. The fresh start comes when the pass ends. A component of the new element that reads fieldStates while it renders in that pass still reads the state of the old element. The incremental renderer then renders it again (see onFreshPaths), as React renders it again after the unmount of the old one. A caller that does not mark its passes with startPass calls it when a pass ends, for example a host that renders with renderSpec alone on a registry of its own. The incremental renderer and a host that uses startPass end a pass with the function that startPass returns, and not with this. The registry counts the passes by these calls, or by startPass: an owner that came to the path in an earlier pass is an owner from before the pass. Without the calls, no owner is from before, and the state of a field stays with its path.-
fieldStatesreadonlyReadonly<Record<string, ReadonlyFieldValidationState>>Validation state by field state path. The registry gives the same object until a state changes, as the state of react does. The object and each state in it are shared by every reader, so they are read-only at each level: the registry of this package freezes the object, each state, and the result of each state with its errors and its checks.-
onFreshPaths?public(listener) => () => voidCall listener with the paths whose state changed: a pass that started a field fresh for a new element that took over the path, or a write of the state, such as a touch or a validateAll. Each renderer of the registry renders the elements that hold such a path again, so they show the state of now, as React renders a component again when the state of its provider changes. A write in a pass reaches the listeners when the pass ends, and a write between two passes at once. The writes of one validateAll reach them together. The registry calls the listeners after the outermost pass ends, and it holds each one weakly: the caller keeps its listener while it needs the calls. An error of a listener goes to reportError, and the other listeners still run. Returns the function that stops the calls.-
registerFieldpublic(path, config, owner?) => voidRegister (or update) a field’s validation config. Called by component implementations during render, normally via ctx.validation. Registrations are reference-counted per path: two elements bound to the same state path each hold one, so one of them going away does not un-validate the other. owner names the element instance that registers. For a registration through ctx.validation, the renderer gives the element, its type, its repeat rows, the keys and the types of the elements above it, and the named slot that holds it. Registrations that name no owner count as one owner. See ValidationRegistry.dropReleased for what it changes.-
releaseFieldpublic(path, owner?) => voidDrop one reference to a field’s registration. The registration goes away once the last reference is released, and ValidationRegistry.dropReleased forgets its state, unless the field registers again first. Until then fieldStates keeps the state, so an element that renders before the field in the same pass still reads it. This is what the render context’s per-element cleanup calls: an element instance releases its registrations when it unmounts or before it re-renders. An element that renders again in place registers again in the same pass, so its state survives — matching the framework ValidationProvider, whose field states outlive a re-render and go at the last unregister. owner is the owner that ValidationRegistry.registerField got.-
startPass?public(options?) => () => voidStart a pass, and return the function that ends it. The incremental renderer calls it before each pass, and a host that renders with renderSpec before its render. A pass of a renderer that starts inside a pass ends with the outer one. A pass of the host that starts inside a pass commits the passes that run when it ends, as react commits a nested flushSync when it returns, and a call of the host after it sees that commit. An owner that comes to a path between two passes, for example through a late read of the children of a component, then comes before the next pass. A caller that does not call it ends and counts each pass with dropReleased alone, and inside a pass dropReleased does nothing. All the callers of one registry follow the same rule: after the first startPass, dropReleased does nothing, and the registry warns one time. An outermost pass that starts before the join of the outermost pass before it ends joins that pass, as react joins the updates of one commit. The batch of the pass before sets how long its join lasts (see PassOptions): to the next microtask for a store write, and to the end of the task, also after an await, for a new spec. A write of a field state, a clear, or a field that registers between the two passes ends the join. A write of a field state or a clear before the commit point of a store write does not: it is part of that commit (see the pass of a store write below). The renderers of one registry that react to one write of the store, or that a host hands new specs in one task, then run one pass. A field that moves from one renderer to the other starts fresh, whatever the order of the two. A pass that a handler of a pass queued is a new pass, as an update that a commit schedules is a new commit: its caller gives join: false. The incremental renderer marks the pass of a store write and the pass of a new spec. React commits a store write and a new spec after the handler that gives them, so the registry holds the effects of such a pass on the fields, a release, a new config and a fresh start, until its commit point: the next microtask, the next pass that does not join it, the bindings of a watch, or a field that registers between two passes. The commit point of a store write ends the join, so a pass after it starts a new commit. The commit point of a new spec keeps the join to the end of the task (see PassOptions). The renderer shows the store writes of the task at the commit point, in one render, as react renders the writes of one handler in one render. The commit point then does the work of the commit, it runs the effects that the components of the commit gave ctx.effect and the checks of the watches, and it renders the holders of the commit again, before its microtask ends. React ends the commit of a synchronous update in its microtask in the same way: it runs the effects of the commit before the renders that its layout effects start. The checks of the watches run after the effects, as react runs the effect of a child before the watch of its parent. The watches of one change see one commit. Their writes and the writes of those effects make one commit after them, and the commit point shows its store writes before its microtask ends, as react renders a store write of an effect at the end of the flush of the effects. A watch compares the store of its commit, from before the effects: when an effect writes a watched path, the watch sees the change at the commit point of that write. A touch, a validate, a clear or a validateAll before the commit point sees the fields of before the write, as in react. A write of a field state between two passes renders the holders of its path, and the registry holds the effects of that render in the same way. The incremental renderer renders them at the commit point when a store write of it waits, in the one render of its store writes, as react renders them after the handler. A render of a holder for its new config, which the end of such a pass starts, waits with it. The end of a pass of the host shows the store writes that wait, as flushSync of react renders the updates that wait, and it commits them with the passes that it joins. A call of the host inside such a pass sees the fields of the last commit, as a call inside the callback of flushSync of react does. This also holds after a store write before the pass: the end of the pass shows and commits that write too. The end of a pass of the host then runs the effects of its commit, as flushSync of react does: the effects that the components of the incremental renderer gave ctx.effect, also in a render before the pass, and then the checks of the watches. It commits their writes, and it runs the effects of those writes in the same way. The end of an outermost pass of the host ends its join, so a later pass starts a new commit.-
touchpublic(path, owner?) => voidMark a field as interacted with, without validating it. owner names the element that touches it, as for registerField.-
unregisterFieldpublic(path) => voidDrop a field’s registration entirely, references and recorded state.-
validatepublic(path, config?, owner?) => ReadonlyValidationResultValidate one field against the live store snapshot and record the result. Uses the field’s registered config unless one is passed explicitly. owner names the element that validates, as for registerField. The result is the result of the state of the field, which every reader of fieldStates shares, so it is read-only at each level: the registry of this package freezes it.-
validateAllpublic() => booleanValidate every registered field. Returns true when all are valid. The listeners of onFreshPaths hear of the new states one time, when the last field is validated, so no holder renders in the loop.-