Chromium Code Reviews| Index: Source/core/css/resolver/ScopedStyleTree.cpp |
| diff --git a/Source/core/css/resolver/ScopedStyleTree.cpp b/Source/core/css/resolver/ScopedStyleTree.cpp |
| index fe3f8a3d2cb031f689dde5679ab7c84a80743faf..218f77744c5d541e4f97ed2698d2482c2d3992ec 100644 |
| --- a/Source/core/css/resolver/ScopedStyleTree.cpp |
| +++ b/Source/core/css/resolver/ScopedStyleTree.cpp |
| @@ -66,6 +66,34 @@ ScopedStyleResolver* ScopedStyleTree::addScopedStyleResolver(ContainerNode& scop |
| return addResult.iterator->value.get(); |
| } |
| +// To make younger shadow root a child of its older shadow root. |
|
dglazkov
2014/01/16 17:31:31
To make younger shadow root _act_ as a child of th
tasak
2014/01/20 03:50:06
Yes. Done.
|
| +ContainerNode* ScopedStyleTree::traverseParent(const ContainerNode* node) const |
| +{ |
| + if (node->isShadowRoot()) { |
| + const ShadowRoot* shadowRoot = toShadowRoot(node); |
| + if (shadowRoot->isOldest()) |
| + return shadowRoot->host(); |
| + return shadowRoot->olderShadowRoot(); |
| + } |
| + |
| + ContainerNode* parent = node->parentOrShadowHostNode(); |
| + return parent && parent->isShadowRoot() ? toShadowRoot(parent)->owner()->youngestShadowRoot() : parent; |
| +} |
| + |
| +static inline bool containsIncludingShadowRoots(const ContainerNode* node1, const ContainerNode* node2) |
| +{ |
| + ASSERT(node1); |
| + ASSERT(node2); |
| + |
| + // If node1 is a older shadow root and node2 is an younger shadow root hosted by the |
| + // same shadow host, treat as if node1 contains node2. |
| + if (node1->isShadowRoot()) { |
| + Node* host = toShadowRoot(node1)->host(); |
| + return host != node2 && host->containsIncludingShadowDOM(node2); |
| + } |
| + return node1->containsIncludingShadowDOM(node2); |
| +} |
| + |
| void ScopedStyleTree::setupScopedStylesTree(ScopedStyleResolver* target) |
| { |
| ASSERT(target); |
| @@ -75,7 +103,7 @@ void ScopedStyleTree::setupScopedStylesTree(ScopedStyleResolver* target) |
| // Since StyleResolver creates RuleSets according to styles' document |
| // order, a parent of the given ScopedRuleData has been already |
| // prepared. |
| - for (ContainerNode* node = scopingNode.parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode()) { |
| + for (ContainerNode* node = traverseParent(&scopingNode); node; node = traverseParent(node)) { |
| if (ScopedStyleResolver* scopedResolver = scopedStyleResolverFor(*node)) { |
| target->setParent(scopedResolver); |
| break; |
| @@ -97,7 +125,7 @@ void ScopedStyleTree::setupScopedStylesTree(ScopedStyleResolver* target) |
| if (it->value == target) |
| continue; |
| ASSERT(it->key->inDocument()); |
| - if (it->value->parent() == target->parent() && scopingNode.containsIncludingShadowDOM(it->key)) |
| + if (it->value->parent() == target->parent() && containsIncludingShadowRoots(&scopingNode, it->key)) |
| it->value->setParent(target); |
| } |
| } |
| @@ -115,43 +143,32 @@ void ScopedStyleTree::resolveScopedStyles(const Element* element, Vector<ScopedS |
| resolvers.append(scopedResolver); |
| } |
| -void ScopedStyleTree::collectScopedResolversForHostedShadowTrees(const Element* element, Vector<ScopedStyleResolver*, 8>& resolvers) |
| -{ |
| - ElementShadow* shadow = element->shadow(); |
| - if (!shadow) |
| - return; |
| - |
| - // Adding scoped resolver for active shadow roots for shadow host styling. |
| - for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) { |
| - if (shadowRoot->hasScopedHTMLStyleChild()) { |
| - if (ScopedStyleResolver* resolver = scopedStyleResolverFor(*shadowRoot)) |
| - resolvers.append(resolver); |
| - } |
| - if (!shadowRoot->containsShadowElements()) |
| - break; |
| - } |
| -} |
| - |
| void ScopedStyleTree::resolveScopedKeyframesRules(const Element* element, Vector<ScopedStyleResolver*, 8>& resolvers) |
| { |
| Document& document = element->document(); |
| TreeScope& treeScope = element->treeScope(); |
| bool applyAuthorStyles = treeScope.applyAuthorStyles(); |
| - // Add resolvers for shadow roots hosted by the given element. |
| - collectScopedResolversForHostedShadowTrees(element, resolvers); |
| - |
| // Add resolvers while walking up DOM tree from the given element. |
| - for (ScopedStyleResolver* scopedResolver = scopedResolverFor(element); scopedResolver; scopedResolver = scopedResolver->parent()) { |
| - if (scopedResolver->treeScope() == treeScope || (applyAuthorStyles && scopedResolver->treeScope() == document)) |
| + ScopedStyleResolver* scopedResolver = scopedResolverFor(element); |
| + for (; scopedResolver; scopedResolver = scopedResolver->parent()) { |
| + if (scopedResolver->treeScope() == treeScope |
| + || (scopedResolver->scopingNode().isShadowRoot() && toShadowRoot(&scopedResolver->scopingNode())->host() == element) |
| + || (applyAuthorStyles && scopedResolver->treeScope() == document)) |
| resolvers.append(scopedResolver); |
| } |
| } |
| inline ScopedStyleResolver* ScopedStyleTree::enclosingScopedStyleResolverFor(const ContainerNode* scopingNode) |
| { |
| - for (; scopingNode; scopingNode = scopingNode->parentOrShadowHostNode()) { |
| - if (ScopedStyleResolver* scopedStyleResolver = scopedStyleResolverFor(*scopingNode)) |
| + const ContainerNode* node; |
| + if (isShadowHost(scopingNode)) { |
|
dglazkov
2014/01/16 17:31:31
There's a definite "style tree" (needs better name
tasak
2014/01/20 03:50:06
I see.
I will done in another patch.
|
| + node = toElement(scopingNode)->shadow()->youngestShadowRoot(); |
| + } else { |
| + node = scopingNode->isShadowRoot() ? toShadowRoot(scopingNode)->owner()->youngestShadowRoot() : scopingNode; |
| + } |
| + for (; node; node = traverseParent(node)) { |
| + if (ScopedStyleResolver* scopedStyleResolver = scopedStyleResolverFor(*node)) |
| return scopedStyleResolver; |
| } |
| return 0; |
| @@ -179,13 +196,43 @@ void ScopedStyleTree::pushStyleCache(const ContainerNode& scopingNode, const Con |
| m_cache.nodeForScopedStyles = &scopingNode; |
| } |
| +static inline bool shadowRootHasTheSameShadowHost(const ContainerNode& node, const Node* host) |
| +{ |
| + if (!node.isShadowRoot()) |
| + return false; |
| + return toShadowRoot(&node)->host() == host; |
| +} |
| + |
| void ScopedStyleTree::popStyleCache(const ContainerNode& scopingNode) |
| { |
| if (!cacheIsValid(&scopingNode)) |
| return; |
| - if (m_cache.scopedResolver && m_cache.scopedResolver->scopingNode() == scopingNode) |
| - m_cache.scopedResolver = m_cache.scopedResolver->parent(); |
| + if (!scopingNode.isShadowRoot()) { |
| + if (m_cache.scopedResolver && m_cache.scopedResolver->scopingNode() == scopingNode) |
| + m_cache.scopedResolver = m_cache.scopedResolver->parent(); |
| + |
| + m_cache.nodeForScopedStyles = scopingNode.parentOrShadowHostNode(); |
| + return; |
| + } |
| + |
| + const ShadowRoot* shadowRoot = toShadowRoot(&scopingNode); |
| + const Node* host = shadowRoot->host(); |
| + |
| + // If a given scoping node is the oldest shadow root and cached resolver's scoping node |
| + // is a shadow root (mostly, the youngest shadow root) hosted by the same host of |
| + // the given shadow root, update cacheed resolver. |
| + if (m_cache.scopedResolver |
| + && shadowRoot->isOldest() |
| + && shadowRootHasTheSameShadowHost(m_cache.scopedResolver->scopingNode(), host)) { |
| + ScopedStyleResolver* resolver = m_cache.scopedResolver; |
| + |
| + while (shadowRootHasTheSameShadowHost(resolver->scopingNode(), host)) |
| + resolver = resolver->parent(); |
| + |
| + m_cache.scopedResolver = resolver; |
| + } |
| + |
| m_cache.nodeForScopedStyles = scopingNode.parentOrShadowHostNode(); |
| } |