[Shadow DOM] Distribution related code on ElementShadow should be minimized.
authormorrita@google.com <morrita@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 10 Jan 2013 02:29:37 +0000 (02:29 +0000)
committermorrita@google.com <morrita@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 10 Jan 2013 02:29:37 +0000 (02:29 +0000)
https://bugs.webkit.org/show_bug.cgi?id=106294

Reviewed by Dimitri Glazkov.

.:

* Source/autotools/symbols.filter:

Source/WebCore:

This change moves ElementShadow::m_selectFeatures,
m_shouldCollectSelectFeatureSet and related methods to
ContentDistributor.

There are also some renaming and small refactorings for better fit
on new place:

- shouldCollectSelectFeatureSet is renamed needsSelectorRuleSet for conciseness.
- setShouldCollectSelectFeatureSet() which used recursion morphed into
  iterative willAffectSelector().
- ensureDistributionFromDocument() becomes a static method.

No new tests. Refactoring.

* WebCore.exp.in:
* dom/Element.cpp:
(WebCore::Element::shouldInvalidateDistributionWhenAttributeChanged):
* dom/ElementShadow.cpp:
(WebCore::ElementShadow::addShadowRoot):
(WebCore::ElementShadow::removeAllShadowRoots):
* dom/ElementShadow.h:
(ElementShadow):
(WebCore::ElementShadow::invalidateDistribution):
(WebCore::ElementShadow::ensureDistribution):
(WebCore::ElementShadow::didAffectSelector):
(WebCore::ElementShadow::willAffectSelector):
(WebCore::ElementShadow::containingShadow):
(WebCore):
* html/shadow/ContentDistributor.cpp:
(WebCore::ScopeContentDistribution::registerInsertionPoint):
(WebCore::ScopeContentDistribution::unregisterInsertionPoint):
(WebCore::ContentDistributor::ContentDistributor):
(WebCore::ContentDistributor::ensureDistribution):
(WebCore):
(WebCore::ContentDistributor::ensureDistributionFromDocument):
(WebCore::ContentDistributor::invalidateDistribution):
(WebCore::ContentDistributor::ensureSelectFeatureSet):
(WebCore::ContentDistributor::collectSelectFeatureSetFrom):
(WebCore::ContentDistributor::didAffectSelector):
(WebCore::ContentDistributor::willAffectSelector):
(WebCore::ContentDistributor::didShadowBoundaryChange):
* html/shadow/ContentDistributor.h:
(ScopeContentDistribution):
(WebCore::ContentDistributor::needsSelectFeatureSet):
(WebCore::ContentDistributor::setNeedsSelectFeatureSet):
(ContentDistributor):
(WebCore::ContentDistributor::setValidity):
(WebCore::ContentDistributor::needsInvalidation):
* html/shadow/HTMLContentElement.cpp:
(WebCore::HTMLContentElement::parseAttribute):
* html/shadow/HTMLContentElement.h:
* html/shadow/HTMLShadowElement.cpp:
(WebCore::HTMLShadowElement::olderShadowRoot):
* html/shadow/InsertionPoint.cpp:
(WebCore::InsertionPoint::getDistributedNodes):
(WebCore::InsertionPoint::insertedInto):
(WebCore::InsertionPoint::removedFrom):
* html/shadow/InsertionPoint.h:
(WebCore::InsertionPoint::canAffectSelector):
* testing/Internals.cpp:
(WebCore::Internals::hasSelectorForIdInShadow):
(WebCore::Internals::hasSelectorForClassInShadow):
(WebCore::Internals::hasSelectorForAttributeInShadow):
(WebCore::Internals::hasSelectorForPseudoClassInShadow):

Source/WebKit/win:

* WebKit.vcproj/WebKit.def.in:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@139269 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
ChangeLog
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/ElementShadow.cpp
Source/WebCore/dom/ElementShadow.h
Source/WebCore/html/shadow/ContentDistributor.cpp
Source/WebCore/html/shadow/ContentDistributor.h
Source/WebCore/html/shadow/HTMLContentElement.cpp
Source/WebCore/html/shadow/HTMLContentElement.h
Source/WebCore/html/shadow/HTMLShadowElement.cpp
Source/WebCore/html/shadow/InsertionPoint.cpp
Source/WebCore/html/shadow/InsertionPoint.h
Source/WebCore/testing/Internals.cpp
Source/WebKit/win/ChangeLog
Source/WebKit/win/WebKit.vcproj/WebKitExports.def.in
Source/autotools/symbols.filter

index 018cc01..c03446b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-01-09  Hajime Morrita  <morrita@google.com>
+
+        [Shadow DOM] Distribution related code on ElementShadow should be minimized.
+        https://bugs.webkit.org/show_bug.cgi?id=106294
+
+        Reviewed by Dimitri Glazkov.
+
+        * Source/autotools/symbols.filter:
+
 2013-01-08  Zan Dobersek  <zandobersek@gmail.com>
 
         Add an Autoconf macro that checks whether a given feature is enabled
