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 act as a child of its older shadow root. |
| 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 // FIXME: we should split "style tree" traversal logic out from this method. |
| 166 if (isShadowHost(scopingNode)) { |
| 167 node = toElement(scopingNode)->shadow()->youngestShadowRoot(); |
| 168 } else { |
| 169 node = scopingNode->isShadowRoot() ? toShadowRoot(scopingNode)->owner()-
>youngestShadowRoot() : scopingNode; |
| 170 } |
| 171 for (; node; node = traverseParent(node)) { |
| 172 if (ScopedStyleResolver* scopedStyleResolver = scopedStyleResolverFor(*n
ode)) |
155 return scopedStyleResolver; | 173 return scopedStyleResolver; |
156 } | 174 } |
157 return 0; | 175 return 0; |
158 } | 176 } |
159 | 177 |
160 void ScopedStyleTree::resolveStyleCache(const ContainerNode* scopingNode) | 178 void ScopedStyleTree::resolveStyleCache(const ContainerNode* scopingNode) |
161 { | 179 { |
162 m_cache.scopedResolver = enclosingScopedStyleResolverFor(scopingNode); | 180 m_cache.scopedResolver = enclosingScopedStyleResolverFor(scopingNode); |
163 m_cache.nodeForScopedStyles = scopingNode; | 181 m_cache.nodeForScopedStyles = scopingNode; |
164 } | 182 } |
165 | 183 |
166 void ScopedStyleTree::pushStyleCache(const ContainerNode& scopingNode, const Con
tainerNode* parent) | 184 void ScopedStyleTree::pushStyleCache(const ContainerNode& scopingNode, const Con
tainerNode* parent) |
167 { | 185 { |
168 if (m_authorStyles.isEmpty()) | 186 if (m_authorStyles.isEmpty()) |
169 return; | 187 return; |
170 | 188 |
171 if (!cacheIsValid(parent)) { | 189 if (!cacheIsValid(parent)) { |
172 resolveStyleCache(&scopingNode); | 190 resolveStyleCache(&scopingNode); |
173 return; | 191 return; |
174 } | 192 } |
175 | 193 |
176 ScopedStyleResolver* scopedResolver = scopedStyleResolverFor(scopingNode); | 194 ScopedStyleResolver* scopedResolver = scopedStyleResolverFor(scopingNode); |
177 if (scopedResolver) | 195 if (scopedResolver) |
178 m_cache.scopedResolver = scopedResolver; | 196 m_cache.scopedResolver = scopedResolver; |
179 m_cache.nodeForScopedStyles = &scopingNode; | 197 m_cache.nodeForScopedStyles = &scopingNode; |
180 } | 198 } |
181 | 199 |
| 200 static inline bool shadowRootHasTheSameShadowHost(const ContainerNode& node, con
st Node* host) |
| 201 { |
| 202 if (!node.isShadowRoot()) |
| 203 return false; |
| 204 return toShadowRoot(&node)->host() == host; |
| 205 } |
| 206 |
182 void ScopedStyleTree::popStyleCache(const ContainerNode& scopingNode) | 207 void ScopedStyleTree::popStyleCache(const ContainerNode& scopingNode) |
183 { | 208 { |
184 if (!cacheIsValid(&scopingNode)) | 209 if (!cacheIsValid(&scopingNode)) |
185 return; | 210 return; |
186 | 211 |
187 if (m_cache.scopedResolver && m_cache.scopedResolver->scopingNode() == scopi
ngNode) | 212 if (!scopingNode.isShadowRoot()) { |
188 m_cache.scopedResolver = m_cache.scopedResolver->parent(); | 213 if (m_cache.scopedResolver && m_cache.scopedResolver->scopingNode() == s
copingNode) |
| 214 m_cache.scopedResolver = m_cache.scopedResolver->parent(); |
| 215 |
| 216 m_cache.nodeForScopedStyles = scopingNode.parentOrShadowHostNode(); |
| 217 return; |
| 218 } |
| 219 |
| 220 const ShadowRoot* shadowRoot = toShadowRoot(&scopingNode); |
| 221 const Node* host = shadowRoot->host(); |
| 222 |
| 223 // If a given scoping node is the oldest shadow root and cached resolver's s
coping node |
| 224 // is a shadow root (mostly, the youngest shadow root) hosted by the same ho
st of |
| 225 // the given shadow root, update cacheed resolver. |
| 226 if (m_cache.scopedResolver |
| 227 && shadowRoot->isOldest() |
| 228 && shadowRootHasTheSameShadowHost(m_cache.scopedResolver->scopingNode(),
host)) { |
| 229 ScopedStyleResolver* resolver = m_cache.scopedResolver; |
| 230 |
| 231 while (shadowRootHasTheSameShadowHost(resolver->scopingNode(), host)) |
| 232 resolver = resolver->parent(); |
| 233 |
| 234 m_cache.scopedResolver = resolver; |
| 235 } |
| 236 |
189 m_cache.nodeForScopedStyles = scopingNode.parentOrShadowHostNode(); | 237 m_cache.nodeForScopedStyles = scopingNode.parentOrShadowHostNode(); |
190 } | 238 } |
191 | 239 |
192 void ScopedStyleTree::collectFeaturesTo(RuleFeatureSet& features) | 240 void ScopedStyleTree::collectFeaturesTo(RuleFeatureSet& features) |
193 { | 241 { |
194 for (HashMap<const ContainerNode*, OwnPtr<ScopedStyleResolver> >::iterator i
t = m_authorStyles.begin(); it != m_authorStyles.end(); ++it) | 242 for (HashMap<const ContainerNode*, OwnPtr<ScopedStyleResolver> >::iterator i
t = m_authorStyles.begin(); it != m_authorStyles.end(); ++it) |
195 it->value->collectFeaturesTo(features); | 243 it->value->collectFeaturesTo(features); |
196 } | 244 } |
197 | 245 |
198 inline void ScopedStyleTree::reparentNodes(const ScopedStyleResolver* oldParent,
ScopedStyleResolver* newParent) | 246 inline void ScopedStyleTree::reparentNodes(const ScopedStyleResolver* oldParent,
ScopedStyleResolver* newParent) |
(...skipping 15 matching lines...) Expand all Loading... |
214 return; | 262 return; |
215 | 263 |
216 reparentNodes(resolverRemoved, resolverRemoved->parent()); | 264 reparentNodes(resolverRemoved, resolverRemoved->parent()); |
217 if (m_cache.scopedResolver == resolverRemoved) | 265 if (m_cache.scopedResolver == resolverRemoved) |
218 m_cache.clear(); | 266 m_cache.clear(); |
219 | 267 |
220 m_authorStyles.remove(scopingNode); | 268 m_authorStyles.remove(scopingNode); |
221 } | 269 } |
222 | 270 |
223 } // namespace WebCore | 271 } // namespace WebCore |
OLD | NEW |