Commit graph

221 commits

Author SHA1 Message Date
Sam Atkins
0f42d5ec3e LibWeb/CSS: Don't resolve @import URLs until they are used
The regression in the "conditional-CSSGroupingRule" test is we now fail
the "inserting an `@import`" subtests differently and the subtests
aren't independent. Specifically, we don't yet implement the checks in
`CSSRuleList::insert_a_css_rule()` that reject certain rules from being
inserted. Previously we didn't insert the `@import` rule because we
failed to parse its relative URL. Now we parse it correctly, we end up
inserting it.
2025-04-09 18:45:57 +01:00
Sam Atkins
1abc628cd8 LibWeb/CSS: Allow CSSImportRule's document to be null on construction
It's possible to parse an `@import` rule that isn't attached to a
document. We only actually need it to have one when fetching the linked
style sheet, and that should only happen when the CSSImportRule is
attached to a document. So, we can just accept a null pointer when
constructing it.

We relied on that Document to get the Realm, so pass that in as a
separate parameter.
2025-04-09 18:45:57 +01:00
Sam Atkins
bc02e3e9a9 LibWeb/CSS: Pass location to parse_a_stylesheet() 2025-04-09 18:45:57 +01:00
Sam Atkins
7216c6b050 LibWeb/CSS: Parse <url> as a new CSS::URL type
Our previous approach to `<url>` had a couple of issues:
- We'd complete the URL during parsing, when we should actually keep it
  as the original string until it's used.
- There's nowhere for us to store `<url-modifier>`s on a `URL::URL`.

So, `CSS::URL` is a solution to this. It holds the original URL string,
and later will also hold any modifiers. This commit parses all `<url>`s
as `CSS::URL`, but then converts it into a `URL::URL`, so no user code
is changed. These will be modified in subsequent commits.

For `@namespace`, we were never supposed to complete the URL at all, so
this makes that more correct already. However, in practice all
`@namespace`s are absolute URLs already, so this should have no
observable effects.
2025-04-09 18:45:57 +01:00
Sam Atkins
c82f4b46a2 LibWeb/CSS: Qualify uses of LibURL
To prepare for introducing a CSS::URL type, we need to qualify any use
of LibURL as `::URL::foo` instead of `URL::foo` so the compiler doesn't
get confused.

Many of these uses will be replaced, but I don't want to mix this in
with what will likely already be a large change.
2025-04-09 18:45:57 +01:00
Tim Ledbetter
02d34dd021 LibWeb: Rename CSSColor to ColorFunctionStyleValue
This gives a better idea of what the class represents.
2025-04-09 12:11:33 +01:00
Sam Atkins
a80408fea6 LibWeb/CSS: Store @property initial value as a style value
For now, it's the "raw" UnresolvedStyleValue. Later, we'll need to try
to parse it into a "real" style value using the property's syntax.
2025-04-08 09:59:41 +01:00
Sam Atkins
9292b769ef LibWeb/CSS: Use descriptor parsing for @property 2025-04-08 09:59:41 +01:00
Tim Ledbetter
408f9f3dde LibWeb: Disallow "default" as a <family-name> identifier
This commit disallows "default" as a font-family name, when the name is
not quoted because unquoted names are treated as custom-idents, for
which the name "default" is not allowed.
2025-04-07 12:14:29 +01:00
Sam Atkins
5aeaeb3097 LibWeb/CSS: Remove redundant font-face src parsing code
We now always parse this as a descriptor.
2025-04-07 10:00:21 +01:00
Sam Atkins
a7f7c2a821 LibWeb/CSS: Teach OpenTypeTaggedStyleValue to serialize without "1" 2025-04-07 10:00:21 +01:00
Tim Ledbetter
e73438e82c LibWeb: Clamp grayscale, invert, filter and opacity filter values to 1 2025-04-04 17:12:47 +01:00
Tim Ledbetter
61f76c7ec5 LibWeb: Set color filter value to 1 if omitted 2025-04-04 17:12:47 +01:00
Sam Atkins
e43bb1410c LibWeb/CSS: Reject non-grouping-rules as descendants of style rules
For example, `@font-face` is not only invalid inside a style rule, it's
also invalid inside a child of a style rule. This fixes a test
regression that we previously passed by accident.
2025-04-04 10:40:32 +01:00
Sam Atkins
f87b454fa9 LibWeb/CSS: Parse @font-face descriptors as style values
CSSFontFaceRule now stores its values as a CSSFontFaceDescriptors, with
a ParsedFontFace produced on request. This is exposed via the `style`
attribute, so we pass a lot of tests that try to read values from
that.

We have one test regression, which we passed by mistake before: The test
wanted to ensure we don't allow `@font-face` nested inside other rules.
We passed it just because we discarded any `@font-face` without a
`font-family`. What we're supposed to do is 1) keep at-rules with
missing required descriptors and just not use them, and 2) reject
certain ones when nested.

We may want to cache the ParsedFontFace in the future, but I didn't here
because 1) it's called rarely, and 2) that would mean knowing to
invalidate it when the CSSFontFaceDescriptors changes, which isn't
obvious to me right now.
2025-04-04 10:40:32 +01:00
Sam Atkins
fd45c53c11 LibWeb: Parse descriptors as style values, using the JSON data
The goal here is to do something a bit smarter with the parsing here
than we do for properties. Instead of the JSON saying "here are the
values, and here are the keywords, and we can have up to 3", here we
place the syntax in the JSON directly (though currently broken up as
one string per option) and then we attempt to parse each one in
sequence. It's something we'll need eventually for `@property` among
other things.

...However, in this first pass, I've gone with the simplest option of
hard-coding the types instead of figuring them out properly. So there's
a PositivePercentage type and a UnicodeRangeTokens type, instead of
properly implementing the grammar for those in a generic way.
2025-04-04 10:40:32 +01:00
Sam Atkins
60c536bdd5 LibWeb/CSS: Add FontSourceStyleValue
This will be used by the `@font { src: ... }` descriptor once we parse
descriptors as style values.
2025-04-04 10:40:32 +01:00
Sam Atkins
79093291b5 LibWeb/CSS: Un-template parse_comma_separated_value_list()
This doesn't need to be a template. Changing it means we can use it from
any FooParsing.cpp file, and also move it ValueParsing.cpp where it
belongs.
2025-04-04 10:40:32 +01:00
Sam Atkins
86b57a5205 LibWeb/CSS: Use font_format_is_supported() when parsing font sources 2025-04-02 15:53:50 +01:00
Tim Ledbetter
ac19b0cda8 LibWeb/CSS: Support media queries in import at-rules 2025-04-02 13:53:03 +01:00
Glenn Skrzypczak
9973b01848 LibWeb/CSS: Improved implementation of background-blend-mode
This is a improved version of a73cd88f0c
The old commit was reverted in 552dd18696

The new version only paints an element into a new layer if background
blend modes other than normal are used. The rasterization performance
of most websites should therefore not suffer.

Co-Authored-By: Alexander Kalenik <kalenik.aliaksandr@gmail.com>
2025-04-01 13:38:00 +02:00
Aliaksandr Kalenik
552dd18696 Revert "LibWeb/CSS: Implement 'background-blend-mode'"
This reverts commit a73cd88f0c.

Emitting SaveLayer for each paintable made rasterization a lot slower
on every website because now Skia has to allocate enormous amounts of
temporary surfaces. Let's revert it for now and figure how to implement
it with less aggressive SaveLayer usage.
2025-03-28 16:48:03 +00:00
Glenn Skrzypczak
a73cd88f0c LibWeb/CSS: Implement 'background-blend-mode'
This implements the 'background-blend-mode' CSS property.
2025-03-28 09:41:06 +00:00
Sam Atkins
09b8f73e11 LibWeb/CSS: Implement UnicodeRangeStyleValue
This is preparation for storing at-rule descriptors as style values.
2025-03-28 09:15:02 +00:00
Sam Atkins
ef3a2bf907 LibWeb/CSS: Move functions for detecting var()/attr() into Token types
This makes them accessible outside of PropertyParsing.cpp (which will be
useful if/when descriptors can include them). I've also renamed them to
use the correct term: "arbitrary substitution function".
2025-03-28 09:15:02 +00:00
Andreas Kling
ba030f0363 LibWeb: Add an engine-internal CSS realm for internal style parsing
This is used for default UA style right now, and we'll expand its use in
the near future.

