Readiness and check()
Readiness holds frame 0 until the fonts, images, media and queries a composition uses have loaded, and it reports each failure by code.
check() seeks a sample of frames twice and compares them.
await wildflower.kinetic.ready() runs readiness for your own code, and check() and render() each begin with the same run.
check() reports the first frame that differs between two passes, an error during its seeks, or a failed readiness.
A passing check() does not see a binding that shows nothing or a list with no rows, so look at the frames too.
Readiness
Kinetic reports ready, and registers window.__hf.buildReady.kinetic for a renderer that waits on it, once all of these are true.
- The document has fired
DOMContentLoaded, so every deferred and module script has registered its scenes. - The framework's first scan is done.
- The fonts are loaded.
- Every query a scene lists in
waitForhas its first rows. - Every
<img>under a scene, and every SVG<image>under the composition root (lottie-web's svg renderer draws these), has decoded. A failed decode does not hold the render, and one still loading after 30 s fails the run (KN-182). - Every audio clip's file has decoded and the level tables are built.
- Every footage clip has its metadata and first frame and, without the runtime, is on its frame for the clock's time. The runtime plays media itself, so with it on the page this is not waited for.
- Every map of a luma transition is drawn or fetched, and every
<img>source of an effect has decoded. - Every animation handed to lottie() has loaded, and every animated image has decoded.
- Every
<img>and<iframe>in the composition withloading="lazy"is set toloading="eager", since Chrome does not load a lazy one inside a hidden clip, which is clipped to nothing, until the clip shows. Only the images under a scene are waited for.
await wildflower.kinetic.ready() runs the same checks for your own code on the page as it is then, fetching again a file that failed before.
It rejects with the first failure to come (Failure), and check() and render() each begin with the same run.
Readiness runs by itself once, at load. A page that adds or replaces its composition root after that calls ready() once the new root is in the page, which reads its size, duration and fps and waits for what it uses.
try {
await wildflower.kinetic.ready();
} catch (err) {
// err.code is 'KN-131', err.where is "scene 'sales-chart' waits for query 'sales'"
}
After the first frame, the run waits for a waitFor query that is loading again and fails on one that a refresh left in error (KN-131).
A query refreshed while you work holds or fails check() and render() until it has its rows again.
Failure
Each failure prints a console error in every build and the first one rejects ready().
- KN-117, a
lumatransition's map that failed to load or decode. - KN-130, an input that is missing, of the wrong type or rejected by its validator.
- KN-131, a
waitForquery that ended in an error. - KN-133, a
waitForname that matches no query. - KN-135, an audio clip whose file failed to load or decode.
- KN-138, a footage clip whose file failed to load or decode, or one with no source; also, during
check()orrender(), a clip whose seek has not landed in 30 s. - KN-180, a Lottie animation that fired
data_failed. - KN-181, an animated image whose file could not be fetched or decoded.
- KN-182, an image under a scene still loading after 30 s.
data-kinetic-ready is still set, to failed, so the page shows.
KN-180 and KN-181 are printed as they happen, also after the first frame.
Each run on its own
Readiness keeps nothing from one run to the next.
The registered entry, ready(), and the start of each check() and render() are separate runs, so check() fails with reason: 'readiness failed' exactly when render() rejects, with the same error, before it touches the page.
- A run counts a bad input or a failed
waitForin any one scene on the page, and the audio clips, whichrender({ audio: false })still loads. - Each run looks at the page as it is then. A map, an animated image, or a footage or audio clip's file that failed is fetched again, so one put on the server since passes.
- Only the clips, scenes and queries on the page count, so a footage or audio clip removed or given a file that loads, a removed scene, a Lottie animation handed back and a query loaded since fail nothing more.
- An animated image made in a scene's
init()counts while that scene is on the page, and one made anywhere else counts for good. - An error without a KN code, one the browser threw, fails a run the same way.
data-kinetic-ready and the registered entry
The root's data-kinetic-ready follows each run, back to true once one passes.
With the HyperFrames runtime on the page, true waits for the runtime's __renderReady (Rendering through HyperFrames).
- A failure outside a run, such as a Lottie animation or animated image made later, or a scene mounted later whose input fails, sets
data-kinetic-readytofaileduntil the next run. - A failure during the seeks of
check()or the frames ofrender(), such as a scene a section mounts partway, fails that call. - Each failure is printed once while it lasts, each Lottie animation on its own, and again if it comes back after its source has passed.
The registered entry never rejects.
On a failure it stays unsettled, so a renderer that waits on it stops at its readiness timeout with the [KN-117], [KN-13x] or [KN-18x] error in its console output.
Development builds also warn about a waitFor query back to loading after frame 0, from a refresh interval or an invalidate() (KN-132), and about waitFor on a tier with no queries (KN-101).
check(options)
check() is the render self-test.
It seeks a shuffled sample of frames, always with the first and the last, seeks them again in reverse order, and compares what the composition root held each time.
- The comparison covers every element's text, inline style, class list, hidden state and other attributes (an SVG path's
d, aviewBox), each animation's position and play state, a hash of each 2-D canvas, and each footage clip'scurrentTime, the time it was sought to. - It begins with a run of readiness, as
render()does, so the footage and the audio clips load first. - It counts the errors printed or thrown while it seeks.
- Seeks go through the runtime's player and its barrier when one is on the page, and through the clock otherwise.
- A playing clock is paused for the call, then its time is restored and it plays on.
const report = await wildflower.kinetic.check({ samples: 30 });
// { ok: true, frames: 180, samples: 30, ready: 'true', errors: 0 }
// { ok: false, reason: 'readiness failed', code: 'KN-117', where: "the map url(wipe.png) of div#intro's data-clip-enter",
// frames: 180, samples: 30, ready: 'failed', errors: 0 }
// { ok: false, reason: 'a seek threw', frames: 180, samples: 30, ready: 'true',
// errors: 60, firstError: "[WildflowerJS] Error in computed property 'bar': ..." }
// { ok: false, frame: 41, time: 1.3667, element: 'ol > li:nth-child(3)',
// property: 'style', first: 'width: 212px;', second: 'width: 230px;',
// ready: 'true', errors: 0 }
samplesis the number of frames to compare, 1 or more, and defaults to 30. A fraction is rounded up, and a number above the composition's frames compares every frame.seedpicks the sample, as a number or a string, and defaults to 1.
The report
Every report has ready, the root's data-kinetic-ready value after the seeks ('true' or 'failed'), and errors, the count of console.error calls, uncaught errors and unhandled rejections during the seeks.
A passing report adds the composition's frames and the samples compared, and a failing one reports the first row of this table that applies.
| Failure | Report |
|---|---|
| The run of readiness failed, or a readiness failure was reported during the seeks, such as a scene a section mounts partway whose input fails. | reason: 'readiness failed', with the failure's code and where (the part of its message after the code) in every build, since render() would reject with that failure (Failure). |
| An error was printed or thrown during the seeks, such as a computed that throws. | reason: 'a seek threw', and firstError holds the first message. |
| A frame differs. | The first such frame in time order, with element as a selector, property as one of text, style, class, hidden, attrs, animations, canvas, currentTime or elements (the count of elements), and the first and second values. |
- Class tokens, style declarations and attributes are compared in sorted order, since a binding changes them one at a time and their order follows what the element held before. A report shows them in the element's order.
- Development builds also warn (KN-160) for each failure.
- The call throws without a composition root or a duration (KN-100).
A passing check() means each sampled frame is the same on every seek, with no error and no failed readiness.
It does not see a binding that shows nothing, a list with no rows, or a scene that never registered, which look the same on every seek, so look at the frames too.
A WebGL canvas without preserveDrawingBuffer reads back blank in both passes, so it cannot fail here.