Changeset 107911 in webkit


Ignore:
Timestamp:
Feb 16, 2012 1:31:17 AM (12 years ago)
Author:
rolandsteiner@chromium.org
Message:

<style scoped>: Implement scoped selector matching in the slow path
https://bugs.webkit.org/show_bug.cgi?id=77528

Source/WebCore:

Added scope information to SelectorCheckingContext, SelectorChecker methods and CSSStyleSelector methods.
Added matchOptions struct to CSSStyleSelector similar to SelectorCheckingContext in SelectorChecker.
Adapted the calling sites.

Reviewed by Antti Koivisto.

No new tests. (extended existing tests)

  • css/CSSStyleSelector.cpp:

(RuleData):
(RuleSet):
(WebCore::CSSStyleSelector::determineScopingElement):
(WebCore::CSSStyleSelector::collectMatchingRules):
(WebCore::CSSStyleSelector::collectMatchingRulesForRegion):
(WebCore::CSSStyleSelector::matchScopedAuthorRules):
(WebCore::CSSStyleSelector::matchAuthorRules):
(WebCore::CSSStyleSelector::collectMatchingRulesForList):

  • css/CSSStyleSelector.h:

(CSSStyleSelector):
(MatchOptions):
(WebCore::CSSStyleSelector::MatchOptions::MatchOptions):

  • css/SelectorChecker.cpp:

(WebCore::SelectorChecker::checkSelector):

  • css/SelectorChecker.h:

(WebCore::SelectorChecker::SelectorCheckingContext::SelectorCheckingContext):
(SelectorCheckingContext):
(SelectorChecker):

LayoutTests:

Extended existing <style scoped> tests to also verify that selector matching doesn't exceed the scoping element.