Note that this required teaching the CSS parser to handle url()
functions when there's no document URL to resolve them against. If we
don't handle that, namespace rules in UA style don't parse correctly.
2025-03-25 23:57:00 +00:00
Jelle Raaijmakers
545d151948 LibWeb: Make transform: scale(calc(..)) work
The `transform` property supports transform functions that sometimes
need their `calc(percentage)` values to be converted to a number instead
of a length. Currently this only applies to the `scale*` family of
functions, which are marked as such in `TransformFunctions.json`.

We were not consistently applying the `NumberPercentage` type to these
functions though, and in addition, any `NumberPercentage` value would
not consider calculated values.
2025-03-25 19:53:36 +00:00
Aliaksandr Kalenik
090ac66af1 LibWeb: Repeat grid track sizing with minmax where both are not definite
...should be treated as invalid value.
2025-03-25 09:53:04 +00:00
Sam Atkins
88e11eea2d LibWeb: Implement functional pseudo-element parsing
"Functional" as in "it's a function token" and not "it works", because
the behaviour for these is unimplemented. :^)

This is modeled after the pseudo-class parsing, but with some changes
based on things I don't like about that implementation. I've
implemented the `<pt-name-selector>` parameter used by view-transitions
for now, but nothing else.
2025-03-25 07:54:13 +00:00
Sam Atkins
5cf04a33ad LibWeb/CSS: Add method for parsing <custom-ident> directly
We specifically want to parse one inside a selector, where we only care
about the string itself and don't want a whole style value.
2025-03-25 07:54:13 +00:00
Sam Atkins
285fbc8f1c LibWeb/CSS: Parse local() font sources more correctly
There were several issues with the previous parsing code, like ignoring
trailing tokens, not handling whitespace, and not requiring the value
to be a `<family-name>`. So, fix all that.

Also correct the serialization code, which didn't call
`serialize_a_string()` previously.
2025-03-25 07:53:59 +00:00
Sam Atkins
93a2c9946f LibWeb: Use FlyString for local font sources
The next commit will make it so we always have a FlyString, so this lets
us keep using it instead of turning it into a String.
2025-03-25 07:53:59 +00:00
Sam Atkins
f8536fc48a LibWeb/CSS: Split out <family-name> parsing
This type is used individually elsewhere in the spec. This also lets us
separate out the `<generic-family>` type.
2025-03-25 07:53:59 +00:00
Sam Atkins
193adee164 LibWeb/CSS: Implement aliases for pseudo-elements
We previously supported a few -webkit vendor-prefixed pseudo-elements.
This patch adds those back, along with -moz equivalents, by aliasing
them to standard ones. They behave identically, except for serializing
with their original name, just like for unrecognized -webkit
pseudo-elements.

It's likely to be a while before the forms spec settles and authors
start using the new pseudo-elements, so until then, we can still make
use of styles they've written for the non-standard ones.
2025-03-24 09:49:50 +00:00
Sam Atkins
ffa1dba96a LibWeb: Generate pseudo-element code from JSON
Initially, this generates the enum and to/from-string functions. The
JSON itself contains more data than that, but it's unused for now.
2025-03-24 09:49:50 +00:00
Sam Atkins
0ed2e71801 LibWeb/CSS: Move and rename PseudoElement types to prep for code gen
The upcoming generated types will match those for pseudo-classes: A
PseudoElementSelector type, that then holds a PseudoElement enum
defining what it is. That enum will be at the top level in the Web::CSS
namespace.

In order to keep the diffs clearer, this commit renames and moves the
types, and then a following one will replace the handwritten enum with
a generated one.
2025-03-24 09:49:50 +00:00
Tim Ledbetter
2672fe99b7 LibWeb: Set correct longhands if grid-area subproperties are omitted 2025-03-20 16:59:27 +00:00
Tim Ledbetter
5d57723ebf LibWeb: Implement CSSImportRule.supportsText
Returns the supports condition specified by the given import at-rule.
2025-03-19 16:42:51 +01:00
Tim Ledbetter
c37a47f76f LibWeb/CSS: Implement import at-rule supports conditions
This indicates the features the browser must support for the given
stylesheet to be fetched.
2025-03-19 16:42:51 +01:00
Sam Atkins
9b06f66571 LibWeb/CSS: Return GC::Ref from Parser::convert_to_style_declaration() 2025-03-19 13:53:00 +00:00
Sam Atkins
83bb92c4e0 LibWeb/CSS: Merge style declaration subclasses into CSSStyleProperties
We previously had PropertyOwningCSSStyleDeclaration and
ResolvedCSSStyleDeclaration, representing the current style properties
and resolved style respectively. Both of these were the
CSSStyleDeclaration type in the CSSOM. (We also had
ElementInlineCSSStyleDeclaration but I removed that in a previous
commit.)

