Changeset 142855 in webkit


Ignore:
Timestamp:
Feb 13, 2013 11:51:43 PM (11 years ago)
Author:
hayato@chromium.org
Message:

[Shadow DOM] Implements a '::distributed()' pseudo element.
https://bugs.webkit.org/show_bug.cgi?id=82169

Reviewed by Dimitri Glazkov.

Source/WebCore:

Implements a '::distributed()' pseudo element.
See the Shadow DOM specification and the filed bug for the detail.

For example, suppose we are given the following DOM tree and shadow tree:

  • <A>
    • <B>
      • <C>

[A's ShadowRoot]

<D>

  • <style>

E content::distributed(B C) { color: green; }

  • <E>
    • <content> (Node B is distributed to this insertion point.)

In this case, the style rule defined in the shadow tree matches node 'C'.

A '::distributed()' pseudo element can not be a pseudo class since
an intersection between matched_elements(some_selector) and
matched_elements(some_selector::distributed(...)) is always an
empty set. A '::distributed()' pseudo element is the first-ever
*functional* pseudo element which takes a parameter, which can be
a selector.

This rule crosses the shadow boundary from a shadow tree to the
tree of its shadow host. That means a rule which includes
'::distributed()' pseudo element is defined in shadow tree, but
the node which is matched in the rule, the subject of the
selector, is outside of the shadow tree. Therefore, we cannot
predict where the subject of the selector will be beforehand.
Current CSS implementation assumes the subject of the selector
must exist in the current scope.

To overcome this issue, DocumentRuleSets now has a instance of
ShadowDistributedRules class. A style rule will be stored in this
instance if the rule includes a '::distributed()' pseudo element.
This class also keeps track of each RuleSet by mapping it with a
scope where the rule was originally defined. In the example, the
scope is A's ShadowRoot. The scope is used to check whether the
left-most matched element (in the example, it's a node 'E') exists
in the scope.

Internally, a '::distributed' pseudo element is represented by a
newly introduced 'ShadowDistributed' relation. That makes an
implementation of SelectorChecker::checkSelector() much simpler.
A transformation from a distributed pseudo element to a
ShadowDistributed is done in parsing stage of CSS.

Since '::distributed()' is an experimental feature, it's actually
prefixed with '-webkit-' and guarded by SHADOW_DOM flag.

Tests: fast/dom/shadow/distributed-pseudo-element-for-shadow-element.html

fast/dom/shadow/distributed-pseudo-element-match-all.html
fast/dom/shadow/distributed-pseudo-element-match-descendant.html
fast/dom/shadow/distributed-pseudo-element-nested.html
fast/dom/shadow/distributed-pseudo-element-no-match.html
fast/dom/shadow/distributed-pseudo-element-reprojection.html
fast/dom/shadow/distributed-pseudo-element-scoped.html
fast/dom/shadow/distributed-pseudo-element-support-selector.html
fast/dom/shadow/distributed-pseudo-element-used-in-selector-list.html
fast/dom/shadow/distributed-pseudo-element-with-any.html
fast/dom/shadow/distributed-pseudo-element.html

  • css/CSSGrammar.y.in:

CSS Grammar was updated to support '::distrbuted(selector)'.
This pseudo element is the first pseudo element which can take a selector as a parameter.

  • css/CSSParser.cpp:

(WebCore::CSSParser::detectDashToken):
(WebCore::CSSParser::rewriteSpecifiersWithNamespaceIfNeeded):
(WebCore::CSSParser::rewriteSpecifiersWithElementName):
Here we are converting a '::distributed' pseudo element into a
ShadowDistributed relation internally. To support the conversion,
these rewriteSpecifiersXXX functions (formally called
updateSpecifiersXXX) now return the specifiers which may be
converted.
(WebCore::CSSParser::rewriteSpecifiers):

  • css/CSSParser.h:
  • css/CSSParserValues.cpp:

(WebCore::CSSParserSelector::CSSParserSelector):

  • css/CSSParserValues.h:

(CSSParserSelector):
(WebCore::CSSParserSelector::functionArgumentSelector):
To hold an intermediate selector which appears at the position of an argument in
functional pseudo element when parsing CSS.
(WebCore::CSSParserSelector::setFunctionArgumentSelector):
(WebCore::CSSParserSelector::isDistributedPseudoElement):

  • css/CSSSelector.cpp:

Add new pseudo element, PseudoDistributed, and its internal representation, ShadowDistributed relation.
(WebCore::CSSSelector::pseudoId):
(WebCore::nameToPseudoTypeMap):
(WebCore::CSSSelector::extractPseudoType):
(WebCore::CSSSelector::selectorText):

  • css/CSSSelector.h:

(CSSSelector):
(WebCore):
(WebCore::CSSSelector::isDistributedPseudoElement):
(WebCore::CSSSelector::isShadowDistributed):

  • css/CSSSelectorList.cpp:

(WebCore):
(SelectorHasShadowDistributed):
(WebCore::SelectorHasShadowDistributed::operator()):
(WebCore::CSSSelectorList::hasShadowDistributedAt):

  • css/CSSSelectorList.h:

(CSSSelectorList):

  • css/DocumentRuleSets.cpp:

(WebCore):
(WebCore::ShadowDistributedRules::addRule):
Every CSS rule which includes '::distributed(...)' should be managed by calling this function.
(WebCore::ShadowDistributedRules::collectMatchRequests):
(WebCore::DocumentRuleSets::resetAuthorStyle):

  • css/DocumentRuleSets.h:

(WebCore):
(ShadowDistributedRules):
(WebCore::ShadowDistributedRules::clear):
(DocumentRuleSets):
(WebCore::DocumentRuleSets::shadowDistributedRules)
DocumentRuleSets owns an instance of ShadowDistributedRules.

  • css/RuleSet.cpp:

(WebCore::RuleSet::addChildRules):
Updated to check whether the rule contains '::distributed()' or not.

  • css/SelectorChecker.cpp:

(WebCore::SelectorChecker::match):
Support ShadowDistributed relation. Check all possible insertion points where a node is distributed.

  • css/SelectorChecker.h:

(WebCore::SelectorChecker::SelectorCheckingContext::SelectorCheckingContext):
Adds enum of BehaviorAtBoundary. '::distributed()' is the only
rule which uses 'CrossedBoundary' since it is the only rule which
crosses shadow boundaries.
(SelectorCheckingContext):

  • css/SelectorFilter.cpp:

(WebCore::SelectorFilter::collectIdentifierHashes):

  • css/StyleResolver.cpp:

(WebCore::StyleResolver::collectMatchingRules):
(WebCore::StyleResolver::matchAuthorRules):
(WebCore::StyleResolver::collectMatchingRulesForList):
(WebCore::StyleResolver::ruleMatches):

  • css/StyleResolver.h:

(MatchRequest):
(WebCore::MatchRequest::MatchRequest): Add behaviorAtBoundary field.
(WebCore):
(StyleResolver):

  • html/shadow/InsertionPoint.cpp:

(WebCore::collectInsertionPointsWhereNodeIsDistributed):
(WebCore):

  • html/shadow/InsertionPoint.h:

(WebCore):

LayoutTests:

  • fast/dom/shadow/distributed-pseudo-element-expected.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-for-shadow-element-expected.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-for-shadow-element.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-match-all-expected.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-match-all.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-match-descendant-expected.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-match-descendant.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-nested-expected.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-nested.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-no-match-expected.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-no-match.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-reprojection-expected.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-reprojection.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-scoped-expected.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-scoped.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-support-selector-expected.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-support-selector.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-used-in-selector-list-expected.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-used-in-selector-list.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-with-any-expected.html: Added.
  • fast/dom/shadow/distributed-pseudo-element-with-any.html: Added.
  • fast/dom/shadow/distributed-pseudo-element.html: Added.
Location:
trunk
Files:
22 added
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r142854 r142855  
     12013-02-13  Hayato Ito  <hayato@chromium.org>
     2
     3        [Shadow DOM] Implements a '::distributed()' pseudo element.
     4        https://bugs.webkit.org/show_bug.cgi?id=82169
     5
     6        Reviewed by Dimitri Glazkov.
     7
     8        * fast/dom/shadow/distributed-pseudo-element-expected.html: Added.
     9        * fast/dom/shadow/distributed-pseudo-element-for-shadow-element-expected.html: Added.
     10        * fast/dom/shadow/distributed-pseudo-element-for-shadow-element.html: Added.
     11        * fast/dom/shadow/distributed-pseudo-element-match-all-expected.html: Added.
     12        * fast/dom/shadow/distributed-pseudo-element-match-all.html: Added.
     13        * fast/dom/shadow/distributed-pseudo-element-match-descendant-expected.html: Added.
     14        * fast/dom/shadow/distributed-pseudo-element-match-descendant.html: Added.
     15        * fast/dom/shadow/distributed-pseudo-element-nested-expected.html: Added.
     16        * fast/dom/shadow/distributed-pseudo-element-nested.html: Added.
     17        * fast/dom/shadow/distributed-pseudo-element-no-match-expected.html: Added.
     18        * fast/dom/shadow/distributed-pseudo-element-no-match.html: Added.
     19        * fast/dom/shadow/distributed-pseudo-element-reprojection-expected.html: Added.
     20        * fast/dom/shadow/distributed-pseudo-element-reprojection.html: Added.
     21        * fast/dom/shadow/distributed-pseudo-element-scoped-expected.html: Added.
     22        * fast/dom/shadow/distributed-pseudo-element-scoped.html: Added.
     23        * fast/dom/shadow/distributed-pseudo-element-support-selector-expected.html: Added.
     24        * fast/dom/shadow/distributed-pseudo-element-support-selector.html: Added.
     25        * fast/dom/shadow/distributed-pseudo-element-used-in-selector-list-expected.html: Added.
     26        * fast/dom/shadow/distributed-pseudo-element-used-in-selector-list.html: Added.
     27        * fast/dom/shadow/distributed-pseudo-element-with-any-expected.html: Added.
     28        * fast/dom/shadow/distributed-pseudo-element-with-any.html: Added.
     29        * fast/dom/shadow/distributed-pseudo-element.html: Added.
     30
    1312013-02-06  Gregg Tavares  <gman@chromium.org>
    232
  • trunk/Source/WebCore/ChangeLog

    r142849 r142855  
     12013-02-13  Hayato Ito  <hayato@chromium.org>
     2
     3        [Shadow DOM] Implements a '::distributed()' pseudo element.
     4        https://bugs.webkit.org/show_bug.cgi?id=82169
     5
     6        Reviewed by Dimitri Glazkov.
     7
     8        Implements a '::distributed()' pseudo element.
     9        See the Shadow DOM specification and the filed bug for the detail.
     10
     11        - http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#selecting-nodes-distributed-to-insertion-points
     12        - https://www.w3.org/Bugs/Public/show_bug.cgi?id=19684
     13
     14        For example, suppose we are given the following DOM tree and shadow tree:
     15
     16        - <A>
     17          - <B>
     18            - <C>
     19
     20        [A's ShadowRoot]
     21          <D>
     22          - <style>
     23              E content::distributed(B C) { color: green; }
     24          - <E>
     25            - <content>  (Node B is distributed to this insertion point.)
     26
     27        In this case, the style rule defined in the shadow tree matches node 'C'.
     28
     29        A '::distributed()' pseudo element can not be a pseudo class since
     30        an intersection between matched_elements(some_selector) and
     31        matched_elements(some_selector::distributed(...)) is always an
     32        empty set. A '::distributed()' pseudo element is the first-ever
     33        *functional* pseudo element which takes a parameter, which can be
     34        a selector.
     35
     36        This rule crosses the shadow boundary from a shadow tree to the
     37        tree of its shadow host. That means a rule which includes
     38        '::distributed()' pseudo element is defined in shadow tree, but
     39        the node which is matched in the rule, the subject of the
     40        selector, is outside of the shadow tree. Therefore, we cannot
     41        predict where the subject of the selector will be beforehand.
     42        Current CSS implementation assumes the subject of the selector
     43        must exist in the current scope.
     44
     45        To overcome this issue, DocumentRuleSets now has a instance of
     46        ShadowDistributedRules class.  A style rule will be stored in this
     47        instance if the rule includes a '::distributed()' pseudo element.
     48        This class also keeps track of each RuleSet by mapping it with a
     49        scope where the rule was originally defined. In the example, the
     50        scope is A's ShadowRoot.  The scope is used to check whether the
     51        left-most matched element (in the example, it's a node 'E') exists
     52        in the scope.
     53
     54        Internally, a '::distributed' pseudo element is represented by a
     55        newly introduced 'ShadowDistributed' relation.  That makes an
     56        implementation of SelectorChecker::checkSelector() much simpler.
     57        A transformation from a distributed pseudo element to a
     58        ShadowDistributed is done in parsing stage of CSS.
     59
     60        Since '::distributed()' is an experimental feature, it's actually
     61        prefixed with '-webkit-' and guarded by SHADOW_DOM flag.
     62
     63        Tests: fast/dom/shadow/distributed-pseudo-element-for-shadow-element.html
     64               fast/dom/shadow/distributed-pseudo-element-match-all.html
     65               fast/dom/shadow/distributed-pseudo-element-match-descendant.html
     66               fast/dom/shadow/distributed-pseudo-element-nested.html
     67               fast/dom/shadow/distributed-pseudo-element-no-match.html
     68               fast/dom/shadow/distributed-pseudo-element-reprojection.html
     69               fast/dom/shadow/distributed-pseudo-element-scoped.html
     70               fast/dom/shadow/distributed-pseudo-element-support-selector.html
     71               fast/dom/shadow/distributed-pseudo-element-used-in-selector-list.html
     72               fast/dom/shadow/distributed-pseudo-element-with-any.html
     73               fast/dom/shadow/distributed-pseudo-element.html
     74
     75        * css/CSSGrammar.y.in:
     76        CSS Grammar was updated to support '::distrbuted(selector)'.
     77        This pseudo element is the first pseudo element which can take a selector as a parameter.
     78        * css/CSSParser.cpp:
     79        (WebCore::CSSParser::detectDashToken):
     80        (WebCore::CSSParser::rewriteSpecifiersWithNamespaceIfNeeded):
     81        (WebCore::CSSParser::rewriteSpecifiersWithElementName):
     82        Here we are converting a '::distributed' pseudo element into a
     83        ShadowDistributed relation internally.  To support the conversion,
     84        these rewriteSpecifiersXXX functions (formally called
     85        updateSpecifiersXXX) now return the specifiers which may be
     86        converted.
     87        (WebCore::CSSParser::rewriteSpecifiers):
     88        * css/CSSParser.h:
     89        * css/CSSParserValues.cpp:
     90        (WebCore::CSSParserSelector::CSSParserSelector):
     91        * css/CSSParserValues.h:
     92        (CSSParserSelector):
     93        (WebCore::CSSParserSelector::functionArgumentSelector):
     94        To hold an intermediate selector which appears at the position of an argument in
     95        functional pseudo element when parsing CSS.
     96        (WebCore::CSSParserSelector::setFunctionArgumentSelector):
     97        (WebCore::CSSParserSelector::isDistributedPseudoElement):
     98        * css/CSSSelector.cpp:
     99        Add new pseudo element, PseudoDistributed, and its internal representation, ShadowDistributed relation.
     100        (WebCore::CSSSelector::pseudoId):
     101        (WebCore::nameToPseudoTypeMap):
     102        (WebCore::CSSSelector::extractPseudoType):
     103        (WebCore::CSSSelector::selectorText):
     104        * css/CSSSelector.h:
     105        (CSSSelector):
     106        (WebCore):
     107        (WebCore::CSSSelector::isDistributedPseudoElement):
     108        (WebCore::CSSSelector::isShadowDistributed):
     109        * css/CSSSelectorList.cpp:
     110        (WebCore):
     111        (SelectorHasShadowDistributed):
     112        (WebCore::SelectorHasShadowDistributed::operator()):
     113        (WebCore::CSSSelectorList::hasShadowDistributedAt):
     114        * css/CSSSelectorList.h:
     115        (CSSSelectorList):
     116        * css/DocumentRuleSets.cpp:
     117        (WebCore):
     118        (WebCore::ShadowDistributedRules::addRule):
     119        Every CSS rule which includes '::distributed(...)' should be managed by calling this function.
     120        (WebCore::ShadowDistributedRules::collectMatchRequests):
     121        (WebCore::DocumentRuleSets::resetAuthorStyle):
     122        * css/DocumentRuleSets.h:
     123        (WebCore):
     124        (ShadowDistributedRules):
     125        (WebCore::ShadowDistributedRules::clear):
     126        (DocumentRuleSets):
     127        (WebCore::DocumentRuleSets::shadowDistributedRules)
     128        DocumentRuleSets owns an instance of ShadowDistributedRules.
     129        * css/RuleSet.cpp:
     130        (WebCore::RuleSet::addChildRules):
     131        Updated to check whether the rule contains '::distributed()' or not.
     132        * css/SelectorChecker.cpp:
     133        (WebCore::SelectorChecker::match):
     134        Support ShadowDistributed relation. Check all possible insertion points where a node is distributed.
     135        * css/SelectorChecker.h:
     136        (WebCore::SelectorChecker::SelectorCheckingContext::SelectorCheckingContext):
     137        Adds enum of BehaviorAtBoundary. '::distributed()' is the only
     138        rule which uses 'CrossedBoundary' since it is the only rule which
     139        crosses shadow boundaries.
     140        (SelectorCheckingContext):
     141        * css/SelectorFilter.cpp:
     142        (WebCore::SelectorFilter::collectIdentifierHashes):
     143        * css/StyleResolver.cpp:
     144        (WebCore::StyleResolver::collectMatchingRules):
     145        (WebCore::StyleResolver::matchAuthorRules):
     146        (WebCore::StyleResolver::collectMatchingRulesForList):
     147        (WebCore::StyleResolver::ruleMatches):
     148        * css/StyleResolver.h:
     149        (MatchRequest):
     150        (WebCore::MatchRequest::MatchRequest): Add behaviorAtBoundary field.
     151        (WebCore):
     152        (StyleResolver):
     153        * html/shadow/InsertionPoint.cpp:
     154        (WebCore::collectInsertionPointsWhereNodeIsDistributed):
     155        (WebCore):
     156        * html/shadow/InsertionPoint.h:
     157        (WebCore):
     158
    11592013-02-13  Kentaro Hara  <haraken@chromium.org>
    2160
  • trunk/Source/WebCore/css/CSSGrammar.y.in

    r142739 r142855  
    6262%}
    6363
     64#if ENABLE_SHADOW_DOM
     65%expect 67
     66#else
    6467%expect 66
     68#endif
    6569
    6670%nonassoc LOWEST_PREC
     
    185189#endif
    186190%token <string> NOTFUNCTION
     191%token <string> DISTRIBUTEDFUNCTION
    187192%token <string> CALCFUNCTION
    188193%token <string> MINFUNCTION
     
    12041209        $$ = $2;
    12051210        if ($$)
    1206             parser->updateSpecifiersWithElementName(nullAtom, $1, $$);
     1211            $$ = parser->rewriteSpecifiersWithElementName(nullAtom, $1, $$);
    12071212    }
    12081213    | specifier_list {
    12091214        $$ = $1;
    12101215        if ($$)
    1211             parser->updateSpecifiersWithNamespaceIfNeeded($$);
     1216            $$ = parser->rewriteSpecifiersWithNamespaceIfNeeded($$);
    12121217    }
    12131218    | namespace_selector element_name {
     
    12171222        $$ = $3;
    12181223        if ($$)
    1219             parser->updateSpecifiersWithElementName($1, $2, $$);
     1224            $$ = parser->rewriteSpecifiersWithElementName($1, $2, $$);
    12201225    }
    12211226    | namespace_selector specifier_list {
    12221227        $$ = $2;
    12231228        if ($$)
    1224             parser->updateSpecifiersWithElementName($1, starAtom, $$);
     1229            $$ = parser->rewriteSpecifiersWithElementName($1, starAtom, $$);
    12251230    }
    12261231  ;
     
    12671272            $$ = 0;
    12681273        else if ($1)
    1269             $$ = parser->updateSpecifiers($1, $2);
     1274            $$ = parser->rewriteSpecifiers($1, $2);
    12701275    }
    12711276    | specifier_list error {
     
    14121417        } else
    14131418            $$ = 0;
     1419    }
     1420#endif
     1421#if ENABLE_SHADOW_DOM
     1422    | ':' ':' DISTRIBUTEDFUNCTION maybe_space selector maybe_space ')' {
     1423        if (!$5)
     1424            $$ = 0;
     1425        else {
     1426            $$ = parser->createFloatingSelector();
     1427            $$->setMatch(CSSSelector::PseudoElement);
     1428            $$->setFunctionArgumentSelector($5);
     1429            $3.lower();
     1430            $$->setValue($3);
     1431        }
    14141432    }
    14151433#endif
  • trunk/Source/WebCore/css/CSSParser.cpp

    r142739 r142855  
    1004410044    } else if (length == 12 && isEqualToCSSIdentifier(name + 1, "webkit-calc"))
    1004510045        m_token = CALCFUNCTION;
     10046#if ENABLE(SHADOW_DOM)
     10047    else if (length == 19 && isEqualToCSSIdentifier(name + 1, "webkit-distributed"))
     10048        m_token = DISTRIBUTEDFUNCTION;
     10049#endif
    1004610050}
    1004710051
     
    1107511079}
    1107611080
    11077 void CSSParser::updateSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers)
     11081CSSParserSelector* CSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers)
    1107811082{
    1107911083    if (m_defaultNamespace != starAtom || specifiers->isCustomPseudoElement())
    11080         updateSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true);
    11081 }
    11082 
    11083 void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
     11084        return rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true);
     11085    return specifiers;
     11086}
     11087
     11088CSSParserSelector* CSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
    1108411089{
    1108511090    AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
    1108611091    QualifiedName tag(namespacePrefix, elementName, determinedNamespace);
    1108711092
     11093#if ENABLE(SHADOW_DOM)
     11094    if (specifiers->isDistributedPseudoElement()) {
     11095        CSSParserSelector* argumentSelector = specifiers->functionArgumentSelector();
     11096        ASSERT(argumentSelector);
     11097        CSSParserSelector* end = argumentSelector;
     11098        while (end->tagHistory())
     11099            end = end->tagHistory();
     11100        OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
     11101        end->setTagHistory(elementNameSelector.release());
     11102        end->setRelation(CSSSelector::ShadowDistributed);
     11103        return argumentSelector;
     11104    }
     11105#endif
     11106
    1108811107    if (!specifiers->isCustomPseudoElement()) {
    1108911108        if (tag == anyQName())
    11090             return;
     11109            return specifiers;
    1109111110#if ENABLE(VIDEO_TRACK)
    1109211111        if (!(specifiers->pseudoType() == CSSSelector::PseudoCue))
    1109311112#endif
    1109411113            specifiers->prependTagSelector(tag, tagIsForNamespaceRule);
    11095         return;
     11114        return specifiers;
    1109611115    }
    1109711116
     
    1110711126        if (tag != anyQName())
    1110811127            lastShadowDescendant->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
    11109         return;
     11128        return specifiers;
    1111011129    }
    1111111130
     
    1111511134    lastShadowDescendant->setTagHistory(elementNameSelector.release());
    1111611135    lastShadowDescendant->setRelation(CSSSelector::ShadowDescendant);
    11117 }
    11118 
    11119 CSSParserSelector* CSSParser::updateSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
     11136    return specifiers;
     11137}
     11138
     11139CSSParserSelector* CSSParser::rewriteSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
    1112011140{
    1112111141#if ENABLE(VIDEO_TRACK)
  • trunk/Source/WebCore/css/CSSParser.h

    r142739 r142855  
    329329    void addNamespace(const AtomicString& prefix, const AtomicString& uri);
    330330    QualifiedName determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName);
    331     void updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector*, bool isNamespacePlaceholder = false);
    332     void updateSpecifiersWithNamespaceIfNeeded(CSSParserSelector*);
    333     CSSParserSelector* updateSpecifiers(CSSParserSelector*, CSSParserSelector*);
     331
     332    CSSParserSelector* rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector*, bool isNamespacePlaceholder = false);
     333    CSSParserSelector* rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector*);
     334    CSSParserSelector* rewriteSpecifiers(CSSParserSelector*, CSSParserSelector*);
    334335
    335336    void invalidBlockHit();
  • trunk/Source/WebCore/css/CSSParserValues.cpp

    r142021 r142855  
    148148CSSParserSelector::CSSParserSelector()
    149149    : m_selector(adoptPtr(fastNew<CSSSelector>()))
     150#if ENABLE(SHADOW_DOM)
     151    , m_functionArgumentSelector(0)
     152#endif
    150153{
    151154}
  • trunk/Source/WebCore/css/CSSParserValues.h

    r141816 r142855  
    187187    void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector);
    188188
     189#if ENABLE(SHADOW_DOM)
     190    CSSParserSelector* functionArgumentSelector() const { return m_functionArgumentSelector; }
     191    void setFunctionArgumentSelector(CSSParserSelector* selector) { m_functionArgumentSelector = selector; }
     192    bool isDistributedPseudoElement() const { return m_selector->isDistributedPseudoElement(); }
     193#endif
     194
    189195    CSSSelector::PseudoType pseudoType() const { return m_selector->pseudoType(); }
    190196    bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); }
     
    202208    OwnPtr<CSSSelector> m_selector;
    203209    OwnPtr<CSSParserSelector> m_tagHistory;
     210#if ENABLE(SHADOW_DOM)
     211    CSSParserSelector* m_functionArgumentSelector;
     212#endif
    204213};
    205214
  • trunk/Source/WebCore/css/CSSSelector.cpp

    r140707 r142855  
    243243#if ENABLE(IFRAME_SEAMLESS)
    244244    case PseudoSeamlessDocument:
     245#endif
     246#if ENABLE(SHADOW_DOM)
     247    case PseudoDistributed:
    245248#endif
    246249        return NOPSEUDO;
     
    333336#if ENABLE(IFRAME_SEAMLESS)
    334337    DEFINE_STATIC_LOCAL(AtomicString, seamlessDocument, ("-webkit-seamless-document", AtomicString::ConstructFromLiteral));
     338#endif
     339#if ENABLE(SHADOW_DOM)
     340    DEFINE_STATIC_LOCAL(AtomicString, distributed, ("-webkit-distributed(", AtomicString::ConstructFromLiteral));
    335341#endif
    336342    DEFINE_STATIC_LOCAL(AtomicString, inRange, ("in-range", AtomicString::ConstructFromLiteral));
     
    417423        nameToPseudoType->set(seamlessDocument.impl(), CSSSelector::PseudoSeamlessDocument);
    418424#endif
     425#if ENABLE(SHADOW_DOM)
     426        nameToPseudoType->set(distributed.impl(), CSSSelector::PseudoDistributed);
     427#endif
    419428        nameToPseudoType->set(inRange.impl(), CSSSelector::PseudoInRange);
    420429        nameToPseudoType->set(outOfRange.impl(), CSSSelector::PseudoOutOfRange);
     
    467476    case PseudoFirstLine:
    468477        compat = true;
     478#if ENABLE(SHADOW_DOM)
     479    case PseudoDistributed:
     480#endif
    469481    case PseudoResizer:
    470482    case PseudoScrollbar:
     
    708720        case CSSSelector::ShadowDescendant:
    709721            return tagHistoryText + str.toString();
     722#if ENABLE(SHADOW_DOM)
     723        case CSSSelector::ShadowDistributed:
     724            return tagHistoryText + "::-webkit-distributed(" + str.toString() + ")";
     725#endif
    710726        }
    711727    }
  • trunk/Source/WebCore/css/CSSSelector.h

    r140707 r142855  
    7878            IndirectAdjacent,
    7979            SubSelector,
    80             ShadowDescendant
     80            ShadowDescendant,
     81#if ENABLE(SHADOW_DOM)
     82            ShadowDistributed
     83#endif
    8184        };
    8285
     
    164167#endif
    165168#if ENABLE(IFRAME_SEAMLESS)
    166             PseudoSeamlessDocument
     169            PseudoSeamlessDocument,
     170#endif
     171#if ENABLE(SHADOW_DOM)
     172            PseudoDistributed
    167173#endif
    168174        };
     
    221227        bool isSiblingSelector() const;
    222228        bool isAttributeSelector() const;
     229#if ENABLE(SHADOW_DOM)
     230        bool isDistributedPseudoElement() const;
     231        bool isShadowDistributed() const;
     232#endif
    223233
    224234        Relation relation() const { return static_cast<Relation>(m_relation); }
     
    333343}
    334344
     345#if ENABLE(SHADOW_DOM)
     346inline bool CSSSelector::isDistributedPseudoElement() const
     347{
     348    return m_match == PseudoElement && pseudoType() == PseudoDistributed;
     349}
     350
     351inline bool CSSSelector::isShadowDistributed() const
     352{
     353    return m_relation == CSSSelector::ShadowDistributed;
     354}
     355#endif
     356
    335357inline void CSSSelector::setValue(const AtomicString& value)
    336358{
  • trunk/Source/WebCore/css/CSSSelectorList.cpp

    r141570 r142855  
    212212}
    213213
    214 
     214#if ENABLE(SHADOW_DOM)
     215class SelectorHasShadowDistributed {
     216public:
     217    bool operator()(const CSSSelector* selector)
     218    {
     219        return selector->isShadowDistributed();
     220    }
     221};
     222
     223bool CSSSelectorList::hasShadowDistributedAt(size_t index) const
     224{
     225    SelectorHasShadowDistributed functor;
     226    return forEachTagSelector(functor, selectorAt(index));
     227}
     228#endif
    215229
    216230} // namespace WebCore
  • trunk/Source/WebCore/css/CSSSelectorList.h

    r140677 r142855  
    6262    bool hasInvalidSelector() const;
    6363
     64#if ENABLE(SHADOW_DOM)
     65    bool hasShadowDistributedAt(size_t index) const;
     66#endif
     67
    6468    String selectorsText() const;
    6569
  • trunk/Source/WebCore/css/DocumentRuleSets.cpp

    r142573 r142855  
    3838
    3939namespace WebCore {
     40
     41#if ENABLE(SHADOW_DOM)
     42void ShadowDistributedRules::addRule(StyleRule* rule, size_t selectorIndex, ContainerNode* scope, AddRuleFlags addRuleFlags)
     43{
     44    if (m_shadowDistributedRuleSetMap.contains(scope))
     45        m_shadowDistributedRuleSetMap.get(scope)->addRule(rule, selectorIndex, addRuleFlags);
     46    else {
     47        OwnPtr<RuleSet> ruleSetForScope = adoptPtr(new RuleSet());
     48        ruleSetForScope->addRule(rule, selectorIndex, addRuleFlags);
     49        m_shadowDistributedRuleSetMap.add(scope, ruleSetForScope.release());
     50    }
     51}
     52
     53void ShadowDistributedRules::collectMatchRequests(bool includeEmptyRules, Vector<MatchRequest>& matchRequests)
     54{
     55    for (ShadowDistributedRuleSetMap::iterator it = m_shadowDistributedRuleSetMap.begin(); it != m_shadowDistributedRuleSetMap.end(); ++it)
     56        matchRequests.append(MatchRequest(it->value.get(), includeEmptyRules, it->key, SelectorChecker::CrossesBoundary));
     57}
     58#endif
    4059
    4160DocumentRuleSets::DocumentRuleSets()
     
    82101    m_authorStyle = RuleSet::create();
    83102    m_authorStyle->disableAutoShrinkToFit();
     103#if ENABLE(SHADOW_DOM)
     104    m_shadowDistributedRules.clear();
     105#endif
    84106}
    85107
  • trunk/Source/WebCore/css/DocumentRuleSets.h

    r142573 r142855  
    2525
    2626#include "RuleFeature.h"
     27#include "RuleSet.h"
    2728
    2829#include <wtf/OwnPtr.h>
     
    3637class DocumentStyleSheetCollection;
    3738class InspectorCSSOMWrappers;
     39class MatchRequest;
    3840class MediaQueryEvaluator;
    3941class RuleSet;
    40 class StyleResolver;
    4142class StyleScopeResolver;
     43
     44#if ENABLE(SHADOW_DOM)
     45class ShadowDistributedRules {
     46public:
     47    void addRule(StyleRule*, size_t selectorIndex, ContainerNode* scope, AddRuleFlags);
     48    void collectMatchRequests(bool includeEmptyRules, Vector<MatchRequest>&);
     49    void clear() { m_shadowDistributedRuleSetMap.clear(); }
     50private:
     51    typedef HashMap<const ContainerNode*, OwnPtr<RuleSet> > ShadowDistributedRuleSetMap;
     52    ShadowDistributedRuleSetMap m_shadowDistributedRuleSetMap;
     53};
     54#endif
    4255
    4356class DocumentRuleSets {
     
    5871    void collectFeatures(bool isViewSource, StyleScopeResolver*);
    5972    void reportMemoryUsage(MemoryObjectInfo*) const;
     73#if ENABLE(SHADOW_DOM)
     74    ShadowDistributedRules& shadowDistributedRules() { return m_shadowDistributedRules; }
     75#endif
    6076
    6177private:
     
    6682    OwnPtr<RuleSet> m_siblingRuleSet;
    6783    OwnPtr<RuleSet> m_uncommonAttributeRuleSet;
     84#if ENABLE(SHADOW_DOM)
     85    ShadowDistributedRules m_shadowDistributedRules;
     86#endif
    6887};
    6988
  • trunk/Source/WebCore/css/RuleSet.cpp

    r141806 r142855  
    308308        StyleRuleBase* rule = rules[i].get();
    309309
    310         if (rule->isStyleRule())
    311             addStyleRule(static_cast<StyleRule*>(rule), addRuleFlags);
    312         else if (rule->isPageRule())
     310        if (rule->isStyleRule()) {
     311            StyleRule* styleRule = static_cast<StyleRule*>(rule);
     312#if ENABLE(SHADOW_DOM)
     313            if (!scope)
     314                addStyleRule(styleRule, addRuleFlags);
     315            else {
     316                const CSSSelectorList& selectorList = styleRule->selectorList();
     317                for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = selectorList.indexOfNextSelectorAfter(selectorIndex)) {
     318                    if (selectorList.hasShadowDistributedAt(selectorIndex))
     319                        resolver->ruleSets().shadowDistributedRules().addRule(styleRule, selectorIndex, const_cast<ContainerNode*>(scope), addRuleFlags);
     320                    else
     321                        addRule(styleRule, selectorIndex, addRuleFlags);
     322                }
     323            }
     324#else
     325            addStyleRule(styleRule, addRuleFlags);
     326#endif
     327
     328        } else if (rule->isPageRule())
    313329            addPageRule(static_cast<StyleRulePage*>(rule));
    314330        else if (rule->isMediaRule()) {
  • trunk/Source/WebCore/css/SelectorChecker.cpp

    r142717 r142855  
    4242#include "HTMLProgressElement.h"
    4343#include "HTMLStyleElement.h"
     44#include "InsertionPoint.h"
    4445#include "InspectorInstrumentation.h"
    4546#include "NodeRenderStyle.h"
     
    282283    // Prepare next selector
    283284    const CSSSelector* historySelector = context.selector->tagHistory();
    284     if (!historySelector)
     285    if (!historySelector) {
     286        if (context.behaviorAtBoundary == CrossesBoundary) {
     287            ASSERT(context.scope);
     288            return context.scope->contains(context.element) ? SelectorMatches : SelectorFailsLocally;
     289        }
    285290        return SelectorMatches;
     291    }
    286292
    287293    SelectorCheckingContext nextContext(context);
     
    380386            return match(nextContext, ignoreDynamicPseudo, siblingTraversalStrategy);
    381387        }
     388#if ENABLE(SHADOW_DOM)
     389    case CSSSelector::ShadowDistributed:
     390        {
     391            Vector<InsertionPoint*, 8> insertionPoints;
     392            for (Element* element = context.element; element; element = element->parentElement()) {
     393                insertionPoints.clear();
     394                collectInsertionPointsWhereNodeIsDistributed(element, insertionPoints);
     395                for (size_t i = 0; i < insertionPoints.size(); ++i) {
     396                    nextContext.element = insertionPoints[i];
     397                    nextContext.isSubSelector = false;
     398                    nextContext.elementStyle = 0;
     399                    if (match(nextContext, ignoreDynamicPseudo, siblingTraversalStrategy) == SelectorMatches)
     400                        return SelectorMatches;
     401                }
     402            }
     403            return SelectorFailsCompletely;
     404        }
     405#endif
    382406    }
    383407
  • trunk/Source/WebCore/css/SelectorChecker.h

    r142717 r142855  
    4949    enum Mode { ResolvingStyle = 0, CollectingRules, QueryingRules, SharingRules };
    5050    explicit SelectorChecker(Document*, Mode);
     51    enum BehaviorAtBoundary { DoesNotCrossBoundary, CrossesBoundary };
    5152
    5253    struct SelectorCheckingContext {
     
    6263            , hasScrollbarPseudo(false)
    6364            , hasSelectionPseudo(false)
     65            , behaviorAtBoundary(DoesNotCrossBoundary)
    6466        { }
    6567
     
    7375        bool hasScrollbarPseudo;
    7476        bool hasSelectionPseudo;
     77        BehaviorAtBoundary behaviorAtBoundary;
    7578    };
    7679
  • trunk/Source/WebCore/css/SelectorFilter.cpp

    r141524 r142855  
    148148        case CSSSelector::IndirectAdjacent:
    149149        case CSSSelector::ShadowDescendant:
     150#if ENABLE(SHADOW_DOM)
     151        case CSSSelector::ShadowDistributed:
     152#endif
    150153            skipOverSubselectors = true;
    151154            break;
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r142791 r142855  
    479479    if (!MatchingUARulesScope::isMatchingUARules()
    480480        && !treeScope->applyAuthorStyles()
    481         && (!matchRequest.scope || matchRequest.scope->treeScope() != treeScope))
     481        && (!matchRequest.scope || matchRequest.scope->treeScope() != treeScope)
     482        && matchRequest.behaviorAtBoundary == SelectorChecker::DoesNotCrossBoundary)
    482483        return;
    483484
     
    624625    collectMatchingRules(matchRequest, ruleRange);
    625626    collectMatchingRulesForRegion(matchRequest, ruleRange);
     627#if ENABLE(SHADOW_DOM)
     628    Vector<MatchRequest> matchRequests;
     629    m_ruleSets.shadowDistributedRules().collectMatchRequests(includeEmptyRules, matchRequests);
     630    for (size_t i = 0; i < matchRequests.size(); ++i)
     631        collectMatchingRules(matchRequests[i], ruleRange);
     632#endif
     633
    626634    sortAndTransferMatchedRules(result);
    627635
     
    664672    // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
    665673    // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
    666     bool canUseFastReject = m_selectorFilter.parentStackIsConsistent(state.parentNode());
     674    bool canUseFastReject = m_selectorFilter.parentStackIsConsistent(state.parentNode()) && matchRequest.behaviorAtBoundary == SelectorChecker::DoesNotCrossBoundary;
    667675
    668676    unsigned size = rules->size();
     
    675683        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule, this);
    676684        PseudoId dynamicPseudo = NOPSEUDO;
    677         if (ruleMatches(ruleData, matchRequest.scope, dynamicPseudo)) {
     685        if (ruleMatches(ruleData, matchRequest.scope, dynamicPseudo, matchRequest.behaviorAtBoundary)) {
    678686            // If the rule has no properties to apply, then ignore it in the non-debug mode.
    679687            const StylePropertySet* properties = rule->properties();
     
    20762084}
    20772085
    2078 inline bool StyleResolver::ruleMatches(const RuleData& ruleData, const ContainerNode* scope, PseudoId& dynamicPseudo)
     2086inline bool StyleResolver::ruleMatches(const RuleData& ruleData, const ContainerNode* scope, PseudoId& dynamicPseudo, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary)
    20792087{
    20802088    State& state = m_state;
     
    21042112    context.scope = scope;
    21052113    context.pseudoStyle = state.pseudoStyle();
     2114    context.behaviorAtBoundary = behaviorAtBoundary;
    21062115    SelectorChecker::Match match = selectorChecker.match(context, dynamicPseudo, DOMSiblingTraversalStrategy());
    21072116    if (match != SelectorChecker::SelectorMatches)
  • trunk/Source/WebCore/css/StyleResolver.h

    r142757 r142855  
    137137};
    138138
     139class MatchRequest {
     140public:
     141    MatchRequest(RuleSet* ruleSet, bool includeEmptyRules = false, const ContainerNode* scope = 0, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary)
     142        : ruleSet(ruleSet)
     143        , includeEmptyRules(includeEmptyRules)
     144        , scope(scope)
     145        , behaviorAtBoundary(behaviorAtBoundary) { }
     146    const RuleSet* ruleSet;
     147    const bool includeEmptyRules;
     148    const ContainerNode* scope;
     149    const SelectorChecker::BehaviorAtBoundary behaviorAtBoundary;
     150};
     151
    139152// This class selects a RenderStyle for a given element based on a collection of stylesheets.
    140153class StyleResolver {
     
    348361    };
    349362
    350     struct MatchRequest {
    351         MatchRequest(RuleSet* ruleSet, bool includeEmptyRules = false, const ContainerNode* scope = 0)
    352             : ruleSet(ruleSet)
    353             , includeEmptyRules(includeEmptyRules)
    354             , scope(scope) { }
    355         const RuleSet* ruleSet;
    356         const bool includeEmptyRules;
    357         const ContainerNode* scope;
    358     };
    359 
    360363    static void addMatchedProperties(MatchResult&, const StylePropertySet* properties, StyleRule* = 0, unsigned linkMatchType = SelectorChecker::MatchAll, PropertyWhitelistType = PropertyWhitelistNone);
    361364    void addElementStyleProperties(MatchResult&, const StylePropertySet*, bool isCacheable = true);
     
    377380    void sortAndTransferMatchedRules(MatchResult&);
    378381
    379     bool ruleMatches(const RuleData&, const ContainerNode* scope, PseudoId&);
     382    bool ruleMatches(const RuleData&, const ContainerNode* scope, PseudoId&, SelectorChecker::BehaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary);
    380383    bool checkRegionSelector(const CSSSelector* regionSelector, Element* regionElement);
    381384    void applyMatchedProperties(const MatchResult&, const Element*);
  • trunk/Source/WebCore/html/shadow/InsertionPoint.cpp

    r140299 r142855  
    230230}
    231231
     232void collectInsertionPointsWhereNodeIsDistributed(const Node* node, Vector<InsertionPoint*, 8>& results)
     233{
     234    const Node* current = node;
     235    while (true) {
     236        if (ElementShadow* shadow = shadowOfParentForDistribution(current)) {
     237            if (ShadowRoot* root = current->containingShadowRoot())
     238                ContentDistributor::ensureDistribution(root);
     239            if (InsertionPoint* insertedTo = shadow->distributor().findInsertionPointFor(node)) {
     240                current = insertedTo;
     241                results.append(insertedTo);
     242                continue;
     243            }
     244        }
     245        if (Node* parent = parentNodeForDistribution(current)) {
     246            if (InsertionPoint* insertedTo = parent->isShadowRoot() ? ScopeContentDistribution::assignedTo(toShadowRoot(parent)) : 0) {
     247                current = insertedTo;
     248                results.append(insertedTo);
     249                continue;
     250            }
     251        }
     252        return;
     253    }
     254}
     255
    232256} // namespace WebCore
  • trunk/Source/WebCore/html/shadow/InsertionPoint.h

    r141516 r142855  
    162162InsertionPoint* resolveReprojection(const Node*);
    163163
     164void collectInsertionPointsWhereNodeIsDistributed(const Node*, Vector<InsertionPoint*, 8>& results);
     165
    164166} // namespace WebCore
    165167
Note: See TracChangeset for help on using the changeset viewer.