The doc gives a high-level overview of the style invalidation process. It does not cover sibling invalidation.
Invalidation is the process of marking which elements need their style recalculated in response to a change in the DOM. The simplest possible approach is to invalidate everything in response to every change.
Invalidation sets give us a way to find a smaller set of elements which need recalculation They are not perfect, they err on the side of correctness, so we invalidate elements that do not need recalculation but this are significantly better than recalculating everything. An invalidation set represents
If we have a style rule ".c1 div.c2 { ... }"
then style recalculation is needed when a c1
-class is added or removed as an ancestor of a c2
-class or when a c2
-class is added or removed from a div that is a descendant of a c1
-class element (here adding/removing can be adding/removing an element or just adding/removing these classes on existing elements). We don't want to do full style recalc at the time of adding/removing because there may be more mutations coming. If we can tell immediately that a change forces style recalc then we mark the node as that, otherwise we collect everything as pending invalidation sets.
In the example, if a c1
-class is added to an element in the tree, we need to invalidate all of its descendants which have class c2
. Rather than perform a search right now, we just mark the element with a pending invalidation set that matches against c2
and descends into all light-descendants. (We won't invalidate all div descendants, as class c2
is more specific.)
If class c2
is added to an element in the tree, then it needs recalculation if it has a c1
-class ancestor. We never search up the tree at this point or during style invalidation, we only do that during recalculation, so this becomes an immediate invalidation, even though it may be unnecessary. Similarly, we don't check if the c2
-class element is a div.
Eventually all DOM changes have been turned into immediate invalidations or pending invalidation sets. At this point, we apply all the pending invalidations and then recalculate style for all of the invalidated elements.
For more details see the original invalidation sets design doc and the sibling invalidation design doc.
The data in RuleFeatureSet is built from the style rules and does not change unless the style rules change.
DOM nodes have several bits of style-related state that control style invalidation and recalculation. These are accessed through:
Node::NeedsStyleInvalidation
Node::ChildNeedsStyleInvalidation
Node::NeedsStyleRecalc
Node::ChildNeedsStyleRecalc
This is a map from DOM Node to invalidation sets that should be applied due to updates to that node.
The overview of style invalidation and recalculation is that
RuleFeatureSet
Each RuleSet
produces its own RuleFeatureSet
by calling CollectFeaturesFromRuleData
for each RuleData
. These contain several indexed collections of InvalidationSet
s and some miscellaneous properties.
All of these are merged together to form a final RuleFeatureSet
which used for style purposes.
Changes in the DOM that require updates to styles may get turned into either immediate invalidations or pending invalidations. When a DOM change that could impact style occurs inside a Node
(e.g. a change in class name) this leads to a call into StyleEngine
to record this style-impacting change via one of several FooChangedForElement
methods.
Depending on the type of change, StyleEngine
gathers the relevant InvalidationSet
s and calls PendingInvalidations::ScheduleInvalidationSetsForNode
which will do one or both of
Node::SetNeedsStyleInvalidation
which ensures that the invalidation process will consider this node and add InvalidationSets for this node to the pending invalidation set map.Node::SetNeedsStyleRecalc
with either kLocalStyleChange
or kSubtreeStyleChange
When style is about to be read, the map of pending invalidations which has been built up needs to be pushed. For each ContainerNode
in the DOM tree we have 0 or more descendant InvalidationSet
waiting to be applied. The invalidation process starts with a call to StyleInvalidator::Invalidate
which recurses down the tree, depth first. Read the method's inline documentation to understand more about the process.