Commit graph

738 commits

Author SHA1 Message Date
Sam Atkins
cb74affdcb LibWeb/CSS: Treat general-enclosed in @container as unknown 2026-05-20 13:00:50 +01:00
Sam Atkins
9996403e73 LibWeb/CSS: Extract base class from MediaFeature
`<media-feature>` and the upcoming `<size-feature>` from `@container`,
share the same syntax and almost all of their behaviour. To avoid a lot
of duplication, pull as much as possible into a FeatureQuery template
class that they will both inherit from.

MediaFeatureValue is renamed FeatureValue as it's also shared by both.

No behaviour change.
2026-05-20 13:00:50 +01:00
Andreas Kling
f4960d9d7d LibWeb: Honor requested CSS tokenizer encoding
Keep decoded CSS text separate from tokenizer byte input. CSSOM and
already-decoded stylesheet text preserve code point preprocessing, so a
lone surrogate maps to one replacement character instead of being
re-decoded as malformed UTF-8 bytes.

Decode tokenizer byte input with the requested encoding unless that
encoding is UTF-8 and the byte stream is strictly valid UTF-8. Keep the
fast path by constructing the decoded string without validating twice
after strict validation succeeds.

Preserve UTF-8 decoder behavior on the byte fast path by stripping an
initial UTF-8 BOM and rejecting encoded surrogate bytes. Invalid UTF-8
still goes through the decoder. Add tokenizer coverage for both the C++
and Rust backends across decoded text, UTF-8 aliases, BOM-prefixed
input, invalid UTF-8, and non-UTF requested encodings.
2026-05-18 14:08:22 +02:00
Andreas Kling
318fb4f2d0 LibWeb: Preserve immutable consumed body bytes
Keep consumed response body bytes in Core::ImmutableBytes instead of
requiring a ByteBuffer. This lets responses that already arrived as
file-backed immutable data keep that representation through body
consumption, while streamed responses can still adopt their
accumulated ByteBuffer without another copy.

Update the body consumers that only inspect bytes to read from
immutable byte views. Font loading still copies at its existing
ownership boundary, where the off-thread preparation path takes a
ByteBuffer.
2026-05-18 01:21:34 +02:00
Callum Law
33705dc12f LibWeb: Generate CSS <paint> parsing
This changes the shape of the parsed value when we don't have a fallback
color for a `<url>` value from having no second value in the
`StyleValueList` to having an `EmptyOptionalStyleValue`.
2026-05-13 11:26:20 +01:00
Sam Atkins
88aea2e11d LibWeb: Give BooleanExpression an evaluation context
Different users of BooleanExpression have different requirements for
evaluation:
- `@media` needs a Document
- `@supports` doesn't need anything
- `@container` needs a container Element

To support these without expanding the API, replace the Document*
parameter with a BooleanExpressionEvaluationContext type which contains
these different values.

No behaviour changes.
2026-05-13 11:05:31 +01:00
Sam Atkins
442319c676 LibWeb/CSS: Update grammar for @container
Corresponds to
efc0c6f847
2026-05-13 11:05:31 +01:00
Sam Atkins
35b43f7d3a LibWeb/CSS: Insert a combinator before all pseudo-element selectors
Previously, and according to the spec, `a::part(foo)::before` would be a
single CompoundSelector, even though it matches against 3 different
targets. This meant some awkward swapping of targets in the middle of
matching, and in particular it made `::part()` and `::slotted()` quite
hacky, requiring them to track extra data on the MatchContext to then
use later. This was scattered around and difficult to follow.

Partly inspired by Gecko, this commit instead introduces an invisible
PseudoElement combinator. After parsing a selector, we find any
CompoundSelectors that contain a pseudo-element and split them up, so
that each CompoundSelector only has a single target in the end. Where
the pseudo-element was at the start of a CompoundSelector, we insert an
invisible universal selector before it to represent its originating
element.

So now, a CompoundSelector deals with one target, and switching targets
is done at the combinator.

The one inconsistency is that we match the target of ::slotted()
and ::part() in pseudo_element_transition_target(), instead of before
then when processing the SimpleSelector. This is to avoid repeating the
same computations twice.

