Commit graph

739 commits

Author SHA1 Message Date
Sam Atkins
b577302f07 LibWeb/CSS: Make media type and feature evaluation combination explicit
Functionally this is the same before, as result is always True or False
before this point, and `True && Foo` evaluates to `Foo`. But this is
more clearly correct, instead of correct by coincidence.
2025-05-23 10:17:58 +01:00
Sam Atkins
a4d3c62524 LibWeb/CSS: Return a MatchResult from MediaFeature::compare()
This commit on its own has no observable behaviour changes, as we still
only return True or False, but for the next commit, we'll need to be
able to return the Unknown state here, and without this change we'd get
regressions.
2025-05-23 10:17:58 +01:00
Sam Atkins
fe7bac73f0 LibWeb/CSS: Stub out a function for serializing ComponentValue sequences
This is very hacky and wrong, but it means there's one place to fix,
instead of one for UnresolvedStyleValue, and one for invalid
MediaFeatureValues which I'm about to implement.
2025-05-23 10:17:58 +01:00
Sam Atkins
987d510dbb LibWeb/CSS: Allow "picture-in-picture" in "display-mode" media feature
We don't implement detection for this yet, but it gets us a WPT pass.
2025-05-23 10:17:58 +01:00
Sam Atkins
38aca62ef5 LibWeb/CSS: Make media-type more permissive
The current spec defines this simply as `<ident>`, but does apparently
serialize as lowercase.

Because of this change, we no longer need to care about the deprecated
media types, as they all behave the same as unknown ones.

We still keep an enum around for KnownMediaType, to avoid repeated
string comparisons when evaluating it.

Gets us 2 WPT passes.
2025-05-23 10:17:58 +01:00
Lion Kortlepel
900500c0b3 LibWeb: Remove obsolete font-style Keyword handling
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
`Parser::parse_font_style_value()` only produces
FontStyleStyleValues now, so we no longer need this
branch.
2025-05-22 17:39:05 +01:00
Lion Kortlepel
b1ee539e9d LibWeb: Fix font-style to slope conversion
In a recent refactor of font styles, the new FontStyleStyleValue was
introduced; however, the `to_font_slope()` function was not changed to
understand this new type. When it tries to convert such a font style to
a keyword, it fails. We then rendered the wrong font-style.
2025-05-22 17:39:05 +01:00
Veeti Paananen
7c4fd9f624 LibWeb/CSS: Use case insensitive tag and attribute name in ancestor hash
Fixes #4793.
2025-05-21 08:54:40 -04:00
Shannon Booth
579730d861 LibWeb: Prefer using equals_ignoring_ascii_case
Which has an optmization if both size of the string being passed
through are FlyStrings, which actually ends up being the case
in some places during selector matching comparing attribute names.
Instead of maintaining more overloads of
Infra::is_ascii_case_insensitive_match, switch
everything over to equals_ignoring_ascii_case instead.
2025-05-21 13:45:02 +01:00
Andreas Kling
d7cd8f0fc7 LibWeb: Make CSS sign(A) ignore A's unit and just look at the raw value
This allows stuff like sign(1em) even when we don't have something to
resolve the em unit against.

+25 new WPT subtest passes.
2025-05-20 13:28:40 +02:00
Andreas Kling
4ef34ebd96 LibWeb: Make CSS sign(A) behave correctly for negative zero
We were incorrectly returning 0 instead of -0 for sign(-0).

+7 new WPT subtest passes.
2025-05-20 13:28:40 +02:00
Andreas Kling
c1e79d0b13 LibWeb: Handle calc() in CSS z-index
We also make getComputedStyle() reflect the actually used z-index value,
since otherwise this change is hard to observe.

+26 new WPT subtest passes.
2025-05-20 13:28:40 +02:00
Andreas Kling
821d54de7f LibWeb: Invalidate layout tree on CSS position property change
When position changes, we may need to make larger structural updates
to the layout tree. A simple relayout is not sufficient.

