Changeset 106331 in webkit


Ignore:
Timestamp:
Jan 30, 2012 9:04:08 PM (12 years ago)
Author:
rolandsteiner@chromium.org
Message:

<style scoped>: Implement scoped stylesheets and basic application
https://bugs.webkit.org/show_bug.cgi?id=73190

Source/WebCore:

Implementing support for <style scoped>:
Add a vector stack to CSSStyleSelector that keeps track of encountered scoping elements. This is
used for O(1) access to all relevant style sheets for a given element.
Adapt matching of author style sheets to also consult appropriate scoped sheets.
Finally, prevent style sharing from crossing into/out of scoped style boundaries.

Reviewed by Antti Koivisto.

Tests: fast/css/style-scoped/style-scoped-attach.html

fast/css/style-scoped/style-scoped-basic.html
fast/css/style-scoped/style-scoped-detach.html
fast/css/style-scoped/style-scoped-remove-scoped.html
fast/css/style-scoped/style-scoped-set-scoped.html

  • css/CSSStyleSelector.cpp:

(RuleSet):
(WebCore::CSSStyleSelector::CSSStyleSelector): add code for scoped style sheets
(WebCore::CSSStyleSelector::collectFeatures): ditto
(WebCore):
(WebCore::CSSStyleSelector::determineScopingElement): determine whether an author sheet is scoped (and to which scope), or global
(WebCore::CSSStyleSelector::scopedRuleSetForElement): returns the RuleSet for the <style scoped> contained by the passed-in element (if any), or 0
(WebCore::CSSStyleSelector::appendAuthorStylesheets): add code for scoped style sheets
(WebCore::CSSStyleSelector::setupScopingElementStack): determine scoping element ancestors of the given element
(WebCore::CSSStyleSelector::pushParent): simplify and refactor SelectorChecker::pushParent, as code in CSStyleSelector needs partial access
(WebCore::CSSStyleSelector::popParent): ditto
(WebCore::CSSStyleSelector::sortAndTransferMatchedRules): helper function
(WebCore::CSSStyleSelector::matchAuthorRules): use AuthorRuleSetIterator to iterate over all relevant RuleSets
(WebCore::CSSStyleSelector::matchRules): adapt for scoped style rules
(WebCore::CSSStyleSelector::matchAllRules): ditto
(WebCore::CSSStyleSelector::locateCousinList): prevent style sharing across scope boundaries
(WebCore::CSSStyleSelector::canShareStyleWithElement): ditto
(WebCore::CSSStyleSelector::locateSharedStyle): ditto
(WebCore::CSSStyleSelector::pseudoStyleForElement): changed call to matchAuthorRules
(WebCore::CSSStyleSelector::styleForPage): add comment
(WebCore::CSSStyleSelector::checkRegionStyle): add global scope parameter
(WebCore::CSSStyleSelector::pseudoStyleRulesForElement): changed call to matchAuthorRules
(WebCore::RuleSet::addRulesFromSheet): adapt for scoped style rules

  • css/CSSStyleSelector.h:

(CSSStyleSelector):
(WebCore::CSSStyleSelector::ScopeStackFrame::ScopeStackFrame): struct holding an Element pointer and a RuleSet pointer, to be used in a Vector
(WebCore::CSSStyleSelector::scopingElementStackIsConsistent): returns if the last seen parent matches the passed-in element

  • css/SelectorChecker.cpp:

(WebCore::SelectorChecker::setupParentStack): set up the parent stack (refactoring)
(WebCore::SelectorChecker::pushParent): simplify and refactor

  • css/SelectorChecker.h:

(WebCore::SelectorChecker::popParent): ditto
(WebCore::SelectorChecker::parentStackIsEmpty): ditto
(WebCore::SelectorChecker::parentStackIsConsistent): make parameter const

LayoutTests:

Test that <style scoped> affects styles and is updated correctly:
-) basic test
-) test setting/un-setting the 'scoped' attribute
-) test inserting/removing a whole <style scoped> element

Reviewed by Antti Koivisto.

  • fast/css/style-scoped/style-scoped-attach-expected.txt: Added.
  • fast/css/style-scoped/style-scoped-attach.html: Added.
  • fast/css/style-scoped/style-scoped-basic-expected.txt: Added.
  • fast/css/style-scoped/style-scoped-basic.html: Added.
  • fast/css/style-scoped/style-scoped-detach-expected.txt: Added.
  • fast/css/style-scoped/style-scoped-detach.html: Added.
  • fast/css/style-scoped/style-scoped-remove-scoped-expected.txt: Added.
  • fast/css/style-scoped/style-scoped-remove-scoped.html: Added.
  • fast/css/style-scoped/style-scoped-set-scoped-expected.txt: Added.
  • fast/css/style-scoped/style-scoped-set-scoped.html: Added.
