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

Side by Side Diff: Source/core/css/resolver/ScopedStyleTree.cpp

Issue 102953007: Selectors in styles in shadowRoots should match in all of the host's shadowRoots. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fixed @keyframes regression Created 6 years, 11 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
4 * Copyright (C) 2012 Google Inc. All rights reserved. 4 * Copyright (C) 2012 Google Inc. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 59
60 if (addResult.isNewEntry) { 60 if (addResult.isNewEntry) {
61 addResult.iterator->value = ScopedStyleResolver::create(scopingNode); 61 addResult.iterator->value = ScopedStyleResolver::create(scopingNode);
62 if (scopingNode.isDocumentNode()) 62 if (scopingNode.isDocumentNode())
63 m_scopedResolverForDocument = addResult.iterator->value.get(); 63 m_scopedResolverForDocument = addResult.iterator->value.get();
64 } 64 }
65 isNewEntry = addResult.isNewEntry; 65 isNewEntry = addResult.isNewEntry;
66 return addResult.iterator->value.get(); 66 return addResult.iterator->value.get();
67 } 67 }
68 68
69 // 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.
70 ContainerNode* ScopedStyleTree::traverseParent(const ContainerNode* node) const
71 {
72 if (node->isShadowRoot()) {
73 const ShadowRoot* shadowRoot = toShadowRoot(node);
74 if (shadowRoot->isOldest())
75 return shadowRoot->host();
76 return shadowRoot->olderShadowRoot();
77 }
78
79 ContainerNode* parent = node->parentOrShadowHostNode();
80 return parent && parent->isShadowRoot() ? toShadowRoot(parent)->owner()->you ngestShadowRoot() : parent;
81 }
82
83 static inline bool containsIncludingShadowRoots(const ContainerNode* node1, cons t ContainerNode* node2)
84 {
85 ASSERT(node1);
86 ASSERT(node2);
87
88 // If node1 is a older shadow root and node2 is an younger shadow root hoste d by the
89 // same shadow host, treat as if node1 contains node2.
90 if (node1->isShadowRoot()) {
91 Node* host = toShadowRoot(node1)->host();
92 return host != node2 && host->containsIncludingShadowDOM(node2);
93 }
94 return node1->containsIncludingShadowDOM(node2);
95 }
96
69 void ScopedStyleTree::setupScopedStylesTree(ScopedStyleResolver* target) 97 void ScopedStyleTree::setupScopedStylesTree(ScopedStyleResolver* target)
70 { 98 {
71 ASSERT(target); 99 ASSERT(target);
72 100
73 const ContainerNode& scopingNode = target->scopingNode(); 101 const ContainerNode& scopingNode = target->scopingNode();
74 102
75 // Since StyleResolver creates RuleSets according to styles' document 103 // Since StyleResolver creates RuleSets according to styles' document
76 // order, a parent of the given ScopedRuleData has been already 104 // order, a parent of the given ScopedRuleData has been already
77 // prepared. 105 // prepared.
78 for (ContainerNode* node = scopingNode.parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode()) { 106 for (ContainerNode* node = traverseParent(&scopingNode); node; node = traver seParent(node)) {
79 if (ScopedStyleResolver* scopedResolver = scopedStyleResolverFor(*node)) { 107 if (ScopedStyleResolver* scopedResolver = scopedStyleResolverFor(*node)) {
80 target->setParent(scopedResolver); 108 target->setParent(scopedResolver);
81 break; 109 break;
82 } 110 }
83 if (node->isDocumentNode()) { 111 if (node->isDocumentNode()) {
84 bool dummy; 112 bool dummy;
85 ScopedStyleResolver* scopedResolver = addScopedStyleResolver(*node, dummy); 113 ScopedStyleResolver* scopedResolver = addScopedStyleResolver(*node, dummy);
86 target->setParent(scopedResolver); 114 target->setParent(scopedResolver);
87 setupScopedStylesTree(scopedResolver); 115 setupScopedStylesTree(scopedResolver);
88 break; 116 break;
89 } 117 }
90 } 118 }
91 119
92 if (m_buildInDocumentOrder) 120 if (m_buildInDocumentOrder)
93 return; 121 return;
94 122
95 // Reparent all nodes whose scoping node is contained by target's one. 123 // Reparent all nodes whose scoping node is contained by target's one.
96 for (HashMap<const ContainerNode*, OwnPtr<ScopedStyleResolver> >::iterator i t = m_authorStyles.begin(); it != m_authorStyles.end(); ++it) { 124 for (HashMap<const ContainerNode*, OwnPtr<ScopedStyleResolver> >::iterator i t = m_authorStyles.begin(); it != m_authorStyles.end(); ++it) {
97 if (it->value == target) 125 if (it->value == target)
98 continue; 126 continue;
99 ASSERT(it->key->inDocument()); 127 ASSERT(it->key->inDocument());
100 if (it->value->parent() == target->parent() && scopingNode.containsInclu dingShadowDOM(it->key)) 128 if (it->value->parent() == target->parent() && containsIncludingShadowRo ots(&scopingNode, it->key))
101 it->value->setParent(target); 129 it->value->setParent(target);
102 } 130 }
103 } 131 }
104 132
105 void ScopedStyleTree::clear() 133 void ScopedStyleTree::clear()
106 { 134 {
107 m_authorStyles.clear(); 135 m_authorStyles.clear();
108 m_scopedResolverForDocument = 0; 136 m_scopedResolverForDocument = 0;
109 m_cache.clear(); 137 m_cache.clear();
110 } 138 }
111 139
112 void ScopedStyleTree::resolveScopedStyles(const Element* element, Vector<ScopedS tyleResolver*, 8>& resolvers) 140 void ScopedStyleTree::resolveScopedStyles(const Element* element, Vector<ScopedS tyleResolver*, 8>& resolvers)
113 { 141 {
114 for (ScopedStyleResolver* scopedResolver = scopedResolverFor(element); scope dResolver; scopedResolver = scopedResolver->parent()) 142 for (ScopedStyleResolver* scopedResolver = scopedResolverFor(element); scope dResolver; scopedResolver = scopedResolver->parent())
115 resolvers.append(scopedResolver); 143 resolvers.append(scopedResolver);
116 } 144 }
117 145
118 void ScopedStyleTree::collectScopedResolversForHostedShadowTrees(const Element* element, Vector<ScopedStyleResolver*, 8>& resolvers)
119 {
120 ElementShadow* shadow = element->shadow();
121 if (!shadow)
122 return;
123
124 // Adding scoped resolver for active shadow roots for shadow host styling.
125 for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shad owRoot = shadowRoot->olderShadowRoot()) {
126 if (shadowRoot->hasScopedHTMLStyleChild()) {
127 if (ScopedStyleResolver* resolver = scopedStyleResolverFor(*shadowRo ot))
128 resolvers.append(resolver);
129 }
130 if (!shadowRoot->containsShadowElements())
131 break;
132 }
133 }
134
135 void ScopedStyleTree::resolveScopedKeyframesRules(const Element* element, Vector <ScopedStyleResolver*, 8>& resolvers) 146 void ScopedStyleTree::resolveScopedKeyframesRules(const Element* element, Vector <ScopedStyleResolver*, 8>& resolvers)
136 { 147 {
137 Document& document = element->document(); 148 Document& document = element->document();
138 TreeScope& treeScope = element->treeScope(); 149 TreeScope& treeScope = element->treeScope();
139 bool applyAuthorStyles = treeScope.applyAuthorStyles(); 150 bool applyAuthorStyles = treeScope.applyAuthorStyles();
140 151
141 // Add resolvers for shadow roots hosted by the given element.
142 collectScopedResolversForHostedShadowTrees(element, resolvers);
143
144 // Add resolvers while walking up DOM tree from the given element. 152 // Add resolvers while walking up DOM tree from the given element.
145 for (ScopedStyleResolver* scopedResolver = scopedResolverFor(element); scope dResolver; scopedResolver = scopedResolver->parent()) { 153 ScopedStyleResolver* scopedResolver = scopedResolverFor(element);
146 if (scopedResolver->treeScope() == treeScope || (applyAuthorStyles && sc opedResolver->treeScope() == document)) 154 for (; scopedResolver; scopedResolver = scopedResolver->parent()) {
155 if (scopedResolver->treeScope() == treeScope
156 || (scopedResolver->scopingNode().isShadowRoot() && toShadowRoot(&sc opedResolver->scopingNode())->host() == element)
157 || (applyAuthorStyles && scopedResolver->treeScope() == document))
147 resolvers.append(scopedResolver); 158 resolvers.append(scopedResolver);
148 } 159 }
149 } 160 }
150 161
151 inline ScopedStyleResolver* ScopedStyleTree::enclosingScopedStyleResolverFor(con st ContainerNode* scopingNode) 162 inline ScopedStyleResolver* ScopedStyleTree::enclosingScopedStyleResolverFor(con st ContainerNode* scopingNode)
152 { 163 {
153 for (; scopingNode; scopingNode = scopingNode->parentOrShadowHostNode()) { 164 const ContainerNode* node;
154 if (ScopedStyleResolver* scopedStyleResolver = scopedStyleResolverFor(*s copingNode)) 165 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.
166 node = toElement(scopingNode)->shadow()->youngestShadowRoot();
167 } else {
168 node = scopingNode->isShadowRoot() ? toShadowRoot(scopingNode)->owner()- >youngestShadowRoot() : scopingNode;
169 }
170 for (; node; node = traverseParent(node)) {
171 if (ScopedStyleResolver* scopedStyleResolver = scopedStyleResolverFor(*n ode))
155 return scopedStyleResolver; 172 return scopedStyleResolver;
156 } 173 }
157 return 0; 174 return 0;
158 } 175 }
159 176
160 void ScopedStyleTree::resolveStyleCache(const ContainerNode* scopingNode) 177 void ScopedStyleTree::resolveStyleCache(const ContainerNode* scopingNode)
161 { 178 {
162 m_cache.scopedResolver = enclosingScopedStyleResolverFor(scopingNode); 179 m_cache.scopedResolver = enclosingScopedStyleResolverFor(scopingNode);
163 m_cache.nodeForScopedStyles = scopingNode; 180 m_cache.nodeForScopedStyles = scopingNode;
164 } 181 }
165 182
166 void ScopedStyleTree::pushStyleCache(const ContainerNode& scopingNode, const Con tainerNode* parent) 183 void ScopedStyleTree::pushStyleCache(const ContainerNode& scopingNode, const Con tainerNode* parent)
167 { 184 {
168 if (m_authorStyles.isEmpty()) 185 if (m_authorStyles.isEmpty())
169 return; 186 return;
170 187
171 if (!cacheIsValid(parent)) { 188 if (!cacheIsValid(parent)) {
172 resolveStyleCache(&scopingNode); 189 resolveStyleCache(&scopingNode);
173 return; 190 return;
174 } 191 }
175 192
176 ScopedStyleResolver* scopedResolver = scopedStyleResolverFor(scopingNode); 193 ScopedStyleResolver* scopedResolver = scopedStyleResolverFor(scopingNode);
177 if (scopedResolver) 194 if (scopedResolver)
178 m_cache.scopedResolver = scopedResolver; 195 m_cache.scopedResolver = scopedResolver;
179 m_cache.nodeForScopedStyles = &scopingNode; 196 m_cache.nodeForScopedStyles = &scopingNode;
180 } 197 }
181 198
199 static inline bool shadowRootHasTheSameShadowHost(const ContainerNode& node, con st Node* host)
200 {
201 if (!node.isShadowRoot())
202 return false;
203 return toShadowRoot(&node)->host() == host;
204 }
205
182 void ScopedStyleTree::popStyleCache(const ContainerNode& scopingNode) 206 void ScopedStyleTree::popStyleCache(const ContainerNode& scopingNode)
183 { 207 {
184 if (!cacheIsValid(&scopingNode)) 208 if (!cacheIsValid(&scopingNode))
185 return; 209 return;
186 210
187 if (m_cache.scopedResolver && m_cache.scopedResolver->scopingNode() == scopi ngNode) 211 if (!scopingNode.isShadowRoot()) {
188 m_cache.scopedResolver = m_cache.scopedResolver->parent(); 212 if (m_cache.scopedResolver && m_cache.scopedResolver->scopingNode() == s copingNode)
213 m_cache.scopedResolver = m_cache.scopedResolver->parent();
214
215 m_cache.nodeForScopedStyles = scopingNode.parentOrShadowHostNode();
216 return;
217 }
218
219 const ShadowRoot* shadowRoot = toShadowRoot(&scopingNode);
220 const Node* host = shadowRoot->host();
221
222 // If a given scoping node is the oldest shadow root and cached resolver's s coping node
223 // is a shadow root (mostly, the youngest shadow root) hosted by the same ho st of
224 // the given shadow root, update cacheed resolver.
225 if (m_cache.scopedResolver
226 && shadowRoot->isOldest()
227 && shadowRootHasTheSameShadowHost(m_cache.scopedResolver->scopingNode(), host)) {
228 ScopedStyleResolver* resolver = m_cache.scopedResolver;
229
230 while (shadowRootHasTheSameShadowHost(resolver->scopingNode(), host))
231 resolver = resolver->parent();
232
233 m_cache.scopedResolver = resolver;
234 }
235
189 m_cache.nodeForScopedStyles = scopingNode.parentOrShadowHostNode(); 236 m_cache.nodeForScopedStyles = scopingNode.parentOrShadowHostNode();
190 } 237 }
191 238
192 void ScopedStyleTree::collectFeaturesTo(RuleFeatureSet& features) 239 void ScopedStyleTree::collectFeaturesTo(RuleFeatureSet& features)
193 { 240 {
194 for (HashMap<const ContainerNode*, OwnPtr<ScopedStyleResolver> >::iterator i t = m_authorStyles.begin(); it != m_authorStyles.end(); ++it) 241 for (HashMap<const ContainerNode*, OwnPtr<ScopedStyleResolver> >::iterator i t = m_authorStyles.begin(); it != m_authorStyles.end(); ++it)
195 it->value->collectFeaturesTo(features); 242 it->value->collectFeaturesTo(features);
196 } 243 }
197 244
198 inline void ScopedStyleTree::reparentNodes(const ScopedStyleResolver* oldParent, ScopedStyleResolver* newParent) 245 inline void ScopedStyleTree::reparentNodes(const ScopedStyleResolver* oldParent, ScopedStyleResolver* newParent)
(...skipping 15 matching lines...) Expand all
214 return; 261 return;
215 262
216 reparentNodes(resolverRemoved, resolverRemoved->parent()); 263 reparentNodes(resolverRemoved, resolverRemoved->parent());
217 if (m_cache.scopedResolver == resolverRemoved) 264 if (m_cache.scopedResolver == resolverRemoved)
218 m_cache.clear(); 265 m_cache.clear();
219 266
220 m_authorStyles.remove(scopingNode); 267 m_authorStyles.remove(scopingNode);
221 } 268 }
222 269
223 } // namespace WebCore 270 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698