This was a source of flakiness in the engine, and gives us at least
+28 new WPT subtest passes.
2025-05-20 13:28:40 +02:00
Sam Atkins
6e45d8ba6c LibWeb/CSS: Set enum sizes for PropertyID and Keyword
The effect of this is hard to measure, but reducing them from 4 bytes
each to 2 bytes can't hurt. :^)
2025-05-20 10:14:21 +12:00
Sam Atkins
c4bcbff59a LibWeb/CSS: Set enum sizes for media query types
This reduces `MediaFeature` from 112 to 104 bytes.
2025-05-20 10:14:21 +12:00
rmg-x
e2fa8cf7a8 LibWeb+Tests: Continue variable expansion if CSS-wide keyword is parsed
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
This allows the existing fallback logic in `Parser::expand_variables` to
run when a CSS-wide keyword is encountered.
2025-05-19 16:32:07 +01:00
Tim Ledbetter
09f4d90594 LibWeb: Clamp interpolated values to the range of their numeric type
This fixes a UBSAN warning that we previously hit when interpolating
color values.
2025-05-19 11:31:47 +01:00
Andreas Kling
cef9564728 LibWeb: Only serialize CSS numbers with up to 5 decimals
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
This fixes an issue where we'd serialize some floating point numbers
with excessive precision, resulting in unpleasant-looking numbers like
0.49999999999999999 and such.

At least 90 new subtests passing on WPT, possibly more. :^)
2025-05-18 17:23:34 +02:00
Sam Atkins
233022c473 LibWeb/CSS: Allow empty trailing group when parsing comma-separated list
Some checks are pending
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
There's discussion in the linked spec issue, but the short version is,
this algorithm will see "foo,bar," as a list of two groups, with "foo"
in the first group and "bar" in the second. However, users of this want
to get a list of three groups, with the last one being empty. So, do
that!
2025-05-17 07:53:24 +01:00
Sam Atkins
338282f74d LibWeb/CSS: Treat x resolution unit separately from dppx
Tests show that we need to preserve whether x or dppx units were used,
so the simplest way is to treat them separately.
2025-05-17 07:53:24 +01:00
Sam Atkins
443f9e5afb LibWeb/CSS: Make dimension types serialize in resolved form
Some dimensions would always serialize in a canonical unit, others never
did, and others we manually would do so in their StyleValue. This
commit moves all of that into the dimension types, which means for
example that Length can apply its special rounding.

Our local serialization test now produces the same output as other
browsers. :^)
2025-05-17 07:53:24 +01:00
Sam Atkins
eec4365542 LibWeb/CSS: Extract SerializationMode into its own header
Prep for using this to serialize dimension types, and perhaps other
things in the future.
2025-05-17 07:53:24 +01:00
Callum Law
2bb40b615a LibWeb: Allow parsing of <quirky-color> 2025-05-17 06:47:55 +01:00
Sam Atkins
ffdf0268dd LibWeb/CSS: Make debug messages in parse_simple_selector() more useful 2025-05-17 00:30:44 +02:00
Sam Atkins
7de5032e73 LibWeb/CSS: Serialize the initial combinator of relative selectors
Selector::serialize() is used for both normal and relative selectors.
For the latter, we need to serialize their initial combinator, and for
the former, we always set the initial combinator as None anyway, so
this would be a no-op there.

Gets us 3 WPT passes.
2025-05-17 00:30:44 +02:00
Sam Atkins
8536e23674 LibWeb/CSS: Parse an ident in :dir(), not a keyword
The spec requires us to accept any ident here, not just ltr/rtl, and
also serialize it back out. That means we need to keep the original
string around.

In order to not call keyword_from_string() every time we want to match
a :dir() selector, we still attempt to parse the keyword and keep it
around.

A small behaviour change is that now we'll serialize the ident with its
original casing, instead of always lowercase. Chrome and Firefox
disagree on this, so I think either is fine until that can be
officially decided.

