Changeset 140371 in webkit
- Timestamp:
- Jan 21, 2013 4:45:14 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r140370 r140371 1 2013-01-21 Andreas Kling <akling@apple.com> 2 3 CSS: Make tag sub-selectors standalone CSSSelectors. 4 <http://webkit.org/b/107111> 5 6 Reviewed by Antti Koivisto. 7 8 TL;DR: Instead of storing a QualifiedName with every CSSSelector, special-case tag selectors 9 by promoting them to stand-alone CSSSelectors. 10 33% reduction in CSS selector memory usage, 4.77 MB progression on Membuster3. 11 Fixed some bugs in Shadow DOM that were exposed by these changes. 12 13 A selector like this: 14 15 div.tripp.trapp#trull { } 16 17 Would previously be represented by a chain of 3 CSSSelector objects like so: 18 19 [ Tag: "div", Type: Class, Value: "tripp" ] 20 [ Tag: *, Type: Class, Value: "trapp" ] 21 [ Tag: *, Type: ID, Value: "trull" ] 22 23 After this change, the memory layout becomes: 24 25 [ Type: Tag, Value: "div" ] 26 [ Type: Class, Value: "tripp" ] 27 [ Type: Class, Value: "trapp" ] 28 [ Type: ID, Value: "trull" ] 29 30 This is a huge net memory win since the majority of selectors don't even have a tag name 31 and those that do now have a flat cost of one more CSSSelector. 32 Traversal is also slightly cleaner since any tag name will now be in a predictable place. 33 34 * css/SelectorChecker.cpp: 35 (WebCore::isFastCheckableMatch): 36 * html/shadow/HTMLContentElement.cpp: 37 (WebCore::validateSubSelector): 38 39 Renamed CSSSelector::None to CSSSelector::Tag. 40 41 * css/SelectorChecker.h: 42 (WebCore::SelectorChecker::tagMatches): 43 * css/StyleResolver.cpp: 44 (WebCore::StyleResolver::ruleMatches): 45 46 Changed SelectorChecker::tagMatches() to take a QualifiedName instead of a CSSSelector. 47 48 * dom/QualifiedName.cpp: 49 (WebCore::QualifiedName::deref): 50 (WebCore::QualifiedName::QualifiedNameImpl::~QualifiedNameImpl): 51 * dom/QualifiedName.h: 52 (QualifiedNameImpl): 53 54 Give QualifiedNameImpl a destructor so it can remove itself from the global cache instead of 55 having QualifiedName do it. This makes it possible to participate in ownership of QualifiedNames 56 via a QualifiedNameImpl pointer, as used by the union member in CSSSelector. 57 58 * css/CSSGrammar.y.in: 59 * css/CSSParser.cpp: 60 (WebCore::CSSParser::createFloatingSelectorWithTagName): 61 (WebCore::CSSParser::updateSpecifiersWithNamespaceIfNeeded): 62 (WebCore::CSSParser::updateSpecifiersWithElementName): 63 * css/CSSParser.h: 64 * css/CSSParserValues.h: 65 (CSSParserSelector): 66 * css/CSSParserValues.cpp: 67 (WebCore::CSSParserSelector::CSSParserSelector): 68 (WebCore::CSSParserSelector::prependTagSelector): 69 70 Make the CSS parser slap a CSSSelector with m_match=Tag at the head of all selectors that match 71 one or more of these criteria: 72 73 - The selector starts with a tag, e.g "div.foo" or just plain "span" 74 - There is a @namespace rule in effect, and the override namespace needs to be stored with the selector. 75 These will have CSSSelectors::m_isTagForNamespaceRule set, this is only so that selector serialization 76 can avoid outputting a '*' tag where we previously didn't. 77 78 (WebCore::CSSParserSelector::isSimple): 79 80 Merged the CSSSelector::isSimple() logic into CSSParserSelector, since it's only needed during parsing 81 to figure out if a selector is allowed within :not(). 82 83 * css/CSSSelector.h: 84 (CSSSelector): 85 (WebCore::CSSSelector::setValue): 86 (WebCore::CSSSelector::CSSSelector): 87 (WebCore::CSSSelector::~CSSSelector): 88 (WebCore::CSSSelector::tagQName): 89 * css/CSSSelector.cpp: 90 (WebCore::CSSSelector::createRareData): 91 (WebCore::CSSSelector::operator==): 92 93 Add a QualifiedNameImpl* m_tagQName member to the CSSSelector data union. This union pointer is used 94 if m_match == Tag. tagQName() is used to retrieve the tag (renamed from tag().) 95 96 (WebCore::CSSSelector::selectorText): 97 98 Only serialize Tag selector components that aren't namespace placeholders. This behavior is web-facing 99 so we make an effort to stay consistent. 100 101 (WebCore::CSSSelector::specificityForOneSelector): 102 (WebCore::CSSSelector::specificityForPage): 103 * css/CSSSelectorList.cpp: 104 (WebCore::SelectorNeedsNamespaceResolutionFunctor::operator()): 105 * css/RuleSet.cpp: 106 (WebCore::isSelectorMatchingHTMLBasedOnRuleHash): 107 * css/SelectorFilter.cpp: 108 (WebCore::collectDescendantSelectorIdentifierHashes): 109 (WebCore::SelectorFilter::collectIdentifierHashes): 110 111 Adapt algorithms to having Tag selectors. 112 113 (WebCore::selectorListContainsUncommonAttributeSelector): 114 115 Loop through all selector components when looking for uncommon attributes. 116 117 (WebCore::determinePropertyWhitelistType): 118 119 Loop through all selector components when looking for ::cue(). 120 121 (WebCore::RuleSet::addRule): 122 (WebCore::RuleSet::findBestRuleSetAndAdd): 123 124 Break addRule into two methods to be able to peek ahead if the first selector is a Tag. 125 Otherwise we'd end up sticking most selectors in m_tagRules, breaking the class/ID/etc optimizations. 126 127 * css/SelectorChecker.cpp: 128 (WebCore::SelectorChecker::fastCheck): 129 (WebCore::SelectorChecker::fastCheckSingleSelector): 130 131 It's no longer necessary to check the tagQName for every selector component, so don't. 132 Also simplified the signature of the template argument function. 133 134 (WebCore::SelectorChecker::fastCheckRightmostSelector): 135 136 Updated for Tag selectors. 137 138 (WebCore::SelectorChecker::checkOne): 139 (WebCore::SelectorChecker::matches): 140 (WebCore::SelectorChecker::match): 141 142 Have match() take a SiblingTraversalStrategy so it can forward that to checkOne(). 143 This is necessary for shadow DOM code that was incorrectly calling checkOne() instead of match(). 144 145 * css/StyleResolver.cpp: 146 (WebCore::StyleResolver::ruleMatches): 147 148 The meaning of "single-part selector" changes a bit with this patch, and no longer includes "div.foo" 149 as that is now a Tag, followed by a Class. Given that, we can't assume the tag check is unnecessary 150 just because the rightmost descendant was found in one of the hashes. 151 152 (WebCore::StyleResolver::matchPageRulesForList): 153 154 Loop through all selector components when matching @page since pseudo types may not always be in 155 the first subselector now. 156 157 * html/shadow/ContentDistributor.cpp: 158 (WebCore::ContentDistributor::collectSelectFeatureSetFrom): 159 160 Collect feature information from subselectors to make sure nothing is missed. (This bug was exposed 161 by offsetting the subselectors.) 162 163 * html/shadow/ContentSelectorQuery.cpp: 164 (WebCore::ContentSelectorChecker::checkContentSelector): 165 166 Call SelectorChecker::match() instead of checkOne() to make subselector traversal work properly. 167 1 168 2013-01-21 Levi Weintraub <leviw@chromium.org> 2 169 -
trunk/Source/WebCore/css/CSSGrammar.y.in
r139866 r140371 841 841 page_selector: 842 842 IDENT { 843 $$ = parser->createFloatingSelector(); 844 $$->setTag(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); 843 $$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); 845 844 $$->setForPage(); 846 845 } … … 848 847 $$ = $2; 849 848 if ($$) { 850 $$-> setTag(QualifiedName(nullAtom, $1, parser->m_defaultNamespace));849 $$->prependTagSelector(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); 851 850 $$->setForPage(); 852 851 } … … 1148 1147 simple_selector: 1149 1148 element_name { 1150 $$ = parser->createFloatingSelector(); 1151 $$->setTag(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); 1149 $$ = parser->createFloatingSelectorWithTagName(QualifiedName(nullAtom, $1, parser->m_defaultNamespace)); 1152 1150 } 1153 1151 | element_name specifier_list { … … 1159 1157 $$ = $1; 1160 1158 if ($$) 1161 parser->updateSpecifiersWith ElementName(nullAtom, starAtom,$$);1159 parser->updateSpecifiersWithNamespaceIfNeeded($$); 1162 1160 } 1163 1161 | namespace_selector element_name { 1164 $$ = parser->createFloatingSelector(); 1165 $$->setTag(parser->determineNameInNamespace($1, $2)); 1162 $$ = parser->createFloatingSelectorWithTagName(parser->determineNameInNamespace($1, $2)); 1166 1163 } 1167 1164 | namespace_selector element_name specifier_list { -
trunk/Source/WebCore/css/CSSParser.cpp
r140300 r140371 10549 10549 } 10550 10550 10551 CSSParserSelector* CSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName) 10552 { 10553 CSSParserSelector* selector = new CSSParserSelector(tagQName); 10554 m_floatingSelectors.add(selector); 10555 return selector; 10556 } 10557 10551 10558 CSSParserSelector* CSSParser::createFloatingSelector() 10552 10559 { … … 10904 10911 } 10905 10912 10906 void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers) 10913 void CSSParser::updateSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers) 10914 { 10915 if (m_defaultNamespace != starAtom || specifiers->isCustomPseudoElement()) 10916 updateSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true); 10917 } 10918 10919 void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule) 10907 10920 { 10908 10921 AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace; 10909 QualifiedName tag = QualifiedName(namespacePrefix, elementName, determinedNamespace); 10922 QualifiedName tag(namespacePrefix, elementName, determinedNamespace); 10923 10910 10924 if (!specifiers->isCustomPseudoElement()) { 10925 if (tag == anyQName()) 10926 return; 10911 10927 #if ENABLE(VIDEO_TRACK) 10912 10928 if (!(specifiers->pseudoType() == CSSSelector::PseudoCue)) 10913 10929 #endif 10914 specifiers-> setTag(tag);10930 specifiers->prependTagSelector(tag, tagIsForNamespaceRule); 10915 10931 return; 10916 10932 } … … 10925 10941 10926 10942 if (lastShadowDescendant->tagHistory()) { 10927 lastShadowDescendant->tagHistory()->setTag(tag); 10943 if (tag != anyQName()) 10944 lastShadowDescendant->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule); 10928 10945 return; 10929 10946 } … … 10931 10948 // For shadow-ID pseudo-elements to be correctly matched, the ShadowDescendant combinator has to be used. 10932 10949 // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*'). 10933 OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector); 10934 elementNameSelector->setTag(tag); 10950 OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag)); 10935 10951 lastShadowDescendant->setTagHistory(elementNameSelector.release()); 10936 10952 lastShadowDescendant->setRelation(CSSSelector::ShadowDescendant); -
trunk/Source/WebCore/css/CSSParser.h
r139866 r140371 267 267 268 268 CSSParserSelector* createFloatingSelector(); 269 CSSParserSelector* createFloatingSelectorWithTagName(const QualifiedName&); 269 270 PassOwnPtr<CSSParserSelector> sinkFloatingSelector(CSSParserSelector*); 270 271 … … 317 318 void addNamespace(const AtomicString& prefix, const AtomicString& uri); 318 319 QualifiedName determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName); 319 void updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector*); 320 void updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector*, bool isNamespacePlaceholder = false); 321 void updateSpecifiersWithNamespaceIfNeeded(CSSParserSelector*); 320 322 CSSParserSelector* updateSpecifiers(CSSParserSelector*, CSSParserSelector*); 321 323 -
trunk/Source/WebCore/css/CSSParserValues.cpp
r134693 r140371 150 150 } 151 151 152 CSSParserSelector::CSSParserSelector(const QualifiedName& tagQName) 153 : m_selector(adoptPtr(new CSSSelector(tagQName))) 154 { 155 } 156 152 157 CSSParserSelector::~CSSParserSelector() 153 158 { … … 172 177 } 173 178 179 bool CSSParserSelector::isSimple() const 180 { 181 if (m_selector->selectorList() || m_selector->matchesPseudoElement()) 182 return false; 183 184 if (!m_tagHistory) 185 return true; 186 187 if (m_selector->m_match == CSSSelector::Tag) { 188 // We can't check against anyQName() here because namespace may not be nullAtom. 189 // Example: 190 // @namespace "http://www.w3.org/2000/svg"; 191 // svg:not(:root) { ... 192 if (m_selector->tagQName().localName() == starAtom) 193 return m_tagHistory->isSimple(); 194 } 195 196 return false; 197 } 198 174 199 void CSSParserSelector::insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector> selector, CSSSelector::Relation after) 175 200 { … … 190 215 } 191 216 192 } 193 217 void CSSParserSelector::prependTagSelector(const QualifiedName& tagQName, bool tagIsForNamespaceRule) 218 { 219 OwnPtr<CSSParserSelector> second = adoptPtr(new CSSParserSelector); 220 second->m_selector = m_selector.release(); 221 second->m_tagHistory = m_tagHistory.release(); 222 m_tagHistory = second.release(); 223 224 m_selector = adoptPtr(new CSSSelector(tagQName, tagIsForNamespaceRule)); 225 m_selector->m_relation = CSSSelector::SubSelector; 226 } 227 228 } 229 -
trunk/Source/WebCore/css/CSSParserValues.h
r134693 r140371 173 173 public: 174 174 CSSParserSelector(); 175 explicit CSSParserSelector(const QualifiedName&); 175 176 ~CSSParserSelector(); 176 177 177 178 PassOwnPtr<CSSSelector> releaseSelector() { return m_selector.release(); } 178 179 179 void setTag(const QualifiedName& value) { m_selector->setTag(value); }180 180 void setValue(const AtomicString& value) { m_selector->setValue(value); } 181 181 void setAttribute(const QualifiedName& value) { m_selector->setAttribute(value); } … … 190 190 bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); } 191 191 192 bool isSimple() const { return !m_tagHistory && m_selector->isSimple(); }192 bool isSimple() const; 193 193 bool hasShadowDescendant() const; 194 194 … … 197 197 void insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector>, CSSSelector::Relation after); 198 198 void appendTagHistory(CSSSelector::Relation, PassOwnPtr<CSSParserSelector>); 199 void prependTagSelector(const QualifiedName&, bool tagIsForNamespaceRule = false); 199 200 200 201 private: -
trunk/Source/WebCore/css/CSSSelector.cpp
r138784 r140371 42 42 void CSSSelector::createRareData() 43 43 { 44 ASSERT(m_match != Tag); 44 45 if (m_hasRareData) 45 46 return; … … 56 57 static const unsigned classMask = 0xff00; 57 58 static const unsigned elementMask = 0xff; 59 60 if (isForPage()) 61 return specificityForPage() & maxValueMask; 62 58 63 unsigned total = 0; 59 64 unsigned temp = 0; 65 60 66 for (const CSSSelector* selector = this; selector; selector = selector->tagHistory()) { 61 if (selector->m_isForPage)62 return (total + selector->specificityForPage()) & maxValueMask;63 67 temp = total + selector->specificityForOneSelector(); 64 68 // Clamp each component to its max in the case of overflow. … … 79 83 // FIXME: Pseudo-elements and pseudo-classes do not have the same specificity. This function 80 84 // isn't quite correct. 81 unsigned s = (m_tag.localName() == starAtom ? 0 : 1);82 85 switch (m_match) { 83 86 case Id: 84 s += 0x10000; 85 break; 87 return 0x10000; 86 88 case Exact: 87 89 case Class: … … 97 99 // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0530.html 98 100 if (pseudoType() == PseudoNot && selectorList()) 99 s += selectorList()->first()->specificityForOneSelector(); 100 else 101 s += 0x100; 102 case None: 103 break; 104 } 105 return s; 101 return selectorList()->first()->specificityForOneSelector(); 102 return 0x100; 103 case Tag: 104 return (tagQName().localName() != starAtom) ? 1 : 0; 105 case Unknown: 106 return 0; 107 } 108 ASSERT_NOT_REACHED(); 109 return 0; 106 110 } 107 111 … … 109 113 { 110 114 // See http://dev.w3.org/csswg/css3-page/#cascading-and-page-context 111 unsigned s = (m_tag.localName() == starAtom ? 0 : 4); 112 113 switch (pseudoType()) { 114 case PseudoFirstPage: 115 s += 2; 116 break; 117 case PseudoLeftPage: 118 case PseudoRightPage: 119 s += 1; 120 break; 121 case PseudoNotParsed: 122 break; 123 default: 124 ASSERT_NOT_REACHED(); 115 unsigned s = 0; 116 117 for (const CSSSelector* component = this; component; component = component->tagHistory()) { 118 switch (component->m_match) { 119 case Tag: 120 s += tagQName().localName() == starAtom ? 0 : 4; 121 break; 122 case PseudoClass: 123 switch (component->pseudoType()) { 124 case PseudoFirstPage: 125 s += 2; 126 break; 127 case PseudoLeftPage: 128 case PseudoRightPage: 129 s += 1; 130 break; 131 case PseudoNotParsed: 132 break; 133 default: 134 ASSERT_NOT_REACHED(); 135 } 136 break; 137 default: 138 break; 139 } 125 140 } 126 141 return s; … … 552 567 553 568 while (sel1 && sel2) { 554 if (sel1->m_tag != sel2->m_tag || sel1->attribute() != sel2->attribute() || 555 sel1->relation() != sel2->relation() || sel1->m_match != sel2->m_match || 556 sel1->value() != sel2->value() || 557 sel1->pseudoType() != sel2->pseudoType() || 558 sel1->argument() != sel2->argument()) 569 if (sel1->attribute() != sel2->attribute() 570 || sel1->relation() != sel2->relation() 571 || sel1->m_match != sel2->m_match 572 || sel1->value() != sel2->value() 573 || sel1->pseudoType() != sel2->pseudoType() 574 || sel1->argument() != sel2->argument()) { 559 575 return false; 576 } 577 if (sel1->m_match == Tag) { 578 if (sel1->tagQName() != sel2->tagQName()) 579 return false; 580 } 560 581 sel1 = sel1->tagHistory(); 561 582 sel2 = sel2->tagHistory(); … … 572 593 StringBuilder str; 573 594 574 const AtomicString& prefix = m_tag.prefix(); 575 const AtomicString& localName = m_tag.localName(); 576 if (m_match == CSSSelector::None || !prefix.isNull() || localName != starAtom) { 577 if (prefix.isNull()) 578 str.append(localName); 595 if (m_match == CSSSelector::Tag && !m_tagIsForNamespaceRule) { 596 if (tagQName().prefix().isNull()) 597 str.append(tagQName().localName()); 579 598 else { 580 str.append( prefix.string());599 str.append(tagQName().prefix().string()); 581 600 str.append('|'); 582 str.append( localName);601 str.append(tagQName().localName()); 583 602 } 584 603 } … … 725 744 } 726 745 727 bool CSSSelector::isSimple() const728 {729 if (selectorList() || tagHistory() || matchesPseudoElement())730 return false;731 732 int numConditions = 0;733 734 // hasTag() cannot be be used here because namespace may not be nullAtom.735 // Example:736 // @namespace "http://www.w3.org/2000/svg";737 // svg:not(:root) { ...738 if (m_tag != starAtom)739 numConditions++;740 741 if (m_match == Id || m_match == Class || m_match == PseudoClass)742 numConditions++;743 744 if (m_hasRareData && m_data.m_rareData->m_attribute != anyQName())745 numConditions++;746 747 // numConditions is 0 for a universal selector.748 // numConditions is 1 for other simple selectors.749 return numConditions <= 1;750 }751 752 746 CSSSelector::RareData::RareData(PassRefPtr<AtomicStringImpl> value) 753 747 : m_value(value.leakRef()) -
trunk/Source/WebCore/css/CSSSelector.h
r139432 r140371 2 2 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) 3 3 * 1999 Waldo Bastian (bastian@kde.org) 4 * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.4 * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 38 38 CSSSelector(); 39 39 CSSSelector(const CSSSelector&); 40 explicit CSSSelector(const QualifiedName&, bool tagIsForNamespaceRule = false); 40 41 41 42 ~CSSSelector(); … … 55 56 /* how the attribute value has to match.... Default is Exact */ 56 57 enum Match { 57 None = 0, 58 Unknown = 0, 59 Tag, 58 60 Id, 59 61 Class, … … 199 201 CSSSelector* tagHistory() const { return m_isLastInTagHistory ? 0 : const_cast<CSSSelector*>(this + 1); } 200 202 201 bool hasTag() const { return m_tag != anyQName(); } 202 203 const QualifiedName& tag() const { return m_tag; } 203 const QualifiedName& tagQName() const; 204 204 // AtomicString is really just an AtomicStringImpl* so the cast below is safe. 205 205 // FIXME: Perhaps call sites could be changed to accept AtomicStringImpl? … … 209 209 CSSSelectorList* selectorList() const { return m_hasRareData ? m_data.m_rareData->m_selectorList.get() : 0; } 210 210 211 void setTag(const QualifiedName& value) { m_tag = value; }212 211 void setValue(const AtomicString&); 213 212 void setAttribute(const QualifiedName&); … … 246 245 bool m_hasRareData : 1; 247 246 bool m_isForPage : 1; 247 bool m_tagIsForNamespaceRule : 1; 248 248 249 249 unsigned specificityForOneSelector() const; … … 276 276 DataUnion() : m_value(0) { } 277 277 AtomicStringImpl* m_value; 278 QualifiedName::QualifiedNameImpl* m_tagQName; 278 279 RareData* m_rareData; 279 280 } m_data; 280 281 QualifiedName m_tag;282 281 }; 283 282 … … 337 336 inline void CSSSelector::setValue(const AtomicString& value) 338 337 { 338 ASSERT(m_match != Tag); 339 339 // Need to do ref counting manually for the union. 340 340 if (m_hasRareData) { … … 361 361 inline CSSSelector::CSSSelector() 362 362 : m_relation(Descendant) 363 , m_match( None)363 , m_match(Unknown) 364 364 , m_pseudoType(PseudoNotParsed) 365 365 , m_parsedNth(false) … … 368 368 , m_hasRareData(false) 369 369 , m_isForPage(false) 370 , m_tag(anyQName()) 371 { 370 , m_tagIsForNamespaceRule(false) 371 { 372 } 373 374 inline CSSSelector::CSSSelector(const QualifiedName& tagQName, bool tagIsForNamespaceRule) 375 : m_relation(Descendant) 376 , m_match(Tag) 377 , m_pseudoType(PseudoNotParsed) 378 , m_parsedNth(false) 379 , m_isLastInSelectorList(false) 380 , m_isLastInTagHistory(true) 381 , m_hasRareData(false) 382 , m_isForPage(false) 383 , m_tagIsForNamespaceRule(tagIsForNamespaceRule) 384 { 385 m_data.m_tagQName = tagQName.impl(); 386 m_data.m_tagQName->ref(); 372 387 } 373 388 … … 381 396 , m_hasRareData(o.m_hasRareData) 382 397 , m_isForPage(o.m_isForPage) 383 , m_tag(o.m_tag) 384 { 385 if (o.m_hasRareData) { 398 , m_tagIsForNamespaceRule(o.m_tagIsForNamespaceRule) 399 { 400 if (o.m_match == Tag) { 401 m_data.m_tagQName = o.m_data.m_tagQName; 402 m_data.m_tagQName->ref(); 403 } else if (o.m_hasRareData) { 386 404 m_data.m_rareData = o.m_data.m_rareData; 387 405 m_data.m_rareData->ref(); … … 394 412 inline CSSSelector::~CSSSelector() 395 413 { 396 if (m_hasRareData) 414 if (m_match == Tag) 415 m_data.m_tagQName->deref(); 416 else if (m_hasRareData) 397 417 m_data.m_rareData->deref(); 398 418 else if (m_data.m_value) … … 400 420 } 401 421 422 inline const QualifiedName& CSSSelector::tagQName() const 423 { 424 ASSERT(m_match == Tag); 425 return *reinterpret_cast<const QualifiedName*>(&m_data.m_tagQName); 426 } 427 402 428 } // namespace WebCore 403 429 -
trunk/Source/WebCore/css/CSSSelectorList.cpp
r134693 r140371 184 184 bool operator()(CSSSelector* selector) 185 185 { 186 if (selector-> hasTag() && selector->tag().prefix() != nullAtom && selector->tag().prefix() != starAtom)186 if (selector->m_match == CSSSelector::Tag && selector->tagQName().prefix() != nullAtom && selector->tagQName().prefix() != starAtom) 187 187 return true; 188 188 if (selector->isAttributeSelector() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom) -
trunk/Source/WebCore/css/RuleSet.cpp
r140173 r140371 56 56 static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector) 57 57 { 58 const AtomicString& selectorNamespace = selector->tag().namespaceURI(); 59 if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI) 60 return false; 61 if (selector->m_match == CSSSelector::None) 62 return true; 63 if (selector->tag() != starAtom) 64 return false; 58 ASSERT(selector); 59 if (selector->m_match == CSSSelector::Tag) { 60 const AtomicString& selectorNamespace = selector->tagQName().namespaceURI(); 61 if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI) 62 return false; 63 if (selector->relation() == CSSSelector::SubSelector) 64 return isSelectorMatchingHTMLBasedOnRuleHash(selector->tagHistory()); 65 return true; 66 } 65 67 if (SelectorChecker::isCommonPseudoClassSelector(selector)) 66 68 return true; … … 73 75 if (!selectorList) 74 76 return false; 75 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { 76 if (subSelector->isAttributeSelector()) 77 return true; 77 for (CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) { 78 for (CSSSelector* component = selector; component; component = component->tagHistory()) { 79 if (component->isAttributeSelector()) 80 return true; 81 } 78 82 } 79 83 return false; … … 114 118 return PropertyWhitelistRegion; 115 119 #if ENABLE(VIDEO_TRACK) 116 if (selector->pseudoType() == CSSSelector::PseudoCue) 117 return PropertyWhitelistCue; 120 for (const CSSSelector* component = selector; component; component = component->tagHistory()) { 121 if (component->pseudoType() == CSSSelector::PseudoCue) 122 return PropertyWhitelistCue; 123 } 118 124 #endif 119 125 return PropertyWhitelistNone; … … 207 213 } 208 214 209 void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addRuleFlags) 210 { 211 RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); 212 213 collectFeaturesFromRuleData(m_features, ruleData); 214 215 CSSSelector* selector = ruleData.selector(); 216 217 if (selector->m_match == CSSSelector::Id) { 218 addToRuleSet(selector->value().impl(), m_idRules, ruleData); 219 return; 220 } 221 if (selector->m_match == CSSSelector::Class) { 222 addToRuleSet(selector->value().impl(), m_classRules, ruleData); 223 return; 224 } 225 if (selector->isCustomPseudoElement()) { 226 addToRuleSet(selector->value().impl(), m_shadowPseudoElementRules, ruleData); 227 return; 215 bool RuleSet::findBestRuleSetAndAdd(const CSSSelector* component, RuleData& ruleData) 216 { 217 if (component->m_match == CSSSelector::Id) { 218 addToRuleSet(component->value().impl(), m_idRules, ruleData); 219 return true; 220 } 221 if (component->m_match == CSSSelector::Class) { 222 addToRuleSet(component->value().impl(), m_classRules, ruleData); 223 return true; 224 } 225 if (component->isCustomPseudoElement()) { 226 addToRuleSet(component->value().impl(), m_shadowPseudoElementRules, ruleData); 227 return true; 228 228 } 229 229 #if ENABLE(VIDEO_TRACK) 230 if ( selector->pseudoType() == CSSSelector::PseudoCue) {230 if (component->pseudoType() == CSSSelector::PseudoCue) { 231 231 m_cuePseudoRules.append(ruleData); 232 return ;233 } 234 #endif 235 if (SelectorChecker::isCommonPseudoClassSelector( selector)) {236 switch ( selector->pseudoType()) {232 return true; 233 } 234 #endif 235 if (SelectorChecker::isCommonPseudoClassSelector(component)) { 236 switch (component->pseudoType()) { 237 237 case CSSSelector::PseudoLink: 238 238 case CSSSelector::PseudoVisited: 239 239 case CSSSelector::PseudoAnyLink: 240 240 m_linkPseudoClassRules.append(ruleData); 241 return ;241 return true; 242 242 case CSSSelector::PseudoFocus: 243 243 m_focusPseudoClassRules.append(ruleData); 244 return ;244 return true; 245 245 default: 246 246 ASSERT_NOT_REACHED(); 247 } 248 return; 249 } 250 const AtomicString& localName = selector->tag().localName(); 251 if (localName != starAtom) { 252 addToRuleSet(localName.impl(), m_tagRules, ruleData); 253 return; 254 } 255 m_universalRules.append(ruleData); 247 return true; 248 } 249 } 250 251 if (component->m_match == CSSSelector::Tag) { 252 if (component->tagQName().localName() != starAtom) { 253 // If this is part of a subselector chain, recurse ahead to find a narrower set (ID/class.) 254 if (component->relation() == CSSSelector::SubSelector 255 && (component->tagHistory()->m_match == CSSSelector::Class || component->tagHistory()->m_match == CSSSelector::Id || SelectorChecker::isCommonPseudoClassSelector(component->tagHistory())) 256 && findBestRuleSetAndAdd(component->tagHistory(), ruleData)) 257 return true; 258 259 addToRuleSet(component->tagQName().localName().impl(), m_tagRules, ruleData); 260 return true; 261 } 262 } 263 return false; 264 } 265 266 void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addRuleFlags) 267 { 268 RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); 269 collectFeaturesFromRuleData(m_features, ruleData); 270 271 if (!findBestRuleSetAndAdd(ruleData.selector(), ruleData)) { 272 // If we didn't find a specialized map to stick it in, file under universal rules. 273 m_universalRules.append(ruleData); 274 } 256 275 } 257 276 -
trunk/Source/WebCore/css/RuleSet.h
r140173 r140371 139 139 private: 140 140 void addChildRules(const Vector<RefPtr<StyleRuleBase> >&, const MediaQueryEvaluator& medium, StyleResolver*, const ContainerNode* scope, bool hasDocumentSecurityOrigin, AddRuleFlags); 141 bool findBestRuleSetAndAdd(const CSSSelector*, RuleData&); 141 142 142 143 public: -
trunk/Source/WebCore/css/SelectorChecker.cpp
r140235 r140371 3 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 6 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> 7 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> … … 80 80 81 81 PseudoId ignoreDynamicPseudo = NOPSEUDO; 82 return match(SelectorCheckingContext(sel, element, SelectorChecker::VisitedMatchDisabled), ignoreDynamicPseudo ) == SelectorMatches;82 return match(SelectorCheckingContext(sel, element, SelectorChecker::VisitedMatchDisabled), ignoreDynamicPseudo, DOMSiblingTraversalStrategy()) == SelectorMatches; 83 83 } 84 84 85 85 namespace { 86 86 87 template <bool checkValue(const Element*, AtomicStringImpl*, const QualifiedName&), bool initAttributeName>87 template <bool checkValue(const Element*, const CSSSelector*)> 88 88 inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement) 89 89 { 90 AtomicStringImpl* value = selector->value().impl();91 const QualifiedName& attribute = initAttributeName ? selector->attribute() : anyQName();92 90 for (; element; element = element->parentElement()) { 93 if (checkValue(element, value, attribute) && SelectorChecker::tagMatches(element,selector)) {91 if (checkValue(element, selector)) { 94 92 if (selector->relation() == CSSSelector::Descendant) 95 93 topChildOrSubselector = 0; … … 121 119 } 122 120 123 inline bool checkClassValue(const Element* element, AtomicStringImpl* value, const QualifiedName&)124 { 125 return element->hasClass() && static_cast<const StyledElement*>(element)->classNames().contains( value);126 } 127 128 inline bool checkIDValue(const Element* element, AtomicStringImpl* value, const QualifiedName&)129 { 130 return element->hasID() && element->idForStyleResolution().impl() == value;131 } 132 133 inline bool checkExactAttributeValue(const Element* element, AtomicStringImpl* value, const QualifiedName& attributeName)134 { 135 return SelectorChecker::checkExactAttribute(element, attributeName, value);136 } 137 138 inline bool checkTagValue(const Element* , AtomicStringImpl*, const QualifiedName&)139 { 140 return true;121 inline bool checkClassValue(const Element* element, const CSSSelector* selector) 122 { 123 return element->hasClass() && static_cast<const StyledElement*>(element)->classNames().contains(selector->value().impl()); 124 } 125 126 inline bool checkIDValue(const Element* element, const CSSSelector* selector) 127 { 128 return element->hasID() && element->idForStyleResolution().impl() == selector->value().impl(); 129 } 130 131 inline bool checkExactAttributeValue(const Element* element, const CSSSelector* selector) 132 { 133 return SelectorChecker::checkExactAttribute(element, selector->attribute(), selector->value().impl()); 134 } 135 136 inline bool checkTagValue(const Element* element, const CSSSelector* selector) 137 { 138 return SelectorChecker::tagMatches(element, selector->tagQName()); 141 139 } 142 140 … … 147 145 ASSERT(isFastCheckableSelector(selector)); 148 146 149 if (!SelectorChecker::tagMatches(element, selector))150 return false;151 147 switch (selector->m_match) { 152 case CSSSelector:: None:153 return true;148 case CSSSelector::Tag: 149 return checkTagValue(element, selector); 154 150 case CSSSelector::Class: 155 return checkClassValue(element, selector ->value().impl(), anyQName());151 return checkClassValue(element, selector); 156 152 case CSSSelector::Id: 157 return checkIDValue(element, selector ->value().impl(), anyQName());153 return checkIDValue(element, selector); 158 154 case CSSSelector::Exact: 159 155 case CSSSelector::Set: 160 return checkExactAttributeValue(element, selector ->value().impl(), selector->attribute());156 return checkExactAttributeValue(element, selector); 161 157 case CSSSelector::PseudoClass: 162 158 return commonPseudoClassSelectorMatches(element, selector, visitedMatchType); … … 185 181 switch (selector->m_match) { 186 182 case CSSSelector::Class: 187 if (!fastCheckSingleSelector<checkClassValue , false>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))183 if (!fastCheckSingleSelector<checkClassValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) 188 184 return false; 189 185 break; 190 186 case CSSSelector::Id: 191 if (!fastCheckSingleSelector<checkIDValue , false>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))192 return false; 193 break; 194 case CSSSelector:: None:195 if (!fastCheckSingleSelector<checkTagValue , false>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))187 if (!fastCheckSingleSelector<checkIDValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) 188 return false; 189 break; 190 case CSSSelector::Tag: 191 if (!fastCheckSingleSelector<checkTagValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) 196 192 return false; 197 193 break; 198 194 case CSSSelector::Set: 199 195 case CSSSelector::Exact: 200 if (!fastCheckSingleSelector<checkExactAttributeValue , true>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))196 if (!fastCheckSingleSelector<checkExactAttributeValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) 201 197 return false; 202 198 break; … … 222 218 if (selector->m_match == CSSSelector::Exact) 223 219 return selector->attribute() != styleAttr && !htmlAttributeHasCaseInsensitiveValue(selector->attribute()); 224 return selector->m_match == CSSSelector:: None|| selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class;220 return selector->m_match == CSSSelector::Tag || selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class; 225 221 } 226 222 … … 251 247 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e 252 248 // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e 253 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext& context, PseudoId& dynamicPseudo) const 249 template<typename SiblingTraversalStrategy> 250 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext& context, PseudoId& dynamicPseudo, const SiblingTraversalStrategy& siblingTraversalStrategy) const 254 251 { 255 252 // first selector has to match 256 if (!checkOne(context, DOMSiblingTraversalStrategy()))253 if (!checkOne(context, siblingTraversalStrategy)) 257 254 return SelectorFailsLocally; 258 255 … … 316 313 nextContext.elementParentStyle = 0; 317 314 for (; nextContext.element; nextContext.element = nextContext.element->parentElement()) { 318 Match match = this->match(nextContext, ignoreDynamicPseudo );315 Match match = this->match(nextContext, ignoreDynamicPseudo, siblingTraversalStrategy); 319 316 if (match == SelectorMatches || match == SelectorFailsCompletely) 320 317 return match; … … 331 328 nextContext.elementStyle = 0; 332 329 nextContext.elementParentStyle = 0; 333 return match(nextContext, ignoreDynamicPseudo );330 return match(nextContext, ignoreDynamicPseudo, siblingTraversalStrategy); 334 331 335 332 case CSSSelector::DirectAdjacent: … … 344 341 nextContext.elementStyle = 0; 345 342 nextContext.elementParentStyle = 0; 346 return match(nextContext, ignoreDynamicPseudo );343 return match(nextContext, ignoreDynamicPseudo, siblingTraversalStrategy); 347 344 348 345 case CSSSelector::IndirectAdjacent: … … 356 353 nextContext.elementParentStyle = 0; 357 354 for (; nextContext.element; nextContext.element = nextContext.element->previousElementSibling()) { 358 Match match = this->match(nextContext, ignoreDynamicPseudo );355 Match match = this->match(nextContext, ignoreDynamicPseudo, siblingTraversalStrategy); 359 356 if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely) 360 357 return match; … … 373 370 return SelectorFailsCompletely; 374 371 nextContext.isSubSelector = true; 375 return match(nextContext, dynamicPseudo );372 return match(nextContext, dynamicPseudo, siblingTraversalStrategy); 376 373 377 374 case CSSSelector::ShadowDescendant: … … 387 384 nextContext.elementStyle = 0; 388 385 nextContext.elementParentStyle = 0; 389 return match(nextContext, ignoreDynamicPseudo );386 return match(nextContext, ignoreDynamicPseudo, siblingTraversalStrategy); 390 387 } 391 388 } … … 549 546 ASSERT(selector); 550 547 551 if ( !SelectorChecker::tagMatches(element, selector))552 return false;548 if (selector->m_match == CSSSelector::Tag) 549 return SelectorChecker::tagMatches(element, selector->tagQName()); 553 550 554 551 if (selector->m_match == CSSSelector::Class) … … 770 767 PseudoId ignoreDynamicPseudo = NOPSEUDO; 771 768 for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { 772 if (match(subContext, ignoreDynamicPseudo ) == SelectorMatches)769 if (match(subContext, ignoreDynamicPseudo, siblingTraversalStrategy) == SelectorMatches) 773 770 return true; 774 771 } … … 803 800 // If we're in quirks mode, then hover should never match anchors with no 804 801 // href and *:hover should not match anything. This is important for sites like wsj.com. 805 if (m_strictParsing || context.isSubSelector || (selector-> hasTag() && !element->hasTagName(aTag)) || element->isLink()) {802 if (m_strictParsing || context.isSubSelector || (selector->m_match == CSSSelector::Tag && selector->tagQName() != anyQName() && !element->hasTagName(aTag)) || element->isLink()) { 806 803 if (m_mode == ResolvingStyle) { 807 804 if (context.elementStyle) … … 817 814 // If we're in quirks mode, then :active should never match anchors with no 818 815 // href and *:active should not match anything. 819 if (m_strictParsing || context.isSubSelector || (selector-> hasTag() && !element->hasTagName(aTag)) || element->isLink()) {816 if (m_strictParsing || context.isSubSelector || (selector->m_match == CSSSelector::Tag && selector->tagQName() != anyQName() && !element->hasTagName(aTag)) || element->isLink()) { 820 817 if (m_mode == ResolvingStyle) { 821 818 if (context.elementStyle) … … 977 974 CSSSelector* const & selector = context.selector; 978 975 for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { 979 if (match(subContext, ignoreDynamicPseudo ) == SelectorMatches)976 if (match(subContext, ignoreDynamicPseudo, siblingTraversalStrategy) == SelectorMatches) 980 977 return true; 981 978 } … … 1136 1133 1137 1134 template 1138 bool SelectorChecker::checkOne(const SelectorChecker::SelectorCheckingContext&, const ShadowDOMSiblingTraversalStrategy&) const; 1139 1140 } 1135 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, PseudoId&, const DOMSiblingTraversalStrategy&) const; 1136 1137 template 1138 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, PseudoId&, const ShadowDOMSiblingTraversalStrategy&) const; 1139 1140 } -
trunk/Source/WebCore/css/SelectorChecker.h
r140235 r140371 3 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 6 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> 7 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> … … 79 79 80 80 bool matches(CSSSelector*, Element*, bool isFastCheckableSelector = false) const; 81 Match match(const SelectorCheckingContext&, PseudoId&) const; 81 template<typename SiblingTraversalStrategy> 82 Match match(const SelectorCheckingContext&, PseudoId&, const SiblingTraversalStrategy&) const; 82 83 template<typename SiblingTraversalStrategy> 83 84 bool checkOne(const SelectorCheckingContext&, const SiblingTraversalStrategy&) const; … … 91 92 void setMode(Mode mode) { m_mode = mode; } 92 93 93 static bool tagMatches(const Element*, const CSSSelector*);94 static bool tagMatches(const Element*, const QualifiedName&); 94 95 static bool isCommonPseudoClassSelector(const CSSSelector*); 95 96 bool matchesFocusPseudoClass(const Element*) const; … … 130 131 } 131 132 132 inline bool SelectorChecker::tagMatches(const Element* element, const CSSSelector* selector)133 inline bool SelectorChecker::tagMatches(const Element* element, const QualifiedName& tagQName) 133 134 { 134 if ( !selector->hasTag())135 if (tagQName == anyQName()) 135 136 return true; 136 const AtomicString& localName = selector->tag().localName();137 const AtomicString& localName = tagQName.localName(); 137 138 if (localName != starAtom && localName != element->localName()) 138 139 return false; 139 const AtomicString& namespaceURI = selector->tag().namespaceURI();140 const AtomicString& namespaceURI = tagQName.namespaceURI(); 140 141 return namespaceURI == starAtom || namespaceURI == element->namespaceURI(); 141 142 } -
trunk/Source/WebCore/css/SelectorFilter.cpp
r138432 r140371 110 110 } 111 111 112 static inline void collectDescendantSelectorIdentifierHashes(const CSSSelector* selector, unsigned*& hash , const unsigned* end)112 static inline void collectDescendantSelectorIdentifierHashes(const CSSSelector* selector, unsigned*& hash) 113 113 { 114 114 switch (selector->m_match) { … … 121 121 (*hash++) = selector->value().impl()->existingHash() * ClassAttributeSalt; 122 122 break; 123 case CSSSelector::Tag: 124 if (selector->tagQName().localName() != starAtom) 125 (*hash++) = selector->tagQName().localName().impl()->existingHash() * TagNameSalt; 126 break; 123 127 default: 124 128 break; 125 129 } 126 if (hash == end)127 return;128 const AtomicString& localName = selector->tag().localName();129 if (localName != starAtom)130 (*hash++) = localName.impl()->existingHash() * TagNameSalt;131 130 } 132 131 … … 144 143 case CSSSelector::SubSelector: 145 144 if (!skipOverSubselectors) 146 collectDescendantSelectorIdentifierHashes(selector, hash , end);145 collectDescendantSelectorIdentifierHashes(selector, hash); 147 146 break; 148 147 case CSSSelector::DirectAdjacent: … … 154 153 case CSSSelector::Child: 155 154 skipOverSubselectors = false; 156 collectDescendantSelectorIdentifierHashes(selector, hash , end);155 collectDescendantSelectorIdentifierHashes(selector, hash); 157 156 break; 158 157 } -
trunk/Source/WebCore/css/StyleResolver.cpp
r140331 r140371 3 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 6 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> 7 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> … … 2273 2273 if (!ruleData.hasMultipartSelector()) 2274 2274 return true; 2275 } else if (!SelectorChecker::tagMatches(m_element, ruleData.selector())) 2275 } 2276 if (ruleData.selector()->m_match == CSSSelector::Tag && !SelectorChecker::tagMatches(m_element, ruleData.selector()->tagQName())) 2276 2277 return false; 2277 2278 if (!SelectorChecker::fastCheckRightmostAttributeSelector(m_element, ruleData.selector())) … … 2286 2287 context.scope = scope; 2287 2288 context.pseudoStyle = m_pseudoStyle; 2288 SelectorChecker::Match match = m_selectorChecker.match(context, m_dynamicPseudo );2289 SelectorChecker::Match match = m_selectorChecker.match(context, m_dynamicPseudo, DOMSiblingTraversalStrategy()); 2289 2290 if (match != SelectorChecker::SelectorMatches) 2290 2291 return false; … … 2602 2603 } 2603 2604 2604 void StyleResolver::matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName) 2605 { 2606 unsigned size = rules.size(); 2607 for (unsigned i = 0; i < size; ++i) { 2608 StyleRulePage* rule = rules[i]; 2609 const AtomicString& selectorLocalName = rule->selector()->tag().localName(); 2610 if (selectorLocalName != starAtom && selectorLocalName != pageName) 2611 continue; 2612 CSSSelector::PseudoType pseudoType = rule->selector()->pseudoType(); 2605 static bool checkPageSelectorComponents(const CSSSelector* selector, bool isLeftPage, bool isFirstPage, const String& pageName) 2606 { 2607 for (const CSSSelector* component = selector; component; component = component->tagHistory()) { 2608 if (component->m_match == CSSSelector::Tag) { 2609 const AtomicString& localName = component->tagQName().localName(); 2610 if (localName != starAtom && localName != pageName) 2611 return false; 2612 } 2613 2614 CSSSelector::PseudoType pseudoType = component->pseudoType(); 2613 2615 if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage) 2614 2616 || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage) 2615 2617 || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage)) 2618 { 2619 return false; 2620 } 2621 } 2622 return true; 2623 } 2624 2625 void StyleResolver::matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName) 2626 { 2627 for (unsigned i = 0; i < rules.size(); ++i) { 2628 StyleRulePage* rule = rules[i]; 2629 2630 if (!checkPageSelectorComponents(rule->selector(), isLeftPage, isFirstPage, pageName)) 2616 2631 continue; 2617 2632 -
trunk/Source/WebCore/dom/QualifiedName.cpp
r131993 r140371 103 103 #endif 104 104 ASSERT(!isHashTableDeletedValue()); 105 m_impl->deref(); 106 } 105 107 106 if (m_impl->hasOneRef())107 gNameCache->remove(m_impl); 108 m_impl->deref();108 QualifiedName::QualifiedNameImpl::~QualifiedNameImpl() 109 { 110 gNameCache->remove(this); 109 111 } 110 112 -
trunk/Source/WebCore/dom/QualifiedName.h
r131993 r140371 44 44 return adoptRef(new QualifiedNameImpl(prefix, localName, namespaceURI)); 45 45 } 46 47 ~QualifiedNameImpl(); 46 48 47 49 unsigned computeHash() const; -
trunk/Source/WebCore/html/shadow/ContentDistributor.cpp
r140299 r140371 407 407 if (ScopeContentDistribution::hasContentElement(root)) { 408 408 for (Element* element = ElementTraversal::firstWithin(root); element; element = ElementTraversal::next(element)) { 409 if (isHTMLContentElement(element)) { 410 const CSSSelectorList& list = toHTMLContentElement(element)->selectorList(); 411 for (CSSSelector* selector = list.first(); selector; selector = list.next(selector)) 412 m_selectFeatures.collectFeaturesFromSelector(selector); 409 if (!isHTMLContentElement(element)) 410 continue; 411 const CSSSelectorList& list = toHTMLContentElement(element)->selectorList(); 412 for (CSSSelector* selector = list.first(); selector; selector = CSSSelectorList::next(selector)) { 413 for (CSSSelector* component = selector; component; component = component->tagHistory()) 414 m_selectFeatures.collectFeaturesFromSelector(component); 413 415 } 414 416 } -
trunk/Source/WebCore/html/shadow/ContentSelectorQuery.cpp
r139406 r140371 46 46 SelectorChecker::SelectorCheckingContext context(selector, toElement(siblings[nth].get()), SelectorChecker::VisitedMatchEnabled); 47 47 ShadowDOMSiblingTraversalStrategy strategy(siblings, nth); 48 return m_selectorChecker.checkOne(context, strategy); 48 PseudoId ignoreDynamicPseudo = NOPSEUDO; 49 return m_selectorChecker.match(context, ignoreDynamicPseudo, strategy) == SelectorChecker::SelectorMatches; 49 50 } 50 51 -
trunk/Source/WebCore/html/shadow/HTMLContentElement.cpp
r139410 r140371 121 121 { 122 122 switch (selector->m_match) { 123 case CSSSelector:: None:123 case CSSSelector::Tag: 124 124 case CSSSelector::Id: 125 125 case CSSSelector::Class:
Note: See TracChangeset
for help on using the changeset viewer.