Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(550)

Unified Diff: Source/core/css/invalidation/StyleInvalidationTreeWalk.cpp

Issue 204873003: Factor the style invalidation tree walk out of RuleFeatureSet, and make it generic. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Move code around. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/css/invalidation/StyleInvalidationTreeWalk.cpp
diff --git a/Source/core/css/invalidation/StyleInvalidationTreeWalk.cpp b/Source/core/css/invalidation/StyleInvalidationTreeWalk.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8740efd6435f543c49e9c33fec8947b4959c1f88
--- /dev/null
+++ b/Source/core/css/invalidation/StyleInvalidationTreeWalk.cpp
@@ -0,0 +1,129 @@
+
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+
+#include "core/css/invalidation/StyleInvalidationTreeWalk.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/ElementTraversal.h"
+#include "core/dom/shadow/ElementShadow.h"
+#include "core/dom/shadow/ShadowRoot.h"
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+
+void StyleInvalidationTreeWalk::computeStyleInvalidation(Document& document, RuleFeatureSet* featureSet)
+{
+ if (Element* documentElement = document.documentElement()) {
+ if (documentElement->childNeedsStyleInvalidation())
+ StyleInvalidationTreeWalk(featureSet).invalidateStyle(documentElement);
+ }
+ document.clearChildNeedsStyleInvalidation();
+ document.clearNeedsStyleInvalidation();
+ featureSet->m_pendingInvalidationMap.clear();
+}
+
+StyleInvalidationTreeWalk::StyleInvalidationTreeWalk(const RuleFeatureSet* featureSet)
+ : m_featureSet(featureSet)
+{
+}
+
+void StyleInvalidationTreeWalk::RecursionData::pushInvalidationSet(const DescendantInvalidationSet& invalidationSet)
+{
+ invalidationSet.getClasses(m_invalidationClasses);
+ m_foundInvalidationSet = true;
+}
+
+bool StyleInvalidationTreeWalk::RecursionData::matchesCurrentInvalidationSets(Element* element)
esprehn 2014/03/19 22:09:04 This should be a method on the InvalidationSet its
chrishtr 2014/03/19 22:49:39 The problem with that is that this code operates o
+{
+ if (!element->hasClass())
+ return false;
+
+ const SpaceSplitString& classNames = element->classNames();
+ for (Vector<AtomicString>::const_iterator it = m_invalidationClasses.begin(); it != m_invalidationClasses.end(); ++it) {
+ if (classNames.contains(*it))
+ return true;
+ }
+
+ return false;
+}
+
+bool StyleInvalidationTreeWalk::checkInvalidationSetsAgainstElement(Element* element)
esprehn 2014/03/19 22:09:04 invalidateOwnStyle. These should match recalcStyl
chrishtr 2014/03/19 22:49:39 This method does not do a full invalidation. We do
+{
+ bool thisElementNeedsStyleRecalc = false;
+ if (element->needsStyleInvalidation()) {
+ if (RuleFeatureSet::InvalidationList* invalidationList = m_featureSet->m_pendingInvalidationMap.get(element)) {
esprehn 2014/03/19 22:09:04 You should expose getters, don't reach into the me
chrishtr 2014/03/19 22:49:39 Done.
+ // FIXME: it's really only necessary to clone the render style for this element, not full style recalc.
+ thisElementNeedsStyleRecalc = true;
+ for (RuleFeatureSet::InvalidationList::const_iterator it = invalidationList->begin(); it != invalidationList->end(); ++it) {
+ m_recursionData.pushInvalidationSet(**it);
+ if ((*it)->wholeSubtreeInvalid()) {
+ element->setNeedsStyleRecalc(SubtreeStyleChange);
+ // Even though we have set needsStyleRecalc on the whole subtree, we need to keep walking over the subtree
+ // in order to clear the invalidation dirty bits on all elements.
+ // FIXME: we can optimize this by having a dedicated function that just traverses the tree and removes the dirty bits,
+ // without checking classes etc.
+ break;
+ }
+ }
+ }
+ }
+ if (!thisElementNeedsStyleRecalc)
+ thisElementNeedsStyleRecalc = m_recursionData.matchesCurrentInvalidationSets(element);
+ return thisElementNeedsStyleRecalc;
+}
+
+bool StyleInvalidationTreeWalk::invalidateStyleForChildren(Element* element)
esprehn 2014/03/19 22:09:04 invalidateChildrenStyle
chrishtr 2014/03/19 22:49:39 Done.
+{
+ bool someChildrenNeedStyleRecalc = false;
+ for (ShadowRoot* root = element->youngestShadowRoot(); root; root = root->olderShadowRoot()) {
+ for (Element* child = ElementTraversal::firstWithin(*root); child; child = ElementTraversal::nextSibling(*child)) {
+ bool childRecalced = invalidateStyle(child);
+ someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalced;
+ }
+ root->clearChildNeedsStyleInvalidation();
+ root->clearNeedsStyleInvalidation();
+ }
+ for (Element* child = ElementTraversal::firstWithin(*element); child; child = ElementTraversal::nextSibling(*child)) {
+ bool childRecalced = invalidateStyle(child);
+ someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalced;
+ }
+ return someChildrenNeedStyleRecalc;
+}
+
+bool StyleInvalidationTreeWalk::invalidateStyle(Element* element)
+{
+ RecursionCheckpoint checkpoint(&m_recursionData);
+
+ bool thisElementNeedsStyleRecalc = checkInvalidationSetsAgainstElement(element);
+
+ bool someChildrenNeedStyleRecalc = false;
+ // foundInvalidationSet() will be true if we are in a subtree of a node with a DescendantInvalidationSet on it.
+ // We need to check all nodes in the subtree of such a node.
+ if (m_recursionData.foundInvalidationSet() || element->childNeedsStyleInvalidation()) {
+ someChildrenNeedStyleRecalc = invalidateStyleForChildren(element);
+ }
esprehn 2014/03/19 22:09:04 extra braces
chrishtr 2014/03/19 22:49:39 Done.
+
+ if (thisElementNeedsStyleRecalc) {
+ element->setNeedsStyleRecalc(LocalStyleChange);
+ } else if (m_recursionData.foundInvalidationSet() && someChildrenNeedStyleRecalc) {
+ // Clone the RenderStyle in order to preserve correct style sharing, if possible. Otherwise recalc style.
+ if (RenderObject* renderer = element->renderer()) {
+ ASSERT(renderer->style());
+ renderer->setStyleInternal(RenderStyle::clone(renderer->style()));
+ } else {
+ element->setNeedsStyleRecalc(LocalStyleChange);
+ }
+ }
+
+ element->clearChildNeedsStyleInvalidation();
+ element->clearNeedsStyleInvalidation();
+
+ return thisElementNeedsStyleRecalc;
+}
+
+} // namespace WebCore

Powered by Google App Engine
This is Rietveld 408576698