Changeset 118886 in webkit
- Timestamp:
- May 29, 2012, 8:33:21 PM (14 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 15 edited
-
ChangeLog (modified) (1 diff)
-
dom/Element.cpp (modified) (2 diffs)
-
dom/ElementShadow.cpp (modified) (8 diffs)
-
dom/ElementShadow.h (modified) (3 diffs)
-
dom/NodeRenderingContext.cpp (modified) (4 diffs)
-
dom/NodeRenderingContext.h (modified) (1 diff)
-
dom/ShadowRoot.cpp (modified) (2 diffs)
-
dom/ShadowRoot.h (modified) (2 diffs)
-
html/HTMLFormControlElement.cpp (modified) (1 diff)
-
html/ValidationMessage.cpp (modified) (2 diffs)
-
html/shadow/ContentDistributor.cpp (modified) (4 diffs)
-
html/shadow/ContentDistributor.h (modified) (1 diff)
-
html/shadow/HTMLContentElement.cpp (modified) (1 diff)
-
html/shadow/InsertionPoint.cpp (modified) (4 diffs)
-
html/shadow/InsertionPoint.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r118885 r118886 1 2012-05-29 MORITA Hajime <morrita@google.com> 2 3 [Shadow DOM] Node distribution should be orthogonal from node attachment 4 https://bugs.webkit.org/show_bug.cgi?id=87223 5 6 Reviewed by Dimitri Glazkov. 7 8 This chagne reorganizes Shadow DOM subtree distribution implementation. 9 10 Originally, it was interleaved across attach() of several classes like 11 InsertionPoint and ShadowRoot. Its invalidation was also mixed as a part of 12 the style recalculation and detach()-es. 13 14 This change extracts these bits of code to a set of ContentDistributor methods, which are 15 facaded by two ElementShadow API. Following two API are the primary entry points: 16 17 - ElementShadow::ensureDistribution() 18 - ElementShadow::invalidateDistribution() 19 20 The actual implementations are ContentDistributor::distribute() and 21 ContentDistributor::invalidate() respectively. 22 23 When clients need to traverse composed tree, before attach() for 24 example, they should call ensureDistribution() to make sure that 25 the traversal data structure ("the distribution") is ready. When 26 there is any DOM mutation which can result a composed tree 27 mutation, then clients should call invalidateDistribution() to 28 mark the distribution being dated. 29 30 Here are such DOM mutations: 31 32 - The children of any ShadowRoots are changed, 33 - The children of any InsertionPoints are changed, 34 - The children of any host elements are changed, 35 - Any insertion point is inserted to or removed from the shadow tree, 36 - @select attribute of <content> is modified and 37 - New ShadowRoot is added to the shadow tree. 38 39 Note that the validity of the distribution is tracked and 40 unnecessary distribution requests are ignored. 41 42 After the invalidation, that shadow subtrees are detached once and 43 request their re-attachment through the style recalculation. 44 Then, on the responding style recalculation and attach(), new 45 distribution will be computed. 46 47 No new tests. Covered by existing tests. 48 49 * dom/Element.cpp: 50 (WebCore::Element::~Element): 51 (WebCore::Element::childrenChanged): 52 * dom/ElementShadow.cpp: 53 (WebCore::ElementShadow::~ElementShadow): 54 (WebCore::ElementShadow::addShadowRoot): 55 (WebCore::ElementShadow::removeAllShadowRoots): 56 (WebCore::ElementShadow::attach): 57 (WebCore::ElementShadow::recalcStyle): 58 (WebCore::ElementShadow::ensureDistribution): 59 (WebCore::ElementShadow::invalidateDistribution): 60 * dom/ElementShadow.h: 61 (ElementShadow): 62 * dom/NodeRenderingContext.cpp: 63 (WebCore::NodeRenderingContext::NodeRenderingContext): 64 (WebCore::NodeRendererFactory::createRendererIfNeeded): 65 * dom/NodeRenderingContext.h: 66 (NodeRenderingContext): 67 * dom/ShadowRoot.cpp: 68 (WebCore::ShadowRoot::setApplyAuthorStyles): 69 (WebCore::ShadowRoot::attach): 70 (WebCore::ShadowRoot::childrenChanged): 71 (WebCore): 72 * dom/ShadowRoot.h: 73 (ShadowRoot): 74 * html/HTMLFormControlElement.cpp: 75 * html/ValidationMessage.cpp: 76 (WebCore::ValidationMessage::buildBubbleTree): 77 * html/shadow/ContentDistributor.cpp: 78 (WebCore::ContentDistributor::ContentDistributor): 79 (WebCore::ContentDistributor::~ContentDistributor): 80 (WebCore::ContentDistributor::findInsertionPointFor): 81 (WebCore::ContentDistributor::distribute): 82 (WebCore::ContentDistributor::invalidate): 83 (WebCore::ContentDistributor::finishInivalidation): 84 (WebCore::ContentDistributor::distributeSelectionsTo): 85 (WebCore::ContentDistributor::distributeShadowChildrenTo): 86 (WebCore::ContentDistributor::invalidateDistributionIn): 87 * html/shadow/ContentDistributor.h: 88 (WebCore::ContentDistributor::needsInvalidation): 89 (ContentDistributor): 90 (WebCore::ContentDistributor::needsDistribution): 91 * html/shadow/HTMLContentElement.cpp: 92 (WebCore::HTMLContentElement::parseAttribute): 93 * html/shadow/InsertionPoint.cpp: 94 (WebCore::InsertionPoint::attach): 95 (WebCore::InsertionPoint::detach): 96 (WebCore::InsertionPoint::nextTo): 97 (WebCore::InsertionPoint::previousTo): 98 (WebCore::InsertionPoint::childrenChanged): 99 * html/shadow/InsertionPoint.h: 100 (WebCore::InsertionPoint::setDistribution): 101 (WebCore::InsertionPoint::clearDistribution): 102 (InsertionPoint): 103 1 104 2012-05-29 Luke Macpherson <macpherson@chromium.org> 2 105 -
trunk/Source/WebCore/dom/Element.cpp
r118804 r118886 133 133 #endif 134 134 135 if (shadow()) 135 if (ElementShadow* elementShadow = shadow()) { 136 elementShadow->removeAllShadowRoots(); 136 137 rareData()->m_shadow.clear(); 138 } 137 139 138 140 if (hasAttrList()) { … … 1331 1333 1332 1334 if (ElementShadow * shadow = this->shadow()) 1333 shadow-> hostChildrenChanged();1335 shadow->invalidateDistribution(); 1334 1336 } 1335 1337 -
trunk/Source/WebCore/dom/ElementShadow.cpp
r118654 r118886 45 45 ElementShadow::~ElementShadow() 46 46 { 47 removeAllShadowRoots();47 ASSERT(m_shadowRoots.isEmpty()); 48 48 } 49 49 … … 75 75 76 76 shadowRoot->setHost(shadowHost); 77 m_shadowRoots.push(shadowRoot.get()); 78 invalidateDistribution(shadowHost); 77 79 ChildNodeInsertionNotifier(shadowHost).notify(shadowRoot.get()); 78 80 79 if (shadowHost->attached()) { 80 shadowRoot->lazyAttach(); 81 detach(); 82 shadowHost->detachChildren(); 83 } 84 85 m_shadowRoots.push(shadowRoot.get()); 81 if (shadowHost->attached() && !shadowRoot->attached()) 82 shadowRoot->attach(); 83 86 84 InspectorInstrumentation::didPushShadowRoot(shadowHost, shadowRoot.get()); 87 85 } … … 92 90 Element* shadowHost = host(); 93 91 94 while (RefPtr<ShadowRoot> oldRoot = m_shadowRoots. removeHead()) {92 while (RefPtr<ShadowRoot> oldRoot = m_shadowRoots.head()) { 95 93 InspectorInstrumentation::willPopShadowRoot(shadowHost, oldRoot.get()); 96 94 shadowHost->document()->removeFocusedNodeOfSubtree(oldRoot.get()); … … 99 97 oldRoot->detach(); 100 98 99 m_shadowRoots.removeHead(); 101 100 oldRoot->setHost(0); 102 101 oldRoot->setPrev(0); … … 106 105 } 107 106 108 if (shadowHost->attached()) 109 shadowHost->attachChildrenLazily(); 107 invalidateDistribution(shadowHost); 110 108 } 111 109 112 110 void ElementShadow::attach() 113 111 { 114 // The pool nodes are populated lazily in 115 // ensureDistributor(), and here we just ensure that it is in clean state. 116 ASSERT(!distributor().poolIsReady()); 117 118 distributor().willDistribute(); 112 ensureDistribution(); 119 113 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { 120 114 if (!root->attached()) 121 115 root->attach(); 122 116 } 123 distributor().didDistribute();124 117 } 125 118 … … 168 161 void ElementShadow::recalcStyle(Node::StyleChange change) 169 162 { 170 ShadowRoot* youngest = youngestShadowRoot(); 171 if (!youngest) 172 return; 173 174 if (needsRedistributing()) 175 reattachHostChildrenAndShadow(); 176 else { 177 StyleResolver* styleResolver = youngest->document()->styleResolver(); 178 179 styleResolver->pushParentShadowRoot(youngest); 180 for (Node* n = youngest->firstChild(); n; n = n->nextSibling()) { 163 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { 164 StyleResolver* styleResolver = root->document()->styleResolver(); 165 styleResolver->pushParentShadowRoot(root); 166 167 for (Node* n = root->firstChild(); n; n = n->nextSibling()) { 181 168 if (n->isElementNode()) 182 169 static_cast<Element*>(n)->recalcStyle(change); … … 184 171 toText(n)->recalcTextStyle(change); 185 172 } 186 styleResolver->popParentShadowRoot(youngest); 187 } 188 189 m_distributor.clearNeedsRedistributing(); 190 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { 173 174 styleResolver->popParentShadowRoot(root); 191 175 root->clearNeedsStyleRecalc(); 192 176 root->clearChildNeedsStyleRecalc(); … … 194 178 } 195 179 196 bool ElementShadow::needsRedistributing() 197 { 198 return m_distributor.needsRedistributing() || (youngestShadowRoot() && youngestShadowRoot()->hasInsertionPoint()); 199 } 200 201 void ElementShadow::hostChildrenChanged() 202 { 203 ASSERT(youngestShadowRoot()); 204 205 if (!youngestShadowRoot()->hasInsertionPoint()) 180 void ElementShadow::ensureDistribution() 181 { 182 if (!m_distributor.needsDistribution()) 206 183 return; 207 208 // This results in forced detaching/attaching of the shadow render tree. See ShadowRoot::recalcStyle(). 209 setNeedsRedistributing(); 210 } 211 212 void ElementShadow::setNeedsRedistributing() 213 { 214 m_distributor.setNeedsRedistributing(); 215 host()->setNeedsStyleRecalc(); 216 } 217 218 void ElementShadow::reattachHostChildrenAndShadow() 219 { 220 ASSERT(youngestShadowRoot()); 221 222 Element* hostNode = youngestShadowRoot()->host(); 223 hostNode->detachChildrenIfNeeded(); 224 detach(); 225 attach(); 226 hostNode->attachChildrenIfNeeded(); 184 m_distributor.distribute(host()); 185 } 186 187 void ElementShadow::invalidateDistribution() 188 { 189 invalidateDistribution(host()); 190 } 191 192 void ElementShadow::invalidateDistribution(Element* host) 193 { 194 if (!m_distributor.needsInvalidation()) 195 return; 196 bool needsReattach = m_distributor.invalidate(host); 197 if (needsReattach && host->attached()) { 198 host->detach(); 199 host->lazyAttach(Node::DoNotSetAttached); 200 } 201 202 m_distributor.finishInivalidation(); 227 203 } 228 204 -
trunk/Source/WebCore/dom/ElementShadow.h
r118654 r118886 53 53 ShadowRoot* oldestShadowRoot() const; 54 54 55 void removeAllShadowRoots(); 55 56 void addShadowRoot(Element* shadowHost, PassRefPtr<ShadowRoot>, ExceptionCode&); 56 57 … … 61 62 bool needsStyleRecalc(); 62 63 void recalcStyle(Node::StyleChange); 63 void setNeedsRedistributing();64 bool needsRedistributing();65 void hostChildrenChanged();66 64 65 void ensureDistribution(); 66 void invalidateDistribution(); 67 67 68 InsertionPoint* insertionPointFor(const Node*) const; 68 69 … … 71 72 72 73 private: 73 void removeAllShadowRoots(); 74 void reattachHostChildrenAndShadow(); 74 void invalidateDistribution(Element* host); 75 75 76 76 DoublyLinkedList<ShadowRoot> m_shadowRoots; -
trunk/Source/WebCore/dom/NodeRenderingContext.cpp
r117723 r118886 78 78 79 79 if (m_visualParentShadow) { 80 m_visualParentShadow->ensureDistribution(); 81 80 82 if ((m_insertionPoint = m_visualParentShadow->insertionPointFor(m_node))) { 81 83 if (m_insertionPoint->shadowRoot()->isUsedForRendering()) { … … 92 94 93 95 if (isShadowBoundary(parent)) { 94 if (!parent->shadowRoot()->isUsedForRendering()) { 96 ShadowRoot* parentShadowRoot = parent->shadowRoot(); 97 parentShadowRoot->owner()->ensureDistribution(); 98 99 if (!parentShadowRoot->isUsedForRendering()) { 95 100 m_phase = AttachingNotDistributed; 96 101 m_parentNodeForRenderingAndStyle = parent; … … 284 289 ASSERT(m_phase != Calculating); 285 290 return m_parentNodeForRenderingAndStyle ? m_parentNodeForRenderingAndStyle->renderer() : 0; 286 }287 288 void NodeRenderingContext::hostChildrenChanged()289 {290 if (m_phase == AttachingNotDistributed && m_visualParentShadow)291 m_visualParentShadow->hostChildrenChanged();292 291 } 293 292 … … 367 366 ASSERT(document->shouldCreateRenderers()); 368 367 369 // FIXME: This side effect should be visible from attach() code.370 m_context.hostChildrenChanged();371 372 368 if (!m_context.shouldCreateRenderer()) 373 369 return; -
trunk/Source/WebCore/dom/NodeRenderingContext.h
r116277 r118886 60 60 61 61 bool shouldCreateRenderer() const; 62 63 void hostChildrenChanged();64 62 65 63 bool isOnUpperEncapsulationBoundary() const; -
trunk/Source/WebCore/dom/ShadowRoot.cpp
r118570 r118886 190 190 if (m_applyAuthorStyles != value) { 191 191 m_applyAuthorStyles = value; 192 if (attached() && owner()) 193 owner()->setNeedsRedistributing(); 192 host()->setNeedsStyleRecalc(); 194 193 } 195 194 } … … 199 198 StyleResolver* styleResolver = document()->styleResolver(); 200 199 styleResolver->pushParentShadowRoot(this); 201 DocumentFragment::attach(); 200 attachChildrenIfNeeded(); 201 attachAsNode(); 202 202 styleResolver->popParentShadowRoot(this); 203 203 } 204 204 205 } 205 void ShadowRoot::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 206 { 207 ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 208 owner()->invalidateDistribution(); 209 } 210 211 } -
trunk/Source/WebCore/dom/ShadowRoot.h
r118131 r118886 61 61 62 62 InsertionPoint* insertionPointFor(Node*) const; 63 void hostChildrenChanged();64 63 65 64 virtual bool applyAuthorStyles() const OVERRIDE; … … 92 91 ShadowRoot(Document*); 93 92 virtual ~ShadowRoot(); 94 95 93 virtual String nodeName() const; 96 94 virtual PassRefPtr<Node> cloneNode(bool deep); 97 95 virtual bool childTypeAllowed(NodeType) const; 96 virtual void childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) OVERRIDE; 98 97 99 98 ShadowRoot* m_prev; -
trunk/Source/WebCore/html/HTMLFormControlElement.cpp
r118725 r118886 27 27 28 28 #include "Attribute.h" 29 #include "ElementShadow.h" 29 30 #include "Event.h" 30 31 #include "EventHandler.h" -
trunk/Source/WebCore/html/ValidationMessage.cpp
r116277 r118886 133 133 { 134 134 HTMLElement* host = toHTMLElement(m_element); 135 135 136 Document* doc = host->document(); 136 137 m_bubble = HTMLDivElement::create(doc); … … 142 143 host->ensureShadowRoot()->appendChild(m_bubble.get(), ec); 143 144 ASSERT(!ec); 145 host->document()->updateLayout(); 144 146 adjustBubblePosition(host->getRect(), m_bubble.get()); 145 147 -
trunk/Source/WebCore/html/shadow/ContentDistributor.cpp
r118131 r118886 29 29 30 30 #include "ContentSelectorQuery.h" 31 #include "ElementShadow.h" 31 32 #include "HTMLContentElement.h" 32 33 #include "ShadowRoot.h" … … 36 37 37 38 ContentDistributor::ContentDistributor() 38 : m_phase(Prevented) 39 , m_needsRedistributing(false) 39 : m_validity(Undetermined) 40 40 { 41 41 } … … 43 43 ContentDistributor::~ContentDistributor() 44 44 { 45 ASSERT(m_pool.isEmpty());46 }47 48 void ContentDistributor::distribute(InsertionPoint* insertionPoint, ContentDistribution* distribution)49 {50 ASSERT(m_phase == Prepared);51 ASSERT(distribution->isEmpty());52 53 ContentSelectorQuery query(insertionPoint);54 55 for (size_t i = 0; i < m_pool.size(); ++i) {56 Node* child = m_pool[i].get();57 if (!child)58 continue;59 if (!query.matches(child))60 continue;61 62 distribution->append(child);63 m_nodeToInsertionPoint.add(child, insertionPoint);64 m_pool[i] = 0;65 }66 }67 68 void ContentDistributor::clearDistribution(ContentDistribution* list)69 {70 for (size_t i = 0; i < list->size(); ++i)71 m_nodeToInsertionPoint.remove(list->at(i).get());72 list->clear();73 45 } 74 46 … … 78 50 } 79 51 80 void ContentDistributor::willDistribute() 52 53 void ContentDistributor::distribute(Element* host) 81 54 { 82 m_phase = Started; 55 ASSERT(needsDistribution()); 56 ASSERT(m_nodeToInsertionPoint.isEmpty()); 57 58 m_validity = Valid; 59 60 ContentDistribution pool; 61 for (Node* node = host->firstChild(); node; node = node->nextSibling()) 62 pool.append(node); 63 64 for (ShadowRoot* root = host->youngestShadowRoot(); root; root = root->olderShadowRoot()) { 65 for (Node* node = root; node; node = node->traverseNextNode(root)) { 66 if (!isInsertionPoint(node)) 67 continue; 68 InsertionPoint* point = toInsertionPoint(node); 69 if (!point->isActive()) 70 continue; 71 ShadowRoot* older = root->olderShadowRoot(); 72 if (point->doesSelectFromHostChildren()) 73 distributeSelectionsTo(point, pool); 74 else if (older && !older->assignedTo()) { 75 distributeShadowChildrenTo(point, older); 76 older->setAssignedTo(point); 77 } 78 } 79 } 83 80 } 84 81 85 void ContentDistributor::didDistribute()82 bool ContentDistributor::invalidate(Element* host) 86 83 { 87 ASSERT(m_phase != Prevented); 88 m_phase = Prevented; 89 m_pool.clear(); 84 ASSERT(needsInvalidation()); 85 bool needsReattach = (m_validity == Undetermined) || !m_nodeToInsertionPoint.isEmpty(); 86 87 for (ShadowRoot* root = host->youngestShadowRoot(); root; root = root->olderShadowRoot()) { 88 root->setAssignedTo(0); 89 90 for (Node* node = root; node; node = node->traverseNextNode(root)) { 91 if (!isInsertionPoint(node)) 92 continue; 93 needsReattach = needsReattach || true; 94 InsertionPoint* point = toInsertionPoint(node); 95 point->clearDistribution(); 96 } 97 } 98 99 m_validity = Invalidating; 100 m_nodeToInsertionPoint.clear(); 101 return needsReattach; 90 102 } 91 103 92 void ContentDistributor:: preparePoolFor(Element* shadowHost)104 void ContentDistributor::finishInivalidation() 93 105 { 94 if (poolIsReady()) 95 return; 106 ASSERT(m_validity == Invalidating); 107 m_validity = Invalidated; 108 } 96 109 97 ASSERT(m_pool.isEmpty()); 98 ASSERT(shadowHost); 99 ASSERT(m_phase == Started); 110 void ContentDistributor::distributeSelectionsTo(InsertionPoint* insertionPoint, ContentDistribution& pool) 111 { 112 ContentDistribution distribution; 113 ContentSelectorQuery query(insertionPoint); 100 114 101 m_phase = Prepared; 102 for (Node* node = shadowHost->firstChild(); node; node = node->nextSibling()) 103 m_pool.append(node); 115 for (size_t i = 0; i < pool.size(); ++i) { 116 Node* child = pool[i].get(); 117 if (!child) 118 continue; 119 if (!query.matches(child)) 120 continue; 121 122 distribution.append(child); 123 m_nodeToInsertionPoint.add(child, insertionPoint); 124 pool[i] = 0; 125 } 126 127 insertionPoint->setDistribution(distribution); 128 } 129 130 void ContentDistributor::distributeShadowChildrenTo(InsertionPoint* insertionPoint, ShadowRoot* root) 131 { 132 ContentDistribution distribution; 133 for (Node* node = root->firstChild(); node; node = node->nextSibling()) { 134 distribution.append(node); 135 m_nodeToInsertionPoint.add(node, insertionPoint); 136 } 137 138 insertionPoint->setDistribution(distribution); 139 } 140 141 void ContentDistributor::invalidateDistributionIn(ContentDistribution* list) 142 { 143 for (size_t i = 0; i < list->size(); ++i) 144 m_nodeToInsertionPoint.remove(list->at(i).get()); 145 list->clear(); 104 146 } 105 147 -
trunk/Source/WebCore/html/shadow/ContentDistributor.h
r118131 r118886 49 49 WTF_MAKE_NONCOPYABLE(ContentDistributor); 50 50 public: 51 enum Validity { 52 Valid = 0, 53 Invalidated = 1, 54 Invalidating = 2, 55 Undetermined = 3 56 }; 57 51 58 ContentDistributor(); 52 59 ~ContentDistributor(); 53 60 54 void distribute(InsertionPoint*, ContentDistribution*);55 void clearDistribution(ContentDistribution*);56 61 InsertionPoint* findInsertionPointFor(const Node* key) const; 57 62 58 void willDistribute(); 59 bool inDistribution() const; 60 void didDistribute(); 63 void distribute(Element* host); 64 bool invalidate(Element* host); 65 void finishInivalidation(); 66 bool needsDistribution() const; 67 bool needsInvalidation() const { return m_validity != Invalidated; } 61 68 62 void preparePoolFor(Element* shadowHost); 63 bool poolIsReady() const; 64 bool needsRedistributing() const { return m_needsRedistributing; } 65 void setNeedsRedistributing() { m_needsRedistributing = true; } 66 void clearNeedsRedistributing() { m_needsRedistributing = false; } 69 void distributeSelectionsTo(InsertionPoint*, ContentDistribution& pool); 70 void distributeShadowChildrenTo(InsertionPoint*, ShadowRoot*); 71 void invalidateDistributionIn(ContentDistribution*); 72 67 73 private: 68 enum DistributionPhase {69 Prevented,70 Started,71 Prepared,72 };73 74 Vector<RefPtr<Node> > m_pool;75 DistributionPhase m_phase;76 74 HashMap<const Node*, InsertionPoint*> m_nodeToInsertionPoint; 77 bool m_needsRedistributing : 1;75 unsigned m_validity : 2; 78 76 }; 79 77 80 inline bool ContentDistributor:: inDistribution() const78 inline bool ContentDistributor::needsDistribution() const 81 79 { 82 return m_phase != Prevented; 83 } 84 85 inline bool ContentDistributor::poolIsReady() const 86 { 87 return m_phase == Prepared; 80 // During the invalidation, re-distribution should be supressed. 81 return m_validity != Valid && m_validity != Invalidating; 88 82 } 89 83 -
trunk/Source/WebCore/html/shadow/HTMLContentElement.cpp
r117898 r118886 92 92 if (attribute.name() == selectAttr) { 93 93 if (ShadowRoot* root = shadowRoot()) 94 root->owner()-> setNeedsRedistributing();94 root->owner()->invalidateDistribution(); 95 95 } else 96 96 InsertionPoint::parseAttribute(attribute); -
trunk/Source/WebCore/html/shadow/InsertionPoint.cpp
r118111 r118886 48 48 void InsertionPoint::attach() 49 49 { 50 if (isShadowBoundary()) { 51 ShadowRoot* root = toShadowRoot(treeScope()->rootNode()); 52 if (doesSelectFromHostChildren()) { 53 distributeHostChildren(root->owner()); 54 attachDistributedNode(); 55 } else if (!root->olderShadowRoot()->assignedTo()) { 56 ASSERT(!root->olderShadowRoot()->attached()); 57 assignShadowRoot(root->olderShadowRoot()); 58 root->olderShadowRoot()->attach(); 59 } 60 } 61 50 if (ShadowRoot* root = shadowRoot()) 51 root->owner()->ensureDistribution(); 52 for (size_t i = 0; i < m_distribution.size(); ++i) 53 m_distribution.at(i)->attach(); 62 54 HTMLElement::attach(); 63 55 } … … 65 57 void InsertionPoint::detach() 66 58 { 67 ShadowRoot* root = shadowRoot(); 68 if (root && isActive()) { 69 ElementShadow* shadow = root->owner(); 70 71 if (doesSelectFromHostChildren()) 72 clearDistribution(shadow); 73 else if (ShadowRoot* assignedShadowRoot = assignedFrom()) 74 clearAssignment(assignedShadowRoot); 75 76 // When shadow element is detached, shadow tree should be recreated to re-calculate selector for 77 // other insertion points. 78 shadow->setNeedsRedistributing(); 79 } 80 81 ASSERT(m_distribution.isEmpty()); 59 if (ShadowRoot* root = shadowRoot()) 60 root->owner()->ensureDistribution(); 61 for (size_t i = 0; i < m_distribution.size(); ++i) 62 m_distribution.at(i)->detach(); 82 63 HTMLElement::detach(); 83 }84 85 ShadowRoot* InsertionPoint::assignedFrom() const86 {87 Node* treeScopeRoot = treeScope()->rootNode();88 if (!treeScopeRoot->isShadowRoot())89 return 0;90 91 ShadowRoot* olderShadowRoot = toShadowRoot(treeScopeRoot)->olderShadowRoot();92 if (olderShadowRoot && olderShadowRoot->assignedTo() == this)93 return olderShadowRoot;94 return 0;95 64 } 96 65 … … 119 88 } 120 89 121 inline void InsertionPoint::distributeHostChildren(ElementShadow* shadow)122 {123 if (!shadow->distributor().inDistribution()) {124 // If ContentDistributor is not int selecting phase, it means InsertionPoint is attached from125 // non-ElementShadow node. To run distribute algorithm, we have to reattach ElementShadow.126 shadow->setNeedsRedistributing();127 return;128 }129 130 shadow->distributor().preparePoolFor(shadow->host());131 shadow->distributor().clearDistribution(&m_distribution);132 shadow->distributor().distribute(this, &m_distribution);133 }134 135 inline void InsertionPoint::clearDistribution(ElementShadow* shadow)136 {137 shadow->distributor().clearDistribution(&m_distribution);138 }139 140 inline void InsertionPoint::attachDistributedNode()141 {142 for (size_t i = 0; i < m_distribution.size(); ++i)143 m_distribution.at(i)->attach();144 }145 146 inline void InsertionPoint::assignShadowRoot(ShadowRoot* shadowRoot)147 {148 shadowRoot->setAssignedTo(this);149 m_distribution.clear();150 for (Node* node = shadowRoot->firstChild(); node; node = node->nextSibling())151 m_distribution.append(node);152 }153 154 inline void InsertionPoint::clearAssignment(ShadowRoot* shadowRoot)155 {156 shadowRoot->setAssignedTo(0);157 m_distribution.clear();158 }159 160 90 Node* InsertionPoint::nextTo(const Node* node) const 161 91 { … … 174 104 } 175 105 106 void InsertionPoint::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 107 { 108 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 109 if (ShadowRoot* root = shadowRoot()) 110 root->owner()->invalidateDistribution(); 111 } 112 113 Node::InsertionNotificationRequest InsertionPoint::insertedInto(ContainerNode* insertionPoint) 114 { 115 HTMLElement::insertedInto(insertionPoint); 116 if (insertionPoint->inDocument()) { 117 if (ShadowRoot* root = shadowRoot()) 118 root->owner()->invalidateDistribution(); 119 } 120 121 return InsertionDone; 122 } 123 124 void InsertionPoint::removedFrom(ContainerNode* insertionPoint) 125 { 126 if (insertionPoint->inDocument()) { 127 Node* parent = parentNode(); 128 if (!parent) 129 parent = insertionPoint; 130 if (ShadowRoot* root = parent->shadowRoot()) { 131 // host can be null when removedFrom() is called from ElementShadow destructor. 132 if (root->host()) 133 root->owner()->invalidateDistribution(); 134 } 135 136 // Since this insertion point is no longer visible from the shadow subtree, it need to clean itself up. 137 clearDistribution(); 138 } 139 140 HTMLElement::removedFrom(insertionPoint); 141 } 142 176 143 177 144 } // namespace WebCore -
trunk/Source/WebCore/html/shadow/InsertionPoint.h
r118111 r118886 44 44 45 45 bool hasDistribution() const { return !m_distribution.isEmpty(); } 46 void setDistribution(ContentDistribution& distribution) { m_distribution.swap(distribution); } 47 void clearDistribution() { m_distribution.clear(); } 46 48 bool isShadowBoundary() const; 47 49 bool isActive() const; … … 53 55 virtual void attach(); 54 56 virtual void detach(); 55 56 57 virtual bool isInsertionPoint() const OVERRIDE { return true; } 57 ShadowRoot* assignedFrom() const;58 58 59 59 size_t indexOf(Node* node) const { return m_distribution.find(node); } … … 68 68 InsertionPoint(const QualifiedName&, Document*); 69 69 virtual bool rendererIsNeeded(const NodeRenderingContext&) OVERRIDE; 70 virtual void childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) OVERRIDE; 71 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; 72 virtual void removedFrom(ContainerNode*) OVERRIDE; 70 73 71 74 private: 72 void distributeHostChildren(ElementShadow*);73 void clearDistribution(ElementShadow*);74 void attachDistributedNode();75 76 void assignShadowRoot(ShadowRoot*);77 void clearAssignment(ShadowRoot*);78 79 75 ContentDistribution m_distribution; 80 76 };
Note:
See TracChangeset
for help on using the changeset viewer.