Reviewed by Antti Koivisto.

  • fast/css/style-scoped/style-scoped-basic-expected.txt:
  • fast/css/style-scoped/style-scoped-basic.html:
  • fast/css/style-scoped/style-scoped-remove-scoped-expected.txt:
  • fast/css/style-scoped/style-scoped-remove-scoped.html:
  • fast/css/style-scoped/style-scoped-set-scoped-expected.txt:
  • fast/css/style-scoped/style-scoped-set-scoped.html:
Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r107910 r107911  
     12012-02-16  Roland Steiner  <rolandsteiner@chromium.org>
     2
     3        <style scoped>: Implement scoped selector matching in the slow path
     4        https://bugs.webkit.org/show_bug.cgi?id=77528
     5
     6        Extended existing <style scoped> tests to also verify that selector matching doesn't exceed the scoping element.
     7
     8        Reviewed by Antti Koivisto.
     9
     10        * fast/css/style-scoped/style-scoped-basic-expected.txt:
     11        * fast/css/style-scoped/style-scoped-basic.html:
     12        * fast/css/style-scoped/style-scoped-remove-scoped-expected.txt:
     13        * fast/css/style-scoped/style-scoped-remove-scoped.html:
     14        * fast/css/style-scoped/style-scoped-set-scoped-expected.txt:
     15        * fast/css/style-scoped/style-scoped-set-scoped.html:
     16
    1172012-02-16  Noel Gordon  <noel.gordon@gmail.com>
    218
  • trunk/LayoutTests/fast/css/style-scoped/style-scoped-basic-expected.txt

    r106331 r107911  
    99Text
    1010
     11Text
    1112Text
    1213Text
     
    2930P2: rgb(0, 128, 0)
    3031R2: rgb(0, 0, 255)
     32E2: rgb(255, 0, 0)
    3133
    3234S3: rgb(0, 0, 0)
  • trunk/LayoutTests/fast/css/style-scoped/style-scoped-basic.html

    r106331 r107911  
    2929            test('P2');
    3030            test('R2');
     31            test('E2');
    3132            log('');
    3233            test('S3');
     
    5253        <span id="S1">Text</span>
    5354        <p id="P1">Text</p>
    54         <pre id = "R1" class="bar">Text</pre>
     55        <pre id="R1" class="bar">Text</pre>
    5556        <pre id="E1" class="baz">Text</pre>
    5657    </div>
    57     <div>
     58    <div id="foo">
     59        <div id="sib"></div>
    5860        <div>
    5961            <style type="text/css" scoped>
     
    6163                p { color: green; }
    6264                div .bar { color: blue; }
     65                #foo .baz { color: rgb(10, 10, 10); } /* should NOT apply! */
     66                sib + * { color: rgb(20, 20, 20); } /* should NOT apply! */
     67                sib ~ * { color: rgb(30, 30, 30); } /* should NOT apply! */
     68                div div { color: rgb(40, 40, 40); } /* should NOT apply! */
    6369            </style>
    6470            <span id="S2">Text</span>
    6571            <p id="P2">Text</p>
    6672            <pre id="R2" class="bar">Text</pre>
     73            <pre id="E2" class="baz">Text</pre>
    6774        </div>
    6875        <span id="S3">Text</span>
    6976        <p id="P3">Text</p>
    70         <pre id = "R3" class="bar">Text</pre>
     77        <pre id="R3" class="bar">Text</pre>
    7178        <pre id="E3" class="baz">Text</pre>
    7279    </div>
     
    7481        <span id="S4">Text</span>
    7582        <p id="P4">Text</p>
    76         <pre id = "R4" class="bar">Text</pre>
     83        <pre id="R4" class="bar">Text</pre>
    7784        <pre id="E4" class="baz">Text</pre>
    7885    </div>
  • trunk/LayoutTests/fast/css/style-scoped/style-scoped-remove-scoped-expected.txt

    r106331 r107911  
    55
    66Text
     7
     8   
     9Text
    710Text
    811
    912Text
     13
     14   
     15Text
    1016Text
    1117
     18Text
     19
     20   
    1221--- ORIGINAL ---
    1322S1: rgb(0, 0, 0)
    1423P1: rgb(0, 0, 0)
     24R1: rgb(0, 0, 0)
    1525S2: rgb(255, 0, 0)
    1626P2: rgb(0, 128, 0)
     27R2: rgb(255, 0, 0)
    1728S3: rgb(0, 0, 0)
    1829P3: rgb(0, 0, 0)
     30R3: rgb(0, 0, 0)
    1931--- AFTER UN-SETTING @SCOPED ---
    2032S1: rgb(255, 0, 0)
    2133P1: rgb(0, 128, 0)
     34R1: rgb(0, 0, 255)
    2235S2: rgb(255, 0, 0)
    2336P2: rgb(0, 128, 0)
     37R2: rgb(0, 0, 255)
    2438S3: rgb(255, 0, 0)
    2539P3: rgb(0, 128, 0)
     40R3: rgb(0, 0, 255)
    2641--- FINISHED ---
    2742
  • trunk/LayoutTests/fast/css/style-scoped/style-scoped-remove-scoped.html

    r106331 r107911  
    1818            test('S1');
    1919            test('P1');
     20            test('R1');
    2021            test('S2');
    2122            test('P2');
     23            test('R2');
    2224            test('S3');
    2325            test('P3');
     26            test('R3');
    2427        }
    2528
     
    5356        <span id="S1">Text</span>
    5457        <p id="P1">Text</p>
     58        <pre id="R1">Text</p>
    5559    </div>
    5660    <div>
     
    5862            div { color: red; }
    5963            p { color: green; }
     64            p ~ div pre { color: blue; } /* should NOT apply while scoped! */
    6065        </style>
    6166        <span id="S2">Text</span>
    6267        <p id="P2">Text</p>
     68        <pre id="R2">Text</p>
    6369    </div>
    6470    <div>
    6571        <span id="S3">Text</span>
    6672        <p id="P3">Text</p>
     73        <pre id="R3">Text</p>
    6774    </div>
    6875    <pre id="console"></pre>
  • trunk/LayoutTests/fast/css/style-scoped/style-scoped-set-scoped-expected.txt

    r106331 r107911  
    55
    66Text
     7
     8   
     9Text
    710Text
    811
    912Text
     13
     14   
     15Text
    1016Text
    1117
     18Text
     19
     20   
    1221--- ORIGINAL ---
    1322S1: rgb(255, 0, 0)
    1423P1: rgb(0, 128, 0)
     24R1: rgb(0, 0, 255)
    1525S2: rgb(255, 0, 0)
    1626P2: rgb(0, 128, 0)
     27R2: rgb(0, 0, 255)
    1728S3: rgb(255, 0, 0)
    1829P3: rgb(0, 128, 0)
     30R3: rgb(0, 0, 255)
    1931--- AFTER SETTING @SCOPED ---
    2032S1: rgb(0, 0, 0)
    2133P1: rgb(0, 0, 0)
     34R1: rgb(0, 0, 0)
    2235S2: rgb(255, 0, 0)
    2336P2: rgb(0, 128, 0)
     37R2: rgb(255, 0, 0)
    2438S3: rgb(0, 0, 0)
    2539P3: rgb(0, 0, 0)
     40R3: rgb(0, 0, 0)
    2641--- FINISHED ---
    2742
  • trunk/LayoutTests/fast/css/style-scoped/style-scoped-set-scoped.html

    r106331 r107911  
    1818            test('S1');
    1919            test('P1');
     20            test('R1');
    2021            test('S2');
    2122            test('P2');
     23            test('R2');
    2224            test('S3');
    2325            test('P3');
     26            test('R3');
    2427        }
    2528
     
    5356        <span id="S1">Text</span>
    5457        <p id="P1">Text</p>
     58        <pre id="R1">Text</p>
    5559    </div>
    5660    <div>
     
    5862            div { color: red; }
    5963            p { color: green; }
     64            p ~ div pre { color: blue; } /* should NOT apply while scoped! */
    6065        </style>
    6166        <span id="S2">Text</span>
    6267        <p id="P2">Text</p>
     68        <pre id="R2">Text</p>
    6369    </div>
    6470    <div>
    6571        <span id="S3">Text</span>
    6672        <p id="P3">Text</p>
     73        <pre id="R3">Text</p>
    6774    </div>
    6875    <pre id="console"></pre>
  • trunk/Source/WebCore/ChangeLog

    r107900 r107911  
     12012-02-16  Roland Steiner  <rolandsteiner@chromium.org>
     2
     3        <style scoped>: Implement scoped selector matching in the slow path
     4        https://bugs.webkit.org/show_bug.cgi?id=77528
     5
     6        Added scope information to SelectorCheckingContext, SelectorChecker methods and CSSStyleSelector methods.
     7        Added matchOptions struct to CSSStyleSelector similar to SelectorCheckingContext in SelectorChecker.
     8        Adapted the calling sites.
     9
     10        Reviewed by Antti Koivisto.
     11
     12        No new tests. (extended existing tests)
     13
     14        * css/CSSStyleSelector.cpp:
     15        (RuleData):
     16        (RuleSet):
     17        (WebCore::CSSStyleSelector::determineScopingElement):
     18        (WebCore::CSSStyleSelector::collectMatchingRules):
     19        (WebCore::CSSStyleSelector::collectMatchingRulesForRegion):
     20        (WebCore::CSSStyleSelector::matchScopedAuthorRules):
     21        (WebCore::CSSStyleSelector::matchAuthorRules):
     22        (WebCore::CSSStyleSelector::collectMatchingRulesForList):
     23        * css/CSSStyleSelector.h:
     24        (CSSStyleSelector):
     25        (MatchOptions):
     26        (WebCore::CSSStyleSelector::MatchOptions::MatchOptions):
     27        * css/SelectorChecker.cpp:
     28        (WebCore::SelectorChecker::checkSelector):
     29        * css/SelectorChecker.h:
     30        (WebCore::SelectorChecker::SelectorCheckingContext::SelectorCheckingContext):
     31        (SelectorCheckingContext):
     32        (SelectorChecker):
     33
    1342012-02-15  Patrick Gansterer  <paroga@webkit.org>
    235
  • trunk/Source/WebCore/css/CSSStyleSelector.cpp

    r107881 r107911  
    174174class RuleData {
    175175public:
    176     RuleData(CSSStyleRule*, CSSSelector*, unsigned position);
     176    RuleData(CSSStyleRule*, CSSSelector*, unsigned position, bool canUseFastCheckSelector = true);
    177177
    178178    unsigned position() const { return m_position; }
     
    226226    void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0, const Element* = 0);
    227227
    228     void addStyleRule(CSSStyleRule*);
    229     void addRule(CSSStyleRule*, CSSSelector*);
     228    void addStyleRule(CSSStyleRule*, bool canUseFastCheckSelector = true);
     229    void addRule(CSSStyleRule*, CSSSelector*, bool canUseFastCheckSelector = true);
    230230    void addPageRule(CSSPageRule*);
    231231    void addToRuleSet(AtomicStringImpl* key, AtomRuleMap&, const RuleData&);
     
    444444
    445445#if ENABLE(STYLE_SCOPED)
    446 Element* CSSStyleSelector::determineScopingElement(const CSSStyleSheet* sheet)
     446const Element* CSSStyleSelector::determineScopingElement(const CSSStyleSheet* sheet)
    447447{
    448448    ASSERT(sheet);
     
    757757}
    758758
    759 void CSSStyleSelector::collectMatchingRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
     759void CSSStyleSelector::collectMatchingRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
    760760{
    761761    ASSERT(rules);
     
    765765    // then sort the buffer.
    766766    if (m_element->hasID())
    767         collectMatchingRulesForList(rules->idRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
     767        collectMatchingRulesForList(rules->idRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, options);
    768768    if (m_element->hasClass()) {
    769769        ASSERT(m_styledElement);
     
    771771        size_t size = classNames.size();
    772772        for (size_t i = 0; i < size; ++i)
    773             collectMatchingRulesForList(rules->classRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
     773            collectMatchingRulesForList(rules->classRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, options);
    774774    }
    775775    const AtomicString& pseudoId = m_element->shadowPseudoId();
    776776    if (!pseudoId.isEmpty()) {
    777777        ASSERT(m_styledElement);
    778         collectMatchingRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
     778        collectMatchingRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, options);
    779779    }
    780780    if (m_element->isLink())
    781         collectMatchingRulesForList(rules->linkPseudoClassRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
     781        collectMatchingRulesForList(rules->linkPseudoClassRules(), firstRuleIndex, lastRuleIndex, options);
    782782    if (m_checker.matchesFocusPseudoClass(m_element))
    783         collectMatchingRulesForList(rules->focusPseudoClassRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
    784     collectMatchingRulesForList(rules->tagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
    785     collectMatchingRulesForList(rules->universalRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
    786 }
    787 
    788 void CSSStyleSelector::collectMatchingRulesForRegion(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
     783        collectMatchingRulesForList(rules->focusPseudoClassRules(), firstRuleIndex, lastRuleIndex, options);
     784    collectMatchingRulesForList(rules->tagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, options);
     785    collectMatchingRulesForList(rules->universalRules(), firstRuleIndex, lastRuleIndex, options);
     786}
     787
     788void CSSStyleSelector::collectMatchingRulesForRegion(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
    789789{
    790790    if (!m_regionForStyling)
     
    797797            RuleSet* regionRules = rules->m_regionSelectorsAndRuleSets.at(i).ruleSet.get();
    798798            ASSERT(regionRules);
    799             collectMatchingRules(regionRules, firstRuleIndex, lastRuleIndex, includeEmptyRules);
     799            collectMatchingRules(regionRules, firstRuleIndex, lastRuleIndex, options);
    800800        }
    801801    }
     
    836836        return;
    837837
     838    MatchOptions options(includeEmptyRules);
     839
    838840    // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent).
    839841    const Element* parent = m_element->parentOrHostElement();
     
    841843        setupScopingElementStack(parent);
    842844    for (size_t i = m_scopingElementStack.size(); i; --i) {
    843         collectMatchingRules(m_scopingElementStack[i - 1].m_ruleSet, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, includeEmptyRules);
    844         collectMatchingRulesForRegion(m_scopingElementStack[i - 1].m_ruleSet, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, includeEmptyRules);
     845        const ScopeStackFrame& frame = m_scopingElementStack[i - 1];
     846        options.scope = frame.m_element;
     847        collectMatchingRules(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
     848        collectMatchingRulesForRegion(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
    845849    }
    846850    // Also include the current element.
    847851    RuleSet* ruleSet = scopedRuleSetForElement(m_element);
    848852    if (ruleSet) {
    849         collectMatchingRules(ruleSet, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, includeEmptyRules);
    850         collectMatchingRulesForRegion(ruleSet, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, includeEmptyRules);
     853        options.scope = m_element;
     854        collectMatchingRules(ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
     855        collectMatchingRulesForRegion(ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
    851856    }
    852857#else
     
    859864{
    860865    m_matchedRules.clear();
    861 
    862866    result.ranges.lastAuthorRule = result.matchedProperties.size() - 1;
    863     collectMatchingRules(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, includeEmptyRules);
    864     collectMatchingRulesForRegion(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, includeEmptyRules);
     867
     868    if (!m_element)
     869        return;
     870
     871    // Match global author rules.
     872    MatchOptions options(includeEmptyRules);
     873    collectMatchingRules(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
     874    collectMatchingRulesForRegion(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
    865875
    866876    matchScopedAuthorRules(result, includeEmptyRules);
     
    922932bool MatchingUARulesScope::m_matchingUARules = false;
    923933
    924 inline static bool matchesInTreeScope(TreeScope* treeScope, bool ruleReachesIntoShadowDOM)
    925 {
    926     return MatchingUARulesScope::isMatchingUARules() || treeScope->applyAuthorSheets() || ruleReachesIntoShadowDOM;
    927 }
    928 
    929 void CSSStyleSelector::collectMatchingRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
     934void CSSStyleSelector::collectMatchingRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
    930935{
    931936    if (!rules)
     
    943948        CSSStyleRule* rule = ruleData.rule();
    944949        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule);
     950#if ENABLE(STYLE_SCOPED)
     951        if (checkSelector(ruleData, options.scope)) {
     952#else
    945953        if (checkSelector(ruleData)) {
    946             if (!matchesInTreeScope(m_element->treeScope(), m_checker.hasUnknownPseudoElements())) {
     954#endif
     955            // Check whether the rule is applicable in the current tree scope. Criteria for this:
     956            // a) it's a UA rule
     957            // b) the tree scope allows author rules
     958            // c) the rules comes from a scoped style sheet within the same tree scope
     959            // d) the rule contains shadow-ID pseudo elements
     960            TreeScope* treeScope = m_element->treeScope();
     961            if (!MatchingUARulesScope::isMatchingUARules()
     962                && !treeScope->applyAuthorSheets()
     963#if ENABLE(STYLE_SCOPED)
     964                && (!options.scope || options.scope->treeScope() != treeScope)
     965#endif
     966                && !m_checker.hasUnknownPseudoElements()) {
     967
    947968                InspectorInstrumentation::didMatchRule(cookie, false);
    948969                continue;
     
    950971            // If the rule has no properties to apply, then ignore it in the non-debug mode.
    951972            StylePropertySet* decl = rule->declaration();
    952             if (!decl || (decl->isEmpty() && !includeEmptyRules)) {
     973            if (!decl || (decl->isEmpty() && !options.includeEmptyRules)) {
    953974                InspectorInstrumentation::didMatchRule(cookie, false);
    954975                continue;
     
    20822103}
    20832104
    2084 inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData)
     2105inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData, const Element* scope)
    20852106{
    20862107    m_dynamicPseudo = NOPSEUDO;
     
    21052126
    21062127    // Slow path.
    2107     SelectorChecker::SelectorCheckingContext context(ruleData.selector(), m_element, SelectorChecker::VisitedMatchEnabled, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
     2128    SelectorChecker::SelectorCheckingContext context(ruleData.selector(), m_element, SelectorChecker::VisitedMatchEnabled);
     2129    context.elementStyle = style();
     2130    context.elementParentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
     2131    context.scope = scope;
    21082132    SelectorChecker::SelectorMatch match = m_checker.checkSelector(context, m_dynamicPseudo);
    21092133    if (match != SelectorChecker::SelectorMatches)
     
    22122236}
    22132237
    2214 RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position)
     2238RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position, bool canUseFastCheckSelector)
    22152239    : m_rule(rule)
    22162240    , m_selector(selector)
    22172241    , m_specificity(selector->specificity())
    22182242    , m_position(position)
    2219     , m_hasFastCheckableSelector(SelectorChecker::isFastCheckableSelector(selector))
     2243    , m_hasFastCheckableSelector(canUseFastCheckSelector && SelectorChecker::isFastCheckableSelector(selector))
    22202244    , m_hasMultipartSelector(!!selector->tagHistory())
    22212245    , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
     
    22862310}
    22872311
    2288 void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* selector)
    2289 {
    2290     RuleData ruleData(rule, selector, m_ruleCount++);
     2312void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* selector, bool canUseFastCheckSelector)
     2313{
     2314    RuleData ruleData(rule, selector, m_ruleCount++, canUseFastCheckSelector);
    22912315    collectFeaturesFromRuleData(m_features, ruleData);
    22922316
     
    23652389        CSSRule* rule = sheet->item(i);
    23662390        if (rule->isStyleRule())
    2367             addStyleRule(static_cast<CSSStyleRule*>(rule));
     2391            addStyleRule(static_cast<CSSStyleRule*>(rule), !scope);
    23682392        else if (rule->isPageRule())
    23692393            addPageRule(static_cast<CSSPageRule*>(rule));
     
    23822406                    CSSRule *childItem = rules->item(j);
    23832407                    if (childItem->isStyleRule())
    2384                         addStyleRule(static_cast<CSSStyleRule*>(childItem));
     2408                        addStyleRule(static_cast<CSSStyleRule*>(childItem), !scope);
    23852409                    else if (childItem->isPageRule())
    23862410                        addPageRule(static_cast<CSSPageRule*>(childItem));
     
    24262450}
    24272451
    2428 void RuleSet::addStyleRule(CSSStyleRule* rule)
     2452void RuleSet::addStyleRule(CSSStyleRule* rule, bool canUseFastCheckSelector)
    24292453{
    24302454    for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s))
    2431         addRule(rule, s);
     2455        addRule(rule, s, canUseFastCheckSelector);
    24322456}
    24332457
  • trunk/Source/WebCore/css/CSSStyleSelector.h

    r107783 r107911  
    107107    ~CSSStyleSelector();
    108108
    109 #if ENABLE(STYLE_SCOPED)
    110     static Element* determineScopingElement(const CSSStyleSheet*);
    111 #endif
    112 
    113109    // Using these during tree walk will allow style selector to optimize child and descendant selector lookups.
    114110    void pushParent(Element* parent);
     
    289285        bool isCacheable;
    290286    };
     287
     288    struct MatchOptions {
     289        MatchOptions(bool includeEmptyRules, const Element* scope = 0) : scope(scope), includeEmptyRules(includeEmptyRules) { }
     290        const Element* scope;
     291        bool includeEmptyRules;
     292    };
     293
    291294    static void addMatchedProperties(MatchResult& matchResult, StylePropertySet* properties, CSSStyleRule* rule = 0, unsigned linkMatchType =  SelectorChecker::MatchAll);
    292295
     
    297300    void matchUserRules(MatchResult&, bool includeEmptyRules);
    298301    void matchScopedAuthorRules(MatchResult&, bool includeEmptyRules);
    299     void collectMatchingRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules);
    300     void collectMatchingRulesForRegion(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules);
    301     void collectMatchingRulesForList(const Vector<RuleData>*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules);
     302    void collectMatchingRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions&);
     303    void collectMatchingRulesForRegion(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions&);
     304    void collectMatchingRulesForList(const Vector<RuleData>*, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions&);
    302305    bool fastRejectSelector(const RuleData&) const;
    303306    void sortMatchedRules();
    304307    void sortAndTransferMatchedRules(MatchResult&);
    305308
    306     bool checkSelector(const RuleData&);
     309    bool checkSelector(const RuleData&, const Element* scope = 0);
    307310    bool checkRegionSelector(CSSSelector* regionSelector, Element* regionElement);
    308311    void applyMatchedProperties(const MatchResult&);
     
    447450
    448451#if ENABLE(STYLE_SCOPED)
     452    static const Element* determineScopingElement(const CSSStyleSheet*);
     453
    449454    typedef HashMap<const Element*, OwnPtr<RuleSet> > ScopedRuleSetMap;
    450455
  • trunk/Source/WebCore/css/SelectorChecker.cpp

    r107509 r107911  
    469469
    470470    if (relation != CSSSelector::SubSelector) {
     471        // Abort if the next selector would exceed the scope.
     472        if (context.element == context.scope)
     473            return SelectorFailsCompletely;
     474
    471475        // Bail-out if this selector is irrelevant for the pseudoStyle
    472476        if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != dynamicPseudo)
     
    488492            if (match == SelectorMatches || match == SelectorFailsCompletely)
    489493                return match;
     494            if (nextContext.element == nextContext.scope)
     495                return SelectorFailsCompletely;
    490496        }
    491497        return SelectorFailsCompletely;
     
    543549    case CSSSelector::ShadowDescendant:
    544550        {
     551            // If we're in the same tree-scope as the scoping element, then following a shadow descendant combinator would escape that and thus the scope.
     552            if (context.scope && context.scope->treeScope() == context.element->treeScope())
     553                return SelectorFailsCompletely;
    545554            Node* shadowHostNode = context.element->shadowAncestorNode();
    546555            if (shadowHostNode == context.element || !shadowHostNode->isElementNode())
  • trunk/Source/WebCore/css/SelectorChecker.h

    r107212 r107911  
    5555    struct SelectorCheckingContext {
    5656        // Initial selector constructor
    57         SelectorCheckingContext(CSSSelector* selector, Element* element, VisitedMatchType visitedMatchType, RenderStyle* elementStyle = 0, RenderStyle* elementParentStyle = 0)
     57        SelectorCheckingContext(CSSSelector* selector, Element* element, VisitedMatchType visitedMatchType)
    5858            : selector(selector)
    5959            , element(element)
     60            , scope(0)
    6061            , visitedMatchType(visitedMatchType)
    61             , elementStyle(elementStyle)
    62             , elementParentStyle(elementParentStyle)
     62            , elementStyle(0)
     63            , elementParentStyle(0)
    6364            , isSubSelector(false)
    6465        { }
     
    6667        CSSSelector* selector;
    6768        Element* element;
     69        const Element* scope;
    6870        VisitedMatchType visitedMatchType;
    6971        RenderStyle* elementStyle;
     
    144146    };
    145147    Vector<ParentStackFrame> m_parentStack;
    146    
     148
    147149    // With 100 unique strings in the filter, 2^12 slot table has false positive rate of ~0.2%.
    148150    static const unsigned bloomFilterKeyBits = 12;
Note: See TracChangeset for help on using the changeset viewer.