index 43f2966..c829163 100644 (file)
@@ -1,3 +1,75 @@
+2013-01-09  Hajime Morrita  <morrita@google.com>
+
+        [Shadow DOM] Distribution related code on ElementShadow should be minimized.
+        https://bugs.webkit.org/show_bug.cgi?id=106294
+
+        Reviewed by Dimitri Glazkov.
+
+        This change moves ElementShadow::m_selectFeatures,
+        m_shouldCollectSelectFeatureSet and related methods to
+        ContentDistributor.
+
+        There are also some renaming and small refactorings for better fit
+        on new place:
+
+        - shouldCollectSelectFeatureSet is renamed needsSelectorRuleSet for conciseness.
+        - setShouldCollectSelectFeatureSet() which used recursion morphed into
+          iterative willAffectSelector().
+        - ensureDistributionFromDocument() becomes a static method.
+
+        No new tests. Refactoring.
+
+        * WebCore.exp.in:
+        * dom/Element.cpp:
+        (WebCore::Element::shouldInvalidateDistributionWhenAttributeChanged):
+        * dom/ElementShadow.cpp:
+        (WebCore::ElementShadow::addShadowRoot):
+        (WebCore::ElementShadow::removeAllShadowRoots):
+        * dom/ElementShadow.h:
+        (ElementShadow):
+        (WebCore::ElementShadow::invalidateDistribution):
+        (WebCore::ElementShadow::ensureDistribution):
+        (WebCore::ElementShadow::didAffectSelector):
+        (WebCore::ElementShadow::willAffectSelector):
+        (WebCore::ElementShadow::containingShadow):
+        (WebCore):
+        * html/shadow/ContentDistributor.cpp:
+        (WebCore::ScopeContentDistribution::registerInsertionPoint):
+        (WebCore::ScopeContentDistribution::unregisterInsertionPoint):
+        (WebCore::ContentDistributor::ContentDistributor):
+        (WebCore::ContentDistributor::ensureDistribution):
+        (WebCore):
+        (WebCore::ContentDistributor::ensureDistributionFromDocument):
+        (WebCore::ContentDistributor::invalidateDistribution):
+        (WebCore::ContentDistributor::ensureSelectFeatureSet):
+        (WebCore::ContentDistributor::collectSelectFeatureSetFrom):
+        (WebCore::ContentDistributor::didAffectSelector):
+        (WebCore::ContentDistributor::willAffectSelector):
+        (WebCore::ContentDistributor::didShadowBoundaryChange):
+        * html/shadow/ContentDistributor.h:
+        (ScopeContentDistribution):
+        (WebCore::ContentDistributor::needsSelectFeatureSet):
+        (WebCore::ContentDistributor::setNeedsSelectFeatureSet):
+        (ContentDistributor):
+        (WebCore::ContentDistributor::setValidity):
+        (WebCore::ContentDistributor::needsInvalidation):
+        * html/shadow/HTMLContentElement.cpp:
+        (WebCore::HTMLContentElement::parseAttribute):
+        * html/shadow/HTMLContentElement.h:
+        * html/shadow/HTMLShadowElement.cpp:
+        (WebCore::HTMLShadowElement::olderShadowRoot):
+        * html/shadow/InsertionPoint.cpp:
+        (WebCore::InsertionPoint::getDistributedNodes):
+        (WebCore::InsertionPoint::insertedInto):
+        (WebCore::InsertionPoint::removedFrom):
+        * html/shadow/InsertionPoint.h:
+        (WebCore::InsertionPoint::canAffectSelector):
+        * testing/Internals.cpp:
+        (WebCore::Internals::hasSelectorForIdInShadow):
+        (WebCore::Internals::hasSelectorForClassInShadow):
+        (WebCore::Internals::hasSelectorForAttributeInShadow):
+        (WebCore::Internals::hasSelectorForPseudoClassInShadow):
+
 2013-01-09  Shinya Kawanaka  <shinyak@chromium.org>
 
         Assert triggered in SelectorChecker::checkOneSelector when scrollbar (e.g. :horizontal) selector is specified.
index 75f83c7..2defb59 100644 (file)
@@ -217,7 +217,6 @@ __ZN7WebCore13AXObjectCache42gAccessibilityEnhancedUserInterfaceEnabledE
 __ZN7WebCore13CharacterData7setDataERKN3WTF6StringERi
 __ZN7WebCore13ContainerNode11appendChildEN3WTF10PassRefPtrINS_4NodeEEERib
 __ZN7WebCore13ContainerNode11removeChildEPNS_4NodeERi
-__ZN7WebCore13ElementShadow31ensureSelectFeatureSetCollectedEv
 __ZN7WebCore13HTTPHeaderMapC1Ev
 __ZN7WebCore13HTTPHeaderMapD1Ev
 __ZN7WebCore13HitTestResultC1ERKS0_
@@ -517,6 +516,7 @@ __ZN7WebCore18DOMWindowExtensionC1EPNS_5FrameEPNS_15DOMWrapperWorldE
 __ZN7WebCore18HTMLContentElement6createEPNS_8DocumentE
 __ZN7WebCore10Pasteboard17generalPasteboardEv
 __ZN7WebCore10Pasteboard14writePlainTextERKN3WTF6StringENS0_18SmartReplaceOptionE
+__ZN7WebCore18ContentDistributor22ensureSelectFeatureSetEPNS_13ElementShadowE
 __ZN7WebCore18PlatformPasteboard10uniqueNameEv
 __ZN7WebCore18PlatformPasteboard13bufferForTypeERKN3WTF6StringE
 __ZN7WebCore18PlatformPasteboard13stringForTypeERKN3WTF6StringE
index 8a1ac91..4934b9d 100644 (file)
@@ -917,15 +917,15 @@ void Element::classAttributeChanged(const AtomicString& newClassString)
 bool Element::shouldInvalidateDistributionWhenAttributeChanged(ElementShadow* elementShadow, const QualifiedName& name, const AtomicString& newValue)
 {
     ASSERT(elementShadow);
-    elementShadow->ensureSelectFeatureSetCollected();
+    const SelectRuleFeatureSet& featureSet = elementShadow->distributor().ensureSelectFeatureSet(elementShadow);
 
     if (isIdAttributeName(name)) {
         AtomicString oldId = attributeData()->idForStyleResolution();
         AtomicString newId = makeIdForStyleResolution(newValue, document()->inQuirksMode());
         if (newId != oldId) {
-            if (!oldId.isEmpty() && elementShadow->selectRuleFeatureSet().hasSelectorForId(oldId))
+            if (!oldId.isEmpty() && featureSet.hasSelectorForId(oldId))
                 return true;
-            if (!newId.isEmpty() && elementShadow->selectRuleFeatureSet().hasSelectorForId(newId))
+            if (!newId.isEmpty() && featureSet.hasSelectorForId(newId))
                 return true;
         }
     }
@@ -937,16 +937,16 @@ bool Element::shouldInvalidateDistributionWhenAttributeChanged(ElementShadow* el
             const bool shouldFoldCase = document()->inQuirksMode();
             const SpaceSplitString& oldClasses = attributeData->classNames();
             const SpaceSplitString newClasses(newClassString, shouldFoldCase);
-            if (checkSelectorForClassChange(oldClasses, newClasses, elementShadow->selectRuleFeatureSet()))
+            if (checkSelectorForClassChange(oldClasses, newClasses, featureSet))
                 return true;
         } else if (const ElementAttributeData* attributeData = this->attributeData()) {
             const SpaceSplitString& oldClasses = attributeData->classNames();
-            if (checkSelectorForClassChange(oldClasses, elementShadow->selectRuleFeatureSet()))
+            if (checkSelectorForClassChange(oldClasses, featureSet))
                 return true;
         }
     }
 
-    return elementShadow->selectRuleFeatureSet().hasSelectorForAttribute(name.localName());
+    return featureSet.hasSelectorForAttribute(name.localName());
 }
 
 // Returns true is the given attribute is an event handler.
index 9e686a7..7201d32 100644 (file)
@@ -42,7 +42,6 @@
 namespace WebCore {
 
 ElementShadow::ElementShadow()
-    : m_shouldCollectSelectFeatureSet(false)
 {
 }
 
@@ -83,8 +82,7 @@ void ElementShadow::addShadowRoot(Element* shadowHost, PassRefPtr<ShadowRoot> sh
     shadowRoot->setHost(shadowHost);
     shadowRoot->setParentTreeScope(shadowHost->treeScope());
     m_shadowRoots.push(shadowRoot.get());
-    setValidityUndetermined();
-    invalidateDistribution(shadowHost);
+    m_distributor.didShadowBoundaryChange(shadowHost);
     ChildNodeInsertionNotifier(shadowHost).notify(shadowRoot.get());
 
     // Existence of shadow roots requires the host and its children to do traversal using ComposedShadowTreeWalker.
@@ -119,7 +117,7 @@ void ElementShadow::removeAllShadowRoots()
         ChildNodeRemovalNotifier(shadowHost).notify(oldRoot.get());
     }
 
-    invalidateDistribution(shadowHost);
+    m_distributor.invalidateDistribution(shadowHost);
 }
 
 void ElementShadow::attach()
@@ -165,94 +163,6 @@ void ElementShadow::recalcStyle(Node::StyleChange change)
         root->recalcStyle(change);
 }
 
-void ElementShadow::ensureDistribution()
-{
-    if (!m_distributor.needsDistribution())
-        return;
-    m_distributor.distribute(host());
-}
-
-void ElementShadow::ensureDistributionFromDocument()
-{
-    Vector<Element*, 8> hosts;
-    for (Element* current = host(); current; current = current->shadowHost())
-        hosts.append(current);
-
-    for (size_t i = hosts.size(); i > 0; --i)
-        hosts[i - 1]->shadow()->ensureDistribution();
-}
-
-void ElementShadow::setValidityUndetermined()
-{
-    m_distributor.setValidity(ContentDistributor::Undetermined);
-}
-
-void ElementShadow::invalidateDistribution()
-{
-    invalidateDistribution(host());
-}
-
-void ElementShadow::invalidateDistribution(Element* host)
-{
-    bool needsInvalidation = m_distributor.needsInvalidation();
-    bool needsReattach = needsInvalidation ? m_distributor.invalidate(host) : false;
-
-    if (needsReattach && host->attached()) {
-        for (Node* n = host->firstChild(); n; n = n->nextSibling())
-            n->lazyReattach();
-        host->setNeedsStyleRecalc();
-    }
-
-    if (needsInvalidation)
-        m_distributor.finishInivalidation();
-}
-
-void ElementShadow::setShouldCollectSelectFeatureSet()
-{
-    if (shouldCollectSelectFeatureSet())
-        return;
-
-    m_shouldCollectSelectFeatureSet = true;
-
-    if (ShadowRoot* parentShadowRoot = host()->containingShadowRoot()) {
-        if (ElementShadow* parentElementShadow = parentShadowRoot->owner())
-            parentElementShadow->setShouldCollectSelectFeatureSet();
-    }
-}
-
-void ElementShadow::ensureSelectFeatureSetCollected()
-{
-    if (!m_shouldCollectSelectFeatureSet)
-        return;
-
-    m_selectFeatures.clear();
-    for (ShadowRoot* root = oldestShadowRoot(); root; root = root->youngerShadowRoot())
-        collectSelectFeatureSetFrom(root);
-    m_shouldCollectSelectFeatureSet = false;
-}
-
-void ElementShadow::collectSelectFeatureSetFrom(ShadowRoot* root)
-{
-    if (ScopeContentDistribution::hasElementShadow(root)) {
-        for (Element* element = ElementTraversal::firstWithin(root); element; element = ElementTraversal::next(element)) {
-            if (ElementShadow* elementShadow = element->shadow()) {
-                elementShadow->ensureSelectFeatureSetCollected();
-                m_selectFeatures.add(elementShadow->m_selectFeatures);
-            }
-        }
-    }
-
-    if (ScopeContentDistribution::hasContentElement(root)) {
-        for (Element* element = ElementTraversal::firstWithin(root); element; element = ElementTraversal::next(element)) {
-            if (isHTMLContentElement(element)) {
-                const CSSSelectorList& list = toHTMLContentElement(element)->selectorList();
-                for (CSSSelector* selector = list.first(); selector; selector = list.next(selector))
-                    m_selectFeatures.collectFeaturesFromSelector(selector);                    
-            }
-        }
-    }
-}
-
 void ElementShadow::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
 {
     MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
@@ -265,11 +175,4 @@ void ElementShadow::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
     info.addMember(m_distributor);
 }
 
