Conversation
lfkdsk
marked this pull request as ready for review
September 14, 2026 21:03
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.
Six spinner sites drive their animation from the guest:
createSpriteAnimationadvances a signal every frame and
<Image src={spinnerSrc()}>swaps the textureevery third frame. The core already owns sprite-atlas playback, and the Octane
variants (
apps/hero/app.octane.tsx,apps/gallery/app.octane.tsx,apps/library/app.octane.tsx) have used it all along — the Solid and Vue Vaporvariants just never followed.
This converts
apps/hero,apps/hero/app.vue-vapor.tsx,apps/hero-vue-vapor,apps/gallery,apps/gallery/app.vue-vapor.tsxandapps/nsengineto<Sprite sprite="spinner-atlas.svg">, and removes the frame lists and the guesthook along with them. Keeping the JSX swap while leaving the frame constants in
place would have packed both the atlas and the eight standalone frames.
spinnerFrameStepis preserved, not droppedapps/blackberry-classic-demoandapps/iphone4s-demoboth pass a non-defaultstep of 6, so the prop had to survive the conversion. The core
set_spritesurface already takes a runtime step and uses it in the same deterministic cell
calculation, so
Sprite.frameStepis wired through the native tree withfinite-number validation, floor and clamp to 1–65535, reactive rebinding, and
fallback to the manifest value.
Measured on
mainAcross the six targets, in-frame traffic drops from 750 calls / 8,136 B to
514 / 6,248 B, and the per-frame
setImagetraffic that drove the animation(236 calls / 1,888 B) goes to zero. On 480-frame idle runs, 1,049 calls /
10,052 B becomes 453 / 5,284 B. Guest-side HostOps time across the six canonical
runs goes 2.168 ms → 1.314 ms.
Every affected PAK shrinks (five by 416 B, nsengine by 432 B) because the eight
standalone frames stop being packed; aggregate JS grows 424 B for the
frameStepplumbing.Verification
1080/1080 canonical frames and 2880/2880 zero-input frames match clean
mainbuilds, and both step-6 apps match 180/180 on the runtime-step path. The eight
atlas cells are pixel-identical to the standalone frames (0 differing pixels).
Mutating hero's manifest step from 3 to 4 diverges the canonical replay at frame
2, so the check has teeth.
The suite shows the same five pre-existing unit failures as clean
main, andthe committed
hero-maintape hashes diverge at the same frame-0 pair on both.