Changeset 106331 in webkit
- Timestamp:
- Jan 30, 2012 9:04:08 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 10 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r106325 r106331 1 2012-01-30 Roland Steiner <rolandsteiner@chromium.org> 2 3 <style scoped>: Implement scoped stylesheets and basic application 4 https://bugs.webkit.org/show_bug.cgi?id=73190 5 6 Test that <style scoped> affects styles and is updated correctly: 7 -) basic test 8 -) test setting/un-setting the 'scoped' attribute 9 -) test inserting/removing a whole <style scoped> element 10 11 Reviewed by Antti Koivisto. 12 13 * fast/css/style-scoped/style-scoped-attach-expected.txt: Added. 14 * fast/css/style-scoped/style-scoped-attach.html: Added. 15 * fast/css/style-scoped/style-scoped-basic-expected.txt: Added. 16 * fast/css/style-scoped/style-scoped-basic.html: Added. 17 * fast/css/style-scoped/style-scoped-detach-expected.txt: Added. 18 * fast/css/style-scoped/style-scoped-detach.html: Added. 19 * fast/css/style-scoped/style-scoped-remove-scoped-expected.txt: Added. 20 * fast/css/style-scoped/style-scoped-remove-scoped.html: Added. 21 * fast/css/style-scoped/style-scoped-set-scoped-expected.txt: Added. 22 * fast/css/style-scoped/style-scoped-set-scoped.html: Added. 23 1 24 2012-01-30 Yuzo Fujishima <yuzo@google.com> 2 25 -
trunk/Source/WebCore/ChangeLog
r106324 r106331 1 2012-01-30 Roland Steiner <rolandsteiner@chromium.org> 2 3 <style scoped>: Implement scoped stylesheets and basic application 4 https://bugs.webkit.org/show_bug.cgi?id=73190 5 6 Implementing support for <style scoped>: 7 Add a vector stack to CSSStyleSelector that keeps track of encountered scoping elements. This is 8 used for O(1) access to all relevant style sheets for a given element. 9 Adapt matching of author style sheets to also consult appropriate scoped sheets. 10 Finally, prevent style sharing from crossing into/out of scoped style boundaries. 11 12 Reviewed by Antti Koivisto. 13 14 Tests: fast/css/style-scoped/style-scoped-attach.html 15 fast/css/style-scoped/style-scoped-basic.html 16 fast/css/style-scoped/style-scoped-detach.html 17 fast/css/style-scoped/style-scoped-remove-scoped.html 18 fast/css/style-scoped/style-scoped-set-scoped.html 19 20 * css/CSSStyleSelector.cpp: 21 (RuleSet): 22 (WebCore::CSSStyleSelector::CSSStyleSelector): add code for scoped style sheets 23 (WebCore::CSSStyleSelector::collectFeatures): ditto 24 (WebCore): 25 (WebCore::CSSStyleSelector::determineScopingElement): determine whether an author sheet is scoped (and to which scope), or global 26 (WebCore::CSSStyleSelector::scopedRuleSetForElement): returns the RuleSet for the <style scoped> contained by the passed-in element (if any), or 0 27 (WebCore::CSSStyleSelector::appendAuthorStylesheets): add code for scoped style sheets 28 (WebCore::CSSStyleSelector::setupScopingElementStack): determine scoping element ancestors of the given element 29 (WebCore::CSSStyleSelector::pushParent): simplify and refactor SelectorChecker::pushParent, as code in CSStyleSelector needs partial access 30 (WebCore::CSSStyleSelector::popParent): ditto 31 (WebCore::CSSStyleSelector::sortAndTransferMatchedRules): helper function 32 (WebCore::CSSStyleSelector::matchAuthorRules): use AuthorRuleSetIterator to iterate over all relevant RuleSets 33 (WebCore::CSSStyleSelector::matchRules): adapt for scoped style rules 34 (WebCore::CSSStyleSelector::matchAllRules): ditto 35 (WebCore::CSSStyleSelector::locateCousinList): prevent style sharing across scope boundaries 36 (WebCore::CSSStyleSelector::canShareStyleWithElement): ditto 37 (WebCore::CSSStyleSelector::locateSharedStyle): ditto 38 (WebCore::CSSStyleSelector::pseudoStyleForElement): changed call to matchAuthorRules 39 (WebCore::CSSStyleSelector::styleForPage): add comment 40 (WebCore::CSSStyleSelector::checkRegionStyle): add global scope parameter 41 (WebCore::CSSStyleSelector::pseudoStyleRulesForElement): changed call to matchAuthorRules 42 (WebCore::RuleSet::addRulesFromSheet): adapt for scoped style rules 43 * css/CSSStyleSelector.h: 44 (CSSStyleSelector): 45 (WebCore::CSSStyleSelector::ScopeStackFrame::ScopeStackFrame): struct holding an Element pointer and a RuleSet pointer, to be used in a Vector 46 (WebCore::CSSStyleSelector::scopingElementStackIsConsistent): returns if the last seen parent matches the passed-in element 47 * css/SelectorChecker.cpp: 48 (WebCore::SelectorChecker::setupParentStack): set up the parent stack (refactoring) 49 (WebCore::SelectorChecker::pushParent): simplify and refactor 50 * css/SelectorChecker.h: 51 (WebCore::SelectorChecker::popParent): ditto 52 (WebCore::SelectorChecker::parentStackIsEmpty): ditto 53 (WebCore::SelectorChecker::parentStackIsConsistent): make parameter const 54 1 55 2012-01-30 Dana Jansens <danakj@chromium.org> 2 56 -
trunk/Source/WebCore/css/CSSStyleSelector.cpp
r106258 r106331 66 66 #include "HTMLNames.h" 67 67 #include "HTMLProgressElement.h" 68 #include "HTMLStyleElement.h" 68 69 #include "HTMLTextAreaElement.h" 69 70 #include "InspectorInstrumentation.h" … … 223 224 typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<RuleData> > > AtomRuleMap; 224 225 225 void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0 );226 void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0, const Element* = 0); 226 227 227 228 void addStyleRule(CSSStyleRule*); … … 338 339 , m_hasPendingShaders(false) 339 340 #endif 341 #if ENABLE(STYLE_SCOPED) 342 , m_scopingElementStackParent(0) 343 #endif 340 344 { 341 345 Element* root = document->documentElement(); … … 369 373 m_authorStyle = adoptPtr(new RuleSet); 370 374 // Adding rules from multiple sheets, shrink at the end. 375 // Adding global rules from multiple sheets, shrink at the end. 376 // Note that there usually is only 1 sheet for scoped rules, so auto-shrink-to-fit is fine. 371 377 m_authorStyle->disableAutoShrinkToFit(); 372 378 … … 398 404 399 405 // Add rules from elements like SVG's <font-face> 400 if (mappedElementSheet) 406 if (mappedElementSheet) { 407 // FIXME: see if style scopes can/should be added here. 401 408 m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this); 409 } 402 410 403 411 // add stylesheets from document … … 424 432 m_features.add(defaultStyle->features()); 425 433 m_features.add(m_authorStyle->features()); 434 #if ENABLE(STYLE_SCOPED) 435 for (ScopedRuleSetMap::iterator it = m_scopedAuthorStyles.begin(); it != m_scopedAuthorStyles.end(); ++it) 436 m_features.add(it->second->features()); 437 #endif 426 438 if (m_userStyle) 427 439 m_features.add(m_userStyle->features()); … … 430 442 m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules); 431 443 } 444 445 #if ENABLE(STYLE_SCOPED) 446 Element* CSSStyleSelector::determineScopingElement(const CSSStyleSheet* sheet) 447 { 448 ASSERT(sheet); 449 450 Node* ownerNode = sheet->findStyleSheetOwnerNode(); 451 if (!ownerNode || !ownerNode->isHTMLElement() || !ownerNode->hasTagName(HTMLNames::styleTag)) 452 return 0; 453 454 HTMLStyleElement* styleElement = static_cast<HTMLStyleElement*>(ownerNode); 455 if (!styleElement->scoped()) 456 return 0; 457 458 return styleElement->parentElement(); 459 } 460 461 inline RuleSet* CSSStyleSelector::scopedRuleSetForElement(const Element* element) const 462 { 463 if (!element->hasScopedHTMLStyleChild()) 464 return 0; 465 ScopedRuleSetMap::const_iterator it = m_scopedAuthorStyles.find(element); 466 return it != m_scopedAuthorStyles.end() ? it->second.get() : 0; 467 } 468 #endif 432 469 433 470 void CSSStyleSelector::appendAuthorStylesheets(unsigned firstNew, const Vector<RefPtr<StyleSheet> >& stylesheets) … … 439 476 if (!stylesheets[i]->isCSSStyleSheet() || stylesheets[i]->disabled()) 440 477 continue; 441 m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(stylesheets[i].get()), *m_medium, this); 478 CSSStyleSheet* cssSheet = static_cast<CSSStyleSheet*>(stylesheets[i].get()); 479 #if ENABLE(STYLE_SCOPED) 480 const Element* scope = determineScopingElement(cssSheet); 481 if (scope) { 482 pair<ScopedRuleSetMap::iterator, bool> addResult = m_scopedAuthorStyles.add(scope, nullptr); 483 if (addResult.second) 484 addResult.first->second = adoptPtr(new RuleSet()); 485 addResult.first->second->addRulesFromSheet(cssSheet, *m_medium, this, scope); 486 continue; 487 } 488 #endif 489 m_authorStyle->addRulesFromSheet(cssSheet, *m_medium, this); 442 490 } 443 491 m_authorStyle->shrinkToFit(); … … 446 494 if (document()->renderer() && document()->renderer()->style()) 447 495 document()->renderer()->style()->font().update(fontSelector()); 496 } 497 498 #if ENABLE(STYLE_SCOPED) 499 void CSSStyleSelector::setupScopingElementStack(const Element* parent) 500 { 501 // Shortcut: abort if <style scoped> isn't used anywhere 502 if (m_scopedAuthorStyles.isEmpty()) { 503 ASSERT(!m_scopingElementStackParent); 504 ASSERT(m_scopingElementStack.isEmpty()); 505 return; 506 } 507 m_scopingElementStack.shrink(0); 508 for (; parent; parent = parent->parentOrHostElement()) { 509 RuleSet* ruleSet = scopedRuleSetForElement(parent); 510 if (ruleSet) 511 m_scopingElementStack.append(ScopeStackFrame(parent, ruleSet)); 512 } 513 m_scopingElementStack.reverse(); 514 m_scopingElementStackParent = parent; 515 } 516 #endif 517 518 void CSSStyleSelector::pushParent(Element* parent) 519 { 520 const Element* parentsParent = parent->parentOrHostElement(); 521 // We are not always invoked consistently. For example, script execution can cause us to enter 522 // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree. 523 // Reset the stack in this case, or if we see a new root element. 524 // Otherwise just push the new parent. 525 if (!parentsParent || m_checker.parentStackIsEmpty()) 526 m_checker.setupParentStack(parent); 527 else 528 m_checker.pushParent(parent); 529 530 #if ENABLE(STYLE_SCOPED) 531 if (!scopingElementStackIsConsistent(parentsParent)) { 532 // In some wacky cases during style resolve we may get invoked for random elements - 533 // recreate the scoping element stack in such cases. 534 setupScopingElementStack(parent); 535 return; 536 } 537 RuleSet* ruleSet = scopedRuleSetForElement(parent); 538 if (ruleSet) 539 m_scopingElementStack.append(ScopeStackFrame(parent, ruleSet)); 540 m_scopingElementStackParent = parent; 541 #endif 542 } 543 544 void CSSStyleSelector::popParent(Element* parent) 545 { 546 // Note that we may get invoked for some random elements in some wacky cases during style resolve. 547 // Pause maintaining the stack in this case. 548 if (m_checker.parentStackIsConsistent(parent)) 549 m_checker.popParent(); 550 #if ENABLE(STYLE_SCOPED) 551 // Only bother to update the scoping element stack if it is consistent. 552 if (scopingElementStackIsConsistent(parent)) { 553 m_scopingElementStack.removeLast(); 554 m_scopingElementStackParent = parent->parentOrHostElement(); 555 } 556 #endif 448 557 } 449 558 … … 688 797 } 689 798 690 void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) 691 { 692 m_matchedRules.clear(); 693 694 if (!rules || !m_element) 695 return; 696 697 collectMatchingRules(rules, firstRuleIndex, lastRuleIndex, includeEmptyRules); 698 collectMatchingRulesForRegion(rules, firstRuleIndex, lastRuleIndex, includeEmptyRules); 699 799 void CSSStyleSelector::sortAndTransferMatchedRules() 800 { 700 801 if (m_matchedRules.isEmpty()) 701 802 return; … … 722 823 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration(), linkMatchType); 723 824 } 825 } 826 827 void CSSStyleSelector::matchAuthorRules(int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) 828 { 829 m_matchedRules.clear(); 830 831 if (!m_element) 832 return; 833 834 // Match global author rules. 835 collectMatchingRules(m_authorStyle.get(), firstRuleIndex, lastRuleIndex, includeEmptyRules); 836 collectMatchingRulesForRegion(m_authorStyle.get(), firstRuleIndex, lastRuleIndex, includeEmptyRules); 837 838 #if ENABLE(STYLE_SCOPED) 839 // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent). 840 const Element* parent = m_element->parentOrHostElement(); 841 if (!scopingElementStackIsConsistent(parent)) 842 setupScopingElementStack(parent); 843 for (size_t i = m_scopingElementStack.size(); i; --i) { 844 collectMatchingRules(m_scopingElementStack[i - 1].m_ruleSet, firstRuleIndex, lastRuleIndex, includeEmptyRules); 845 collectMatchingRulesForRegion(m_scopingElementStack[i - 1].m_ruleSet, firstRuleIndex, lastRuleIndex, includeEmptyRules); 846 } 847 // Also include the current element. 848 RuleSet* ruleSet = scopedRuleSetForElement(m_element); 849 if (ruleSet) { 850 collectMatchingRules(ruleSet, firstRuleIndex, lastRuleIndex, includeEmptyRules); 851 collectMatchingRulesForRegion(ruleSet, firstRuleIndex, lastRuleIndex, includeEmptyRules); 852 } 853 #endif 854 855 sortAndTransferMatchedRules(); 856 } 857 858 void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) 859 { 860 m_matchedRules.clear(); 861 862 if (!rules || !m_element) 863 return; 864 865 collectMatchingRules(rules, firstRuleIndex, lastRuleIndex, includeEmptyRules); 866 collectMatchingRulesForRegion(rules, firstRuleIndex, lastRuleIndex, includeEmptyRules); 867 868 sortAndTransferMatchedRules(); 724 869 } 725 870 … … 871 1016 // Check the rules in author sheets next. 872 1017 if (m_matchAuthorAndUserStyles) 873 match Rules(m_authorStyle.get(),result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, false);1018 matchAuthorRules(result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, false); 874 1019 875 1020 // Now check our inline style attribute. … … 934 1079 if (!parent || !parent->isStyledElement()) 935 1080 return 0; 1081 #if ENABLE(STYLE_SCOPED) 1082 if (parent->hasScopedHTMLStyleChild()) 1083 return 0; 1084 #endif 936 1085 StyledElement* p = static_cast<StyledElement*>(parent); 937 1086 if (p->inlineStyleDecl()) … … 1097 1246 return false; 1098 1247 1248 #if ENABLE(STYLE_SCOPED) 1249 if (element->hasScopedHTMLStyleChild()) 1250 return false; 1251 #endif 1252 1099 1253 bool isControl = element->isFormControlElement(); 1100 1254 … … 1168 1322 if (parentStylePreventsSharing(m_parentStyle)) 1169 1323 return 0; 1324 #if ENABLE(STYLE_SCOPED) 1325 if (m_styledElement->hasScopedHTMLStyleChild()) 1326 return 0; 1327 #endif 1170 1328 1171 1329 // Check previous siblings and their cousins. … … 1487 1645 if (m_matchAuthorAndUserStyles) { 1488 1646 matchRules(m_userStyle.get(), matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false); 1489 match Rules(m_authorStyle.get(),matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, false);1647 matchAuthorRules(matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, false); 1490 1648 } 1491 1649 … … 1524 1682 matchPageRules(defaultPrintStyle, isLeft, isFirst, page); 1525 1683 matchPageRules(m_userStyle.get(), isLeft, isFirst, page); 1684 // Only consider the global author RuleSet for @page rules, as per the HTML5 spec. 1526 1685 matchPageRules(m_authorStyle.get(), isLeft, isFirst, page); 1527 1686 m_lineHeightValue = 0; … … 1767 1926 bool CSSStyleSelector::checkRegionStyle(Element* regionElement) 1768 1927 { 1928 // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment, 1929 // so all region rules are global by default. Verify whether that can stand or needs changing. 1930 1769 1931 unsigned rulesSize = m_authorStyle->m_regionSelectorsAndRuleSets.size(); 1770 1932 for (unsigned i = 0; i < rulesSize; ++i) { … … 1837 1999 1838 2000 // Check the rules in author sheets. 1839 match Rules(m_authorStyle.get(),dummy.ranges.firstAuthorRule, dummy.ranges.lastAuthorRule, rulesToInclude & EmptyCSSRules);2001 matchAuthorRules(dummy.ranges.firstAuthorRule, dummy.ranges.lastAuthorRule, rulesToInclude & EmptyCSSRules); 1840 2002 1841 2003 m_sameOriginOnly = false; … … 2115 2277 } 2116 2278 2117 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector )2279 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector, const Element* scope) 2118 2280 { 2119 2281 ASSERT(sheet); … … 2135 2297 CSSImportRule* import = static_cast<CSSImportRule*>(rule); 2136 2298 if (import->styleSheet() && (!import->media() || medium.eval(import->media(), styleSelector))) 2137 addRulesFromSheet(import->styleSheet(), medium, styleSelector );2299 addRulesFromSheet(import->styleSheet(), medium, styleSelector, scope); 2138 2300 } 2139 2301 else if (rule->isMediaRule()) { … … 2151 2313 else if (childItem->isFontFaceRule() && styleSelector) { 2152 2314 // Add this font face to our set. 2315 // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment. 2316 if (scope) 2317 continue; 2153 2318 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem); 2154 2319 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule); … … 2156 2321 } else if (childItem->isKeyframesRule() && styleSelector) { 2157 2322 // Add this keyframe rule to our set. 2323 // FIXME(BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment. 2324 if (scope) 2325 continue; 2158 2326 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem)); 2159 2327 } … … 2162 2330 } else if (rule->isFontFaceRule() && styleSelector) { 2163 2331 // Add this font face to our set. 2332 // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment. 2333 if (scope) 2334 continue; 2164 2335 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(rule); 2165 2336 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule); 2166 2337 styleSelector->invalidateMatchedDeclarationCache(); 2167 } else if (rule->isKeyframesRule()) 2338 } else if (rule->isKeyframesRule()) { 2339 // FIXME (BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment. 2340 if (scope) 2341 continue; 2168 2342 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(rule)); 2169 else if (rule->isRegionRule() && styleSelector) 2343 } else if (rule->isRegionRule() && styleSelector) { 2344 // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment. 2345 if (scope) 2346 continue; 2170 2347 addRegionRule(static_cast<WebKitCSSRegionRule*>(rule)); 2348 } 2171 2349 } 2172 2350 if (m_autoShrinkToFitEnabled) -
trunk/Source/WebCore/css/CSSStyleSelector.h
r106120 r106331 107 107 ~CSSStyleSelector(); 108 108 109 #if ENABLE(STYLE_SCOPED) 110 static Element* determineScopingElement(const CSSStyleSheet*); 111 #endif 112 109 113 // Using these during tree walk will allow style selector to optimize child and descendant selector lookups. 110 void pushParent(Element* parent) { m_checker.pushParent(parent); }111 void popParent(Element* parent) { m_checker.popParent(parent); }114 void pushParent(Element* parent); 115 void popParent(Element* parent); 112 116 113 117 PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false, RenderRegion* regionForStyling = 0); … … 276 280 void matchUARules(MatchResult&); 277 281 void matchRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); 282 void matchAuthorRules(int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); 278 283 void collectMatchingRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); 279 284 void collectMatchingRulesForRegion(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); … … 281 286 bool fastRejectSelector(const RuleData&) const; 282 287 void sortMatchedRules(); 288 void sortAndTransferMatchedRules(); 283 289 284 290 bool checkSelector(const RuleData&); … … 434 440 bool m_applyPropertyToVisitedLinkStyle; 435 441 const CSSStyleApplyProperty& m_applyProperty; 436 442 437 443 #if ENABLE(CSS_SHADERS) 438 444 bool m_hasPendingShaders; 445 #endif 446 447 #if ENABLE(STYLE_SCOPED) 448 typedef HashMap<const Element*, OwnPtr<RuleSet> > ScopedRuleSetMap; 449 450 RuleSet* scopedRuleSetForElement(const Element*) const; 451 452 void setupScopingElementStack(const Element*); 453 bool scopingElementStackIsConsistent(const Element* parent) const { return parent && parent == m_scopingElementStackParent; } 454 455 ScopedRuleSetMap m_scopedAuthorStyles; 456 457 struct ScopeStackFrame { 458 ScopeStackFrame() : m_element(0), m_ruleSet(0) { } 459 ScopeStackFrame(const Element* element, RuleSet* ruleSet) : m_element(element), m_ruleSet(ruleSet) { } 460 const Element* m_element; 461 RuleSet* m_ruleSet; 462 }; 463 // Vector (used as stack) that keeps track of scoping elements (i.e., elements with a <style scoped> child) 464 // encountered during tree iteration for style resolution. 465 Vector<ScopeStackFrame> m_scopingElementStack; 466 // Element last seen as parent element when updating m_scopingElementStack. 467 // This is used to decide whether m_scopingElementStack is consistent, separately from SelectorChecker::m_parentStack. 468 const Element* m_scopingElementStackParent; 439 469 #endif 440 470 -
trunk/Source/WebCore/css/SelectorChecker.cpp
r104152 r106331 41 41 #include "HTMLOptionElement.h" 42 42 #include "HTMLProgressElement.h" 43 #include "HTMLStyleElement.h" 43 44 #include "InspectorInstrumentation.h" 44 45 #include "NodeRenderStyle.h" … … 126 127 } 127 128 129 void SelectorChecker::setupParentStack(Element* parent) 130 { 131 ASSERT(m_parentStack.isEmpty() == !m_ancestorIdentifierFilter); 132 // Kill whatever we stored before. 133 m_parentStack.shrink(0); 134 m_ancestorIdentifierFilter = adoptPtr(new BloomFilter<bloomFilterKeyBits>); 135 // Fast version if parent is a root element: 136 if (!parent->parentOrHostNode()) { 137 pushParentStackFrame(parent); 138 return; 139 } 140 // Otherwise climb up the tree. 141 Vector<Element*, 30> ancestors; 142 for (Element* ancestor = parent; ancestor; ancestor = ancestor->parentOrHostElement()) 143 ancestors.append(ancestor); 144 for (size_t n = ancestors.size(); n; --n) 145 pushParentStackFrame(ancestors[n - 1]); 146 } 147 128 148 void SelectorChecker::pushParent(Element* parent) 129 149 { 130 if (m_parentStack.isEmpty()) { 131 ASSERT(!m_ancestorIdentifierFilter); 132 m_ancestorIdentifierFilter = adoptPtr(new BloomFilter<bloomFilterKeyBits>); 133 // If the element is not the root itself, build the stack starting from the root. 134 if (parent->parentOrHostNode()) { 135 Vector<Element*, 30> ancestors; 136 for (Element* ancestor = parent; ancestor; ancestor = ancestor->parentOrHostElement()) 137 ancestors.append(ancestor); 138 int count = ancestors.size(); 139 for (int n = count - 1; n >= 0; --n) 140 pushParentStackFrame(ancestors[n]); 141 return; 142 } 143 } else if (!parent->parentOrHostElement()) { 144 // We are not always invoked consistently. For example, script execution can cause us to enter 145 // style recalc in the middle of tree building. Reset the stack if we see a new root element. 146 ASSERT(m_ancestorIdentifierFilter); 147 m_ancestorIdentifierFilter->clear(); 148 m_parentStack.resize(0); 149 } else { 150 ASSERT(m_ancestorIdentifierFilter); 151 // We may get invoked for some random elements in some wacky cases during style resolve. 152 // Pause maintaining the stack in this case. 153 if (m_parentStack.last().element != parent->parentOrHostElement()) 154 return; 155 } 150 ASSERT(m_ancestorIdentifierFilter); 151 // We may get invoked for some random elements in some wacky cases during style resolve. 152 // Pause maintaining the stack in this case. 153 if (m_parentStack.last().element != parent->parentOrHostElement()) 154 return; 156 155 pushParentStackFrame(parent); 157 }158 159 void SelectorChecker::popParent(Element* parent)160 {161 if (m_parentStack.isEmpty() || m_parentStack.last().element != parent)162 return;163 popParentStackFrame();164 156 } 165 157 -
trunk/Source/WebCore/css/SelectorChecker.h
r104734 r106331 61 61 static void collectIdentifierHashes(const CSSSelector*, unsigned* identifierHashes, unsigned maximumIdentifierCount); 62 62 63 void setupParentStack(Element* parent); 63 64 void pushParent(Element* parent); 64 void popParent(Element* parent); 65 bool parentStackIsConsistent(ContainerNode* parentNode) const { return !m_parentStack.isEmpty() && m_parentStack.last().element == parentNode; } 65 void popParent() { popParentStackFrame(); } 66 bool parentStackIsEmpty() const { return m_parentStack.isEmpty(); } 67 bool parentStackIsConsistent(const ContainerNode* parentNode) const { return !m_parentStack.isEmpty() && m_parentStack.last().element == parentNode; } 66 68 67 69 EInsideLink determineLinkState(Element*) const;
Note: See TracChangeset
for help on using the changeset viewer.