We add scroll-timeline rule into the stylesheet rule type, and add a new
perference to protect it: layout.css.scroll-linked-animations.enabled.
We will use this perference for animation-timeline property as well.
Differential Revision: https://phabricator.services.mozilla.com/D125765
Not hooked anywhere yet, so this doesn't change behavior, but adds the
basic data model etc.
Adding parsing support requires some changes to cssparser to allow the
same at rule to be block and statement-like at the same time, so better
done separately.
Differential Revision: https://phabricator.services.mozilla.com/D124079
This should be both a memory and speed win for pages using a lot of
Shadow DOM.
In order to make the cache properly work we need to start keying media query
results on the actual StyleSheetContents, as that's what we share on Gecko, but
that should all be fine.
Differential Revision: https://phabricator.services.mozilla.com/D107266
In order to determine whether classes or ids are case insensitive we
need the document quirks mode. The sheet quirks mode almost always
matches, but may not match when sheets are added by privileged APIs.
Differential Revision: https://phabricator.services.mozilla.com/D95061
Also, for changes in CSS declarations, like changing
cssRules[i].style.color or something, we end up avoiding a lot of the
work we were doing.
This page still trips us in the sense that they add a stylesheet, then
call getBoundingClientRect(), then insert more rules in the stylesheet,
which causes us to rebuild a lot of the cascade data.
We could try to detect appends to the last stylesheet on the list or
something I guess, and avoid rebuilding the cascade data in some cases.
Depends on D85615
Differential Revision: https://phabricator.services.mozilla.com/D85616
This fixes performance issues when there's a massive number of rules and
a massive DOM.
Instead of going through all rules for all the DOM, we now look stuff in
hashmaps.
Differential Revision: https://phabricator.services.mozilla.com/D83506
Instead add a pseudo-class that does the expected size="" attribute parsing.
Removing the Gtk-specific rule setting the text color since it doesn't
seem to have any effect currently.
Differential Revision: https://phabricator.services.mozilla.com/D83448
This should help out quite a bit with uBO, which has lots of very
general attribute selectors. We invalidate per attribute name rather
than using a SelectorMap, which prevents matching for attribute
selectors that can't have changed.
The idea is that this should be generally cheaper, though there are
cases where this would be a slight pesimization. For example, if there's
an attribute selector like:
my-specific-element[my-attribute] { /* ... */ }
And you change `my-attribute` in an element that isn't a
`my-specific-element`, before that the SelectorMap would've prevented us
from selector-matching completely. Now we'd still run selector-matching
for that (though the matching would be pretty cheap).
However I think this should speed up things generally, let's see what
the perf tests think before landing this though.
Differential Revision: https://phabricator.services.mozilla.com/D76825
After bug 1632647, we can have pseudo-classes inside :not / :is /
:where, which the invalidation and matching code weren't handling.
Add a few tests for this stuff working as expected.
Differential Revision: https://phabricator.services.mozilla.com/D76160
See the comment about why this is valuable. For a selector like:
.foo:is(.bar) > .baz
Before this patch we'd generate an Dependency for .bar like this:
Dependency {
selector: .bar,
offset: 0,
parent: Some(Dependency {
selector: .foo:is(.bar) > .baz,
offset: 1, // Pointing to the `>` combinator.
parent: None,
}),
}
After this patch we'd generate just:
Dependency {
selector: .foo:is(.bar) > .baz,
offset: 1, // Pointing to the `>` combinator.
parent: None,
}
This is not only less memory but also less work. The reason for that is that,
before this patch, when .bar changes, we'd look the dependency, and see there's
a parent, and then scan that, so we'd match `.bar` two times, one for the
initial dependency, and one for .foo:is(.bar).
Instead, with this we'd only check `.foo:is(.bar)` once.
Differential Revision: https://phabricator.services.mozilla.com/D71423
That way we can look at the parent dependency as described in the previous
patch. An alternative would be to add a:
parent_dependency: Option<&'a Dependency>
on construction to `Invalidation`, but this way seems slightly better to avoid
growing the struct. It's not even one more indirection because the selector is
contained directly in the Dependency struct.
Differential Revision: https://phabricator.services.mozilla.com/D71422
The tricky part of :is() and :where() is that they can have combinators inside,
so something like this is valid:
foo:is(#bar > .baz) ~ taz
The current invalidation logic is based on the assumption that you can
represent a combinator as a (selector, offset) tuple, which are stored in the
Dependency struct. This assumption breaks with :is() and :where(), so we need
to make them be able to represent a combinator in an "inner" selector.
For this purpose, we add a `parent` dependency. With it, when invalidating
inside the `:is()` we can represent combinators inside as a stack.
The basic idea is that, for the example above, when an id of "bar" is added or
removed, we'd find a dependency like:
Dependency {
selector: #bar > .baz,
offset: 1, // pointing to the `>` combinator
parent: Some(Dependency {
selector: foo:is(#bar > .baz) > taz,
offset: 1, // Pointing to the `~` combinator.
parent: None,
})
}
That way, we'd start matching at the element that changed, towards the right,
and if we find an element that matches .baz, instead of invalidating that
element, we'd look at the parent dependency, then double-check that the whole
left-hand-side of the selector (foo:is(#bar > .baz)) actually changed, and then
keep invalidating to the right using the parent dependency as usual.
This patch only builds the data structure and keeps the code compiling, the
actual invalidation work will come in a following patch.
Differential Revision: https://phabricator.services.mozilla.com/D71421
See the comment about why this is valuable. For a selector like:
.foo:is(.bar) > .baz
Before this patch we'd generate an Dependency for .bar like this:
Dependency {
selector: .bar,
offset: 0,
parent: Some(Dependency {
selector: .foo:is(.bar) > .baz,
offset: 1, // Pointing to the `>` combinator.
parent: None,
}),
}
After this patch we'd generate just:
Dependency {
selector: .foo:is(.bar) > .baz,
offset: 1, // Pointing to the `>` combinator.
parent: None,
}
This is not only less memory but also less work. The reason for that is that,
before this patch, when .bar changes, we'd look the dependency, and see there's
a parent, and then scan that, so we'd match `.bar` two times, one for the
initial dependency, and one for .foo:is(.bar).
Instead, with this we'd only check `.foo:is(.bar)` once.
Differential Revision: https://phabricator.services.mozilla.com/D71423
That way we can look at the parent dependency as described in the previous
patch. An alternative would be to add a:
parent_dependency: Option<&'a Dependency>
on construction to `Invalidation`, but this way seems slightly better to avoid
growing the struct. It's not even one more indirection because the selector is
contained directly in the Dependency struct.
Differential Revision: https://phabricator.services.mozilla.com/D71422
The tricky part of :is() and :where() is that they can have combinators inside,
so something like this is valid:
foo:is(#bar > .baz) ~ taz
The current invalidation logic is based on the assumption that you can
represent a combinator as a (selector, offset) tuple, which are stored in the
Dependency struct. This assumption breaks with :is() and :where(), so we need
to make them be able to represent a combinator in an "inner" selector.
For this purpose, we add a `parent` dependency. With it, when invalidating
inside the `:is()` we can represent combinators inside as a stack.
The basic idea is that, for the example above, when an id of "bar" is added or
removed, we'd find a dependency like:
Dependency {
selector: #bar > .baz,
offset: 1, // pointing to the `>` combinator
parent: Some(Dependency {
selector: foo:is(#bar > .baz) > taz,
offset: 1, // Pointing to the `~` combinator.
parent: None,
})
}
That way, we'd start matching at the element that changed, towards the right,
and if we find an element that matches .baz, instead of invalidating that
element, we'd look at the parent dependency, then double-check that the whole
left-hand-side of the selector (foo:is(#bar > .baz)) actually changed, and then
keep invalidating to the right using the parent dependency as usual.
This patch only builds the data structure and keeps the code compiling, the
actual invalidation work will come in a following patch.
Differential Revision: https://phabricator.services.mozilla.com/D71421
This implements the easy / straight-forward parts of the :where / :is
selectors.
The biggest missing piece is to handle properly invalidation when there
are combinators present inside the :where. That's the hard part of this,
actually.
But this is probably worth landing in the interim. This fixes some of
the visitors that were easy to fix.
Differential Revision: https://phabricator.services.mozilla.com/D70788
Other browsers allow this and the spec doesn't really disallow it, so fix it,
add a test and carry on.
Differential Revision: https://phabricator.services.mozilla.com/D65107
--HG--
extra : moz-landing-system : lando
We're vendoring it already so no reason not to. Only a couple dependencies left
after these to get rid of 0.6.
Differential Revision: https://phabricator.services.mozilla.com/D56044
--HG--
extra : moz-landing-system : lando
Some of the stuff, in particular inside GeckoBindings stuff should be
refactored to be less ugly and duplicate a bit less code, but the rest of the
code should be landable as is.
Some invalidation changes are already needed because we weren't matching with
the right shadow host during invalidation (which made existing ::part() tests
fail).
Pending invalidation work:
* Making exportparts work right on the snapshots.
* Invalidating parts from descendant hosts.
They're not very hard but I need to think how to best implement it:
* Maybe get rid of ShadowRoot::mParts and just walk DOM descendants in the
Shadow DOM.
* Maybe implement a ElementHasExportPartsAttr much like HasPartAttr and use
that to keep the list of elements.
* Maybe invalidate :host and ::part() together in here[1]
* Maybe something else.
Opinions?
[1]: https://searchfox.org/mozilla-central/rev/131338e5017bc0283d86fb73844407b9a2155c98/servo/components/style/invalidation/element/invalidator.rs#561
Differential Revision: https://phabricator.services.mozilla.com/D53730
--HG--
extra : moz-landing-system : lando
And do a full restyle only when the state goes from visited to unvisited or vice
versa. That is, use regular invalidation for addition or removals of href
attributes, for example.
Differential Revision: https://phabricator.services.mozilla.com/D50821
--HG--
extra : moz-landing-system : lando
If the sets get too big we cannot allocate anything else, we'll just empty them
and invalidate the whole document.
Differential Revision: https://phabricator.services.mozilla.com/D46828
--HG--
extra : moz-landing-system : lando
This patch invalidates the style for `::selection`, which will restore the behavior before the regression.
However, it's still not quite correct, because repaint is not triggered. Given that `::selection` requires some major change to implement https://github.com/w3c/csswg-drafts/issues/2474, we can address this problem later.
Differential Revision: https://phabricator.services.mozilla.com/D35305
--HG--
extra : moz-landing-system : lando
Still does nothing, since we still do not collect part rules, but this is all
the plumbing that should allow us to invalidate parts when attributes or state
change on their ancestors.
Depends on D32641
Differential Revision: https://phabricator.services.mozilla.com/D32642
--HG--
extra : moz-landing-system : lando