Repository navigation
fix(native): one resolved-style cache key per distinct input set - #434
Open
YevheniiKotyrlo wants to merge 1 commit into
Open
YevheniiKotyrlo wants to merge 1 commit into
YevheniiKotyrlo wants to merge 1 commit into
Conversation
YevheniiKotyrlo
force-pushed
the
fix/mapping-config-identity
branch
from
August 19, 2026 17:51
c877b35 to
7bc057a
Compare
YevheniiKotyrlo
force-pushed
the
fix/mapping-config-identity
branch
2 times, most recently
from
August 20, 2026 04:55
18b5d2b to
152b5ad
Compare
This was referenced Aug 20, 2026
Draft
Contributor
Author
No device frameThe change is how many cache entries identical elements share, not what they paint, and the description's tests count them. |
generateStateHash keys the resolved-style cache on weak-key identity, so it shares only when equal inputs arrive as one object, and two defects broke that on main. The config was minted per instance: useCssElement derived one from a module constant on every mount, so N identical elements each held their own cache entry, sorted rule array and observable. It is now derived once per mapping through weakFamily, and a mapping that is not an object is refused by name rather than failing inside the WeakMap. The key was lossy: folding the key numbers into one and printing it base-36 is a digest, and family returns the entry it holds whatever rules the second caller brought, so a collision rendered one element's styles on another. The numbers are now sorted and joined, which is exact and order-independent, in a Float64Array so the sort is native and the unbounded key counter does not wrap. family gains size() so the invariant is assertable.
YevheniiKotyrlo
force-pushed
the
fix/mapping-config-identity
branch
from
October 11, 2026 12:35
152b5ad to
8e16252
Compare
This branch has not been deployed
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.
Problem
generateStateHashkeys the resolved-style cache on weak-key identity, so it shares an entry only when equal inputs arrive as one object. Two defects onmainbreak that:useCssElementderives one from a module constant on every mount, so N identical elements each hold their own cache entry, sorted rule array and observable.familyreturns the entry it holds whatever rules the second caller brought, so a collision renders one element's styles on another.Solution
weakFamily. A mapping that is not an object is refused by name, rather than failing inside theWeakMapwith a message that names neitherstyled()nor the argument.Float64Array, so the sort is numeric without a comparator and the unbounded key counter does not wrap.familygainssize(), so the invariant is assertable.Tests
config-identity.test.tsandstate-hash.test.tspin the derivation and the key: one mapping gives one config, a mapping that is not an object is refused by name, distinct key sets never share a key, and order does not matter.style-cache.test.tsxcounts entries for identical and differing elements, and checks that elements sharing an entry and its config each see the valuenativeStyleMappingtook.mainwith onlysize()added, 8 of the 14 cases fail: 50 identical elements hold 50 entries, and three identical buttons hold three. Each of 6 mutations fails its own cases.Verification
On Windows with Node 26:
yarn lintcleanyarn typecheckcleanyarn test --coverage: every failure also fails onmainon this machine (the four babel cases)yarn buildcleanyarn example expo export --platform webexportedMerge order
#436 builds on this, so this lands first.
It also shares lines with #412 (
native/reactivity.ts); whichever lands second rebases.Base
Re-written on
main(a5002c5). #451 makesfamilyandweakFamilycache on presence, which this fixed too, so that half is gone.