-void ElementShadow::didAffectSelector(AffectedSelectorMask mask)
-{
-    ensureSelectFeatureSetCollected();
-    if (selectRuleFeatureSet().hasSelectorFor(mask))
-        invalidateDistribution();
-}
-
 } // namespace
index 594c9e6..939e9b6 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "ContentDistributor.h"
 #include "ExceptionCode.h"
-#include "SelectRuleFeatureSet.h"
 #include "ShadowRoot.h"
 #include <wtf/DoublyLinkedList.h>
 #include <wtf/Noncopyable.h>
@@ -52,6 +51,7 @@ public:
     Element* host() const;
     ShadowRoot* youngestShadowRoot() const;
     ShadowRoot* oldestShadowRoot() const;
+    ElementShadow* containingShadow() const;
 
     void removeAllShadowRoots();
     void addShadowRoot(Element* shadowHost, PassRefPtr<ShadowRoot>, ShadowRoot::ShadowRootType, ExceptionCode&);
@@ -63,31 +63,19 @@ public:
     bool needsStyleRecalc();
     void recalcStyle(Node::StyleChange);
 
-    void setValidityUndetermined();
-    void invalidateDistribution();
-    void ensureDistribution();
-    void ensureDistributionFromDocument();
+    void invalidateDistribution() { m_distributor.invalidateDistribution(host()); }
+    void ensureDistribution() { m_distributor.ensureDistribution(host()); }
+    void didAffectSelector(AffectedSelectorMask mask) { m_distributor.didAffectSelector(host(), mask); }
+    void willAffectSelector() { m_distributor.willAffectSelector(host()); }
 
     ContentDistributor& distributor();
     const ContentDistributor& distributor() const;
 
-    void didAffectSelector(AffectedSelectorMask);
-    bool shouldCollectSelectFeatureSet() const { return m_shouldCollectSelectFeatureSet; }
-    void setShouldCollectSelectFeatureSet();
-    void ensureSelectFeatureSetCollected();
-
-    const SelectRuleFeatureSet& selectRuleFeatureSet() const;
-
     void reportMemoryUsage(MemoryObjectInfo*) const;
 private:
-    void invalidateDistribution(Element* host);
-
-    void collectSelectFeatureSetFrom(ShadowRoot*);
 
     DoublyLinkedList<ShadowRoot> m_shadowRoots;
     ContentDistributor m_distributor;
-    SelectRuleFeatureSet m_selectFeatures;
-    bool m_shouldCollectSelectFeatureSet : 1;
 };
 
 inline ShadowRoot* ElementShadow::youngestShadowRoot() const
@@ -116,12 +104,6 @@ inline Element* ElementShadow::host() const
     return youngestShadowRoot()->host();
 }
 
-inline const SelectRuleFeatureSet& ElementShadow::selectRuleFeatureSet() const
-{
-    ASSERT(!m_shouldCollectSelectFeatureSet);
-    return m_selectFeatures;
-}
-
 inline ShadowRoot* Node::youngestShadowRoot() const
 {
     if (!this->isElementNode())
@@ -131,6 +113,14 @@ inline ShadowRoot* Node::youngestShadowRoot() const
     return 0;
 }
 
+inline ElementShadow* ElementShadow::containingShadow() const
+{
+    ShadowRoot* parentRoot = host()->containingShadowRoot();
+    if (!parentRoot)
+        return 0;
+    return parentRoot->owner();
+}
+
 class ShadowRootVector : public Vector<RefPtr<ShadowRoot> > {
 public:
     explicit ShadowRootVector(ElementShadow* tree)
index 77c4d3b..0d3dbea 100644 (file)
@@ -110,7 +110,7 @@ const Vector<RefPtr<InsertionPoint> >& ScopeContentDistribution::ensureInsertion
     return m_insertionPointList;
 }
 
