From 4cd0f7f4fd157666bbb21bbbb72d29c3dda48c5a Mon Sep 17 00:00:00 2001 From: "shinyak@chromium.org" Date: Fri, 24 Feb 2012 02:37:02 +0000 Subject: [PATCH] ShadowRootList should have recalculation flag instead of ShadowRoot. https://bugs.webkit.org/show_bug.cgi?id=79071 Reviewed by Hajime Morita. When light children or shadow children are changed, we currently re-construct a shadow subtree. However, when supporting multiple shadow subtrees, all shadow subtrees should be re-constructed. So ShadowRootList should have re-construction flag instead of ShadowRoot. Also, re-construction methods in ShadowRoot should be moved to ShadowRootList. No new tests, should be convered by existing tests. * dom/Element.cpp: (WebCore::Element::recalcStyle): (WebCore::Element::childrenChanged): * dom/NodeRenderingContext.cpp: (WebCore::NodeRenderingContext::hostChildrenChanged): * dom/ShadowRoot.cpp: (WebCore::ShadowRoot::ShadowRoot): (WebCore::ShadowRoot::list): * dom/ShadowRoot.h: (WebCore): (ShadowRoot): * dom/ShadowRootList.cpp: (WebCore::ShadowRootList::ShadowRootList): (WebCore::ShadowRootList::reattach): (WebCore): (WebCore::ShadowRootList::childNeedsStyleRecalc): (WebCore::ShadowRootList::needsStyleRecalc): (WebCore::ShadowRootList::recalcShadowTreeStyle): (WebCore::ShadowRootList::needsReattachHostChildrenAndShadow): (WebCore::ShadowRootList::hostChildrenChanged): (WebCore::ShadowRootList::setNeedsReattachHostChildrenAndShadow): (WebCore::ShadowRootList::reattachHostChildrenAndShadow): * dom/ShadowRootList.h: (WebCore): (ShadowRootList): (WebCore::ShadowRootList::clearNeedsReattachHostChildrenAndShadow): * html/shadow/HTMLContentElement.cpp: (WebCore::HTMLContentElement::attach): (WebCore::HTMLContentElement::detach): (WebCore::HTMLContentElement::parseAttribute): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@108713 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Source/WebCore/ChangeLog | 46 ++++++++++ Source/WebCore/dom/Element.cpp | 10 +-- Source/WebCore/dom/NodeRenderingContext.cpp | 2 +- Source/WebCore/dom/ShadowRoot.cpp | 56 +----------- Source/WebCore/dom/ShadowRoot.h | 18 +--- Source/WebCore/dom/ShadowRootList.cpp | 100 ++++++++++++++++++++-- Source/WebCore/dom/ShadowRootList.h | 20 ++++- Source/WebCore/html/shadow/HTMLContentElement.cpp | 8 +- 8 files changed, 175 insertions(+), 85 deletions(-) diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index 91a5c6c..98c6512 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,49 @@ +2012-02-23 Shinya Kawanaka + + ShadowRootList should have recalculation flag instead of ShadowRoot. + https://bugs.webkit.org/show_bug.cgi?id=79071 + + Reviewed by Hajime Morita. + + When light children or shadow children are changed, we currently re-construct a shadow subtree. + However, when supporting multiple shadow subtrees, all shadow subtrees should be re-constructed. + So ShadowRootList should have re-construction flag instead of ShadowRoot. + + Also, re-construction methods in ShadowRoot should be moved to ShadowRootList. + + No new tests, should be convered by existing tests. + + * dom/Element.cpp: + (WebCore::Element::recalcStyle): + (WebCore::Element::childrenChanged): + * dom/NodeRenderingContext.cpp: + (WebCore::NodeRenderingContext::hostChildrenChanged): + * dom/ShadowRoot.cpp: + (WebCore::ShadowRoot::ShadowRoot): + (WebCore::ShadowRoot::list): + * dom/ShadowRoot.h: + (WebCore): + (ShadowRoot): + * dom/ShadowRootList.cpp: + (WebCore::ShadowRootList::ShadowRootList): + (WebCore::ShadowRootList::reattach): + (WebCore): + (WebCore::ShadowRootList::childNeedsStyleRecalc): + (WebCore::ShadowRootList::needsStyleRecalc): + (WebCore::ShadowRootList::recalcShadowTreeStyle): + (WebCore::ShadowRootList::needsReattachHostChildrenAndShadow): + (WebCore::ShadowRootList::hostChildrenChanged): + (WebCore::ShadowRootList::setNeedsReattachHostChildrenAndShadow): + (WebCore::ShadowRootList::reattachHostChildrenAndShadow): + * dom/ShadowRootList.h: + (WebCore): + (ShadowRootList): + (WebCore::ShadowRootList::clearNeedsReattachHostChildrenAndShadow): + * html/shadow/HTMLContentElement.cpp: + (WebCore::HTMLContentElement::attach): + (WebCore::HTMLContentElement::detach): + (WebCore::HTMLContentElement::parseAttribute): + 2012-02-23 Roland Steiner Unreviewed: add clause in ASSERT missing from r108474. diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp index 9f26195..edc5a62 100644 --- a/Source/WebCore/dom/Element.cpp +++ b/Source/WebCore/dom/Element.cpp @@ -1126,10 +1126,10 @@ void Element::recalcStyle(StyleChange change) } // FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world. if (hasShadowRoot()) { - ShadowRoot* shadow = shadowRootList()->youngestShadowRoot(); - if (change >= Inherit || shadow->childNeedsStyleRecalc() || shadow->needsStyleRecalc()) { + ShadowRootList* list = shadowRootList(); + if (change >= Inherit || list->childNeedsStyleRecalc() || list->needsStyleRecalc()) { parentPusher.push(); - shadow->recalcShadowTreeStyle(change); + list->recalcShadowTreeStyle(change); } } @@ -1360,8 +1360,8 @@ void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* af checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta); if (hasRareData()) { - if (ShadowRootList* list = shadowRootList()) - list->hostChildrenChanged(); + if (hasShadowRoot()) + shadowRootList()->hostChildrenChanged(); } } diff --git a/Source/WebCore/dom/NodeRenderingContext.cpp b/Source/WebCore/dom/NodeRenderingContext.cpp index 2408f2a..2627601 100644 --- a/Source/WebCore/dom/NodeRenderingContext.cpp +++ b/Source/WebCore/dom/NodeRenderingContext.cpp @@ -264,7 +264,7 @@ RenderObject* NodeRenderingContext::parentRenderer() const void NodeRenderingContext::hostChildrenChanged() { if (m_phase == AttachingNotDistributed) - m_visualParentShadowRoot->hostChildrenChanged(); + m_visualParentShadowRoot->host()->shadowRootList()->hostChildrenChanged(); } bool NodeRenderingContext::shouldCreateRenderer() const diff --git a/Source/WebCore/dom/ShadowRoot.cpp b/Source/WebCore/dom/ShadowRoot.cpp index 0626022..6cf50ac 100644 --- a/Source/WebCore/dom/ShadowRoot.cpp +++ b/Source/WebCore/dom/ShadowRoot.cpp @@ -36,7 +36,6 @@ #include "NodeRareData.h" #include "ShadowRootList.h" #include "SVGNames.h" -#include "Text.h" #if ENABLE(SHADOW_DOM) #include "RuntimeEnabledFeatures.h" @@ -50,7 +49,6 @@ ShadowRoot::ShadowRoot(Document* document) , m_prev(0) , m_next(0) , m_applyAuthorSheets(false) - , m_needsRecalculateContent(false) { ASSERT(document); @@ -159,38 +157,11 @@ bool ShadowRoot::childTypeAllowed(NodeType type) const } } -void ShadowRoot::recalcShadowTreeStyle(StyleChange change) +ShadowRootList* ShadowRoot::list() const { - if (needsReattachHostChildrenAndShadow()) - reattachHostChildrenAndShadow(); - else { - for (Node* n = firstChild(); n; n = n->nextSibling()) { - if (n->isElementNode()) - static_cast(n)->recalcStyle(change); - else if (n->isTextNode()) - toText(n)->recalcTextStyle(change); - } - } - - clearNeedsReattachHostChildrenAndShadow(); - clearNeedsStyleRecalc(); - clearChildNeedsStyleRecalc(); -} - -void ShadowRoot::setNeedsReattachHostChildrenAndShadow() -{ - m_needsRecalculateContent = true; - if (shadowHost()) - shadowHost()->setNeedsStyleRecalc(); -} - -void ShadowRoot::hostChildrenChanged() -{ - if (!hasContentElement()) - return; - - // This results in forced detaching/attaching of the shadow render tree. See ShadowRoot::recalcStyle(). - setNeedsReattachHostChildrenAndShadow(); + if (host()) + return host()->shadowRootList(); + return 0; } bool ShadowRoot::hasContentElement() const @@ -226,23 +197,4 @@ void ShadowRoot::attach() selector->didSelect(); } -void ShadowRoot::reattachHostChildrenAndShadow() -{ - Node* hostNode = host(); - if (!hostNode) - return; - - for (Node* child = hostNode->firstChild(); child; child = child->nextSibling()) { - if (child->attached()) - child->detach(); - } - - reattach(); - - for (Node* child = hostNode->firstChild(); child; child = child->nextSibling()) { - if (!child->attached()) - child->attach(); - } } - -} // namespace diff --git a/Source/WebCore/dom/ShadowRoot.h b/Source/WebCore/dom/ShadowRoot.h index d3bf351..9b9db14 100644 --- a/Source/WebCore/dom/ShadowRoot.h +++ b/Source/WebCore/dom/ShadowRoot.h @@ -38,6 +38,7 @@ class Document; class HTMLContentElement; class HTMLContentSelector; class InsertionPoint; +class ShadowRootList; class ShadowRoot : public DocumentFragment, public TreeScope, public DoublyLinkedListNode { friend class WTF::DoublyLinkedListNode; @@ -64,16 +65,18 @@ public: void hostChildrenChanged(); virtual void attach(); - void reattachHostChildrenAndShadow(); virtual bool applyAuthorSheets() const; void setApplyAuthorSheets(bool); Element* host() const { return shadowHost(); } + ShadowRootList* list() const; ShadowRoot* youngerShadowRoot() { return prev(); } ShadowRoot* olderShadowRoot() { return next(); } + bool hasContentElement() const; + private: ShadowRoot(Document*); virtual ~ShadowRoot(); @@ -82,24 +85,11 @@ private: virtual PassRefPtr cloneNode(bool deep); virtual bool childTypeAllowed(NodeType) const; - bool hasContentElement() const; - ShadowRoot* m_prev; ShadowRoot* m_next; bool m_applyAuthorSheets : 1; - bool m_needsRecalculateContent : 1; }; -inline void ShadowRoot::clearNeedsReattachHostChildrenAndShadow() -{ - m_needsRecalculateContent = false; -} - -inline bool ShadowRoot::needsReattachHostChildrenAndShadow() -{ - return m_needsRecalculateContent || hasContentElement(); -} - inline ShadowRoot* toShadowRoot(Node* node) { ASSERT(!node || node->isShadowRoot()); diff --git a/Source/WebCore/dom/ShadowRootList.cpp b/Source/WebCore/dom/ShadowRootList.cpp index 264764e..3adee63 100644 --- a/Source/WebCore/dom/ShadowRootList.cpp +++ b/Source/WebCore/dom/ShadowRootList.cpp @@ -32,10 +32,12 @@ #include "HTMLContentSelector.h" #include "RuntimeEnabledFeatures.h" #include "ShadowRoot.h" +#include "Text.h" namespace WebCore { ShadowRootList::ShadowRootList() + : m_needsRecalculateContent(false) { } @@ -94,12 +96,6 @@ void ShadowRootList::willRemove() root->willRemove(); } -void ShadowRootList::hostChildrenChanged() -{ - for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) - root->hostChildrenChanged(); -} - void ShadowRootList::attach() { // FIXME: Currently we only support the case that the shadow root list has at most one shadow root. @@ -139,6 +135,98 @@ bool ShadowRootList::isSelectorActive() const return m_selector && m_selector->hasCandidates(); } +void ShadowRootList::reattach() +{ + detach(); + attach(); +} + +bool ShadowRootList::childNeedsStyleRecalc() +{ + ASSERT(youngestShadowRoot()); + if (!youngestShadowRoot()) + return false; + + return youngestShadowRoot()->childNeedsStyleRecalc(); +} + +bool ShadowRootList::needsStyleRecalc() +{ + ASSERT(youngestShadowRoot()); + if (!youngestShadowRoot()) + return false; + + return youngestShadowRoot()->needsStyleRecalc(); +} + +void ShadowRootList::recalcShadowTreeStyle(Node::StyleChange change) +{ + ShadowRoot* youngest = youngestShadowRoot(); + if (!youngest) + return; + + if (needsReattachHostChildrenAndShadow()) + reattachHostChildrenAndShadow(); + else { + for (Node* n = youngest->firstChild(); n; n = n->nextSibling()) { + if (n->isElementNode()) + static_cast(n)->recalcStyle(change); + else if (n->isTextNode()) + toText(n)->recalcTextStyle(change); + } + } + + clearNeedsReattachHostChildrenAndShadow(); + for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { + root->clearNeedsStyleRecalc(); + root->clearChildNeedsStyleRecalc(); + } +} + +bool ShadowRootList::needsReattachHostChildrenAndShadow() +{ + return m_needsRecalculateContent || (youngestShadowRoot() && youngestShadowRoot()->hasContentElement()); +} + +void ShadowRootList::hostChildrenChanged() +{ + ASSERT(youngestShadowRoot()); + + if (!youngestShadowRoot()->hasContentElement()) + return; + + // This results in forced detaching/attaching of the shadow render tree. See ShadowRoot::recalcStyle(). + setNeedsReattachHostChildrenAndShadow(); +} + +void ShadowRootList::setNeedsReattachHostChildrenAndShadow() +{ + m_needsRecalculateContent = true; + + host()->setNeedsStyleRecalc(); +} + +void ShadowRootList::reattachHostChildrenAndShadow() +{ + ASSERT(youngestShadowRoot()); + + Node* hostNode = youngestShadowRoot()->host(); + if (!hostNode) + return; + + for (Node* child = hostNode->firstChild(); child; child = child->nextSibling()) { + if (child->attached()) + child->detach(); + } + + reattach(); + + for (Node* child = hostNode->firstChild(); child; child = child->nextSibling()) { + if (!child->attached()) + child->attach(); + } +} + HTMLContentSelector* ShadowRootList::ensureSelector() { if (!m_selector) diff --git a/Source/WebCore/dom/ShadowRootList.h b/Source/WebCore/dom/ShadowRootList.h index 2b49849..db3170a 100644 --- a/Source/WebCore/dom/ShadowRootList.h +++ b/Source/WebCore/dom/ShadowRootList.h @@ -37,8 +37,8 @@ namespace WebCore { class Node; class Element; -class HTMLContentElement; class HTMLContentSelector; +class InsertionPoint; class ShadowRootList { public: @@ -58,10 +58,18 @@ public: void removedFromTree(bool deep); void willRemove(); - void hostChildrenChanged(); - void attach(); void detach(); + void reattach(); + + bool childNeedsStyleRecalc(); + bool needsStyleRecalc(); + void recalcShadowTreeStyle(Node::StyleChange); + void setNeedsReattachHostChildrenAndShadow(); + void clearNeedsReattachHostChildrenAndShadow(); + bool needsReattachHostChildrenAndShadow(); + void reattachHostChildrenAndShadow(); + void hostChildrenChanged(); InsertionPoint* insertionPointFor(Node*) const; @@ -75,6 +83,7 @@ private: DoublyLinkedList m_shadowRoots; OwnPtr m_selector; + bool m_needsRecalculateContent : 1; WTF_MAKE_NONCOPYABLE(ShadowRootList); }; @@ -98,6 +107,11 @@ inline HTMLContentSelector* ShadowRootList::selector() const return m_selector.get(); } +inline void ShadowRootList::clearNeedsReattachHostChildrenAndShadow() +{ + m_needsRecalculateContent = false; +} + inline Element* ShadowRootList::host() const { ASSERT(hasShadowRoot()); diff --git a/Source/WebCore/html/shadow/HTMLContentElement.cpp b/Source/WebCore/html/shadow/HTMLContentElement.cpp index 06be230..989acae 100644 --- a/Source/WebCore/html/shadow/HTMLContentElement.cpp +++ b/Source/WebCore/html/shadow/HTMLContentElement.cpp @@ -74,7 +74,7 @@ void HTMLContentElement::attach() // Before calling StyledElement::attach, selector must be calculated. if (root) { - HTMLContentSelector* selector = root->host()->shadowRootList()->ensureSelector(); + HTMLContentSelector* selector = root->list()->ensureSelector(); selector->unselect(&m_selections); selector->select(this, &m_selections); } @@ -90,12 +90,12 @@ void HTMLContentElement::attach() void HTMLContentElement::detach() { if (ShadowRoot* root = toShadowRoot(shadowTreeRootNode())) { - if (HTMLContentSelector* selector = root->host()->shadowRootList()->selector()) + if (HTMLContentSelector* selector = root->list()->selector()) selector->unselect(&m_selections); // When content element is detached, shadow tree should be recreated to re-calculate selector for // other content elements. - root->setNeedsReattachHostChildrenAndShadow(); + root->list()->setNeedsReattachHostChildrenAndShadow(); } ASSERT(m_selections.isEmpty()); @@ -122,7 +122,7 @@ void HTMLContentElement::parseAttribute(Attribute* attr) { if (attr->name() == selectAttr) { if (ShadowRoot* root = toShadowRoot(shadowTreeRootNode())) - root->setNeedsReattachHostChildrenAndShadow(); + root->list()->setNeedsReattachHostChildrenAndShadow(); } else InsertionPoint::parseAttribute(attr); } -- 2.7.4