When we had:
@layer A.B;
We were registering "A" and "B", not "A" and "A.B", which was the intention.
Fix is trivial.
Depends on D124620
Differential Revision: https://phabricator.services.mozilla.com/D124621
This makes layer order use a fixed set of bits per nesting level, to "reserve"
bits for children before they are registered.
See the comment in LayerOrder for the implementation limits it imposes, and
potential alternatives if these limits are not enough (but I think they should
be).
Enable the tests, as they mostly pass now (commit incoming to fix the remaining
ones).
Differential Revision: https://phabricator.services.mozilla.com/D124620
This works modulo the existing nested layer order bug. Will be covered
by WPT /css/css-cascade/layer-import.html once the feature is enabled (I
can probably enable it right away for those tests, but I'd rather fix
the obvious bugs first).
Differential Revision: https://phabricator.services.mozilla.com/D124538
Same, I want to land this separately to see if it affects
micro-benchmarks. If so, we might want to pack the layer order
_somewhere_ (though in this case I'm not sure where, tbh).
With this, layer rules should have an effect on the page. There are
a few things missing before being able to enable them:
* Fix nested layer order in some cases (when parent layers are declared
out of order, see the previous commit mentioning this).
* Some kind of OM representation, perhaps.
* Tests of course, which are coming in bug 1728722 and bug 1727276.
But this should be enough to allow playing with them.
Depends on D124337
Differential Revision: https://phabricator.services.mozilla.com/D124338
I want to land this separately because we might want to get smarter with
the size of the Rule struct (maybe restricting layer order to a u8 per
scope and packing it with the source order, since 255 layers seem
plenty), but I'd rather do the obvious thing for now.
Depends on D124336
Differential Revision: https://phabricator.services.mozilla.com/D124337
This code is really hot, and we've had perf regressions in the past for
introducing function calls in the hot path.
After the previous patch, add_rule is recursive and thus it can't be
inlined, causing a function call for each CSS rule.
This reduces the overhead by making the function take a rule list
instead, causing a function call per rule _list_, which should be
unnoticeable in practice.
Depends on D124335
Differential Revision: https://phabricator.services.mozilla.com/D124336
For that, deal with children in add_rule recursively, to keep the
current layer name up-to-date in block layer rules.
This is not the final version of this code, as right now something like
this:
@layer A {
...
}
@layer B {
...
}
@layer A.A {
...
}
Would give A.A more priority over B, which is not correct. There are
tests for this incoming in wpt sync and such, but that can be tweaked
later.
Differential Revision: https://phabricator.services.mozilla.com/D124335
This shouldn't have any behavior change, but is necessary because for
cascade layers we are going to need to handle the child rules / sheets
ourselves, in order to handle nested layers properly.
Differential Revision: https://phabricator.services.mozilla.com/D124334
See the discussion here: https://twitter.com/Rich_Harris/status/1433153204678799365
This should make attribute selectors roughly as fast as class selectors.
I think it's worth trying and see if perf bots complain on
micro-benchmarks and stylebench and such.
I made attributes more specific than local names, but less specific than
classes, which I think makes sense. When doing something like
foo[data-bar], filtering by data-bar seems likely to yield less elements
than filtering by foo.
While at it, remove the bloom filter pref since we shipped it in
bug 1704551 for 87 and we haven't heard complaints.
Differential Revision: https://phabricator.services.mozilla.com/D124383
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 prevents incorrectly reusing cached results when the contents go
away and new contents are allocated with the same address.
Note that these keep alive transitively everything else under them, so
all other medialist keys don't need this.
By making this a proper hashmap it should also improve cache lookup
times if the cache grows too big.
Differential Revision: https://phabricator.services.mozilla.com/D115202
So that sheets are properly marked as committed. The issue is that we
have this "committed" optimization, to avoid doing work if somebody adds
and removes an stylesheet without us flushing in the meantime:
https://searchfox.org/mozilla-central/rev/f018480dfed4fc583703a5770a6db9ab9dc0fb99/servo/components/style/stylesheet_set.rs#308-319
The "committed" bit is set when we consume the flusher (in each(..)).
However when we hit the cache, before this patch, we wouldn't consume
it, which means that we may fail to do some full rebuilds even though we
need them.
Fix it by making sure we call each() in that case.
We add a test (the test would show a red square before this patch, and a
lime square with the fix).
Differential Revision: https://phabricator.services.mozilla.com/D113206
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
Actually, there's not so much we can improve right now, in the sense
that:
* We need the ::-moz-page-content pseudo-element to be able to set
`display` on the page, since that's a style rule rather than a @page
rule. We could get away without it.
* Keeping the current code-path (slightly cleaned up) is less code, for
now at least. We can have a separate code-path or what not that
actually performs the @page rule selector-matching and what not if
needed when we get to named pages or other page selectors. Selectors
like :first should be pretty trivial to implement, actually.
We make some paged mode anon boxes non-inheriting anon boxes. This
allows us to share the styles and is generally nicer. They don't need to
inherit from anywhere.
We could remove the origin handling and don't look at UA rules or what
not, but it seems pretty harmless to do that.
We also fix the name of the pseudo-elements to match the capitalization.
Differential Revision: https://phabricator.services.mozilla.com/D104772
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
The current API was pretty awkward as a result of two things:
* Not being able to create empty iterators for smallbitvec.
* We used to call the `F` function multiple times, but turns out that
collecting the declarations in a SmallVec was a perf win.
So clean this up so that it looks more similar to other APIs, taking an
iterator directly.
This is a bit more code, but hopefully easier to understand (and also hopefully
easier to optimize).
The motivation for this work is that I plan to investigate rebasing / landing
https://github.com/servo/servo/pull/20151, and I don't want more instantiations
of apply_declarations and such.
Differential Revision: https://phabricator.services.mozilla.com/D74369
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
The micro-benchmark `style-attr-1.html` regressed slightly with my patch, after
the CascadeLevel size increase.
This benchmark is meant to test for the "changing the style attribute doesn't
cause selector-matching" optimization (which, mind you, keeps working).
But in the process it creates 10k rules which form a perfect path in the rule
tree and that we put into a SmallVec during the cascade, and the benchmark
spends most of the time pushing to that SmallVec and iterating the declarations
(as there's only one property to apply).
So we could argue that the regression is minor and is not what the benchark is
supposed to be testing, but given I did the digging... :)
My patch made CascadeLevel bigger, which means that we create a somewhat bigger
vector in this case. Thankfully it also removed the dependency in the
CascadeLevel, so we can stop using that and use just Origin which is one byte to
revert the perf regression.
Differential Revision: https://phabricator.services.mozilla.com/D53181
I still haven't implemented each_part(), so this will do nothing yet.
The cascade order stuff is fishy, I know, and I'll fix in a followup if it's
fine with you. I moved the sorting of the rules to rule_collector, since it
seemed to me it was better that way that duplicating the code, and those
SelectorMap functions only have a single caller anyway.
Differential Revision: https://phabricator.services.mozilla.com/D32647
Unlike for :host() or ::slotted(), or regular rules, we don't need a whole
SelectorMap<>, so gotta make the code a bit more generic.
Differential Revision: https://phabricator.services.mozilla.com/D32646
This makes *|*::marker do the intended thing in UA sheets, so I think it's
better, and it's a bit less special-casey.
We may want to re-introduce the changes for pseudo-elements at some point,
depending on the WG decision, but this patch makes each_non_document_style_data
consistent with the rule collector.
The changes of each_non_document_style_data on their own should fix some bugs,
but it doesn't because:
* This is only hit for pseudos that allow user-action-state pseudo-classes.
* The containing shadow check worked for them anyway.
* We don't allow any pseudo after ::slotted() or that isn't tree-abiding per
the CSS specs (we should maybe enable one of the moz-range stuff to be
tree-abiding).
So ::placeholder is the only one that right now fits the bill to trigger the
bugs this would fix, but it doesn't since I couldn't make ::placeholder match
:hover / :active / :focus anyhow (inside or outside a shadow tree).
I've left the ProbeMarkerPseudoStyle changes for now since they are technically
a bit more consistent than what was there before, but we could revert those if
they cause trouble, we could rely on the UA rule matching, but we would need to
change that if we allow the ::foo::before and such to match.
Differential Revision: https://phabricator.services.mozilla.com/D29542
We want to drop the cascade data memory as soon as possible, so bug 1544546
introduced an UpdateStylistIfNeeded call from ShellDetachedFromDocument.
Unfortunately, this call can reenter into the global user-agent cascade data if
some of the CSS values kept alive by the cascade data keep alive an SVG
document, see the stack on this bug for an example. Make sure to drop the
user-agent cascade datas when not holding the cache lock to avoid this
situation.
Before bug 1535788, we just destroyed the stylist, so we kept holding a
reference from the cache, and that reference will be dropped sometime later when
other document updated their user-agent stylesheets (if they happened not to
match the cache of course).
Seems to me this doesn't ended up happening in our automation, but it could
happen in the wild, in theory at least.
It's nice that Rust made this a safe deadlock caught by our tests rather than a
very subtle and infrequent memory corruption.
The relevant SVG documents are probably the <input type=number> rules:
https://searchfox.org/mozilla-central/rev/d80f0a570736dce76a2eb184fb65517462089e8a/layout/style/res/forms.css#1050
Differential Revision: https://phabricator.services.mozilla.com/D28299