-void ScopeContentDistribution::registerInsertionPoint(ShadowRoot* scope, InsertionPoint* point)
+void ScopeContentDistribution::registerInsertionPoint(InsertionPoint* point)
 {
     switch (point->insertionPointType()) {
     case InsertionPoint::ShadowInsertionPoint:
@@ -118,14 +118,13 @@ void ScopeContentDistribution::registerInsertionPoint(ShadowRoot* scope, Inserti
         break;
     case InsertionPoint::ContentInsertionPoint:
         ++m_numberOfContentElementChildren;
-        scope->owner()->setShouldCollectSelectFeatureSet();
         break;
     }
 
     invalidateInsertionPointList();
 }
 
-void ScopeContentDistribution::unregisterInsertionPoint(ShadowRoot* scope, InsertionPoint* point)
+void ScopeContentDistribution::unregisterInsertionPoint(InsertionPoint* point)
 {
     switch (point->insertionPointType()) {
     case InsertionPoint::ShadowInsertionPoint:
@@ -135,8 +134,6 @@ void ScopeContentDistribution::unregisterInsertionPoint(ShadowRoot* scope, Inser
     case InsertionPoint::ContentInsertionPoint:
         ASSERT(m_numberOfContentElementChildren > 0);
         --m_numberOfContentElementChildren;
-        if (scope->owner())
-            scope->owner()->setShouldCollectSelectFeatureSet();
         break;
     }
 
@@ -181,7 +178,8 @@ InsertionPoint* ScopeContentDistribution::assignedTo(const ShadowRoot* holder)
 }
 
 ContentDistributor::ContentDistributor()
-    : m_validity(Undetermined)
+    : m_needsSelectFeatureSet(false)
+    , m_validity(Undetermined)
 {
 }
 
@@ -287,12 +285,6 @@ bool ContentDistributor::invalidate(Element* host)
     return needsReattach;
 }
 
-void ContentDistributor::finishInivalidation()
-{
-    ASSERT(m_validity == Invalidating);
-    m_validity = Invalidated;
-}
-
 void ContentDistributor::distributeSelectionsTo(InsertionPoint* insertionPoint, const ContentDistribution& pool, Vector<bool>& distributed)
 {
     ContentDistribution distribution;
@@ -342,11 +334,98 @@ void ContentDistributor::distributeNodeChildrenTo(InsertionPoint* insertionPoint
     insertionPoint->setDistribution(distribution);
 }
 
-void ContentDistributor::invalidateDistributionIn(ContentDistribution* list)
+void ContentDistributor::ensureDistribution(Element* host)
+{
+    if (!needsDistribution())
+        return;
+    distribute(host);
+}
+
+void ContentDistributor::ensureDistributionFromDocument(Element* source)
+{
+    ContainerNode* mayShadow = source->treeScope()->rootNode();
+    if (!mayShadow->isShadowRoot())
+        return;
+
+    Vector<Element*, 8> hosts;
+    for (Element* current = toShadowRoot(mayShadow)->host(); current; current = current->shadowHost())
+        hosts.append(current);
+
+    for (size_t i = hosts.size(); i > 0; --i)
+        hosts[i - 1]->shadow()->ensureDistribution();
+}
+
+
+void ContentDistributor::invalidateDistribution(Element* host)
+{
+    bool didNeedInvalidation = needsInvalidation();
+    bool needsReattach = didNeedInvalidation ? invalidate(host) : false;
+
+    if (needsReattach && host->attached()) {
+        for (Node* n = host->firstChild(); n; n = n->nextSibling())
+            n->lazyReattach();
+        host->setNeedsStyleRecalc();
+    }
+
+    if (didNeedInvalidation) {
+        ASSERT(m_validity == Invalidating);
+        m_validity = Invalidated;
+    }
+}
+
+const SelectRuleFeatureSet& ContentDistributor::ensureSelectFeatureSet(ElementShadow* shadow)
+{
+    if (!m_needsSelectFeatureSet)
+        return m_selectFeatures;
+
+    m_selectFeatures.clear();
+    for (ShadowRoot* root = shadow->oldestShadowRoot(); root; root = root->youngerShadowRoot())
+        collectSelectFeatureSetFrom(root);
+    m_needsSelectFeatureSet = false;
+    return m_selectFeatures;
+}
+
+void ContentDistributor::collectSelectFeatureSetFrom(ShadowRoot* root)
+{
+    if (ScopeContentDistribution::hasElementShadow(root)) {
+        for (Element* element = ElementTraversal::firstWithin(root); element; element = ElementTraversal::next(element)) {
+            if (ElementShadow* elementShadow = element->shadow())
+                m_selectFeatures.add(elementShadow->distributor().ensureSelectFeatureSet(elementShadow));
+        }
+    }
+
+    if (ScopeContentDistribution::hasContentElement(root)) {
+        for (Element* element = ElementTraversal::firstWithin(root); element; element = ElementTraversal::next(element)) {
+            if (isHTMLContentElement(element)) {
+                const CSSSelectorList& list = toHTMLContentElement(element)->selectorList();
+                for (CSSSelector* selector = list.first(); selector; selector = list.next(selector))
+                    m_selectFeatures.collectFeaturesFromSelector(selector);
+            }
+        }
+    }
+}
+
+void ContentDistributor::didAffectSelector(Element* host, AffectedSelectorMask mask)
+{
+    if (ensureSelectFeatureSet(host->shadow()).hasSelectorFor(mask))
+        invalidateDistribution(host);
+}
+
+void ContentDistributor::willAffectSelector(Element* host)
+{
+    for (ElementShadow* shadow = host->shadow(); shadow; shadow = shadow->containingShadow()) {
+        if (shadow->distributor().needsSelectFeatureSet())
+            break;
+        shadow->distributor().setNeedsSelectFeatureSet();
+    }
+
+    invalidateDistribution(host);
+}
+
+void ContentDistributor::didShadowBoundaryChange(Element* host)
 {
-    for (size_t i = 0; i < list->size(); ++i)
-        m_nodeToInsertionPoint.remove(list->at(i).get());
-    list->clear();
+    setValidity(Undetermined);
+    invalidateDistribution(host);
 }
 
 }
index f983837..460d413 100644 (file)
@@ -31,6 +31,7 @@
 #ifndef ContentDistributor_h
 #define ContentDistributor_h
 
+#include "SelectRuleFeatureSet.h"
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
@@ -77,8 +78,8 @@ public:
     InsertionPoint* insertionPointAssignedTo() const { return m_insertionPointAssignedTo; }
     void setInsertionPointAssignedTo(InsertionPoint* insertionPoint) { m_insertionPointAssignedTo = insertionPoint; }
 
-    void registerInsertionPoint(ShadowRoot*, InsertionPoint*);
-    void unregisterInsertionPoint(ShadowRoot*, InsertionPoint*);
+    void registerInsertionPoint(InsertionPoint*);
+    void unregisterInsertionPoint(InsertionPoint*);
     bool hasShadowElementChildren() const { return m_numberOfShadowElementChildren > 0; }
     bool hasContentElementChildren() const { return m_numberOfContentElementChildren > 0; }
 
@@ -122,23 +123,35 @@ public:
     ~ContentDistributor();
 
     InsertionPoint* findInsertionPointFor(const Node* key) const;
-
-    void setValidity(Validity validity) { m_validity = validity; }
-
-    void distribute(Element* host);
-    bool invalidate(Element* host);
-    void finishInivalidation();
-    bool needsDistribution() const;
-    bool needsInvalidation() const { return m_validity != Invalidated; }
+    const SelectRuleFeatureSet& ensureSelectFeatureSet(ElementShadow*);
 
     void distributeSelectionsTo(InsertionPoint*, const ContentDistribution& pool, Vector<bool>& distributed);
     void distributeNodeChildrenTo(InsertionPoint*, ContainerNode*);
-    void invalidateDistributionIn(ContentDistribution*);
+
+    void ensureDistribution(Element* host);
+    void invalidateDistribution(Element* host);
+    void didShadowBoundaryChange(Element* host);
+    void didAffectSelector(Element* host, AffectedSelectorMask);
+    void willAffectSelector(Element* host);
+
+    static void ensureDistributionFromDocument(Element* source);
 
 private:
+    void distribute(Element* host);
+    bool invalidate(Element* host);
     void populate(Node*, ContentDistribution&);
 
+    void collectSelectFeatureSetFrom(ShadowRoot*);
+    bool needsSelectFeatureSet() const { return m_needsSelectFeatureSet; }
+    void setNeedsSelectFeatureSet() { m_needsSelectFeatureSet = true; }
+
+    void setValidity(Validity validity) { m_validity = validity; }
+    bool needsDistribution() const;
+    bool needsInvalidation() const { return m_validity != Invalidated; }
+
     HashMap<const Node*, RefPtr<InsertionPoint> > m_nodeToInsertionPoint;
+    SelectRuleFeatureSet m_selectFeatures;
+    bool m_needsSelectFeatureSet : 1;
     unsigned m_validity : 2;
 };
 
