A couple of differences from before:
- Only the fixed set of strings are allowed. Some formats can only be an
ident (eg, svg).
- We don't allow these foo-variations values in ident form.
- The comparison is done case-insensitively. It's unclear if this is
more or less correct, but as most things in CSS are insensitive,
including idents, it makes sense that these would be too.
"format(woff-variations)" and pals are supposed to expand like so:
"format(woff) tech(variations)".
However, since we don't support tech() yet, this patch just adds a small
hack where we still treat "woff-variations" as "woff" so that fonts
load and get used, even if we don't make use of the variations yet.
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.
ParsedFontFace and FontLoader now both keep track of which
CSSStyleSheet (if any) was the source of the font-face, so the URLs can
be completed correctly.
Math functions like abs(), clamp(), round(), etc, can be used by
themselves in property values, without wrapping them in calc().
Before this change, we were neglecting to run calc simplification on the
generated calculation node trees. By doing that manually after parsing a
standalone math function, we score at least a couple hundred WPT points.
We now don't absolutize the URL during parsing, keeping it as a CSS::URL
object which we then pass to the "fetch an external image for a
stylesheet" algorithm. Our version of this algorithm is a bit ad-hoc,
in order to make use of SharedResourceRequest. To try and reduce
duplication, I've pulled all of fetch_a_style_resource() into a static
function, apart from the "actually do the fetch" step.
Our previous approach to `<url>` had a couple of issues:
- We'd complete the URL during parsing, when we should actually keep it
as the original string until it's used.
- There's nowhere for us to store `<url-modifier>`s on a `URL::URL`.
So, `CSS::URL` is a solution to this. It holds the original URL string,
and later will also hold any modifiers. This commit parses all `<url>`s
as `CSS::URL`, but then converts it into a `URL::URL`, so no user code
is changed. These will be modified in subsequent commits.
For `@namespace`, we were never supposed to complete the URL at all, so
this makes that more correct already. However, in practice all
`@namespace`s are absolute URLs already, so this should have no
observable effects.
To prepare for introducing a CSS::URL type, we need to qualify any use
of LibURL as `::URL::foo` instead of `URL::foo` so the compiler doesn't
get confused.
Many of these uses will be replaced, but I don't want to mix this in
with what will likely already be a large change.
This commit disallows "default" as a font-family name, when the name is
not quoted because unquoted names are treated as custom-idents, for
which the name "default" is not allowed.
The goal here is to do something a bit smarter with the parsing here
than we do for properties. Instead of the JSON saying "here are the
values, and here are the keywords, and we can have up to 3", here we
place the syntax in the JSON directly (though currently broken up as
one string per option) and then we attempt to parse each one in
sequence. It's something we'll need eventually for `@property` among
other things.
...However, in this first pass, I've gone with the simplest option of
hard-coding the types instead of figuring them out properly. So there's
a PositivePercentage type and a UnicodeRangeTokens type, instead of
properly implementing the grammar for those in a generic way.
The `transform` property supports transform functions that sometimes
need their `calc(percentage)` values to be converted to a number instead
of a length. Currently this only applies to the `scale*` family of
functions, which are marked as such in `TransformFunctions.json`.
We were not consistently applying the `NumberPercentage` type to these
functions though, and in addition, any `NumberPercentage` value would
not consider calculated values.
The upcoming generated types will match those for pseudo-classes: A
PseudoElementSelector type, that then holds a PseudoElement enum
defining what it is. That enum will be at the top level in the Web::CSS
namespace.
In order to keep the diffs clearer, this commit renames and moves the
types, and then a following one will replace the handwritten enum with
a generated one.
Before this change, an element masked with 'mask-image: url(...)' would
show the mask, but 'mask: url(...)' would not. On e.g. dialogic.nl it
would show white boxes instead of the actual images in the top
navigation bar. We still do not support many of the other mask
properties, but with this change at least the masks show up in both
cases.
Having multiple kinds of node that hold numeric values made things more
complicated than they needed to be, and we were already converting
ConstantCalculationNodes to NumericCalculationNodes in the first
simplification pass that happens at parse-time, so they didn't exist
after that.
As noted, the spec allows for other contexts to introduce their own
numeric keywords, which might be resolved later than parse-time. We'll
need a different mechanism to support those, but
ConstantCalculationNode could not have done so anyway.
Before this change, we only parsed fit-content as a standalone keyword,
but CSS-SIZING-3 added it as a function as well. I don't know of
anything else in CSS that is overloaded like this, so it ends up looking
a little awkward in the implementation.
Note that a lot of code had already been prepped for fit-content values
to have an argument, we just weren't parsing it.
If the expansion of a custom property in variable expansion returns
tokens, then the custom property is not the initial guaranteed-invalid
value.
If it didn't return any tokens, then it is the initial
guaranteed-invalid value, and thus we should move on to the fallback
value.
Makes Shopify checkout show the background colours, borders, skeletons,
etc.
This is not really a context, but more of a set of parameters for
creating a Parser. So, treat it as such: Rename it to ParsingParams,
and store its values and methods directly in the Parser instead of
keeping the ParsingContext around.
This has a nice side-effect of not including DOM/Document.h everywhere
that needs a Parser.
This file has been a pain to edit for a while, even with the previous
splits. So, I've divided it up into 3 parts:
- Parser.cpp has the "base" code. It's the algorithms and entry-points
defined in the Syntax spec.
- ValueParsing.cpp contains code for parsing single values, such as a
length, or a color, or a calculation.
- PropertyParsing.cpp contains code for parsing an entire property's
value. A few of these sit in a grey area between being a property's
value and a value in their own right, but the rule I've used is "is
this useful outside of a single property and its shorthands?"
This only moves code, with as few modifications as possible to make that
work. I did add explicit instantiations for the template implementations
as part of this, which revealed a few that are actually only compatible
with a single type, so I'll clear those up in a subsequent commit.