Changeset 132303 in webkit


Ignore:
Timestamp:
Oct 23, 2012 9:37:23 PM (12 years ago)
Author:
tasak@google.com
Message:

[Shadow DOM] Needs @host rule for ShadowDOM styling
https://bugs.webkit.org/show_bug.cgi?id=88606

Reviewed by Hajime Morita.

Source/WebCore:

Implemented @host-@rules according to the shadow dom spec:
http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#host-at-rule
The design doc is:
https://docs.google.com/document/d/1P2yorchF8lci2sccr-mVSRf2dtvjKeiuyQWzCB2bEA8/edit

Test: fast/dom/shadow/athost-atrules.html

  • css/CSSGrammar.y.in:

Added rules for parsing @host @-rules.

  • css/CSSParser.cpp:

(WebCore::CSSParser::detectAtToken):
Added a new token "@host".
(WebCore::CSSParser::createHostRule):
Added a new method to create an @host @-rule, which is invoked from
(WebCore):

  • css/CSSParser.h:

Added a declaration of the above new method: createHostRule.

  • css/CSSPropertySourceData.h:

Added HOST_RULE to enum Type.

  • css/RuleSet.cpp:

(WebCore::RuleData::RuleData):
Modified multiple bool arguments into one argument. Now it
uses combinations of values from enum AddRuleFlags.
(WebCore::RuleSet::addRule):
(WebCore::RuleSet::addRegionRule):
(WebCore::RuleSet::addStyleRule):
Updated according to the RuleData's change.
Modified to Invoke increaseSpecificity if the given rule is @host
@-rule.
(WebCore::RuleSet::addRulesFromSheet):
Invoked addHostRule if the given rule is @host @-rule.

  • css/RuleSet.h:

(RuleData):
(WebCore::RuleData::increaseSpecificity):
Added a new method to increase selector's specificity. This method is
used to make @host @-rules' specificity larger than normal author
rules' specificity.
(RuleSet):

  • css/StyleResolver.cpp:

(WebCore::makeRuleSet):
(WebCore::StyleResolver::addHostRule):
A wrapper method to invoke StyleScopeResolver::addHostRule. The method
is used to make only StyleResolver know an implementation detail about
class StyleScopeResolver.
(WebCore::StyleResolver::appendAuthorStylesheets):
Updated according to the RuleData's change.
(WebCore::StyleResolver::styleSharingCandidateMatchesHostRules):
A new method to find matched host rules when an element is given.
This method invokes
StyleScopeResolver::styleSharingCandidateMatchesHostRules to find
matched host rules.
(WebCore):
(WebCore::StyleResolver::matchHostRules):
A new method to find matched host rules when an element is given.
This method invokes StyleScopeResolver::matchHostRules to find
matched host rules.
(WebCore::StyleResolver::matchScopedAuthorRules):
Modified to invoke matchHostRules.
(WebCore::StyleResolver::locateSharedStyle):
Disable sibling style cache if the given element is a shadow host and
any @host @-rules are applied to the element.

  • css/StyleResolver.h:

(WebCore::StyleResolver::ensureScopeResolver):
If no scopeResolver is created, create and return the instance.
If created, just return the instance.
(StyleResolver):

  • css/StyleRule.cpp:

(WebCore::StyleRuleBase::reportMemoryUsage):
(WebCore::StyleRuleBase::destroy):
(WebCore::StyleRuleBase::copy):
(WebCore::StyleRuleBase::createCSSOMWrapper):
(WebCore::StyleRuleHost::StyleRuleHost):
Implemented class StyleRuleHost. The class is almost the same as
StyleRuleBlock except type.
(WebCore):

  • css/StyleRule.h:

(WebCore::StyleRuleBase::isHostRule):
(StyleRuleHost):
(WebCore::StyleRuleHost::create):
(WebCore::StyleRuleHost::copy):
(WebCore):

  • css/StyleScopeResolver.cpp:

(WebCore::StyleScopeResolver::ensureAtHostRuleSetFor):
A new method to create a new RuleSet for the given shadow root.
(WebCore):
(WebCore::StyleScopeResolver::atHostRuleSetFor):
A new private inline method to obtain @host @-rules declared in
the given shadow root.
(WebCore::StyleScopeResolver::addHostRule):
Added a new method to register @host @-rules with shadow roots.
(WebCore::StyleScopeResolver::styleSharingCandidateMatchesHostRules):
A new method to find whether any @host @-rules are applied to
the given host element.
(WebCore::StyleScopeResolver::matchHostRules):
A new method to find matched rules for the given host element.
(WebCore::StyleScopeResolver::reportMemoryUsage):

  • css/StyleScopeResolver.h:

(WebCore):
(StyleScopeResolver):

  • css/StyleSheetContents.cpp:

(WebCore::childRulesHaveFailedOrCanceledSubresources):

LayoutTests:

  • fast/dom/shadow/athost-atrules-expected.txt: Added.
  • fast/dom/shadow/athost-atrules.html: Added.
Location:
trunk
Files:
2 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r132301 r132303  
     12012-10-23  Takashi Sakamoto  <tasak@google.com>
     2
     3        [Shadow DOM] Needs @host rule for ShadowDOM styling
     4        https://bugs.webkit.org/show_bug.cgi?id=88606
     5
     6        Reviewed by Hajime Morita.
     7
     8        * fast/dom/shadow/athost-atrules-expected.txt: Added.
     9        * fast/dom/shadow/athost-atrules.html: Added.
     10
    1112012-10-23  Simon Fraser  <simon.fraser@apple.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r132302 r132303  
     12012-10-23  Takashi Sakamoto  <tasak@google.com>
     2
     3        [Shadow DOM] Needs @host rule for ShadowDOM styling
     4        https://bugs.webkit.org/show_bug.cgi?id=88606
     5
     6        Reviewed by Hajime Morita.
     7
     8        Implemented @host-@rules according to the shadow dom spec:
     9        http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#host-at-rule
     10        The design doc is:
     11        https://docs.google.com/document/d/1P2yorchF8lci2sccr-mVSRf2dtvjKeiuyQWzCB2bEA8/edit
     12
     13        Test: fast/dom/shadow/athost-atrules.html
     14
     15        * css/CSSGrammar.y.in:
     16        Added rules for parsing @host @-rules.
     17        * css/CSSParser.cpp:
     18        (WebCore::CSSParser::detectAtToken):
     19        Added a new token "@host".
     20        (WebCore::CSSParser::createHostRule):
     21        Added a new method to create an @host @-rule, which is invoked from
     22        (WebCore):
     23        * css/CSSParser.h:
     24        Added a declaration of the above new method: createHostRule.
     25        * css/CSSPropertySourceData.h:
     26        Added HOST_RULE to enum Type.
     27        * css/RuleSet.cpp:
     28        (WebCore::RuleData::RuleData):
     29        Modified multiple bool arguments into one argument. Now it
     30        uses combinations of values from enum AddRuleFlags.
     31        (WebCore::RuleSet::addRule):
     32        (WebCore::RuleSet::addRegionRule):
     33        (WebCore::RuleSet::addStyleRule):
     34        Updated according to the RuleData's change.
     35        Modified to Invoke increaseSpecificity if the given rule is @host
     36        @-rule.
     37        (WebCore::RuleSet::addRulesFromSheet):
     38        Invoked addHostRule if the given rule is @host @-rule.
     39        * css/RuleSet.h:
     40        (RuleData):
     41        (WebCore::RuleData::increaseSpecificity):
     42        Added a new method to increase selector's specificity. This method is
     43        used to make @host @-rules' specificity larger than normal author
     44        rules' specificity.
     45        (RuleSet):
     46        * css/StyleResolver.cpp:
     47        (WebCore::makeRuleSet):
     48        (WebCore::StyleResolver::addHostRule):
     49        A wrapper method to invoke StyleScopeResolver::addHostRule. The method
     50        is used to make only StyleResolver know an implementation detail about
     51        class StyleScopeResolver.
     52        (WebCore::StyleResolver::appendAuthorStylesheets):
     53        Updated according to the RuleData's change.
     54        (WebCore::StyleResolver::styleSharingCandidateMatchesHostRules):
     55        A new method to find matched host rules when an element is given.
     56        This method invokes
     57        StyleScopeResolver::styleSharingCandidateMatchesHostRules to find
     58        matched host rules.
     59        (WebCore):
     60        (WebCore::StyleResolver::matchHostRules):
     61        A new method to find matched host rules when an element is given.
     62        This method invokes StyleScopeResolver::matchHostRules to find
     63        matched host rules.
     64        (WebCore::StyleResolver::matchScopedAuthorRules):
     65        Modified to invoke matchHostRules.
     66        (WebCore::StyleResolver::locateSharedStyle):
     67        Disable sibling style cache if the given element is a shadow host and
     68        any @host @-rules are applied to the element.
     69        * css/StyleResolver.h:
     70        (WebCore::StyleResolver::ensureScopeResolver):
     71        If no scopeResolver is created, create and return the instance.
     72        If created, just return the instance.
     73        (StyleResolver):
     74        * css/StyleRule.cpp:
     75        (WebCore::StyleRuleBase::reportMemoryUsage):
     76        (WebCore::StyleRuleBase::destroy):
     77        (WebCore::StyleRuleBase::copy):
     78        (WebCore::StyleRuleBase::createCSSOMWrapper):
     79        (WebCore::StyleRuleHost::StyleRuleHost):
     80        Implemented class StyleRuleHost. The class is almost the same as
     81        StyleRuleBlock except type.
     82        (WebCore):
     83        * css/StyleRule.h:
     84        (WebCore::StyleRuleBase::isHostRule):
     85        (StyleRuleHost):
     86        (WebCore::StyleRuleHost::create):
     87        (WebCore::StyleRuleHost::copy):
     88        (WebCore):
     89        * css/StyleScopeResolver.cpp:
     90        (WebCore::StyleScopeResolver::ensureAtHostRuleSetFor):
     91        A new method to create a new RuleSet for the given shadow root.
     92        (WebCore):
     93        (WebCore::StyleScopeResolver::atHostRuleSetFor):
     94        A new private inline method to obtain @host @-rules declared in
     95        the given shadow root.
     96        (WebCore::StyleScopeResolver::addHostRule):
     97        Added a new method to register @host @-rules with shadow roots.
     98        (WebCore::StyleScopeResolver::styleSharingCandidateMatchesHostRules):
     99        A new method to find whether any @host @-rules are applied to
     100        the given host element.
     101        (WebCore::StyleScopeResolver::matchHostRules):
     102        A new method to find matched rules for the given host element.
     103        (WebCore::StyleScopeResolver::reportMemoryUsage):
     104        * css/StyleScopeResolver.h:
     105        (WebCore):
     106        (StyleScopeResolver):
     107        * css/StyleSheetContents.cpp:
     108        (WebCore::childRulesHaveFailedOrCanceledSubresources):
     109
    11102012-10-23  Andreas Kling  <kling@webkit.org>
    2111
  • trunk/Source/WebCore/css/CSSGrammar.y.in

    r131783 r132303  
    9696#endif
    9797%token FONT_FACE_SYM
     98#if ENABLE_SHADOW_DOM
     99%token HOST_SYM
     100#endif
    98101%token CHARSET_SYM
    99102%token NAMESPACE_SYM
     
    188191%type <rule> margin_box
    189192%type <rule> font_face
     193#if ENABLE_SHADOW_DOM
     194%type <rule> host
     195#endif
    190196%type <rule> keyframes
    191197%type <rule> invalid_rule
     
    402408#if ENABLE_CSS3_CONDITIONAL_RULES
    403409  | supports
     410#endif
     411#if ENABLE_SHADOW_DOM
     412  | host
    404413#endif
    405414  ;
     
    901910    }
    902911;
     912
     913#if ENABLE_SHADOW_DOM
     914before_host_rule:
     915    /* empty */ {
     916        parser->markRuleHeaderStart(CSSRuleSourceData::HOST_RULE);
     917    }
     918    ;
     919
     920host:
     921    before_host_rule HOST_SYM at_rule_header_end_maybe_space
     922    '{' at_rule_body_start maybe_space block_rule_list save_block {
     923        $$ = parser->createHostRule($7);
     924    }
     925    | before_host_rule HOST_SYM at_rule_header_end_maybe_space ';' {
     926        $$ = 0;
     927        parser->popRuleData();
     928    }
     929    ;
     930#endif
    903931
    904932region_selector:
  • trunk/Source/WebCore/css/CSSParser.cpp

    r132227 r132303  
    91869186        return;
    91879187
     9188#if ENABLE(SHADOW_DOM)
     9189    case 'h':
     9190        if (length == 5 && isEqualToCSSIdentifier(name + 2, "ost"))
     9191            m_token = HOST_SYM;
     9192        return;
     9193#endif
     9194
    91889195    case 'i':
    91899196        if (length == 7 && isEqualToCSSIdentifier(name + 2, "mport")) {
     
    1001810025}
    1001910026
     10027#if ENABLE(SHADOW_DOM)
     10028StyleRuleBase* CSSParser::createHostRule(RuleList* rules)
     10029{
     10030    m_allowImportRules = m_allowNamespaceDeclarations = false;
     10031    RefPtr<StyleRuleHost> rule;
     10032    if (rules)
     10033        rule = StyleRuleHost::create(*rules);
     10034    else {
     10035        RuleList emptyRules;
     10036        rule = StyleRuleHost::create(emptyRules);
     10037    }
     10038    StyleRuleHost* result = rule.get();
     10039    m_parsedRules.append(rule.release());
     10040    processAndAddNewRuleToSourceTreeIfNeeded();
     10041    return result;
     10042}
     10043#endif
     10044
    1002010045void CSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
    1002110046{
  • trunk/Source/WebCore/css/CSSParser.h

    r132227 r132303  
    283283    StyleRuleBase* createRegionRule(CSSSelectorVector* regionSelector, RuleList* rules);
    284284    StyleRuleBase* createMarginAtRule(CSSSelector::MarginBoxType);
     285#if ENABLE(SHADOW_DOM)
     286    StyleRuleBase* createHostRule(RuleList* rules);
     287#endif
    285288    void startDeclarationsForMarginBox();
    286289    void endDeclarationsForMarginBox();
  • trunk/Source/WebCore/css/CSSPropertySourceData.h

    r127757 r132303  
    9595        PAGE_RULE,
    9696        KEYFRAMES_RULE,
    97         REGION_RULE
     97        REGION_RULE,
     98        HOST_RULE
    9899    };
    99100
  • trunk/Source/WebCore/css/RuleSet.cpp

    r130612 r132303  
    108108}
    109109
    110 RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule)
     110RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, AddRuleFlags addRuleFlags)
    111111    : m_rule(rule)
    112112    , m_selectorIndex(selectorIndex)
    113113    , m_position(position)
    114114    , m_specificity(selector()->specificity())
    115     , m_hasFastCheckableSelector(canUseFastCheckSelector && SelectorChecker::isFastCheckableSelector(selector()))
     115    , m_hasFastCheckableSelector((addRuleFlags & RuleCanUseFastCheckSelector) && SelectorChecker::isFastCheckableSelector(selector()))
    116116    , m_hasMultipartSelector(!!selector()->tagHistory())
    117117    , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector()))
    118118    , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector()))
    119119    , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector()))
    120     , m_hasDocumentSecurityOrigin(hasDocumentSecurityOrigin)
    121     , m_isInRegionRule(inRegionRule)
     120    , m_hasDocumentSecurityOrigin(addRuleFlags & RuleHasDocumentSecurityOrigin)
     121    , m_isInRegionRule(addRuleFlags & RuleIsInRegionRule)
    122122{
    123123    ASSERT(m_position == position);
     
    208208}
    209209
    210 void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule)
    211 {
    212     RuleData ruleData(rule, selectorIndex, m_ruleCount++, hasDocumentSecurityOrigin, canUseFastCheckSelector, inRegionRule);
     210void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addRuleFlags)
     211{
     212    RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags);
     213    static const unsigned athostRuleSpecificity = 0x100000;
     214
     215    if (addRuleFlags & RuleIsHostRule)
     216        ruleData.increaseSpecificity(athostRuleSpecificity);
     217
    213218    collectFeaturesFromRuleData(m_features, ruleData);
    214219
     
    265270    // Collect the region rules into a rule set
    266271    const Vector<RefPtr<StyleRuleBase> >& childRules = regionRule->childRules();
     272    AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState;
     273    addRuleFlags = static_cast<AddRuleFlags>(addRuleFlags | RuleCanUseFastCheckSelector | RuleIsInRegionRule);
    267274    for (unsigned i = 0; i < childRules.size(); ++i) {
    268275        StyleRuleBase* regionStylingRule = childRules[i].get();
    269276        if (regionStylingRule->isStyleRule())
    270             regionRuleSet->addStyleRule(static_cast<StyleRule*>(regionStylingRule), hasDocumentSecurityOrigin, true, true);
     277            regionRuleSet->addStyleRule(static_cast<StyleRule*>(regionStylingRule), addRuleFlags);
    271278    }
    272279    // Update the "global" rule count so that proper order is maintained
     
    287294    }
    288295    bool hasDocumentSecurityOrigin = resolver && resolver->document()->securityOrigin()->canRequest(sheet->baseURL());
     296    AddRuleFlags addRuleFlags = static_cast<AddRuleFlags>((hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0) | (!scope ? RuleCanUseFastCheckSelector : 0));
    289297
    290298    const Vector<RefPtr<StyleRuleBase> >& rules = sheet->childRules();
     
    294302        ASSERT(!rule->isImportRule());
    295303        if (rule->isStyleRule())
    296             addStyleRule(static_cast<StyleRule*>(rule), hasDocumentSecurityOrigin, !scope);
     304            addStyleRule(static_cast<StyleRule*>(rule), addRuleFlags);
    297305        else if (rule->isPageRule())
    298306            addPageRule(static_cast<StyleRulePage*>(rule));
     
    306314                    StyleRuleBase* childRule = childRules[j].get();
    307315                    if (childRule->isStyleRule())
    308                         addStyleRule(static_cast<StyleRule*>(childRule), hasDocumentSecurityOrigin, !scope);
     316                        addStyleRule(static_cast<StyleRule*>(childRule), addRuleFlags);
    309317                    else if (childRule->isPageRule())
    310318                        addPageRule(static_cast<StyleRulePage*>(childRule));
     
    348356        }
    349357#endif
     358#if ENABLE(SHADOW_DOM)
     359        else if (rule->isHostRule())
     360            resolver->addHostRule(static_cast<StyleRuleHost*>(rule), hasDocumentSecurityOrigin, scope);
     361#endif
    350362    }
    351363    if (m_autoShrinkToFitEnabled)
     
    353365}
    354366
    355 void RuleSet::addStyleRule(StyleRule* rule, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule)
     367void RuleSet::addStyleRule(StyleRule* rule, AddRuleFlags addRuleFlags)
    356368{
    357369    for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = rule->selectorList().indexOfNextSelectorAfter(selectorIndex))
    358         addRule(rule, selectorIndex, hasDocumentSecurityOrigin, canUseFastCheckSelector, isInRegionRule);
     370        addRule(rule, selectorIndex, addRuleFlags);
    359371}
    360372
  • trunk/Source/WebCore/css/RuleSet.h

    r130465 r132303  
    3232namespace WebCore {
    3333
     34enum AddRuleFlags {
     35    RuleHasNoSpecialState         = 0,
     36    RuleHasDocumentSecurityOrigin = 1,
     37    RuleCanUseFastCheckSelector   = 1 << 1,
     38    RuleIsInRegionRule            = 1 << 2,
     39    RuleIsHostRule                = 1 << 3,
     40};
     41
    3442class CSSSelector;
    3543class ContainerNode;
     
    4149class RuleData {
    4250public:
    43     RuleData(StyleRule*, unsigned selectorIndex, unsigned position, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule);
     51    RuleData(StyleRule*, unsigned selectorIndex, unsigned position, AddRuleFlags);
    4452
    4553    unsigned position() const { return m_position; }
     
    5664    bool hasDocumentSecurityOrigin() const { return m_hasDocumentSecurityOrigin; }
    5765    bool isInRegionRule() const { return m_isInRegionRule; }
     66    void increaseSpecificity(unsigned value) { m_specificity += value; }
    5867
    5968    // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance.
     
    99108    void addRulesFromSheet(StyleSheetContents*, const MediaQueryEvaluator&, StyleResolver* = 0, const ContainerNode* = 0);
    100109
    101     void addStyleRule(StyleRule*, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule = false);
    102     void addRule(StyleRule*, unsigned selectorIndex, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule = false);
     110    void addStyleRule(StyleRule*, AddRuleFlags);
     111    void addRule(StyleRule*, unsigned selectorIndex, AddRuleFlags);
    103112    void addPageRule(StyleRulePage*);
    104113    void addToRuleSet(AtomicStringImpl* key, AtomRuleMap&, const RuleData&);
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r132174 r132303  
    118118#include "StyleRule.h"
    119119#include "StyleRuleImport.h"
    120 #include "StyleScopeResolver.h"
    121120#include "StyleSheetContents.h"
    122121#include "StyleSheetList.h"
     
    373372    OwnPtr<RuleSet> ruleSet = RuleSet::create();
    374373    for (size_t i = 0; i < size; ++i)
    375         ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin, false);
     374        ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState);
    376375    ruleSet->shrinkToFit();
    377376    return ruleSet.release();
     
    412411            continue;
    413412        StyleSheetContents* sheet = cssSheet->contents();
     413#if ENABLE(STYLE_SCOPED)
    414414        if (const ContainerNode* scope = StyleScopeResolver::scopeFor(cssSheet)) {
    415             if (!m_scopeResolver)
    416                 m_scopeResolver = adoptPtr(new StyleScopeResolver());
    417             m_scopeResolver->ensureRuleSetFor(scope)->addRulesFromSheet(sheet, *m_medium, this, scope);
     415            ensureScopeResolver()->ensureRuleSetFor(scope)->addRulesFromSheet(sheet, *m_medium, this, scope);
    418416            continue;
    419417        }
     418#endif
    420419
    421420        m_authorStyle->addRulesFromSheet(sheet, *m_medium, this);
     
    711710{
    712711#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
    713     if (!m_scopeResolver || !m_scopeResolver->hasScopedStyles())
     712    if (!m_scopeResolver)
     713        return;
     714
     715    matchHostRules(result, includeEmptyRules);
     716
     717    if (!m_scopeResolver->hasScopedStyles())
    714718        return;
    715719
     
    737741    }
    738742
     743#else
     744    UNUSED_PARAM(result);
     745    UNUSED_PARAM(includeEmptyRules);
     746#endif
     747}
     748
     749inline bool StyleResolver::styleSharingCandidateMatchesHostRules()
     750{
     751#if ENABLE(SHADOW_DOM)
     752    return m_scopeResolver && m_scopeResolver->styleSharingCandidateMatchesHostRules(m_element);
     753#else
     754    return false;
     755#endif
     756}
     757
     758void StyleResolver::matchHostRules(MatchResult& result, bool includeEmptyRules)
     759{
     760#if ENABLE(SHADOW_DOM)
     761    ASSERT(m_scopeResolver);
     762
     763    Vector<RuleSet*> matchedRules;
     764    m_scopeResolver->matchHostRules(m_element, matchedRules);
     765    if (matchedRules.isEmpty())
     766        return;
     767
     768    MatchOptions options(includeEmptyRules);
     769    options.scope = m_element;
     770    for (unsigned i = matchedRules.size(); i > 0; --i)
     771        collectMatchingRules(matchedRules.at(i-1), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
    739772#else
    740773    UNUSED_PARAM(result);
     
    13321365    // Can't share if attribute rules apply.
    13331366    if (styleSharingCandidateMatchesRuleSet(m_uncommonAttributeRuleSet.get()))
     1367        return 0;
     1368    // Can't share if @host @-rules apply.
     1369    if (styleSharingCandidateMatchesHostRules())
    13341370        return 0;
    13351371    // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
  • trunk/Source/WebCore/css/StyleResolver.h

    r132009 r132303  
    3030#include "RenderStyle.h"
    3131#include "RuleFeature.h"
     32#include "RuntimeEnabledFeatures.h"
    3233#include "SelectorChecker.h"
    3334#include "StyleInheritedData.h"
     35#include "StyleScopeResolver.h"
    3436#include <wtf/HashMap.h>
    3537#include <wtf/HashSet.h>
     
    8183class StylePropertySet;
    8284class StyleRule;
     85class StyleRuleHost;
    8386class StyleRuleKeyframes;
    8487class StyleRulePage;
     
    138141    void pushParentShadowRoot(const ShadowRoot*);
    139142    void popParentShadowRoot(const ShadowRoot*);
     143#if ENABLE(SHADOW_DOM)
     144    void addHostRule(StyleRuleHost* rule, bool hasDocumentSecurityOrigin, const ContainerNode* scope) { ensureScopeResolver()->addHostRule(rule, hasDocumentSecurityOrigin, scope); }
     145#endif
    140146
    141147    PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, StyleSharingBehavior = AllowStyleSharing,
     
    167173
    168174private:
     175#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
     176    StyleScopeResolver* ensureScopeResolver()
     177    {
     178        ASSERT(RuntimeEnabledFeatures::shadowDOMEnabled() || RuntimeEnabledFeatures::styleScopedEnabled());
     179        if (!m_scopeResolver)
     180            m_scopeResolver = adoptPtr(new StyleScopeResolver());
     181        return m_scopeResolver.get();
     182    }
     183#endif
     184
    169185    void initForStyleResolve(Element*, RenderStyle* parentStyle = 0, PseudoId = NOPSEUDO);
    170186    void initElement(Element*);
     
    172188    RenderStyle* locateSharedStyle();
    173189    bool styleSharingCandidateMatchesRuleSet(RuleSet*);
     190    bool styleSharingCandidateMatchesHostRules();
    174191    Node* locateCousinList(Element* parent, unsigned& visitedNodeCount) const;
    175192    StyledElement* findSiblingForStyleSharing(Node*, unsigned& count) const;
     
    324341    void matchUserRules(MatchResult&, bool includeEmptyRules);
    325342    void matchScopedAuthorRules(MatchResult&, bool includeEmptyRules);
     343    void matchHostRules(MatchResult&, bool includeEmptyRules);
    326344    void collectMatchingRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions&);
    327345    void collectMatchingRulesForRegion(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions&);
  • trunk/Source/WebCore/css/StyleRule.cpp

    r129466 r132303  
    8080        static_cast<const StyleRuleKeyframes*>(this)->reportDescendantMemoryUsage(memoryObjectInfo);
    8181        return;
     82    case Host:
     83        static_cast<const StyleRuleBlock*>(this)->reportDescendantMemoryUsage(memoryObjectInfo);
     84        return;
    8285    case Unknown:
    8386    case Charset:
     
    117120    case Keyframes:
    118121        delete static_cast<StyleRuleKeyframes*>(this);
     122        return;
     123    case Host:
     124        delete static_cast<StyleRuleHost*>(this);
    119125        return;
    120126    case Unknown:
     
    151157    case Keyframes:
    152158        return static_cast<const StyleRuleKeyframes*>(this)->copy();
     159    case Host:
     160        return static_cast<const StyleRuleHost*>(this)->copy();
    153161    case Unknown:
    154162    case Charset:
     
    192200        rule = WebKitCSSKeyframesRule::create(static_cast<StyleRuleKeyframes*>(self), parentSheet);
    193201        break;
     202    case Host:
    194203    case Unknown:
    195204    case Charset:
  • trunk/Source/WebCore/css/StyleRule.h

    r128572 r132303  
    4747        Keyframes,
    4848        Keyframe, // Not used. These are internally non-rule StyleKeyframe objects.
     49        Host,
    4950        Region = 16
    5051    };
     
    5960    bool isRegionRule() const { return type() == Region; }
    6061    bool isImportRule() const { return type() == Import; }
     62    bool isHostRule() const { return type() == Host; }
    6163
    6264    PassRefPtr<StyleRuleBase> copy() const;
     
    224226};
    225227
     228class StyleRuleHost : public StyleRuleBlock {
     229public:
     230    static PassRefPtr<StyleRuleHost> create(Vector<RefPtr<StyleRuleBase> >& adoptRules)
     231    {
     232        return adoptRef(new StyleRuleHost(adoptRules));
     233    }
     234
     235    PassRefPtr<StyleRuleHost> copy() const { return adoptRef(new StyleRuleHost(*this)); }
     236
     237private:
     238    StyleRuleHost(Vector<RefPtr<StyleRuleBase> >& adoptRules) : StyleRuleBlock(Host, adoptRules) { }
     239    StyleRuleHost(const StyleRuleHost& o) : StyleRuleBlock(o) { }
     240};
     241
    226242} // namespace WebCore
    227243
  • trunk/Source/WebCore/css/StyleScopeResolver.cpp

    r130987 r132303  
    3030#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
    3131
     32#include "CSSStyleRule.h"
    3233#include "CSSStyleSheet.h"
    3334#include "ContextFeatures.h"
     35#include "ElementShadow.h"
    3436#include "HTMLNames.h"
    3537#include "HTMLStyleElement.h"
     
    155157}
    156158
     159inline RuleSet* StyleScopeResolver::ensureAtHostRuleSetFor(const ShadowRoot* shadowRoot)
     160{
     161    ScopedRuleSetMap::AddResult addResult = m_atHostRules.add(shadowRoot, nullptr);
     162    if (addResult.isNewEntry)
     163        addResult.iterator->value = RuleSet::create();
     164    return addResult.iterator->value.get();
     165}
     166
     167inline RuleSet* StyleScopeResolver::atHostRuleSetFor(const ShadowRoot* shadowRoot) const
     168{
     169    ScopedRuleSetMap::const_iterator it = m_atHostRules.find(shadowRoot);
     170    return it != m_atHostRules.end() ? it->value.get() : 0;
     171}
     172
     173void StyleScopeResolver::addHostRule(StyleRuleHost* hostRule, bool hasDocumentSecurityOrigin, const ContainerNode* scope)
     174{
     175    if (!scope || !scope->isInShadowTree())
     176        return;
     177
     178    ShadowRoot* shadowRoot = scope->shadowRoot();
     179    if (!shadowRoot || !shadowRoot->host())
     180        return;
     181
     182    RuleSet* rule = ensureAtHostRuleSetFor(shadowRoot);
     183
     184    const Vector<RefPtr<StyleRuleBase> >& childRules = hostRule->childRules();
     185    AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState;
     186    addRuleFlags = static_cast<AddRuleFlags>(addRuleFlags | RuleCanUseFastCheckSelector | RuleIsHostRule);
     187    for (unsigned i = 0; i < childRules.size(); ++i) {
     188        StyleRuleBase* hostStylingRule = childRules[i].get();
     189        if (hostStylingRule->isStyleRule())
     190            rule->addStyleRule(static_cast<StyleRule*>(hostStylingRule), addRuleFlags);
     191    }
     192}
     193
     194bool StyleScopeResolver::styleSharingCandidateMatchesHostRules(const Element* element)
     195{
     196    if (m_atHostRules.isEmpty())
     197        return false;
     198
     199    ElementShadow* shadow = element->shadow();
     200    if (!shadow)
     201        return false;
     202
     203    // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827
     204    // add a new flag to ElementShadow and cache whether any@host @-rules are
     205    // applied to the element or not. So we can avoid always traversing
     206    // shadow roots.
     207    for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) {
     208        if (atHostRuleSetFor(shadowRoot))
     209            return true;
     210
     211        if (!shadowRoot->hasShadowInsertionPoint())
     212            break;
     213    }
     214    return false;
     215}
     216
     217void StyleScopeResolver::matchHostRules(const Element* element, Vector<RuleSet*>& matchedRules)
     218{
     219    if (m_atHostRules.isEmpty())
     220        return;
     221
     222    ElementShadow* shadow = element->shadow();
     223    if (!shadow)
     224        return;
     225
     226    // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827
     227    // add a new flag to ElementShadow and cache whether any @host @-rules are
     228    // applied to the element or not. So we can quickly exit this method
     229    // by using the flag.
     230    for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) {
     231        if (RuleSet* ruleSet = atHostRuleSetFor(shadowRoot))
     232            matchedRules.append(ruleSet);
     233        if (!shadowRoot->hasShadowInsertionPoint())
     234            break;
     235    }
     236}
     237
    157238void StyleScopeResolver::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
    158239{
     
    160241    info.addMember(m_authorStyles);
    161242    info.addMember(m_stack);
     243    info.addMember(m_atHostRules);
    162244}
    163245
  • trunk/Source/WebCore/css/StyleScopeResolver.h

    r130987 r132303  
    3838class ContainerNode;
    3939class CSSStyleSheet;
     40class Element;
    4041class RuleSet;
    4142class RuleFeatureSet;
     43class ShadowRoot;
     44class StyleRuleHost;
    4245
    4346#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
     
    7376    void collectFeaturesTo(RuleFeatureSet&);
    7477
     78    void addHostRule(StyleRuleHost*, bool hasDocumentSecurityOrigin, const ContainerNode* scope);
     79    bool styleSharingCandidateMatchesHostRules(const Element*);
     80    void matchHostRules(const Element*, Vector<RuleSet*>& matchedRules);
     81
    7582    void reportMemoryUsage(MemoryObjectInfo*) const;
    7683
     
    7986    void setupStack(const ContainerNode*);
    8087    bool stackIsConsistent(const ContainerNode* parent) const { return parent && parent == m_stackParent; }
     88    RuleSet* ensureAtHostRuleSetFor(const ShadowRoot*);
     89    RuleSet* atHostRuleSetFor(const ShadowRoot*) const;
    8190
    8291    ScopedRuleSetMap m_authorStyles;
     
    8998    const ContainerNode* m_stackParent;
    9099    int m_stackParentBoundsIndex;
     100
     101    ScopedRuleSetMap m_atHostRules;
    91102};
    92103
  • trunk/Source/WebCore/css/StyleSheetContents.cpp

    r130612 r132303  
    436436                return true;
    437437            break;
     438        case StyleRuleBase::Host:
     439            if (childRulesHaveFailedOrCanceledSubresources(static_cast<const StyleRuleHost*>(rule)->childRules()))
     440                return true;
     441            break;
    438442        case StyleRuleBase::Import:
    439443            ASSERT_NOT_REACHED();
Note: See TracChangeset for help on using the changeset viewer.