Location:
trunk
Files:
10 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r106325 r106331  
     12012-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
    1242012-01-30  Yuzo Fujishima  <yuzo@google.com>
    225
  • trunk/Source/WebCore/ChangeLog

    r106324 r106331  
     12012-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
    1552012-01-30  Dana Jansens  <danakj@chromium.org>
    256
  • trunk/Source/WebCore/css/CSSStyleSelector.cpp

    r106258 r106331  
    6666#include "HTMLNames.h"
    6767#include "HTMLProgressElement.h"
     68#include "HTMLStyleElement.h"
    6869#include "HTMLTextAreaElement.h"
    6970#include "InspectorInstrumentation.h"
     
    223224    typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<RuleData> > > AtomRuleMap;
    224225
    225     void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
     226    void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0, const Element* = 0);
    226227
    227228    void addStyleRule(CSSStyleRule*);
     
    338339    , m_hasPendingShaders(false)
    339340#endif
     341#if ENABLE(STYLE_SCOPED)
     342    , m_scopingElementStackParent(0)
     343#endif
    340344{
    341345    Element* root = document->documentElement();
     
    369373    m_authorStyle = adoptPtr(new RuleSet);
    370374    // 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.
    371377    m_authorStyle->disableAutoShrinkToFit();
    372378
     
    398404
    399405    // 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.
    401408        m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this);
     409    }
    402410
    403411    // add stylesheets from document
     
    424432    m_features.add(defaultStyle->features());
    425433    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
    426438    if (m_userStyle)
    427439        m_features.add(m_userStyle->features());
     
    430442    m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
    431443}
     444
     445#if ENABLE(STYLE_SCOPED)
     446Element* 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
     461inline 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
    432469
    433470void CSSStyleSelector::appendAuthorStylesheets(unsigned firstNew, const Vector<RefPtr<StyleSheet> >& stylesheets)
     
    439476        if (!stylesheets[i]->isCSSStyleSheet() || stylesheets[i]->disabled())
    440477            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);
    442490    }
    443491    m_authorStyle->shrinkToFit();
     
    446494    if (document()->renderer() && document()->renderer()->style())
    447495        document()->renderer()->style()->font().update(fontSelector());
     496}
     497
     498#if ENABLE(STYLE_SCOPED)
     499void 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
     518void 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
     544void 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
    448557}
    449558
     
    688797}
    689798
    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 
     799void CSSStyleSelector::sortAndTransferMatchedRules()
     800{
    700801    if (m_matchedRules.isEmpty())
    701802        return;
     
    722823        addMatchedDeclaration(m_matchedRules[i]->rule()->declaration(), linkMatchType);
    723824    }
     825}
     826
     827void 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
     858void 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();
    724869}
    725870
     
    8711016    // Check the rules in author sheets next.
    8721017    if (m_matchAuthorAndUserStyles)
    873         matchRules(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, false);
     1018        matchAuthorRules(result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, false);
    8741019
    8751020    // Now check our inline style attribute.
     
    9341079    if (!parent || !parent->isStyledElement())
    9351080        return 0;
     1081#if ENABLE(STYLE_SCOPED)
     1082    if (parent->hasScopedHTMLStyleChild())
     1083        return 0;
     1084#endif
    9361085    StyledElement* p = static_cast<StyledElement*>(parent);
    9371086    if (p->inlineStyleDecl())
     
    10971246        return false;
    10981247
     1248#if ENABLE(STYLE_SCOPED)
     1249    if (element->hasScopedHTMLStyleChild())
     1250        return false;
     1251#endif
     1252
    10991253    bool isControl = element->isFormControlElement();
    11001254
     
    11681322    if (parentStylePreventsSharing(m_parentStyle))
    11691323        return 0;
     1324#if ENABLE(STYLE_SCOPED)
     1325    if (m_styledElement->hasScopedHTMLStyleChild())
     1326        return 0;
     1327#endif
    11701328
    11711329    // Check previous siblings and their cousins.
     
    14871645    if (m_matchAuthorAndUserStyles) {
    14881646        matchRules(m_userStyle.get(), matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false);
    1489         matchRules(m_authorStyle.get(), matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, false);
     1647        matchAuthorRules(matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, false);
    14901648    }
    14911649
     
    15241682    matchPageRules(defaultPrintStyle, isLeft, isFirst, page);
    15251683    matchPageRules(m_userStyle.get(), isLeft, isFirst, page);
     1684    // Only consider the global author RuleSet for @page rules, as per the HTML5 spec.
    15261685    matchPageRules(m_authorStyle.get(), isLeft, isFirst, page);
    15271686    m_lineHeightValue = 0;
     
    17671926bool CSSStyleSelector::checkRegionStyle(Element* regionElement)
    17681927{
     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
    17691931    unsigned rulesSize = m_authorStyle->m_regionSelectorsAndRuleSets.size();
    17701932    for (unsigned i = 0; i < rulesSize; ++i) {
     
    18371999
    18382000        // Check the rules in author sheets.
    1839         matchRules(m_authorStyle.get(), dummy.ranges.firstAuthorRule, dummy.ranges.lastAuthorRule, rulesToInclude & EmptyCSSRules);
     2001        matchAuthorRules(dummy.ranges.firstAuthorRule, dummy.ranges.lastAuthorRule, rulesToInclude & EmptyCSSRules);
    18402002
    18412003        m_sameOriginOnly = false;
     
    21152277}
    21162278
    2117 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
     2279void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector, const Element* scope)
    21182280{
    21192281    ASSERT(sheet);
     
    21352297            CSSImportRule* import = static_cast<CSSImportRule*>(rule);
    21362298            if (import->styleSheet() && (!import->media() || medium.eval(import->media(), styleSelector)))
    2137                 addRulesFromSheet(import->styleSheet(), medium, styleSelector);
     2299                addRulesFromSheet(import->styleSheet(), medium, styleSelector, scope);
    21382300        }
    21392301        else if (rule->isMediaRule()) {
     
    21512313                    else if (childItem->isFontFaceRule() && styleSelector) {
    21522314                        // 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;
    21532318                        const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem);
    21542319                        styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
     
    21562321                    } else if (childItem->isKeyframesRule() && styleSelector) {
    21572322                        // 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;
    21582326                        styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem));
    21592327                    }
     
    21622330        } else if (rule->isFontFaceRule() && styleSelector) {
    21632331            // 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;
    21642335            const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(rule);
    21652336            styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
    21662337            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;
    21682342            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;
    21702347            addRegionRule(static_cast<WebKitCSSRegionRule*>(rule));
     2348        }
    21712349    }
    21722350    if (m_autoShrinkToFitEnabled)
  • trunk/Source/WebCore/css/CSSStyleSelector.h

    r106120 r106331  
    107107    ~CSSStyleSelector();
    108108
     109#if ENABLE(STYLE_SCOPED)
     110    static Element* determineScopingElement(const CSSStyleSheet*);
     111#endif
     112
    109113    // 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);
    112116
    113117    PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false, RenderRegion* regionForStyling = 0);
     
    276280    void matchUARules(MatchResult&);
    277281    void matchRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules);
     282    void matchAuthorRules(int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules);
    278283    void collectMatchingRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules);
    279284    void collectMatchingRulesForRegion(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules);
     
    281286    bool fastRejectSelector(const RuleData&) const;
    282287    void sortMatchedRules();
     288    void sortAndTransferMatchedRules();
    283289
    284290    bool checkSelector(const RuleData&);
     
    434440    bool m_applyPropertyToVisitedLinkStyle;
    435441    const CSSStyleApplyProperty& m_applyProperty;
    436    
     442
    437443#if ENABLE(CSS_SHADERS)
    438444    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;
    439469#endif
    440470
  • trunk/Source/WebCore/css/SelectorChecker.cpp

    r104152 r106331  
    4141#include "HTMLOptionElement.h"
    4242#include "HTMLProgressElement.h"
     43#include "HTMLStyleElement.h"
    4344#include "InspectorInstrumentation.h"
    4445#include "NodeRenderStyle.h"
     
    126127}
    127128
     129void 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
    128148void SelectorChecker::pushParent(Element* parent)
    129149{
    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;
    156155    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();
    164156}
    165157
  • trunk/Source/WebCore/css/SelectorChecker.h

    r104734 r106331  
    6161    static void collectIdentifierHashes(const CSSSelector*, unsigned* identifierHashes, unsigned maximumIdentifierCount);
    6262
     63    void setupParentStack(Element* parent);
    6364    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; }
    6668
    6769    EInsideLink determineLinkState(Element*) const;
Note: See TracChangeset for help on using the changeset viewer.