No outward-facing behaviour changes, though the invalidation metrics
have changed.
2026-05-13 11:03:02 +01:00
Callum Law
f578d95be0 LibWeb: Support multiple keywords in parse_specific_keyword_value
This will allow us to combine multiple calls into one and avoid
repeatedly parsing and then discarding `KeywordStyleValue`s
2026-05-13 11:00:07 +01:00
mikiubo
b9ed64d1ce LibWeb: Add dedicated overflow-clip-margin style value
Store overflow-clip-margin as a structured style value instead of
collapsing it into generic keyword/length lists during parsing.

Keep omitted visual-box as a distinct state so painting can apply
the spec default per element type (content-box for replaced,
padding-box otherwise), while preserving canonical serialization.
2026-05-12 14:09:13 +02:00
mikiubo
a3e420bb9e LibWeb: Parse visual-box in overflow-clip-margin
Support content-box, padding-box, and border-box in
overflow-clip-margin parsing, including combinations with length.

Canonicalize parsed values to match the grammar and expected CSSOM
serialization in css-overflow parsing tests.
2026-05-12 14:09:13 +02:00
Sam Atkins
d7344a96bb LibWeb: Parse and propagate container and container-name properties 2026-05-07 17:48:53 +02:00
Aliaksandr Kalenik
f8640d813a LibGfx+LibWeb: Make DecodedImageFrame a value type
DecodedImageFrame only wraps a ref-counted Bitmap and color-space
metadata. The frame object itself does not provide shared mutable
state or lifetime ownership beyond those members, so ref-counting it
adds an unnecessary layer of indirection.
2026-05-07 16:08:13 +02:00
Callum Law
b1d0746292 LibWeb: Absolutize <paint> fallback colors
Previously we stored these within the `URLStyleValue` which didn't
itself have an `absolutized` method so wouldn't absolutize the fallback
color. We now store the two values alongside each other in a
`StyleValueList` which correctly handles absolutization
2026-05-07 10:07:09 +01:00
Aliaksandr Kalenik
76c79ee522 LibGfx: Remove ImmutableBitmap
DecodedImageFrame now owns decoded bitmap pixels directly, so the
separate ImmutableBitmap wrapper no longer carries useful semantics.
Remove the class and pass decoded image frames or bitmaps at the
boundaries where pixels are actually required.

The Skia image cache now keys off DecodedImageFrame, matching the
display-list commands that paint decoded images. Video frames stay
owned by LibMedia, with the explicit YUV-to-bitmap conversion living
at HTMLVideoElement's decoded-frame entry point for canvas and WebGL
callers.
2026-05-05 14:39:17 -05:00
Andreas Kling
355fb6b825 LibWeb: Stream Rust CSS tokenizer tokens over FFI
Avoid building a temporary Rust token vector before calling back into
C++. The tokenizer now invokes the callback as each token is produced,
while borrowing the already-filtered input for source slices.

Reserve an initial C++ token capacity from the input size so the common
path avoids repeated growth while appending the converted tokens.

With this change, the Rust CSS tokenizer is now ~1.3x faster than the
C++ CSS tokenizer at churning through all the https://vercel.com/ CSS.
2026-05-03 17:22:17 +02:00
Sam Atkins
4278194d96 LibWeb/CSS: Port the CSS Tokenizer to Rust
test-css-tokenizer is updated to run both the C++ and Rust tokenizers
and compare their output, to ensure they behave identically. The Parser
still uses the C++ Tokenizer.

The LibWeb crate, FFI layer etc are all based on the existing ones for
other libraries.

