Previously, some StyleValues created a large number of intermediate
strings during serialization. Passing a StringBUilder into the
serialization function allows us to avoid a large number of these
unnecessary allocations.
This adds visit_edges(Cell::Visitor&) methods to various helper structs
that contain GC pointers, and makes sure they are called from owning
GC-heap-allocated objects as needed.
These were found by our Clang plugin after expanding its capabilities.
The added rules will be enforced by CI going forward.
The color stop members were RefPtr which compares by pointer identity.
This caused false positives in style invalidation when the same gradient
color values were recomputed as different objects.
The x and y members were RefPtr which compares by pointer identity.
This caused false positives in style invalidation when the same values
were recomputed as different objects.
The member type was NonnullRefPtr which compares by pointer identity.
This caused false positives in style invalidation when the same values
were recomputed as different objects.
The member types were NonnullRefPtr which compares by pointer identity.
This caused false positives in style invalidation when the same color
values were recomputed as different objects.
Previously the logic to compute transitions was split across
`ComputedProperties`, `StyleComputer`, and `Animatable` - this commit
consolidates it all in `ComputedProperties`
The `:has()` pseudo-class requires traversing descendants (or siblings)
to find matches.
With this change we cache results keyed by `(Selector*, Element*)`
pairs. The cache is stored in `StyleComputer` and cleared at the start
of each style computation pass in `Document::update_style()`.
When `:has()` uses a descendant combinator and we find a match, we also
cache that all ancestors between the matching descendant and the
anchor match. For example with `div:has(.target)`:
```html
<div id="A"> <!-- checking :has(.target) here -->
<div id="B">
<div id="C">
<span class="target"/>
</div>
</div>
</div>
```
When we find `.target` while checking `div#A`, we also cache that
`div#B` and `div#C` match `:has(.target)` since they also contain
`.target`. Later when styling these elements, we get cache hits and skip
traversal.
`EdgeStyleValues` which consist of an offset of a `calc()`s which
resolves to 50% should be considered "centered" for
`SerializationMode::ResolvedValue` for the purpose of omitting the
position value from gradient serialization.
As well as being required to implement absolutization this also means we
now bypass a limitation with `LengthPercentage` where we would always
use `SerializationMode::Normal` for the constituent lengths which gains
us some WPT passes