Created
October 26, 2014 17:25
-
-
Save Constellation/8a1995829e2c7ed65abb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/Source/WebCore/css/SelectorChecker.cpp b/Source/WebCore/css/SelectorChecker.cpp | |
| index c4d461c..4a0e550 100644 | |
| --- a/Source/WebCore/css/SelectorChecker.cpp | |
| +++ b/Source/WebCore/css/SelectorChecker.cpp | |
| @@ -171,14 +171,14 @@ static inline int countElementsOfTypeAfter(const Element* element, const Qualifi | |
| bool SelectorChecker::match(const CSSSelector* selector, Element* element, const CheckingContext& providedContext) const | |
| { | |
| CheckingContextWithStatus context(providedContext, selector, element); | |
| - PseudoId pseudoId = NOPSEUDO; | |
| - if (matchRecursively(context, pseudoId) != SelectorMatches) | |
| + PseudoIdSet pseudoIdSet = NOPSEUDO; | |
| + if (matchRecursively(context, pseudoIdSet) != SelectorMatches) | |
| return false; | |
| - if (context.pseudoId != NOPSEUDO && context.pseudoId != pseudoId) | |
| + if (context.pseudoId != NOPSEUDO && !(pseudoIdSet & (1 << context.pseudoId))) | |
| return false; | |
| - if (context.pseudoId == NOPSEUDO && pseudoId != NOPSEUDO) { | |
| - if (context.resolvingMode == Mode::ResolvingStyle && pseudoId < FIRST_INTERNAL_PSEUDOID) | |
| - context.elementStyle->setHasPseudoStyle(pseudoId); | |
| + if (context.pseudoId == NOPSEUDO && pseudoIdSet != NOPSEUDO) { | |
| + if (context.resolvingMode == Mode::ResolvingStyle && pseudoIdSet & PUBLIC_PSEUDOID_MASK) | |
| + context.elementStyle->setHasPseudoStyles(pseudoIdSet); | |
| // When ignoring virtual pseudo elements, the context's pseudo should also be NOPSEUDO but that does | |
| // not cause a failure. | |
| @@ -187,20 +187,21 @@ bool SelectorChecker::match(const CSSSelector* selector, Element* element, const | |
| return true; | |
| } | |
| -inline static bool hasScrollbarPseudoElement(PseudoId& dynamicPseudo) | |
| +inline static bool hasScrollbarPseudoElement(const PseudoIdSet& dynamicPseudoIdSet) | |
| { | |
| - if (dynamicPseudo == SCROLLBAR | |
| - || dynamicPseudo == SCROLLBAR_THUMB | |
| - || dynamicPseudo == SCROLLBAR_BUTTON | |
| - || dynamicPseudo == SCROLLBAR_TRACK | |
| - || dynamicPseudo == SCROLLBAR_TRACK_PIECE | |
| - || dynamicPseudo == SCROLLBAR_CORNER) { | |
| + if (dynamicPseudoIdSet & | |
| + ((1 << SCROLLBAR) | | |
| + (1 << SCROLLBAR_THUMB) | | |
| + (1 << SCROLLBAR_BUTTON) | | |
| + (1 << SCROLLBAR_TRACK) | | |
| + (1 << SCROLLBAR_TRACK_PIECE) | | |
| + (1 << SCROLLBAR_CORNER))) { | |
| return true; | |
| } | |
| // RESIZER does not always have a scrollbar but it is a scrollbar-like pseudo element | |
| // because it can have more than one pseudo element. | |
| - return dynamicPseudo == RESIZER; | |
| + return dynamicPseudoIdSet & (1 << RESIZER); | |
| } | |
| static SelectorChecker::CheckingContextWithStatus checkingContextForParent(const SelectorChecker::CheckingContextWithStatus& context) | |
| @@ -219,7 +220,7 @@ static SelectorChecker::CheckingContextWithStatus checkingContextForParent(const | |
| // * SelectorFailsLocally - the selector fails for the element e | |
| // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e | |
| // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e | |
| -SelectorChecker::Match SelectorChecker::matchRecursively(const CheckingContextWithStatus& context, PseudoId& dynamicPseudo) const | |
| +SelectorChecker::Match SelectorChecker::matchRecursively(const CheckingContextWithStatus& context, PseudoIdSet& dynamicPseudoIdSet) const | |
| { | |
| // The first selector has to match. | |
| if (!checkOne(context)) | |
| @@ -246,7 +247,7 @@ static SelectorChecker::CheckingContextWithStatus checkingContextForParent(const | |
| PseudoId pseudoId = CSSSelector::pseudoId(context.selector->pseudoElementType()); | |
| if (pseudoId != NOPSEUDO) | |
| - dynamicPseudo = pseudoId; | |
| + dynamicPseudoIdSet |= (1 << pseudoId); | |
| } | |
| } | |
| @@ -261,10 +262,10 @@ static SelectorChecker::CheckingContextWithStatus checkingContextForParent(const | |
| CheckingContextWithStatus nextContext(context); | |
| nextContext.selector = historySelector; | |
| - PseudoId ignoreDynamicPseudo = NOPSEUDO; | |
| + PseudoIdSet ignoreDynamicPseudo = NOPSEUDO; | |
| if (relation != CSSSelector::SubSelector) { | |
| // Bail-out if this selector is irrelevant for the pseudoId | |
| - if (context.pseudoId != NOPSEUDO && context.pseudoId != dynamicPseudo) | |
| + if (context.pseudoId != NOPSEUDO && !((1 << context.pseudoId) & dynamicPseudoIdSet)) | |
| return SelectorFailsCompletely; | |
| // Disable :visited matching when we try to match anything else than an ancestors. | |
| @@ -334,13 +335,13 @@ static SelectorChecker::CheckingContextWithStatus checkingContextForParent(const | |
| // a selector is invalid if something follows a pseudo-element | |
| // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else) | |
| // to follow the pseudo elements. | |
| - nextContext.hasScrollbarPseudo = hasScrollbarPseudoElement(dynamicPseudo); | |
| - nextContext.hasSelectionPseudo = dynamicPseudo == SELECTION; | |
| - if ((context.elementStyle || context.resolvingMode == Mode::CollectingRules) && dynamicPseudo != NOPSEUDO | |
| + nextContext.hasScrollbarPseudo = hasScrollbarPseudoElement(dynamicPseudoIdSet); | |
| + nextContext.hasSelectionPseudo = dynamicPseudoIdSet & (1 << SELECTION); | |
| + if ((context.elementStyle || context.resolvingMode == Mode::CollectingRules) && dynamicPseudoIdSet != NOPSEUDO | |
| && !nextContext.hasSelectionPseudo | |
| && !(nextContext.hasScrollbarPseudo && nextContext.selector->match() == CSSSelector::PseudoClass)) | |
| return SelectorFailsCompletely; | |
| - return matchRecursively(nextContext, dynamicPseudo); | |
| + return matchRecursively(nextContext, dynamicPseudoIdSet); | |
| case CSSSelector::ShadowDescendant: | |
| { | |
| @@ -534,7 +535,7 @@ bool SelectorChecker::checkOne(const CheckingContextWithStatus& context) const | |
| subcontext.firstSelectorOfTheFragment = selectorList->first(); | |
| #if ENABLE(CSS_SELECTORS_LEVEL4) | |
| - PseudoId ignoreDynamicPseudo = NOPSEUDO; | |
| + PseudoIdSet ignoreDynamicPseudo = NOPSEUDO; | |
| if (matchRecursively(subcontext, ignoreDynamicPseudo) == SelectorMatches) { | |
| ASSERT(ignoreDynamicPseudo == NOPSEUDO); | |
| return false; | |
| @@ -770,7 +771,7 @@ bool SelectorChecker::checkOne(const CheckingContextWithStatus& context) const | |
| { | |
| CheckingContextWithStatus subContext(context); | |
| subContext.inFunctionalPseudoClass = true; | |
| - PseudoId ignoreDynamicPseudo = NOPSEUDO; | |
| + PseudoIdSet ignoreDynamicPseudo = NOPSEUDO; | |
| for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { | |
| subContext.firstSelectorOfTheFragment = subContext.selector; | |
| if (matchRecursively(subContext, ignoreDynamicPseudo) == SelectorMatches) | |
| @@ -915,7 +916,7 @@ bool SelectorChecker::checkOne(const CheckingContextWithStatus& context) const | |
| if (selector->match() == CSSSelector::PseudoElement && selector->pseudoElementType() == CSSSelector::PseudoElementCue) { | |
| CheckingContextWithStatus subContext(context); | |
| - PseudoId ignoreDynamicPseudo = NOPSEUDO; | |
| + PseudoIdSet ignoreDynamicPseudo = NOPSEUDO; | |
| const CSSSelector* const & selector = context.selector; | |
| for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { | |
| subContext.firstSelectorOfTheFragment = subContext.selector; | |
| @@ -938,7 +939,7 @@ bool SelectorChecker::matchSelectorList(const CheckingContextWithStatus& baseCon | |
| subcontext.selector = subselector; | |
| subcontext.inFunctionalPseudoClass = true; | |
| subcontext.firstSelectorOfTheFragment = subselector; | |
| - PseudoId ignoreDynamicPseudo = NOPSEUDO; | |
| + PseudoIdSet ignoreDynamicPseudo = NOPSEUDO; | |
| if (matchRecursively(subcontext, ignoreDynamicPseudo) == SelectorMatches) { | |
| ASSERT(ignoreDynamicPseudo == NOPSEUDO); | |
| return true; | |
| diff --git a/Source/WebCore/css/SelectorChecker.h b/Source/WebCore/css/SelectorChecker.h | |
| index 655b195..54ee943 100644 | |
| --- a/Source/WebCore/css/SelectorChecker.h | |
| +++ b/Source/WebCore/css/SelectorChecker.h | |
| @@ -83,7 +83,7 @@ class SelectorChecker { | |
| static unsigned determineLinkMatchType(const CSSSelector*); | |
| private: | |
| - Match matchRecursively(const CheckingContextWithStatus&, PseudoId&) const; | |
| + Match matchRecursively(const CheckingContextWithStatus&, PseudoIdSet&) const; | |
| bool checkOne(const CheckingContextWithStatus&) const; | |
| bool matchSelectorList(const CheckingContextWithStatus&, Element&, const CSSSelectorList&) const; | |
| diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h | |
| index 9863950..ff3f18a 100644 | |
| --- a/Source/WebCore/rendering/style/RenderStyle.h | |
| +++ b/Source/WebCore/rendering/style/RenderStyle.h | |
| @@ -234,6 +234,13 @@ class RenderStyle: public RefCounted<RenderStyle> { | |
| ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID); | |
| m_flags |= oneBitMask << (pseudoBitsOffset - 1 + pseudo); | |
| } | |
| + void setHasPseudoStyles(PseudoIdSet pseudo) | |
| + { | |
| + ASSERT(pseudo != NOPSEUDO); | |
| + ASSERT((pseudo & PUBLIC_PSEUDOID_MASK) == pseudo); | |
| + static_assert(pseudoBitsOffset >= 1, "(pseudoBitsOffset - 1) should be valid."); | |
| + m_flags |= (static_cast<uint64_t>(pseudo) << (pseudoBitsOffset - 1)); | |
| + } | |
| ETableLayout tableLayout() const { return static_cast<ETableLayout>(getValue(tableLayoutBitMask, tableLayoutOffset)); } | |
| void setTableLayout(ETableLayout tableLayout) { updateValue(tableLayout, tableLayoutBitMask, tableLayoutOffset); } | |
| @@ -561,6 +568,7 @@ class RenderStyle: public RefCounted<RenderStyle> { | |
| bool hasAnyPublicPseudoStyles() const; | |
| bool hasPseudoStyle(PseudoId pseudo) const; | |
| void setHasPseudoStyle(PseudoId pseudo); | |
| + void setHasPseudoStyles(PseudoIdSet pseudo); | |
| bool hasUniquePseudoStyle() const; | |
| // attribute getter methods | |
| @@ -2155,6 +2163,11 @@ inline void RenderStyle::setHasPseudoStyle(PseudoId pseudo) | |
| noninherited_flags.setHasPseudoStyle(pseudo); | |
| } | |
| +inline void RenderStyle::setHasPseudoStyles(PseudoIdSet pseudo) | |
| +{ | |
| + noninherited_flags.setHasPseudoStyles(pseudo); | |
| +} | |
| + | |
| } // namespace WebCore | |
| #endif // RenderStyle_h | |
| diff --git a/Source/WebCore/rendering/style/RenderStyleConstants.h b/Source/WebCore/rendering/style/RenderStyleConstants.h | |
| index 2a4aef5..6884901 100644 | |
| --- a/Source/WebCore/rendering/style/RenderStyleConstants.h | |
| +++ b/Source/WebCore/rendering/style/RenderStyleConstants.h | |
| @@ -80,6 +80,8 @@ enum PseudoId : unsigned char { | |
| PUBLIC_PSEUDOID_MASK = ((1 << FIRST_INTERNAL_PSEUDOID) - 1) & ~((1 << FIRST_PUBLIC_PSEUDOID) - 1) | |
| }; | |
| +typedef unsigned PseudoIdSet; | |
| + | |
| enum ColumnFill { ColumnFillBalance, ColumnFillAuto }; | |
| enum ColumnSpan { ColumnSpanNone = 0, ColumnSpanAll }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment