83b6bc4 went too far by forbidding SVGSVGElement from establishing a
stacking context. This element type does follow the behavior of CSS
boxes, unlike inner SVG elements like `<rect>`, `<circle>`, etc., which
are not supposed to be aware of concepts like stacking contexts,
overflow clipping, scroll offsets, etc.
This change allows us to delete overrides of `before_paint()` and
`after_paint()` in SVGPaintable and SVGSVGPaintable, because display
list recording code has been rearranged to take care of clipping and
scrolling before recursing into SVGSVGPaintable descendants.
`Screenshot/images/css-transform-box-ref.png` expectation is updated and
fixes a bug where a rectangle at the very bottom of the page was not
clipped correctly.
`Screenshot/images/svg-filters-lb-website-ref.png` has a more subtle
difference, but if you look closely, you’ll see it matches other
browsers more closely now.
Whenever we end up with a scrollable overflow rect that goes beyond
either of its axes (i.e. the rect has a negative X or Y position
relative to its parent's absolute padding box position), we need to clip
that rect to prevent going into the "unreachable scrollable overflow".
This fixes the horizontal scrolling on https://ladybird.org (gets more
pronounced if you make the window very narrow).
We forgot to implement a couple of "otherwise," statements from the
"populating a session history entry" spec. While we're here, let's
update the spec copy where relevant.
Destubs AudioNode::disconnect() and its related overloads.
Ensures that inverse connections are properly removed
when disconnecting AudioNodeConnections. Adds associated
WPT but skips them for now because they rely on
OfflineRenderContext::start_rendering to be fully implemented.
By avoiding recompilation every time `apply_mask_bitmap()` is called, we
save ~5 ms (20ms -> 15ms) in rendering of browser channel on Discord on
my machine.
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.
This is according to the default user-agent style from the SVG2 spec.
In order for this to work correctly, we also have to assign width and
height to foreignObject boxes during SVG layout, since they are handled
manually by SVGFormattingContext.
Before this change, we would never apply CSS rules where the selector
had a mixed-case tag name. This happened because our rule caches would
key them on the lowercased tag name, but we didn't lowercase the tag
name when fetching things from the cache.
This uncovered the fact that the SVG2 spec has a bunch of style applied
to non-rendered elements in a way that doesn't match other browsers.
Instead of blindly following the spec, we now match other browsers.