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.
By doing that we avoid lots of `PropertyKey` -> `Value` -> `PropertyKey`
transforms, which are quite expensive because of underlying
`FlyString` -> `PrimitiveString` -> `FlyString` conversions.
10% improvement on MicroBench/object-keys.js
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.
Adds `matches_webm_signature()` and `parse_vint()` helpers per WPT
spec. Uses these helpers to resolve the WebM FIXME that was in
`match_an_audio_or_video_type_pattern()`.
Our Ranges should maintain the invariant that their offsets are always
within range of 0..length (inclusive) of their respective containers.
Note that we cannot maintain this in AbstractRange, which is the base
for StaticRange and can still have invalid offsets.
156c1083e9 introduced a text blocks cache
for better performance when searching through text on a page, but when
we partially recreate the layout tree, this cache does not get
invalidated. We now rebuild the entire text blocks cache after a layout
update.
We were calling into `Range::set_start_or_end()` indirectly through
`::set_start()` and `::set_end()`, but that algorithm only calls for an
invocation whenever the start or end of a range needs to be set to a
boundary point. If an algorithm step calls for setting the node or
offset, we should directly modify the range.
The problem with calling into `::set_start_or_end()` is that this
algorithm potentially modifies _both_ the start and end of the range,
but algorithms trying to update a range's start or end often have
explicit steps to take both the start and end into account and end up
overcompensating for the start or end offset resulting in an invalid
range (e.g. with an end offset beyond a node's length).
This makes updating a range's start/end a bit more efficient and removes
a piece of ad-hoc code in CharacterData needed to make it work before.
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.
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.
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.
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.
This implements the previously stubbed out `report_validity` method.
The specification is not very clear on how to exactly report the
validity. For now, we bring the first visible invalid control into
view and focus it. In the future, however, it would make sense to
support more complex scenarios and be more aligned with the other
implementations.