Instead of throwing all pseudo-element rules in one bucket, let's have
one bucket per pseudo-element.
This means we only run ::before rules for ::before pseudo-elements,
only ::after rules for ::after, etc.
Average style update time on https://tailwindcss.com/ 250ms -> 215ms.
(cherry picked from commit 87056ee0d2505c26149a36fc5b69446504b172bb)
Once we know the final value of the `content` property for a
pseudo-element, we can bail early if the value is `none` or `normal`
(note that `normal` only applies to ::before and ::after).
In those cases, no pseudo-element will be generated, so everything
that follows in StyleComputer would be wasted work.
This noticeably improves performance on many pages, such as
https://tailwindcss.com/ where style updates go from 360ms -> 250ms.
(cherry picked from commit d22228ab93b387e043b5bce29f79ef5ffa7c0f9d)
And also make it inline. We were spending 8% of selector matching on
creating and destroying FlyString copies here. With this change, it's
now ~1%.
(cherry picked from commit b2aff403fc596bfab64c0ab43a45f3d39f836afb)
Some websites (like vercel.com...) have a *lot* of :hover selectors that
we can simply skip for any element that isn't currently hovered.
(cherry picked from commit ef4f5ac8fb761f43839e9fbd753716a57544c795)
Instead of only bucketing these by class name, let's also bucket by
tag name and ID.
Reduces the number of selectors evaluated on https://tailwindcss.com/
from 2.9% to 1.9%.
(cherry picked from commit 5bb0f43b90a56275a0bfb92116826b2349c69dd3)
This can be a local variable while building a rule cache, no need to
take up space in MatchingRule.
(cherry picked from commit 49d2b11085c8a59db2f1c54ad8e8f5938e6776c9)
By filtering first, we end up allocating much less vector space
most of the time.
This is mostly helpful in pathological cases where there's a huge number
of rules present, but most of them get rejected early.
(cherry picked from commit c8f22f65d9631c9da12390eeec05033e6efa76f2)
This makes cascade layer filtering take <2% of CPU time when loading
https://vercel.com instead of 30%.
(cherry picked from commit 44e4ea3d7aaf9aed6ad09cc9f049b2842e3e0d28)
Before this change, the ancestor filter would only reject rules that
required a certain set of descendant strings (class, ID or tag name)
to be present in the current element's ancestor chain.
An immediate child is also a descendant, so we can include this
relationship in the ancestor filter as well.
This substantially improves the efficiency of the ancestor filter on
websites using Tailwind CSS.
For example, https://tailwindcss.com/ itself goes from full style
updates taking ~1400ms to ~350ms. Still *way* too long, but a huge
improvement nonetheless.
(cherry picked from commit 34fdd0d44fcf916540ea66ba9c895ba005a54b9a)
By bucketing these seletors by class or ID, we can avoid running them
in more cases.
Before, we were only avoiding them if the context element wasn't a div.
Now we avoid them for any element that doesn't have that specific class
or ID.
This reduces the number of selectors ran on https://vercel.com by a bit
more, from 1.90% to 1.65%.
(cherry picked from commit b365a5c42f4e978496fb03924b129406d4a6c5b0)
These are just roundabout ways of writing .foo, so we can still put them
in the rules-by-class bucket and skip running them when the element
doesn't have that class.
Note that :is(.foo .bar) is also bucketed as a class rule, since the
context element must have the `bar` class for the selector to match.
This is a massive speedup on https://vercel.com/ as it cuts the number
of selectors we actually evaluate from 7.0% to 1.9%.
(cherry picked from commit ad37c8cd26208157be405fb3a329d0955f402fc9)
Similar to LadybirdBrowser/ladybird#1714.
We don't implement the linejoin values `miter-clip` and `arcs`, because
according to the SVG 2 spec:
> The values miter-clip and arcs of the stroke-linejoin property are at
> risk. There are no known browser implementations. See issue Github
> issue w3c/svgwg#592.
Nothing uses this yet. The next step is to change
SVGPathPaintable::paint() to read `graphics_element.stroke_linejoin()`
and `graphics_element.stroke_miterlimit()` when painting.
(cherry picked from commit 421cf8d9bf276cff61acdc32dc55d978d37fb671;
amended to resolve conflict on `height:` in
getComputedStyle-print-all.txt)
Previously we would serialize these as the empty string. eg, this:
```
<div style="grid-auto-columns: auto"></div>
```
would have a computed `grid-auto-columns` value of ``.
(cherry picked from commit 7c2680b7efd2588cf2c5e595f7a60813dabf3b92)
In order to know whether `calc(2.5)` is a number or an integer, we have
to see what the property will accept. So, add that knowledge to
`Parser::expand_unresolved_values()`.
This makes `counter-increment: foo calc(2 * var(--n));` work correctly,
in a test I'm working on.
(cherry picked from commit 69d064697ad8bbf602eb2dc73fc532b0e1b16716)
This allows us to run the WPT tests under quirks/unitless-length/
without crashing, giving us over 4600 new passing subtests. :^)
(cherry picked from commit 5df6c6eecff678bf2a1fe8960149302d42015439)
This allows us to progress further on this WPT test:
https://wpt.live/quirks/unitless-length/quirks.html
...although it still crashes before finishing.
(cherry picked from commit 5e240f997caa8b62275d3c5d18a1cf1885349971)
Example of the difference:
50 * 2.55 --> 127.4999 --> round towards +∞ --> 127
50 * 255 / 100 --> 127.5000 --> round towards +∞ --> 128
Now, 9 failing WPT tests in /css/css-color/ pass.
(cherry picked from commit 6c3ecf6a342cbc0a83c1deac89e1a7edf6d959c4;
amended because css-color-functions.html is a reftest for us, not
a screenshot test)
These are legacy name aliases for the properties without the 'grid-'
prefix. See https://drafts.csswg.org/css-align-3/#gap-legacy
(cherry picked from commit c79f261bec40a61373d45508c1935f839454c95d)
Adapt the existing `font-face-src-local-serialization.html` test into a
more general test for these.
(cherry picked from commit c497e5f850a5c7f43d6f216d9fd74a58ddefd9a0)
(cherry picked from commit 55812aaed20ce8f7aeea233a47bcab73b60edd5e;
amended to include AK/QuickSort.h in Parser.cpp to fix a compile
error, and to update height: in getComputedStyle-print-all.txt)
Multiple font properties are either the `normal` keyword or some
non-keyword value, so this lets us avoid some boilerplate for those, at
the cost of the existing `none` users having marginally more verbose
code.
(cherry picked from commit 1a127c9d37e47b8793057ab68305bf399ad3106f)
This is a special form of `<string>` so doesn't need its own style value
type. It's used in a couple of font-related properties. For completeness
it's included in ValueType.
(cherry picked from commit cd13b30fb871ab521777ce164bff7696aa0fbfca)
Two font properties, font-feature-settings and font-variation-settings,
contain a list of values that are an `<opentype-tag>` followed by a
single value. This class is intended to fill both roles.
(cherry picked from commit c22a2d8f2b720b7cd69a1c3b84d1cf7d443498ee)
CSS Fonts level 4 renames font-stretch to font-width, with font-stretch
being left as a legacy alias. Unfortunately the other specs have not yet
been updated, so both terms are used in different places.
(cherry picked from commit 4a67b28600437901e6d8a366c56a5ddd8665deb1)
This matches the name in the CSS Typed OM spec. There's quite a lot
still to do to make it match the spec behavior, but this is the first
step.
(cherry picked from commit 76daba3069de4c184c6b2317d0c89b50f81a8c00)
I didn't want to add another set of boilerplatey tree-walking methods,
so here's a general-purpose one. :^)
`for_each_effective_rule()` walks the tree of effective style rules, and
runs the callback on each one, in either pre- or postorder. The
previous `for_each_effective_style/keyframes_rule()` methods of
`CSSStyleSheet` are then reimplemented in terms of
`for_each_effective_rule()`, and we can get rid of their equivalents
elsewhere.
(cherry picked from commit cbb4be3e5e266da09d145435fe8279a83099f363)
Depending on usage, `@layer` has two forms, with two different CSSOM
types. One simply lists layer names and the other defines a layer with
its contained rules.
(cherry picked from commit 1c6133aa523fe29c25b11284d8b3353de0a03c0f)
Function is defined as `round(<rounding-strategy>?, A, B?)`
With this change resolved type is `typeof(resolve(A))`, instead of
`typeof(A)`.
For example `round(up, 20%, 1px)` with 200px percentage basis is now
correctly resolved in 40px instead of 40%.
Progress on https://www.notion.so/ landing page.
(cherry picked from commit 41e37f00795920686fad7b211381905618fb345a)
These are a remnant of when Length itself could hold a pointer to a
CalculatedStyleValue. That hasn't been the case for a long time now.
(cherry picked from commit 35cb6badc203b0dddb0a0e4850432950dbc4fd2c)
This makes the way we've implemented the CSS `revert` keyword a lot less
expensive.
Until now, we were making a deep copy of all property values at the
start of each cascade origin. (Those are the values that `revert` would
bring us back to if encountered.)
With this patch, the revert property set becomes a shallow copy, and we
only clone the property set if the cascade ends up writing something.
This knocks a 5% profile item down to 1.3% on https://tailwindcss.com
(cherry picked from commit e399b472e9254294f48a057d8848814bdf25b2af)
When a property is a "legacy name alias", any time it is used in CSS or
via the CSSOM its aliased name is used instead.
(See https://drafts.csswg.org/css-cascade-5/#legacy-name-alias)
This means we only care about the alias when parsing a string as a
PropertyID - and we can just return the PropertyID it is an alias for.
No need for a distinct PropertyID for it, and no need for LibWeb to
care about it at all.
Previously, we had a bunch of these properties, which misused our code
for "logical aliases", some of which I've discovered were not even
fully implemented. But with this change, all that code can go away, and
making a legacy alias is just a case of putting it in the JSON. This
also shrinks `StyleProperties` as it doesn't need to contain data for
these aliases, and removes a whole load of `-webkit-*` spam from the
style inspector.
(cherry picked from commit fdcece2e88b91b9ec6cf63c3466525fb77540316;
amended to:
* resolve a conflict on height: in getComputedStyle-print-all.txt
* run prettier on CSSGeneratedFiles.md)
You can now build with STYLE_INVALIDATION_DEBUG and get a debug stream
of reasons why style invalidations are happening and where.
I've rewritten this code many times, so instead of throwing it away once
again, I figured we should at least have it behind a flag.
(cherry picked from commit ddbfac38b0074819470766846fca08fd78630eb0;
minorly amended for conflicts in AK/Debug.h.in and
Meta/CMake/all_the_debug_macros.cmake due to us having more debug
macros. Also, downstream got alphabetical order for
STYLE_INVALIDATION_DEBUG wrong.)