index 90c786a..37d570b 100644 (file)
@@ -99,10 +99,8 @@ void HTMLContentElement::ensureSelectParsed()
 void HTMLContentElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
     if (name == selectAttr) {
-        if (ShadowRoot* root = containingShadowRoot()) {
-            root->owner()->setShouldCollectSelectFeatureSet();
-            root->owner()->invalidateDistribution();
-        }
+        if (ShadowRoot* root = containingShadowRoot())
+            root->owner()->willAffectSelector();
         m_shouldParseSelectorList = true;
     } else
         InsertionPoint::parseAttribute(name, value);
index a6dc5f4..a318cf7 100644 (file)
@@ -50,6 +50,7 @@ public:
     virtual bool isSelectValid();
     virtual const CSSSelectorList& selectorList();
     virtual Type insertionPointType() const OVERRIDE { return ContentInsertionPoint; }
+    virtual bool canAffectSelector() const OVERRIDE { return true; }
 
 protected:
     HTMLContentElement(const QualifiedName&, Document*);
index 22c0765..1747ecd 100644 (file)
@@ -70,7 +70,7 @@ ShadowRoot* HTMLShadowElement::olderShadowRoot()
     if (!treeScope()->rootNode()->isShadowRoot())
         return 0;
 
-    toShadowRoot(treeScope()->rootNode())->owner()->ensureDistributionFromDocument();
+    ContentDistributor::ensureDistributionFromDocument(this);
 
     ShadowRoot* older = toShadowRoot(treeScope()->rootNode())->olderShadowRoot();
     if (!older || older->type() != ShadowRoot::AuthorShadowRoot || ScopeContentDistribution::assignedTo(older) != this)