In the meantime, the spec has changed so that these should now be a new
CSSStyleProperties type in the CSSOM. Also, we need to subclass
CSSStyleDeclaration for things like CSSFontFaceRule's list of
descriptors, which means it wouldn't hold style properties.

So, this commit does the fairly messy work of combining these two types
into a new CSSStyleProperties class. A lot of what previously was done
as separate methods in the two classes, now follows the spec steps of
"if the readonly flag is set, do X" instead, which is hopefully easier
to follow too.

There is still some functionality in CSSStyleDeclaration that belongs in
CSSStyleProperties, but I'll do that next. To avoid a huge diff for
"CSSStyleDeclaration-all-supported-properties-and-default-values.txt"
both here and in the following commit, we don't apply the (currently
empty) CSSStyleProperties prototype yet.
2025-03-19 13:53:00 +00:00
Sam Atkins
50455c2f5e LibWeb: Stop constructing temporary ElementInlineCSSStyleDeclarations
Previously, parse_css_style_attribute() would parse the string, extract
the properties, add them to a newly-created
ElementInlineCSSStyleDeclarations, and then user code would take the
properties back out of it again and throw it away. Instead, just return
the list of properties, and the caller can create an EICSD if it needs
one.
2025-03-19 13:53:00 +00:00
Sam Atkins
97e917bdf5 LibWeb/CSS: Allow bare zero for gradient angles
Corresponds to f952e97da9
2025-03-18 20:04:08 +00:00
Sam Atkins
db597843d6 LibWeb/CSS: Correct parsing of @supports selector()
A couple of fixes here:
- Parse a `<complex-selector>` instead of a `<selector-list>`
- Don't match if any unknown `::-webkit-*` pseudo-elements are found
2025-03-17 10:00:19 +00:00
Sam Atkins
b6fb4baeb7 LibWeb/CSS: Implement @supports font-format() and font-tech()
These let authors query whether we support font formats and features.
2025-03-17 10:00:19 +00:00
Sam Atkins
0f5e054f97 LibWeb: Implement generic boolean logic for media/supports queries
CSS Values 5 now defines a `<boolean-expr[]>` type that is used in place
of the bespoke grammar that previously existed for `@media` and
`@supports` queries. This commit implements some BooleanExpression
types to represent the nodes in a `<boolean-expr[]>`, and reimplements
`@media` and `@supports` queries using this.

The one part of this implementation I'm not convinced on is that the
`evaluate()` methods take a `HTML::Window*`. This is a compromise
because `@media` requires a Window, and `@supports` does not require
anything at all. As more users of `<boolean-expr[]>` get implemented in
the future, it will become clear if this is sufficient, or if we need
to do something smarter.

As a bonus, this actually improves our serialization of media queries!
2025-03-17 10:00:19 +00:00
Sam Atkins
84a695c958 LibWeb/CSS: Evaluate Supports query components during parsing
Instead of parsing the parts of a `@supports` query, then only
evaluating them when constructing the Supports itself, we can instead
evaluate them as we parse them. This simplifies things as we no longer
need to pass a Realm around, and don't have to re-parse the conditions
again with a new Parser instance.
2025-03-17 10:00:19 +00:00
Tim Ledbetter
18cccd7633 LibWeb/CSS: Don't allow negative values in border-radius property 2025-03-14 15:07:57 +00:00
Tim Ledbetter
632fc73643 LibWeb/CSS: Don't allow negative border radius in box-shadow property 2025-03-14 15:07:57 +00:00
Tim Ledbetter
dc58c11217 LibWeb: Reject invalid background-position-* property values 2025-03-14 15:07:57 +00:00