The resolved property sets are stored with the element in a
per-pseudo-element array (same as for pseudo element layout nodes).
Longer term, we should stop storing this with elements entirely and make
it temporary state in StyleComputer somehow, so we don't waste memory
keeping all the resolved properties around.
This makes various gradients show up on https://shopify.com/ :^)
The root element font metrics were getting queried again and again
during style computation. Before this change we would do some work to
recalculate them each time.
This patch simply caches them in a StyleComputer member. Since style
updates always start with the root element, we know that it'll be
up-to-date by the time we look at any other element.
Before this change, we were spending ~5% of CPU time on Google Groups
in root_element_font_metrics().
Before this patch, we would build full computed style for these pseudo
elements, for every DOM element, even if no ::before/::after selector
actually matched.
This was a colossal waste of time, and we can also just not do that.
Instead, just abort pseudo element style resolution early if no relevant
selectors matched. :^)
Instead of putting every rule that matches a pseudo element in the
same bucket, let them go in the best ID/class/tag name bucket instead.
Then, add a flag to MatchingRule that says whether it contains a
pseudo element in the rightmost compound selector.
When deciding which selectors to run for an element, we can now simply
filter in/out pseudo element selectors as appropriate depending on what
we're trying to match.
This fixes an issue where pages using Font Awesome had 1700+ rules in the
pseudo-element rule cache. (This meant all those rules had to run
against every element twice or more while instantiating pseudo elements.)
We were already sorting the author style selectors into buckets.
Now we do it for the built-in UA style as well.
This means less work for the selector engine everywhere :^)
This class had slightly confusing semantics and the added weirdness
doesn't seem worth it just so we can say "." instead of "->" when
iterating over a vector of NNRPs.
This patch replaces NonnullRefPtrVector<T> with Vector<NNRP<T>>.
DeprecatedFlyString relies heavily on DeprecatedString's StringImpl, so
let's rename it to A) match the name of DeprecatedString, B) write a new
FlyString class that is tied to String.
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
Previously, we were running the "load fonts if needed" machine at the
start of every style computation. That was a lot of unnecessary work,
especially on sites with lots of style rules, since we had to traverse
every style sheet to see if any @font-face rules needed loading.
With this patch, we now load fonts once per sheet, right after adding
it to a document's style sheet list.
"Component value" is the term used in the spec, and it doesn't conflict
with any other types, so let's use the shorter name. :^)
Also, this doesn't need to be friends with the Parser any more.
When encountering a @font-face rule, StyleComputer will now fire off
a resource request and download the first source URL specified.
Once downloaded, we try to parse it as a TrueType font file, and if it
works, it's added to a cache in StyleComputer. This effectively makes
fonts per-document since every document has its own StyleComputer.
This is very unoptimized and could definitely use some caching, etc.
But it does work on Acid3. :^)
Get rid of the old, roundabout way of invalidating the rule cache by
incrementing the StyleSheetList "generation".
Instead, when something wants to invalidate the rule cache, just have it
directly invalidate the rule cache. This makes it much easier to see
what's happening anyway.
Previously we were making a copy of the full set of custom properties
that applied to a DOM element. This was very costly and dominated the
profile when mousing around on GitHub.
Note that this may break custom properties on pseudo elements a little
bit, and that's something we'll have to look into.
Previously this queried the root layout-node's font, which was both
wrong and could crash if the layout wasn't ready yet. Now, it's just
wrong. But at least all the font-related wrongness is grouped together
in StyleComputer. :^)
Build the final custom property map right away instead of first making
a temporary pointer-only map. We also precompute the final needed
capacity for the map to avoid incremental rehashing.
This works a little differently from the other caches - ALL rules
containing a pseudo-element are in this bucket. This lets us only look
at this bucket when finding styles for a pseudo-element, and ignore it
if we're not.
Since each selector can only have zero or one pseudo-element, we match
against it as a separate step, before matching the rest of the
selector. This should be faster, but mostly I did this because I could
not figure out how else to stop selectors without a pseudo-element from
matching the pseudo-element, eg so `.foo` styles don't affect
`.foo::before`.
This patch introduces the StyleComputer::RuleCache, which divides all of
our (author) CSS rules into buckets.
Currently, there are two buckets:
- Rules where a specific class must be present.
- All other rules.
This allows us to check a significantly smaller set of rules for each
element, since we can skip over any rule that requires a class attribute
not present on the element.
This takes the typical numer of rules tested per element on Discord from
~16000 to ~550. :^)
We can definitely improve the cache invalidation. It currently happens
too often due to media queries. And we also need to make sure we
invalidate when mutating style through CSSOM APIs.
Previously we would re-run the entire CSS selector machinery for each
property resolved. Instead of doing that, we now resolve a final set of
custom property key/value pairs at the start of the cascade.
- Replace "auto" with "auto const" where appropriate.
- Remove an unused struct.
- Make sort_matching_rules() a file-local static function.
- Remove some unnecessary includes.
CSS has rules about automatic blockification or inlinification of boxes
in certain circumstances.
This patch implements automatic blockification of absolutely positioned
and floating elements. This makes the smile appear on ACID2. :^)
We now detect situations like this, where variables infinitely recur,
without crashing:
```css
div {
--a: var(--b);
--b: var(--a);
background: var(--a);
}
p {
--foo: var(--foo);
background: var(--foo);
}
```
If a property is custom or contains a `var()` reference, it cannot be
parsed into a proper StyleValue immediately, so we store it as an
UnresolvedStyleValue until the property is compute. Then, at compute
time, we resolve them by expanding out any `var()` references, and
parsing the result.
The implementation here is very naive, and involves copying the
UnresolvedStyleValue's tree of StyleComponentValueRules while copying
the contents of any `var()`s it finds along the way. This is quite an
expensive operation to do every time that the style is computed.
Resolved style is a spec concept that refers to the weird mix of
computed style and used style reflected by getComputedStyle().
The purpose of this class is to produce the *computed* style for a given
element, so let's call it StyleComputer.