Now that we use a Variant for the SimpleSelector's data, we don't need
to instantiate empty structs or variables for the types that aren't
used, and so we can remove `PseudoElement::None`,
`PsuedoClass::Type::None` and `Attribute::MatchType::None`.
Also, we now always initialize a SimpleSelector with a type, so
`SimpleSelector::Type::Invalid` can go too.
The ifs below the switch no longer functioned, so let's move everything
into the switch cases. This also means we can replace the StringBuilder
usage with String::formatted().
Dimension tokens don't make use of the m_value string for anything else,
so we can sneak the unit string in there.
- Token goes from 72 to 64 bytes
- StyleComponentValueRule goes from 80 to 72 bytes
These three are all integers - we just repeatedly multiply them by 10
and then add a digit - so using an integer here is both faster and more
accurate. :^)
There's really no reason to use doubles here, except at the time I
wanted to use doubles everywhere in CSS. I now realize that is
excessive, so everything can be floats instead.
There was no real benefit to creating the SimpleSelector early and then
modifying it, and doing so made this code harder to follow than it
needs to be.
This is a change to CSS-TEXT-4, listed here:
https://www.w3.org/TR/2022/WD-css-text-4-20220318/#changes
We don't actually support these properties yet, but it doesn't hurt to
keep them up to date for when they get implemented in the future. :^)
I came across some websites that change an elements CSS "opacity" in
their :hover selectors. That caused us to relayout on hover, which we'd
like to avoid.
With this patch, we now check if a property only affects the stacking
context tree, and if nothing layout-affecting has changed, we only
invalidate the stacking context tree, causing it to be rebuilt on next
paint or hit test.
This makes :hover { opacity: ... } rules much faster. :^)
We want to return a view to a constant object, not a constant view,
which we can implicitly copy to get a mutable reference to the object.
Clang-Tidy helpfully pointed this out.
The spec says:
> <delim-token> has a value composed of a single code point.
So using StringView is a bit overkill.
This also allows us to use switch statements in the future.
For CSS properties that are known to not affect layout, we can avoid
doing a layout before returning their current resolved value.
It should be enough to only update style for the target element here,
but we don't currently have a mechanism for that.
This doesn't have parsing support for multiple languages in the same
selector. Support for language subcodes is not great either. But it
does do the basics.
If the current Document is not attached to a Web::Page for whatever
reason, but we're trying to look up a color from the system palette,
let's just fail the lookup instead of crashing the process.
ID selectors need to be serialized as identifiers in the spec, but other
hash-values do not. This was causing hex colors that start with a
number, like `#54a3ff`, to serialize as `#\35 4a3ff`, which is silly
and unnecessary.
Selector serialization is done elsewhere, so this case in Token is
probably also unnecessary, but there might be situations I haven't
thought of where serializing an ID does need to happen while it's still
a Token.
`static const` variables can be computed and initialized at run-time
during initialization or the first time a function is called. Change
them to `static constexpr` to ensure they are computed at
compile-time.
This allows some removal of `strlen` because the length of the
`StringView` can be used which is pre-computed at compile-time.
- background properties
- box-shadow
- cursor
- SVG fill/stroke properties
- image-rendering
- outline properties
- pointer-events
- user-select
This should be basically all of them. I skipped `opacity` and
`transform` since establishing a stacking context feels like a
layout-affecting thing, but I could be very wrong on that!
In Selectors level 4, `:nth-child()` and `:nth-last-child()` can both
optionally take a selector-list argument. This selector-list acts as a
filter, so that only elements matching the list are counted. For
example, this means that the following are equivalent:
```css
:nth-child(2n+1 of p) {}
p:nth-of-type(2n+1) {}
```
This fixes the specificity for :not(), :is() and :where(). Also, we now
clamp the specificity numbers instead of letting them overflow, and I
sprinkled in some spec comments for good measure.
`<forgiving-selector-list>` and `<forgiving-relative-selector-list>` are
the same as regular selector-lists, except that an invalid selector
does not make the whole list invalid. The former is used by the `:is()`
pseudo-class.
For example:
```css
/* This entire selector-list is invalid */
.foo, .bar, !?invalid { }
/* This is valid, but the "!?invalid" selector is removed */
:is(.foo, .bar, !?invalid) { }
```
Also as part of this, I've removed the `parse_a_selector(TokenStream)`
and `parse_a_relative_selector(TokenStream)` methods as they don't add
anything useful.
As noted, this is not 100% to the spec, but effectively the same -
`no-preference` is only allowed to appear in features that evaluate it
as false in a boolean context. This is also the only identifier besides
`none` that evaluates to false. If other identifiers gain this property
in the future, we can make it more robust then.
This adds (or at least stubs-out) the following:
- display-mode
- dynamic-range
- environment-blending
- forced-colors
- horizontal-viewport-segments
- vertical-viewport-segments
- inverted-colors
- nav-controls
- prefers-contrast
- prefers-reduced-data
- prefers-reduced-motion
- prefers-reduced-transparency
- scripting
- video-color-gamut
- video-dynamic-range
The `@media (inverted-colors)` CSS that the spec requires we add to the
UA style sheet does not actually do anything for us yet since we don't
support `filter`, but it seemed sensible to include it now to avoid
forgetting later. :^)