Changeset 109563 in webkit
- Timestamp:
- Mar 2, 2012 5:27:22 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r109554 r109563 1 2012-03-02 Roland Steiner <rolandsteiner@chromium.org> 2 3 Scoped stylesheets don't appear to work in Shadow DOM 4 https://bugs.webkit.org/show_bug.cgi?id=79549 5 6 Test that <style scoped> works in shadow DOM as direct child of the ShadowRoot 7 8 Reviewed by Antti Koivisto. 9 10 * fast/css/style-scoped/style-scoped-in-shadow-expected.txt: Added. 11 * fast/css/style-scoped/style-scoped-in-shadow.html: Added. 12 1 13 2012-03-02 Philippe Normand <pnormand@igalia.com> 2 14 -
trunk/Source/WebCore/ChangeLog
r109562 r109563 1 2012-03-02 Roland Steiner <rolandsteiner@chromium.org> 2 3 Scoped stylesheets don't appear to work in Shadow DOM 4 https://bugs.webkit.org/show_bug.cgi?id=79549 5 6 Make the scope stack in CSSStyleSelector use ContainerNode* instead of Element*. 7 Adapt using sites accordingly. 8 Push the ShadowRoot to the scope stack in the same way that elements are pushed. 9 Fix an issue with removedFromDocument() on destruction. 10 11 Reviewed by Antti Koivisto. 12 13 Test: fast/css/style-scoped/style-scoped-in-shadow.html 14 15 * css/CSSStyleSelector.cpp: 16 (RuleSet): 17 (WebCore::CSSStyleSelector::CSSStyleSelector): 18 (WebCore::CSSStyleSelector::determineScope): 19 (WebCore::CSSStyleSelector::ruleSetForScope): 20 (WebCore::CSSStyleSelector::appendAuthorStylesheets): 21 (WebCore::CSSStyleSelector::setupScopeStack): 22 (WebCore::CSSStyleSelector::pushScope): 23 (WebCore): 24 (WebCore::CSSStyleSelector::popScope): 25 (WebCore::CSSStyleSelector::pushParentElement): 26 (WebCore::CSSStyleSelector::popParentElement): 27 (WebCore::CSSStyleSelector::pushParentShadowRoot): 28 (WebCore::CSSStyleSelector::popParentShadowRoot): 29 (WebCore::CSSStyleSelector::matchScopedAuthorRules): 30 (WebCore::CSSStyleSelector::collectMatchingRulesForList): 31 * css/CSSStyleSelector.h: 32 (CSSStyleSelector): 33 (WebCore::CSSStyleSelector::pushScope): 34 (WebCore::CSSStyleSelector::popScope): 35 (WebCore::CSSStyleSelector::MatchOptions::MatchOptions): 36 (MatchOptions): 37 (WebCore::CSSStyleSelector::scopeStackIsConsistent): 38 (WebCore::CSSStyleSelector::ScopeStackFrame::ScopeStackFrame): 39 (ScopeStackFrame): 40 * css/SelectorChecker.h: 41 (SelectorCheckingContext): 42 * dom/Element.cpp: 43 (WebCore::StyleSelectorParentPusher::push): 44 (WebCore::StyleSelectorParentPusher::~StyleSelectorParentPusher): 45 (WebCore::Element::beginParsingChildren): 46 (WebCore::Element::finishParsingChildren): 47 * dom/ShadowRoot.cpp: 48 (WebCore::ShadowRoot::attach): 49 (WebCore): 50 * dom/ShadowRoot.h: 51 (ShadowRoot): 52 * dom/ShadowTree.cpp: 53 (WebCore::ShadowTree::recalcShadowTreeStyle): 54 * html/HTMLStyleElement.cpp: 55 (WebCore::HTMLStyleElement::removedFromDocument): 56 1 57 2012-03-02 Yoshifumi Inoue <yosin@chromium.org> 2 58 -
trunk/Source/WebCore/css/CSSStyleSelector.cpp
r109541 r109563 93 93 #include "Settings.h" 94 94 #include "ShadowData.h" 95 #include "ShadowRoot.h" 95 96 #include "ShadowValue.h" 96 97 #include "SkewTransformOperation.h" … … 228 229 typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<RuleData> > > AtomRuleMap; 229 230 230 void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0, const Element* = 0);231 void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0, const ContainerNode* = 0); 231 232 232 233 void addStyleRule(StyleRule*, bool canUseFastCheckSelector = true, bool isInRegionRule = false); … … 344 345 #endif 345 346 #if ENABLE(STYLE_SCOPED) 346 , m_scop ingElementStackParent(0)347 , m_scopeStackParent(0) 347 348 #endif 348 349 { … … 448 449 449 450 #if ENABLE(STYLE_SCOPED) 450 const Element* CSSStyleSelector::determineScopingElement(const CSSStyleSheet* sheet)451 const ContainerNode* CSSStyleSelector::determineScope(const CSSStyleSheet* sheet) 451 452 { 452 453 ASSERT(sheet); … … 463 464 return 0; 464 465 465 return styleElement->parentElement(); 466 } 467 468 inline RuleSet* CSSStyleSelector::scopedRuleSetForElement(const Element* element) const 469 { 470 if (!element->hasScopedHTMLStyleChild()) 466 ContainerNode* parent = styleElement->parentNode(); 467 if (!parent) 471 468 return 0; 472 ScopedRuleSetMap::const_iterator it = m_scopedAuthorStyles.find(element); 469 470 return (parent->isElementNode() || parent->isShadowRoot()) ? parent : 0; 471 } 472 473 inline RuleSet* CSSStyleSelector::ruleSetForScope(const ContainerNode* scope) const 474 { 475 if (!scope->hasScopedHTMLStyleChild()) 476 return 0; 477 ScopedRuleSetMap::const_iterator it = m_scopedAuthorStyles.find(scope); 473 478 return it != m_scopedAuthorStyles.end() ? it->second.get() : 0; 474 479 } … … 485 490 CSSStyleSheet* cssSheet = static_cast<CSSStyleSheet*>(stylesheets[i].get()); 486 491 #if ENABLE(STYLE_SCOPED) 487 const Element* scope = determineScopingElement(cssSheet);492 const ContainerNode* scope = determineScope(cssSheet); 488 493 if (scope) { 489 494 pair<ScopedRuleSetMap::iterator, bool> addResult = m_scopedAuthorStyles.add(scope, nullptr); … … 504 509 505 510 #if ENABLE(STYLE_SCOPED) 506 void CSSStyleSelector::setupScop ingElementStack(const Element* parent)511 void CSSStyleSelector::setupScopeStack(const ContainerNode* parent) 507 512 { 508 513 // The scoping element stack shouldn't be used if <style scoped> isn't used anywhere. 509 514 ASSERT(!m_scopedAuthorStyles.isEmpty()); 510 515 511 m_scop ingElementStack.shrink(0);512 for (; parent; parent = parent->parentOrHost Element()) {513 RuleSet* ruleSet = scopedRuleSetForElement(parent);516 m_scopeStack.shrink(0); 517 for (; parent; parent = parent->parentOrHostNode()) { 518 RuleSet* ruleSet = ruleSetForScope(parent); 514 519 if (ruleSet) 515 m_scopingElementStack.append(ScopeStackFrame(parent, ruleSet)); 516 } 517 m_scopingElementStack.reverse(); 518 m_scopingElementStackParent = parent; 520 m_scopeStack.append(ScopeStackFrame(parent, ruleSet)); 521 } 522 m_scopeStack.reverse(); 523 m_scopeStackParent = parent; 524 } 525 526 void CSSStyleSelector::pushScope(const ContainerNode* scope, const ContainerNode* scopeParent) 527 { 528 // Shortcut: Don't bother with the scoping element stack if <style scoped> isn't used anywhere. 529 if (m_scopedAuthorStyles.isEmpty()) { 530 ASSERT(!m_scopeStackParent); 531 ASSERT(m_scopeStack.isEmpty()); 532 return; 533 } 534 // In some wacky cases during style resolve we may get invoked for random elements. 535 // Recreate the whole scoping element stack in such cases. 536 if (!scopeStackIsConsistent(scopeParent)) { 537 setupScopeStack(scope); 538 return; 539 } 540 // Otherwise just push the parent onto the stack. 541 RuleSet* ruleSet = ruleSetForScope(scope); 542 if (ruleSet) 543 m_scopeStack.append(ScopeStackFrame(scope, ruleSet)); 544 m_scopeStackParent = scope; 545 } 546 547 void CSSStyleSelector::popScope(const ContainerNode* scope) 548 { 549 // Only bother to update the scoping element stack if it is consistent. 550 if (scopeStackIsConsistent(scope)) { 551 m_scopeStack.removeLast(); 552 m_scopeStackParent = scope->parentOrHostNode(); 553 } 519 554 } 520 555 #endif 521 556 522 void CSSStyleSelector::pushParent (Element* parent)523 { 524 const Element* parentsParent = parent->parentOrHostElement();557 void CSSStyleSelector::pushParentElement(Element* parent) 558 { 559 const ContainerNode* parentsParent = parent->parentOrHostNode(); 525 560 // We are not always invoked consistently. For example, script execution can cause us to enter 526 561 // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree. … … 531 566 else 532 567 m_checker.pushParent(parent); 533 534 #if ENABLE(STYLE_SCOPED) 535 // Shortcut: Don't bother with the scoping element stack if <style scoped> isn't used anywhere. 536 if (m_scopedAuthorStyles.isEmpty()) { 537 ASSERT(!m_scopingElementStackParent); 538 ASSERT(m_scopingElementStack.isEmpty()); 539 return; 540 } 541 // In some wacky cases during style resolve we may get invoked for random elements. 542 // Recreate the whole scoping element stack in such cases. 543 if (!scopingElementStackIsConsistent(parentsParent)) { 544 setupScopingElementStack(parent); 545 return; 546 } 547 // Otherwise just push the parent onto the stack. 548 RuleSet* ruleSet = scopedRuleSetForElement(parent); 549 if (ruleSet) 550 m_scopingElementStack.append(ScopeStackFrame(parent, ruleSet)); 551 m_scopingElementStackParent = parent; 552 #endif 553 } 554 555 void CSSStyleSelector::popParent(Element* parent) 568 pushScope(parent, parentsParent); 569 } 570 571 void CSSStyleSelector::popParentElement(Element* parent) 556 572 { 557 573 // Note that we may get invoked for some random elements in some wacky cases during style resolve. … … 559 575 if (m_checker.parentStackIsConsistent(parent)) 560 576 m_checker.popParent(); 561 #if ENABLE(STYLE_SCOPED) 562 // Only bother to update the scoping element stack if it is consistent. 563 if (scopingElementStackIsConsistent(parent)) { 564 m_scopingElementStack.removeLast(); 565 m_scopingElementStackParent = parent->parentOrHostElement(); 566 } 567 #endif 577 popScope(parent); 578 } 579 580 void CSSStyleSelector::pushParentShadowRoot(const ShadowRoot* shadowRoot) 581 { 582 ASSERT(shadowRoot->host()); 583 pushScope(shadowRoot, shadowRoot->host()); 584 } 585 586 void CSSStyleSelector::popParentShadowRoot(const ShadowRoot* shadowRoot) 587 { 588 ASSERT(shadowRoot->host()); 589 popScope(shadowRoot); 568 590 } 569 591 … … 859 881 860 882 // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent). 861 const Element* parent = m_element->parentOrHostElement();862 if (!scop ingElementStackIsConsistent(parent))863 setupScop ingElementStack(parent);864 for (size_t i = m_scop ingElementStack.size(); i; --i) {865 const ScopeStackFrame& frame = m_scop ingElementStack[i - 1];866 options.scope = frame.m_ element;883 const ContainerNode* parent = m_element->parentOrHostNode(); 884 if (!scopeStackIsConsistent(parent)) 885 setupScopeStack(parent); 886 for (size_t i = m_scopeStack.size(); i; --i) { 887 const ScopeStackFrame& frame = m_scopeStack[i - 1]; 888 options.scope = frame.m_scope; 867 889 collectMatchingRules(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options); 868 890 collectMatchingRulesForRegion(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options); 869 891 } 870 892 // Also include the current element. 871 RuleSet* ruleSet = scopedRuleSetForElement(m_element);893 RuleSet* ruleSet = ruleSetForScope(m_element); 872 894 if (ruleSet) { 873 895 options.scope = m_element; … … 2121 2143 } 2122 2144 2123 inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData, const Element* scope)2145 inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData, const ContainerNode* scope) 2124 2146 { 2125 2147 m_dynamicPseudo = NOPSEUDO; … … 2393 2415 } 2394 2416 2395 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector, const Element* scope)2417 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector, const ContainerNode* scope) 2396 2418 { 2397 2419 ASSERT(sheet); -
trunk/Source/WebCore/css/CSSStyleSelector.h
r109342 r109563 108 108 109 109 // Using these during tree walk will allow style selector to optimize child and descendant selector lookups. 110 void pushParent(Element* parent); 111 void popParent(Element* parent); 110 void pushParentElement(Element*); 111 void popParentElement(Element*); 112 void pushParentShadowRoot(const ShadowRoot*); 113 void popParentShadowRoot(const ShadowRoot*); 112 114 113 115 PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false, RenderRegion* regionForStyling = 0); … … 151 153 PassRefPtr<RenderStyle> styleForKeyframe(const RenderStyle*, const WebKitCSSKeyframeRule*, KeyframeValue&); 152 154 155 #if ENABLE(STYLE_SCOPED) 156 void pushScope(const ContainerNode* scope, const ContainerNode* scopeParent); 157 void popScope(const ContainerNode* scope); 158 #else 159 void pushScope(const ContainerNode*, const ContainerNode*) { } 160 void popScope(const ContainerNode*) { } 161 #endif 162 153 163 public: 154 164 // These methods will give back the set of rules that matched for a given element (or a pseudo-element). … … 290 300 291 301 struct MatchOptions { 292 MatchOptions(bool includeEmptyRules, const Element* scope = 0) : scope(scope), includeEmptyRules(includeEmptyRules) { }293 const Element* scope;302 MatchOptions(bool includeEmptyRules, const ContainerNode* scope = 0) : scope(scope), includeEmptyRules(includeEmptyRules) { } 303 const ContainerNode* scope; 294 304 bool includeEmptyRules; 295 305 }; … … 311 321 void sortAndTransferMatchedRules(MatchResult&); 312 322 313 bool checkSelector(const RuleData&, const Element* scope = 0);323 bool checkSelector(const RuleData&, const ContainerNode* scope = 0); 314 324 bool checkRegionSelector(CSSSelector* regionSelector, Element* regionElement); 315 325 void applyMatchedProperties(const MatchResult&); … … 454 464 455 465 #if ENABLE(STYLE_SCOPED) 456 static const Element* determineScopingElement(const CSSStyleSheet*);457 458 typedef HashMap<const Element*, OwnPtr<RuleSet> > ScopedRuleSetMap;459 460 RuleSet* scopedRuleSetForElement(const Element*) const;461 462 void setupScop ingElementStack(const Element*);463 bool scop ingElementStackIsConsistent(const Element* parent) const { return parent && parent == m_scopingElementStackParent; }466 static const ContainerNode* determineScope(const CSSStyleSheet*); 467 468 typedef HashMap<const ContainerNode*, OwnPtr<RuleSet> > ScopedRuleSetMap; 469 470 RuleSet* ruleSetForScope(const ContainerNode*) const; 471 472 void setupScopeStack(const ContainerNode*); 473 bool scopeStackIsConsistent(const ContainerNode* parent) const { return parent && parent == m_scopeStackParent; } 464 474 465 475 ScopedRuleSetMap m_scopedAuthorStyles; 466 476 467 477 struct ScopeStackFrame { 468 ScopeStackFrame() : m_ element(0), m_ruleSet(0) { }469 ScopeStackFrame(const Element* element, RuleSet* ruleSet) : m_element(element), m_ruleSet(ruleSet) { }470 const Element* m_element;478 ScopeStackFrame() : m_scope(0), m_ruleSet(0) { } 479 ScopeStackFrame(const ContainerNode* scope, RuleSet* ruleSet) : m_scope(scope), m_ruleSet(ruleSet) { } 480 const ContainerNode* m_scope; 471 481 RuleSet* m_ruleSet; 472 482 }; 473 483 // Vector (used as stack) that keeps track of scoping elements (i.e., elements with a <style scoped> child) 474 484 // encountered during tree iteration for style resolution. 475 Vector<ScopeStackFrame> m_scop ingElementStack;485 Vector<ScopeStackFrame> m_scopeStack; 476 486 // Element last seen as parent element when updating m_scopingElementStack. 477 487 // This is used to decide whether m_scopingElementStack is consistent, separately from SelectorChecker::m_parentStack. 478 const Element* m_scopingElementStackParent;488 const ContainerNode* m_scopeStackParent; 479 489 #endif 480 490 -
trunk/Source/WebCore/css/SelectorChecker.h
r107911 r109563 67 67 CSSSelector* selector; 68 68 Element* element; 69 const Element* scope;69 const ContainerNode* scope; 70 70 VisitedMatchType visitedMatchType; 71 71 RenderStyle* elementStyle; -
trunk/Source/WebCore/dom/Element.cpp
r109417 r109563 95 95 return; 96 96 m_pushedStyleSelector = m_parent->document()->styleSelector(); 97 m_pushedStyleSelector->pushParent (m_parent);97 m_pushedStyleSelector->pushParentElement(m_parent); 98 98 } 99 99 ~StyleSelectorParentPusher() … … 109 109 return; 110 110 111 m_pushedStyleSelector->popParent (m_parent);111 m_pushedStyleSelector->popParentElement(m_parent); 112 112 } 113 113 … … 1311 1311 CSSStyleSelector* styleSelector = document()->styleSelectorIfExists(); 1312 1312 if (styleSelector && attached()) 1313 styleSelector->pushParent (this);1313 styleSelector->pushParentElement(this); 1314 1314 } 1315 1315 … … 1320 1320 checkForSiblingStyleChanges(this, renderStyle(), true, lastChild(), 0, 0); 1321 1321 if (CSSStyleSelector* styleSelector = document()->styleSelectorIfExists()) 1322 styleSelector->popParent (this);1322 styleSelector->popParentElement(this); 1323 1323 } 1324 1324 -
trunk/Source/WebCore/dom/ShadowRoot.cpp
r109313 r109563 28 28 #include "ShadowRoot.h" 29 29 30 #include "CSSStyleSelector.h" 30 31 #include "Document.h" 31 32 #include "DocumentFragment.h" … … 199 200 } 200 201 201 } 202 void ShadowRoot::attach() 203 { 204 CSSStyleSelector* styleSelector = document()->styleSelector(); 205 styleSelector->pushParentShadowRoot(this); 206 DocumentFragment::attach(); 207 styleSelector->popParentShadowRoot(this); 208 } 209 210 } -
trunk/Source/WebCore/dom/ShadowRoot.h
r109313 r109563 82 82 bool hasInsertionPoint() const; 83 83 84 virtual void attach(); 85 84 86 private: 85 87 ShadowRoot(Document*); -
trunk/Source/WebCore/dom/ShadowTree.cpp
r109313 r109563 28 28 #include "ShadowTree.h" 29 29 30 #include "CSSStyleSelector.h" 30 31 #include "Document.h" 31 32 #include "Element.h" … … 246 247 reattachHostChildrenAndShadow(); 247 248 else { 249 CSSStyleSelector* styleSelector = youngest->document()->styleSelector(); 250 251 styleSelector->pushParentShadowRoot(youngest); 248 252 for (Node* n = youngest->firstChild(); n; n = n->nextSibling()) { 249 253 if (n->isElementNode()) … … 252 256 toText(n)->recalcTextStyle(change); 253 257 } 258 styleSelector->popParentShadowRoot(youngest); 254 259 } 255 260 -
trunk/Source/WebCore/html/HTMLStyleElement.cpp
r108814 r109563 165 165 { 166 166 #if ENABLE(STYLE_SCOPED) 167 ASSERT(!m_isRegisteredWithScopingNode); 167 // In come cases on teardown willRemove is not called - test here for unregistering again 168 // FIXME: Do we need to bother? 169 if (m_isRegisteredWithScopingNode) 170 unregisterWithScopingNode(); 168 171 #endif 169 172 HTMLElement::removedFromDocument();
Note: See TracChangeset
for help on using the changeset viewer.