Gets us 2 WPT passes (including 1 from the as-yet-unmerged :dir() test).
2025-05-17 00:30:44 +02:00
Sam Atkins
7aed541ed0 LibWeb/CSS: Automatically serialize functional pseudo-class arguments
The spec gives us a hard-coded list of functional pseudo-classes and how
to serialize them - but this list is incomplete and likely to always be
outdated compared to the list of pseudo-classes that exist. So instead,
use the generated metadata we already have to serialize their arguments
based on their type.

This fixes :dir() and :has(), which previously did not serialize their
arguments.

Gets us 26 passes (including 6 from that as-yet-unmerged :dir() test).
2025-05-17 00:30:44 +02:00
Sam Atkins
26d71207d4 LibWeb/CSS: Treat *|* selector like * when serializing
1 new WPT pass.
2025-05-17 00:30:44 +02:00
Sam Atkins
c9484e279f LibWeb/CSS: Implement CSSPageRule.setSelectorText()
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Gets us 12 WPT subtest passes.
2025-05-16 16:42:10 +01:00
Sam Atkins
d852ae17e8 LibWeb/CSS: Make @page selector parsing accessible
Mostly minor changes - the code has moved, and has to support Token or
ComponentValue TokenStreams, but otherwise it's the same.
2025-05-16 16:42:10 +01:00
Sam Atkins
107b47f884 LibWeb/CSS: Move PageSelector into its own files
The main motivation here is that the CSS Parser needs to know about
PageSelectorList so that we can parse one in
`CSSPageRule::set_selector_text()`. Including all of `CSSPageRule.h`
there would pull in a lot of other headers that aren't needed.
2025-05-16 16:42:10 +01:00
Sam Atkins
869abe0b21 LibWeb/CSS: Match *-namespace selectors against all attributes
Previously we only matched against the first attribute with a given
local name. What we actually want to do is look at each attribute with
that local name in turn and only return false if none of them match.

Also remove a hack for HTML elements in HTML documents, where we would
refuse to match any namespaced attributes. This doesn't seem to be
based on the spec, but we had regressions without it, until now. :^)

Gets us 21 more WPT subtest passes.
2025-05-16 16:41:57 +01:00
Sam Atkins
ecdfb96a0a LibWeb/CSS: Limit case-insensitive default comparison to HTML attributes
The HTML spec gives us a list of HTML attributes that must have their
values compared case-insensitively by default (when the attribute
selector does not specify a case-sensitiveness). However, ifwe have a
namespace, then we are not looking for an HTML attribute, so this
should not apply.

Gets us 8 more WPT subtest passes.
2025-05-16 16:41:57 +01:00
Sam Atkins
d9113e45f0 LibWeb/CSS: Discard trailing whitespace inside attribute selectors
This gets us 84 more subtests, so everything in this syntax test passes.
2025-05-16 16:41:57 +01:00
Sam Atkins
3914bf05fb LibWeb/CSS: Serialize * namespace in attribute selectors
Gets us 13 WPT subtest passes.
2025-05-16 16:41:57 +01:00
Sam Atkins
870f24f181 LibWeb/CSS: Add basic implementation of CSSMarginRule
This is a bit under-specced, specifically there's no definition of
CSSMarginDescriptors so I've gone with CSSStyleProperties for now. Gets
us 17 WPT subtests.
2025-05-16 11:01:39 +01:00
Sam Atkins
aa9fa88428 LibWeb/CSS: Treat at-rule names insensitively to determine context type
`@MeDiA` is entirely valid.
2025-05-16 11:01:39 +01:00
Sam Atkins
1fe29ac642 LibWeb/CSS: Bring :lang() matching closer to spec
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
With this, we pass the 8 ref tests in css/selectors/selectors-4/ which
previously failed. This is not technically a full implementation, as we
are supposed to first canonicalize the language range and tag, but that
will require downloading and processing the IANA language subtag
registry:

https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry

That's significantly more work, and WPT doesn't seem to test any cases
that require that, so we can leave it for now.
2025-05-15 16:40:44 +01:00
Sam Atkins
3a235e9050 LibWeb/CSS: Parse @page bleed, marks, page-orientation descriptors
These don't have WPT tests so I've added some myself.
2025-05-15 09:53:29 +01:00
Sam Atkins
9415bffd9b LibWeb/CSS: Parse @page size descriptor 2025-05-15 09:53:29 +01:00
Sam Atkins
d8c6b872a3 LibWeb/CSS: Allow descriptors to be shorthands
I was wrong when I added those notes before about this being impossible,
it's *very* possible, for example with the `@page margin` descriptor.
However, until we have a large number of these shorthands and not just a
single example, we can get away with hard-coding support for it.
2025-05-15 09:53:29 +01:00
Sam Atkins
1aa5631610 LibWeb/CSS: Parse @page selectors
Ideally we'd be able to share the code between page selectors and style
ones, but given how simple page selectors are, some code duplication is
the simpler option.
2025-05-15 09:53:29 +01:00
Sam Atkins
aaf07ae30d LibWeb: Add basic implementation of @page
This doesn't support selectors, and the only descriptors for now are for
margins.
2025-05-15 09:53:29 +01:00
Sam Atkins
73fa567e7a LibWeb/CSS: Remove now-unused AllowUnresolved enum
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
This mechanism has been replaced with PendingSubstitutionValues.
2025-05-14 11:46:47 +01:00
Sam Atkins
4edafb35cd LibWeb/CSS: Use PendingSubstitutionValue for unresolved shorthands
Previously, we would just assign the UnresolvedStyleValue to each
longhand, which was completely wrong but happened to work if it was a
ShorthandStyleValue (because that's basically a list of "set property X
to Y", and doesn't care which property it's the value of).

For example, the included `var-in-margin-shorthand.html` test would:
1. Set `margin-top` to `var(--a) 10px`
2. Resolve it to `margin-top: 5px 10px`
3. Reject that as invalid

What now happens is:
1. Set `margin-top` to a PendingSubstitutionValue
2. Resolve `margin` to `5px 10px`
3. Expand that out into its longhands
4. `margin-top` is `5px` 🎉

In order to support this, `for_each_property_expanding_shorthands()` now
runs the callback for the shorthand too if it's an unresolved or
pending-substitution value. This is so that we can store those in the
CascadedProperties until they can be resolved - otherwise, by the time
we want to resolve them, we don't have them any more.

`cascade_declarations()` has an unfortunate hack: it tracks, for each
declaration, which properties have already been given values, so that
it can avoid overwriting an actual value with a pending one. This is
necessary because of the unfortunate way that CSSStyleProperties holds
expanded longhands, and not just the original declarations. The spec
disagrees with itself about this, but we do need to do that expansion
for `element.style` to work correctly. This HashTable is unfortunate
but it does solve the problem until a better solution can be found.
2025-05-14 11:46:47 +01:00
Sam Atkins
398d2f9981 LibWeb/CSS: Implement pending-substitution value
This is a special value temporarily assigned to longhands when their
shorthand is unresolved, and then later replaced once that is resolved.
2025-05-14 11:46:47 +01:00
Sam Atkins
59e8a669de LibWeb/CSS: Unify code in StyleComputer::cascade_declarations() 2025-05-14 11:46:47 +01:00
Sam Atkins
d1dadd43a1 LibWeb/CSS: Implement guaranteed-invalid value
This is a special value produced when var/attr substitution fails, and
is also the initial value for custom properties.
2025-05-14 11:46:47 +01:00
Sam Atkins
804c1eeeed LibWeb/CSS: Remove double set_property_expanding_shorthands() call
If `value` was UnresolvedStyleValue, we'd attempt to `set_property...()`
with its resolved value, then call that again with the original
UnresolvedStyleValue. For any other kind of `value`, we'd simply call
call `set_property...()` twice with the same parameters.
2025-05-14 11:46:47 +01:00
Sam Atkins
ded3c95da5 LibWeb/CSS: Remove unused FontVariant style value type 2025-05-14 11:46:47 +01:00