index 44e34b9..5ac520d 100644 (file)
@@ -99,10 +99,7 @@ bool InsertionPoint::isActive() const
 
 PassRefPtr<NodeList> InsertionPoint::getDistributedNodes() const
 {
-    ContainerNode* rootNode = treeScope()->rootNode();
-    if (rootNode->isShadowRoot())
-        if (ElementShadow* rootOwner = toShadowRoot(rootNode)->owner())
-            rootOwner->ensureDistributionFromDocument();
+    ContentDistributor::ensureDistributionFromDocument(const_cast<InsertionPoint*>(this));
 
     Vector<RefPtr<Node> > nodes;
 
@@ -131,11 +128,12 @@ Node::InsertionNotificationRequest InsertionPoint::insertedInto(ContainerNode* i
 
     if (ShadowRoot* root = containingShadowRoot()) {
         if (ElementShadow* rootOwner = root->owner()) {
-            rootOwner->setValidityUndetermined();
-            rootOwner->invalidateDistribution();
+            rootOwner->distributor().didShadowBoundaryChange(root->host());
             if (isActive() && !m_registeredWithShadowRoot && insertionPoint->treeScope()->rootNode() == root) {
                 m_registeredWithShadowRoot = true;
-                root->ensureScopeDistribution()->registerInsertionPoint(root, this);
+                root->ensureScopeDistribution()->registerInsertionPoint(this);
+                if (canAffectSelector())
+                    rootOwner->willAffectSelector();
             }
         }
     }
@@ -160,7 +158,9 @@ void InsertionPoint::removedFrom(ContainerNode* insertionPoint)
     if (m_registeredWithShadowRoot && insertionPoint->treeScope()->rootNode() == root) {
         ASSERT(root);
         m_registeredWithShadowRoot = false;
-        root->ensureScopeDistribution()->unregisterInsertionPoint(root, this);
+        root->ensureScopeDistribution()->unregisterInsertionPoint(this);
+        if (rootOwner && canAffectSelector())
+            rootOwner->willAffectSelector();
     }
 
     HTMLElement::removedFrom(insertionPoint);
index 3bd752c..20ce77d 100644 (file)
@@ -62,6 +62,7 @@ public:
     virtual bool isSelectValid() = 0;
     virtual const CSSSelectorList& selectorList() = 0;
     virtual Type insertionPointType() const = 0;
+    virtual bool canAffectSelector() const { return false; }
 
     bool resetStyleInheritance() const;
     void setResetStyleInheritance(bool);
@@ -88,6 +89,7 @@ protected:
     virtual void removedFrom(ContainerNode*) OVERRIDE;
     virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
     virtual bool isInsertionPointNode() const OVERRIDE { return true; }
+
 private:
 
     ContentDistribution m_distribution;
index 4e8bf8f..9a4379f 100644 (file)
@@ -340,8 +340,7 @@ bool Internals::hasSelectorForIdInShadow(Element* host, const String& idValue, E
         return 0;
     }
 
-    host->shadow()->ensureSelectFeatureSetCollected();
-    return host->shadow()->selectRuleFeatureSet().hasSelectorForId(idValue);
+    return host->shadow()->distributor().ensureSelectFeatureSet(host->shadow()).hasSelectorForId(idValue);
 }
 
 bool Internals::hasSelectorForClassInShadow(Element* host, const String& className, ExceptionCode& ec)
@@ -351,8 +350,7 @@ bool Internals::hasSelectorForClassInShadow(Element* host, const String& classNa
         return 0;
     }
 
-    host->shadow()->ensureSelectFeatureSetCollected();
-    return host->shadow()->selectRuleFeatureSet().hasSelectorForClass(className);
+    return host->shadow()->distributor().ensureSelectFeatureSet(host->shadow()).hasSelectorForClass(className);
 }
 
 bool Internals::hasSelectorForAttributeInShadow(Element* host, const String& attributeName, ExceptionCode& ec)
@@ -362,8 +360,7 @@ bool Internals::hasSelectorForAttributeInShadow(Element* host, const String& att
         return 0;
     }
 
-    host->shadow()->ensureSelectFeatureSetCollected();
-    return host->shadow()->selectRuleFeatureSet().hasSelectorForAttribute(attributeName);
+    return host->shadow()->distributor().ensureSelectFeatureSet(host->shadow()).hasSelectorForAttribute(attributeName);
 }
 
 bool Internals::hasSelectorForPseudoClassInShadow(Element* host, const String& pseudoClass, ExceptionCode& ec)
@@ -373,8 +370,7 @@ bool Internals::hasSelectorForPseudoClassInShadow(Element* host, const String& p
         return 0;
     }
 
-    host->shadow()->ensureSelectFeatureSetCollected();
-    const SelectRuleFeatureSet& featureSet = host->shadow()->selectRuleFeatureSet();
+    const SelectRuleFeatureSet& featureSet = host->shadow()->distributor().ensureSelectFeatureSet(host->shadow());
     if (pseudoClass == "checked")
         return featureSet.hasSelectorForChecked();
     if (pseudoClass == "enabled")
index 4fbe6a0..6b53916 100644 (file)
@@ -1,3 +1,12 @@
+2013-01-09  Hajime Morrita  <morrita@google.com>
+
+        [Shadow DOM] Distribution related code on ElementShadow should be minimized.
+        https://bugs.webkit.org/show_bug.cgi?id=106294
+
+        Reviewed by Dimitri Glazkov.
+
+        * WebKit.vcproj/WebKit.def.in:
+
 2013-01-09  Roger Fong  <roger_fong@apple.com>
 
         Rename export files to make them more easily findable.
index 6c805fc..1d0d1d4 100644 (file)
@@ -181,7 +181,6 @@ EXPORTS
         ?createWrapper@WebCore@@YA?AVJSValue@JSC@@PAVExecState@3@PAVJSDOMGlobalObject@1@PAVNode@1@@Z
         ?deserialize@SerializedScriptValue@WebCore@@QAE?AVJSValue@JSC@@PAVExecState@4@PAVJSGlobalObject@4@PAV?$Vector@V?$RefPtr@VMessagePort@WebCore@@@WTF@@$00@WTF@@W4SerializationErrorMode@2@@Z
         ?documentState@HistoryItem@WebCore@@QBEABV?$Vector@VString@WTF@@$0A@@WTF@@XZ
-        ?ensureSelectFeatureSetCollected@ElementShadow@WebCore@@QAEXXZ
         ?equal@WTF@@YA_NPBVStringImpl@1@PBE@Z
         ?equal@WTF@@YA_NPBVStringImpl@1@0@Z
         ?equalIgnoringCase@WTF@@YA_NPAVStringImpl@1@PBE@Z
