OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |