`<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.
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.
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.
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`.
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.
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
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.
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.
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
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
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.
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.
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.
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.
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
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.