@@ -570,7 +569,6 @@ EXPORTS
         ?createWrapper@WebCore@@YA?AVJSValue@JSC@@PAVExecState@3@PAVJSDOMGlobalObject@1@PAVNode@1@@Z
         ?deserialize@SerializedScriptValue@WebCore@@QAE?AVJSValue@JSC@@PAVExecState@4@PAVJSGlobalObject@4@PAV?$Vector@V?$RefPtr@VMessagePort@WebCore@@@WTF@@$00@WTF@@W4SerializationErrorMode@2@@Z
         ?documentState@HistoryItem@WebCore@@QBEABV?$Vector@VString@WTF@@$0A@@WTF@@XZ
-        ?ensureSelectFeatureSetCollected@ElementShadow@WebCore@@QAEXXZ
         ?equal@WTF@@YA_NPBVStringImpl@1@PBE@Z
         ?equal@WTF@@YA_NPBVStringImpl@1@0@Z
         ?equalIgnoringCase@WTF@@YA_NPAVStringImpl@1@PBE@Z
@@ -959,7 +957,6 @@ EXPORTS
         ?createWrapper@WebCore@@YA?AVJSValue@JSC@@PAVExecState@3@PAVJSDOMGlobalObject@1@PAVNode@1@@Z
         ?deserialize@SerializedScriptValue@WebCore@@QAE?AVJSValue@JSC@@PAVExecState@4@PAVJSGlobalObject@4@PAV?$Vector@V?$RefPtr@VMessagePort@WebCore@@@WTF@@$00@WTF@@W4SerializationErrorMode@2@@Z
         ?documentState@HistoryItem@WebCore@@QBEABV?$Vector@VString@WTF@@$0A@@WTF@@XZ
-        ?ensureSelectFeatureSetCollected@ElementShadow@WebCore@@QAEXXZ
         ?equal@WTF@@YA_NPBVStringImpl@1@PBE@Z
         ?equal@WTF@@YA_NPBVStringImpl@1@0@Z
         ?equalIgnoringCase@WTF@@YA_NPAVStringImpl@1@PBE@Z
@@ -1348,11 +1345,11 @@ EXPORTS
         ?createWrapper@WebCore@@YA?AVJSValue@JSC@@PAVExecState@3@PAVJSDOMGlobalObject@1@PAVNode@1@@Z
         ?deserialize@SerializedScriptValue@WebCore@@QAE?AVJSValue@JSC@@PAVExecState@4@PAVJSGlobalObject@4@PAV?$Vector@V?$RefPtr@VMessagePort@WebCore@@@WTF@@$00@WTF@@W4SerializationErrorMode@2@@Z
         ?documentState@HistoryItem@WebCore@@QBEABV?$Vector@VString@WTF@@$0A@@WTF@@XZ
-        ?ensureSelectFeatureSetCollected@ElementShadow@WebCore@@QAEXXZ
         ?equal@WTF@@YA_NPBVStringImpl@1@PBE@Z
         ?equal@WTF@@YA_NPBVStringImpl@1@0@Z
         ?equalIgnoringCase@WTF@@YA_NPAVStringImpl@1@PBE@Z
         ?externalRepresentation@WebCore@@YA?AVString@WTF@@PAVElement@1@I@Z
+        ?ensureSelectFeatureSet@ContentDistributor@WebCore@@QAEABVSelectRuleFeatureSet@2@PAVElementShadow@2@@Z
         ?hasShadowElement@ScopeContentDistribution@WebCore@@SA_NPBVShadowRoot@2@@Z
         ?hasContentElement@ScopeContentDistribution@WebCore@@SA_NPBVShadowRoot@2@@Z
         ?countElementShadow@ScopeContentDistribution@WebCore@@SAIPBVShadowRoot@2@@Z
index a914702..5761ca8 100644 (file)
@@ -58,7 +58,6 @@ _ZN7WebCore12TextIterator26rangeFromLocationAndLengthEPNS_13ContainerNodeEiib;
 _ZN7WebCore12TextIterator29getLocationAndLengthFromRangeEPNS_7ElementEPKNS_5RangeERjS6_;
 _ZN7WebCore12TextIterator29getLocationAndLengthFromRangeEPNS_7ElementEPKNS_5RangeERmS6_;
 _ZN7WebCore12PrintContext20pageNumberForElementEPNS_7ElementERKNS_9FloatSizeE;
-_ZN7WebCore13ElementShadow31ensureSelectFeatureSetCollectedEv;
 _ZN7WebCore13createWrapperEPN3JSC9ExecStateEPNS_17JSDOMGlobalObjectEPNS_4NodeE;
 _ZN7WebCore14ClientRectListC1ERKN3WTF6VectorINS_9FloatQuadELj0EEE;
 _ZN7WebCore14ClientRectListC1ERKN3WTF6VectorINS_9FloatQuadELm0EEE;
@@ -154,6 +153,7 @@ _ZNK7WebCore5Range4textEv;
 _ZN7WebCore22counterValueForElementEPNS_7ElementE;
 _ZNK7WebCore14DocumentMarker11descriptionEv;
 _ZN7WebCore8Document16isPageBoxVisibleEi;
+_ZN7WebCore18ContentDistributor22ensureSelectFeatureSetEPNS_13ElementShadowE;
 _ZN7WebCore19AnimationController17suspendAnimationsEv;
 _ZN7WebCore19AnimationController16resumeAnimationsEv;
 _ZN7WebCore19AnimationController20pauseAnimationAtTimeEPNS_12RenderObjectERKN3WTF6StringEd;