This is a direct AI translation to get us started, and not idiomatic
Rust. Future work can be done to make it more sensible.
2026-05-03 09:49:00 +02:00
Sam Atkins
8b09a8e568 LibWeb/CSS: Add missing spec comment to consume_string_token() 2026-05-03 09:49:00 +02:00
Sam Atkins
30043210e3 LibWeb/CSS: Stop using a define for the replacement character 2026-05-03 09:49:00 +02:00
Zaggy1024
ccaaefbf27 LibWeb+Meta: Don't require the custom ident blacklist parameter
With a default parameter, we can avoid having to store None for the
blacklist when it's not applicable.
2026-04-30 09:32:22 +02:00
Callum Law
66c10ed190 LibWeb: Generate `<font-weight-absolute> parsing 2026-04-29 11:42:57 +01:00
Callum Law
9a3f2b23a1 LibWeb: Add method to parse specific CSS keyword
This revealed an issue with `@counter-style/range` where parsing could
consume and ignore invalid keywords
2026-04-29 11:42:57 +01:00
Callum Law
44ad7e30b4 LibWeb: Generate <symbol> parsing 2026-04-29 11:42:57 +01:00
Callum Law
8849435d6f Meta+LibWeb: Initial scaffolding for CSS value type parsing code gen
In the future we should switch to using a better file format for this,
i.e. one that supports directly pasting CSS grammar production blocks
(https://drafts.csswg.org/css-values-4/#css-grammar-production-block)
and has support for inline comments, but we use JSON for now for
simplicity's sake.
2026-04-29 11:42:57 +01:00
Andreas Kling
61d79a1e47 LibWeb: Parse CSS image-set()
Add an abstract image style value for image-set() and parse both the
standard and -webkit-prefixed spellings through the existing <image>
value path. The parser accepts URL and string image candidates,
optional resolution descriptors, and type() filters.

Track attr-taint through substituted component values so image-set()
candidates using attr()-derived URL-producing tokens are rejected when
resolved for URL-using properties.

Update the relevant WPT baselines now that image-set() parsing is
supported in additional value contexts.
2026-04-25 14:54:10 +02:00
Callum Law
6b7fb4b273 LibWeb: Replace ViewFunctionStyleValue with FunctionStyleValue 2026-04-24 07:34:54 +01:00
Callum Law
6aeaf69cd3 LibWeb: Replace ScrollFunctionStyleValue with FunctionStyleValue 2026-04-24 07:34:54 +01:00
Callum Law
4faab1aa57 LibWeb: Replace FitContentSV with KeywordSV and FunctionSV
The `fit-content` keyword is stored as a `KeywordStyleValue` and
`fit-content()` function is stored as `FunctionStyleValue`
2026-04-24 07:34:54 +01:00
Callum Law
3bfebf862b LibWeb: Replace AddFunctionStyleValue with FunctionStyleValue 2026-04-24 07:34:54 +01:00
Callum Law
c846b289a9 LibWeb: Replace FontVariantAlternatesFunctionSV with FunctionSV 2026-04-24 07:34:54 +01:00
Andreas Kling
e4800b2498 LibWeb: Parse @keyframes name as logical string, not token text
The @keyframes parser was storing the keyframes name via
Token::to_string(), which keeps a string token in its quoted,
serialized form. That meant @keyframes "foo" was stored as
"\"foo\"" while animation-name: "foo" resolved to "foo",
and the two never matched.

Store the unquoted string or identifier value so the @keyframes name
and the animation-name reference compare on the same string.
2026-04-22 20:59:00 +02:00
Callum Law
eab7935686 LibWeb: Explicitly pass calculation context when parsing
Previously we would generate the calculation context based on the
current value parsing context. The main problem with this was that
contexts were defined per property by default and had to be overriden
per component value using "special" contexts, which was easy to forget.

We now generate the calculation context per component value in the
relevant `parse_foo_value` methods.

The new failures in `typed_arithmetic.html` are because we no longer
treat percentages as resolving to their property-level type when
computing what the resolved type of a calculation is i.e. when we are
parsing the `<number>` portion of `line-height` we treat percentages as
raw percentages, not lengths. This brings us in line with WebKit but no
longer with Chrome and WPT, I am not sure what the correct behavior is.
2026-04-22 14:24:12 +01:00
Callum Law
76250ba142 LibWeb: Validate literal numeric values at parse time
This brings a couple of advantages:
 - Previously we relied on the caller validating the parsed value was in
   bounds after the fact - this was usually fine but there are a couple
   of places that it was forgotten (see the tests added in this commit),
   requiring the bounds to be passed as arguments makes us consider the
   desired range more explicitly.
 - In a future commit we will use the passed bounds as the clamping
   bounds for computed values, removing the need for the existing
   `ValueParsingContext` based method we have at the moment.
 - Generating code is easier with this approach
2026-04-22 14:24:12 +01:00
Callum Law
ca1b433d27 LibWeb: Restrict CSS dimension-percentage mix parsing
We should only try to parse a dimension-percentage mix in
`parse_css_value_for_properties` if percentages resolve relative to that
dimension, not simply because percentages are allowed in general.

This doesn't currently cause any issues since we check that percentages
are resolved relative to the relevant dimension within the
`parse_foo_percentage_value` functions
2026-04-22 14:24:12 +01:00
Callum Law
76caf4d041 LibWeb: Deduplicate dimension literal parsing
This extracts the shared logic between <foo> and <foo-percentage>
parsing into helper methods
2026-04-22 14:24:12 +01:00
Callum Law
aa9f2ed83f LibWeb: Rename AcceptedTypeRange to NumericRange
This name wasn't very clear, also updates associated type and variable
names.
2026-04-22 14:24:12 +01:00
Callum Law
fc5dae8615 LibWeb: Clamp calculated values in FiltervalueListSV ::absolutized()
In a future commit we will use the allowed literal values as the bounds
for calculated values rather than the existing `ValueParsingContext`
based system. Since the computed bounds are different from the allowed
literal values here we need to handle clamping them manually.
2026-04-22 14:24:12 +01:00
Callum Law
83ed7e7419 LibWeb: Add spec comments for <filter-value-list> parsing 2026-04-22 14:24:12 +01:00
Callum Law
8a7332b7b9 LibWeb: Add OpacityValueStyleValue
This allows us to avoid the ugly hack in
`property_accepted_type_ranges()`.

This also updates the `ValueType` to be `opacity-value` rather than
`opacity` to match the spec.
2026-04-22 14:24:12 +01:00
Callum Law
d6dbabdf0e LibWeb: Clamp CSS numeric token values to float range
This matches the behavior of other browsers. We did the equivalent
change for <integer> in b86377b

We continue to store these as doubles for the extra precision.
2026-04-22 14:24:12 +01:00
Callum Law
dbe0cb4b1d LibWeb: Use number_value() for Number token debug string
This brings us in line with the other numeric types (percentage and
dimension) and allows us to test the clamping behavior that will be
added in a future commit.
2026-04-22 14:24:12 +01:00
Callum Law
cbf6e4454d LibWeb: Remove Token::number()
In a future commit we will be applying clamping to numeric (i.e.
number, percentage, dimension) values which will be done in the
appropriate `Token` getters so accessing the underlying number value
would be a potential footgun
2026-04-22 14:24:12 +01:00
Tim Ledbetter
882bd57b83 LibWeb: Drop unnecessary ColorFunctionStyleValue constructor 2026-04-22 11:52:56 +01:00
Tim Ledbetter
8d4f8a2d7f LibWeb: Route lch()/oklch() through unified ColorFunctionStyleValue 2026-04-22 11:52:56 +01:00
Tim Ledbetter
43ba21a45b LibWeb: Route lab()/oklab() through unified ColorFunctionStyleValue 2026-04-22 11:52:56 +01:00
Tim Ledbetter
e358cf1f0d LibWeb: Route hwb() through unified ColorFunctionStyleValue 2026-04-22 11:52:56 +01:00
Tim Ledbetter
ebe12a8766 LibWeb: Route hsl()/hsla() through unified ColorFunctionStyleValue 2026-04-22 11:52:56 +01:00
Tim Ledbetter
9ea880dcf0 LibWeb: Route rgb()/rgba() through unified ColorFunctionStyleValue 2026-04-22 11:52:56 +01:00
Tim Ledbetter
e4c29811be LibWeb: Generalize ColorFunctionStyleValue to cover every color space
Introduce a descriptor table keyed by `ColorType` that encodes
per-space metadata: channel kind, percent reference value, clamp
bounds, function name and serialization behavior.

This descriptor table is then used so that a single class can back
every CSS color type. Resolution, serialization, and absolutization
are driven by the descriptor.
2026-04-22 11:52:56 +01:00
Sam Atkins
5d965d6d37 LibWeb/CSS: Simplify parse_as_pseudo_element_selector()
Now that we have a method that parses a single pseudo-element selector,
use that. This actually fixes a bug too.
2026-04-18 08:56:25 +02:00