We now do the proper thing in terms of:
- Allowing percentages
- Returning the computed value in getComputedStyle
- Handling values out of the [0,1] range
Gains us 13 WPT passes in the imported tests.
Add global registry for registered properties and partial support
for `@property` rule. Enables registering properties with initial
values. Also adds basic retrieval via `var()`.
Note: This is not a complete `@property` implementation.
`<syntax>` is a limited subset of the "value definition syntax" used in
CSS specs. It's used for `@property`'s `syntax` descriptor, and for the
`type()` function in `attr()`.
UnresolvedStyleValue::create() has one user where we know if there are
any arbitrary substitution functions in the list of CVs, and two users
where we don't know and just hope there aren't any. I'm about to add
another user that also doesn't know, and so it seems worth just making
UnresolvedStyleValue::create() do that work instead.
We keep the parameter, now Optional<>, so that we save some redundant
work in that one place where we do already know.
The existing resolve methods are not to spec and we are working to
replace them with new ones based on the `simplify_a_calculation_tree`
method.
These are marked as deprecated rather than replaced outright as work
will need to be done on the caller side to be made compatible with the
new methods, for instance the new methods can fail to resolve (e.g.
if we are missing required context), where the existing methods will
always resolve (albeit sometimes with an incorrect value).
No functionality changes.
We were previously handling this ad-hoc via logic in
`get_property_internal` but this didn't cover all contexts (for
instance `CSSStyleProperties::serialized`.
Gains us 9 more WPT tests as we now cover properties which weren't
included in the previous ad-hoc approach.
Previously if we encountered a keyword other than `fill` when parsing
`<border-image-slice` we would return a nullptr.
This could cause issues when we parse `<border-image-slice>` as part of
parsing `border-image`, for example `border-image: 100% none` would fail
as we would try parse `none` as part of the `<border-image-slice>`
instead of `<border-image-source>`.
This change makes it so that we don't consume the token and leave it to
be parsed as part of the next section of the grammar.
The attack unfortunately still slows us down, but this prevents us from
OOMing. Currently, we don't save the value of `var(--foo)` after
computing it once, so in this example, we end up computing `--prop1` 4
times to compute `--prop3`, but then we start again from scratch when
computing `--prop4`:
```css
--prop1: lol;
--prop2: var(--prop1) var(--prop1);
--prop3: var(--prop2) var(--prop2);
--prop4: var(--prop3) var(--prop3);
}
```
This should be solvable later if we update the computed values as we go.
"Arbitrary substitution functions" are a family of functions that
includes var() and attr(). All of them resolve to an arbitrary set of
component values that are not known at parse-time, so they have to be
substituted at computed-value time.
Besides it being nice to follow the spec closely, this means we'll be
able to implement the others (such as `if()` and `inherit()`) more
easily.
The main omission here is the new "spread syntax", which can be
implemented in the future.
This has an extra parameter to allow stopping at the first comma token,
which we need for var() and attr()'s "argument grammar".
Co-authored-by: Tim Ledbetter <tim.ledbetter@ladybird.org>
Custom properties are required to produce a computed value just like
regular properties. The computed value is defined in the spec as
"specified value with variables substituted, or the guaranteed-invalid
value", though in reality all arbitrary substitution functions should be
substituted, not just `var()`.
To support this, we parse the CSS-wide keywords normally in custom
properties, instead of ignoring them. We don't yet handle all of them
properly, and because that will require us to cascade them like regular
properties. This is just enough to prevent regressions when implementing
ASFs.
Our output in this new test is not quite correct, because of the awkward
way we handle whitespace in property values - so it has 3 spaces in the
middle instead of 1, until that's fixed.
It's possible this computed-value production should go in
cascade_custom_properties(), but I had issues with that. Hopefully once
we start cascading custom properties properly, it'll be clearer how
this should all work.
Treating these like any other ComponentValue means not having to convert
between different types of Vector, and that we will be able to use
TokenStream to parse the "argument grammars" of arbitrary substitution
functions.
Previously the type argument in attr() could be the name of a CSS type
on its own. This has changed, and now only `raw-string`
(previously `string`) or the name of a dimension unit is allowed. Other
types and more complex grammar use the `type()` function, which we
don't yet support.
I've updated the syntax comment, but not the algorithm itself, which
will be reimplemented in a later commit.
Add `create_foo()` static methods for the missing Token::Types, and use
them in the Tokenizer. This means we slightly deviate from the spec now:
it says "create foo token... set its bar to 32", but we now just wait
and construct the Token fully-formed. But those cases are short so it
should still be clear what we're doing.
This makes it possible to construct all kinds of Token elsewhere, such
as for testing purposes.
No functional changes. The main difference is renaming the cursor enum
to match the spec term `<cursor-predefined>`, which is a bit more
verbose but clearer in meaning.
Corresponds to 1a57a4025c
This brings parsing of grid-row-* and grid-column-* properties (and
their associated shorthands) more inline with spec.
Changes:
- Only set omitted properties for combined-value shorthands (e.g.
`grid-row: a` rather than `grid-row: a / b`) if the single value is
`<custom-ident>`.
- `[ [ <integer [-∞,-1]> | <integer [1,∞]> ] && <custom-ident>? ]`:
- Properly resolve `calc`s for `<integer>` that rely on compute-time
information.
- `[ span && [ <integer [1,∞]> || <custom-ident> ] ]`
- Allow `calc`s for `<integer>`
- Allow `<custom-ident>`
There is still work to be done to properly use these parsed values.
Gains us 46 WPT tests.
Our floating point number parser was based on the fast_float library:
https://github.com/fastfloat/fast_float
However, our implementation only supports 8-bit characters. To support
UTF-16, we will need to be able to convert char16_t-based strings to
numbers as well. This works out-of-the-box with fast_float.
We can also use fast_float for integer parsing.
Previously, we would allow calc values such as `calc(min(1 2))`, which
would be simplified to `calc(3)` because we assumed that numbers not
separated by an operator represented a sum. We now validate that the
number of operators we see is as we would expect before collecting
these values into a sum node.
Reimplements `grid`, `grid-template`, `grid-template-rows`, and
`grid-template-columns` in a way that uses a separate function for each
grammar rule defined in the specification. This change results in many
additional passing tests from the already imported WPT suite. Most of
the remaining test failures are related to incorrect serialization of
grid properties.