2011-01-08 Dimitri Glazkov <dglazkov@chromium.org>
authordglazkov@chromium.org <dglazkov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jan 2011 21:05:33 +0000 (21:05 +0000)
committerdglazkov@chromium.org <dglazkov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jan 2011 21:05:33 +0000 (21:05 +0000)
        Reviewed by David Hyatt.

        Make pseudo-style resolution less hard-coded when used to select a shadow node
        https://bugs.webkit.org/show_bug.cgi?id=46595

        New test that comprehensively travels the code paths affected by the change.

        * fast/css/unknown-pseudo-element-matching-expected.txt: Added.
        * fast/css/unknown-pseudo-element-matching.html: Added.
2011-01-08  Dimitri Glazkov  <dglazkov@chromium.org>

        Reviewed by David Hyatt.

        Make pseudo-style resolution less hard-coded when used to select a shadow node
        https://bugs.webkit.org/show_bug.cgi?id=46595

        Essentially implements the plumbing for the XBL2 pseudo attribute:
        http://dev.w3.org/2006/xbl2/#the-pseudo-attribute

        Test: fast/css/unknown-pseudo-element-matching.html

        * css/CSSGrammar.y: Changed to handle specifier_list structure with the
            CSSParser::updateSpecifierWithElementName helper, added logic to
            keep unknown pseudo-element selectors at the top of the selector chain,
            so that we can easily check for them and grab them, and also because
            they would either not match anything or act as a descendant selector
            (descendant into a shadow DOM subtree that is), not a specifier.
        * css/CSSParser.cpp:
        (WebCore::CSSParser::updateSpecifiersWithElementName): Generalized/combined
            the logic adding element name to selectors and added the special case
            to handle unknown pseudo-element selectors.
        * css/CSSParser.h: Added def.
        * css/CSSSelector.cpp:
        (WebCore::CSSSelector::pseudoId): Removed any mention of PseudoSliderThumb/SLIDER_THUMB.
        (WebCore::nameToPseudoTypeMap): Ditto.
        (WebCore::CSSSelector::extractPseudoType): Ditto.
        * css/CSSSelector.h: Added a new ShadowDescendant relation type,
            removed PseudoSliderThumb def.
        (WebCore::CSSSelector::isUnknownPseudoElement): Added a helper method.
        * css/CSSSelectorList.cpp:
        (WebCore::SelectorHasUnknownPseudoElementFunctor::operator()): Added a functor
            to check for an unknown pseudo-element in the list.
        (WebCore::CSSSelectorList::hasUnknownPseudoElements): Added.
        * css/CSSSelectorList.h: Added a def.
        * css/CSSStyleSelector.cpp:
        (WebCore::CSSRuleSet::getPseudoRules): Added accessor to pseudo-element hash.
        (WebCore::CSSStyleSelector::matchRules): Added matching pseudo elements.
        (WebCore::CSSStyleSelector::SelectorChecker::checkSelector): Added handling
            of ShadowDescendant relation.
        (WebCore::CSSStyleSelector::SelectorChecker::checkOneSelector): Enabled handling
            of unknown pseudo-element selectors.
        (WebCore::CSSRuleSet::addRule): Added populating unknown pseudo-element hash.
        * css/html.css:
        (input[type="range"]::-webkit-slider-thumb): Added previously-hard-coded
            display:block.
        * dom/Element.h:
        (WebCore::Element::shadowPseudoId): Added new virtual method to allow
            elements to provide the value of pseudo-element selector they would match.
        * dom/Node.cpp:
        (WebCore::Node::querySelector): Added checking for unknown pseudo-element selectors,
            so that we can throw a SYNTAX_ERR if found.
        (WebCore::Node::querySelectorAll): Ditto.
        * html/shadow/SliderThumbElement.h:
        (WebCore::SliderThumbElement::shadowPseudoId): Added to return "-webkit-slider-thumb";
        * rendering/RenderSlider.cpp:
        (WebCore::RenderSlider::createThumbStyle): Changed to use the new styleForElement logic.
        * rendering/style/RenderStyleConstants.h: Removed SLIDER_THUMB.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@75543 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css/unknown-pseudo-element-matching-expected.txt [new file with mode: 0644]
LayoutTests/fast/css/unknown-pseudo-element-matching.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/css/CSSGrammar.y
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSParser.h
Source/WebCore/css/CSSSelector.cpp
Source/WebCore/css/CSSSelector.h
Source/WebCore/css/CSSSelectorList.cpp
Source/WebCore/css/CSSSelectorList.h
Source/WebCore/css/CSSStyleSelector.cpp
Source/WebCore/css/html.css
Source/WebCore/dom/Element.h
Source/WebCore/dom/Node.cpp
Source/WebCore/html/shadow/SliderThumbElement.h
Source/WebCore/rendering/RenderSlider.cpp
Source/WebCore/rendering/style/RenderStyleConstants.h

index 21bd2d3..ae0afa2 100644 (file)
@@ -1,3 +1,15 @@
+2011-01-08  Dimitri Glazkov  <dglazkov@chromium.org>
+
+        Reviewed by David Hyatt.
+
+        Make pseudo-style resolution less hard-coded when used to select a shadow node
+        https://bugs.webkit.org/show_bug.cgi?id=46595
+
+        New test that comprehensively travels the code paths affected by the change.
+
+        * fast/css/unknown-pseudo-element-matching-expected.txt: Added.
+        * fast/css/unknown-pseudo-element-matching.html: Added.
+
 2011-01-11  Dean Jackson  <dino@apple.com>
 
         Reviewed by Simon Fraser.
diff --git a/LayoutTests/fast/css/unknown-pseudo-element-matching-expected.txt b/LayoutTests/fast/css/unknown-pseudo-element-matching-expected.txt
new file mode 100644 (file)
index 0000000..081997d
--- /dev/null
@@ -0,0 +1,26 @@
+Tests various selector combinations, containing unknown pseudo element selectors.
+
+::-webkit-slider-thumb should match: PASS
+::-webkit-slider-thumb, where HTML is not default namespace should not match: PASS
+*|::-webkit-slider-thumb, where HTML is not default namespace should match: PASS
+html|::-webkit-slider-thumb, where HTML is not default namespace should match: PASS
+#foo::-webkit-slider-thumb should match: PASS
+.bar::-webkit-slider-thumb should match: PASS
+#foo::-webkit-slider-thumb, where HTML is not default namespace should not match: PASS
+.bar::-webkit-slider-thumb, where HTML is not default namespace should not match: PASS
+html|#foo::-webkit-slider-thumb, where HTML is not default namespace should match: PASS
+html|.bar::-webkit-slider-thumb, where HTML is not default namespace should match: PASS
+*|#foo::-webkit-slider-thumb, where HTML is not default namespace should match: PASS
+input::-webkit-slider-thumb should match: PASS
+input#foo::-webkit-slider-thumb should match: PASS
+input.bar::-webkit-slider-thumb should match: PASS
+input::-webkit-slider-thumb, where HTML is not default namespace should not match: PASS
+input#foo::-webkit-slider-thumb, where HTML is not default namespace should not match: PASS
+input.bar::-webkit-slider-thumb, where HTML is not default namespace should not match: PASS
+html|input::-webkit-slider-thumb, where HTML is not default namespace should match: PASS
+html|input#foo::-webkit-slider-thumb, where HTML is not default namespace should match: PASS
+html|input.bar::-webkit-slider-thumb, where HTML is not default namespace should match: PASS
+*|input#foo::-webkit-slider-thumb, where HTML is not default namespace should match: PASS
+input[type=range]::-webkit-slider-thumb should match: PASS
+input#foo[type=range]::-webkit-slider-thumb should match: PASS
+input.bar[type=range]::-webkit-slider-thumb should match: PASS
diff --git a/LayoutTests/fast/css/unknown-pseudo-element-matching.html b/LayoutTests/fast/css/unknown-pseudo-element-matching.html
new file mode 100644 (file)
index 0000000..0faf160
--- /dev/null
@@ -0,0 +1,79 @@
+<html>
+<head>
+<title>Pseudo Element Matching in Shadow DOM</title>
+<style>
+    input[type=range] {
+        -webkit-appearance: none;
+    }
+</style>
+<script>
+
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+var head;
+var input;
+var logDiv;
+var NAMESPACE_DECLARATION = '@namespace "http://example.com/foo/namespace";\n@namespace html "http://www.w3.org/1999/xhtml";\n';
+var SELECTOR_TEST_PROPERTIES = ' { height: 1px; -webkit-appearance: none; }';
+
+// convenience constants
+var MATCH = true;
+var NO_MATCH = false;
+var WITH_NAMESPACES = true;
+
+function log(msg, success)
+{
+    logDiv.appendChild(document.createElement('div')).innerHTML = msg + ': ' + (success ? 'PASS' : 'FAIL');
+}
+
+function runSelectorTest(matchExpected, selector, useNamespaces)
+{
+    var style = document.createElement('style');
+    style.textContent = (useNamespaces ? NAMESPACE_DECLARATION : '') + selector + SELECTOR_TEST_PROPERTIES;
+    head.appendChild(style);
+    var matched = input.offsetHeight == 1;
+    log('<code>' + selector + '</code>' + (useNamespaces ? ', where  HTML is not default namespace' : '') + ' <strong>should' + (matchExpected ? '' : ' not') + '</strong> match', matchExpected ? matched : !matched);
+    head.removeChild(style);
+}
+
+function runTest()
+{
+    head = document.getElementsByTagName('head')[0];
+    input = document.getElementsByTagName('input')[0];
+    logDiv = document.getElementById('log');
+    runSelectorTest(MATCH, '::-webkit-slider-thumb');
+    runSelectorTest(NO_MATCH, '::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, '*|::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, 'html|::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, '#foo::-webkit-slider-thumb');
+    runSelectorTest(MATCH, '.bar::-webkit-slider-thumb');
+    runSelectorTest(NO_MATCH, '#foo::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(NO_MATCH, '.bar::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, 'html|#foo::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, 'html|.bar::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, '*|#foo::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, 'input::-webkit-slider-thumb');
+    runSelectorTest(MATCH, 'input#foo::-webkit-slider-thumb');
+    runSelectorTest(MATCH, 'input.bar::-webkit-slider-thumb');
+    runSelectorTest(NO_MATCH, 'input::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(NO_MATCH, 'input#foo::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(NO_MATCH, 'input.bar::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, 'html|input::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, 'html|input#foo::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, 'html|input.bar::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, '*|input#foo::-webkit-slider-thumb', WITH_NAMESPACES);
+    runSelectorTest(MATCH, 'input[type=range]::-webkit-slider-thumb');
+    runSelectorTest(MATCH, 'input#foo[type=range]::-webkit-slider-thumb');
+    runSelectorTest(MATCH, 'input.bar[type=range]::-webkit-slider-thumb');
+    document.body.removeChild(input);
+}
+
+</script>
+</head>
+<body onload="runTest()">
+    <p>Tests various selector combinations, containing unknown pseudo element selectors.</p>
+    <input id="foo" class="bar" type="range">
+    <div id="log"></div>
+</body>
+</html>
index 2f564bd..3c34a83 100644 (file)
@@ -1,3 +1,62 @@
+2011-01-08  Dimitri Glazkov  <dglazkov@chromium.org>
+
+        Reviewed by David Hyatt.
+
+        Make pseudo-style resolution less hard-coded when used to select a shadow node
+        https://bugs.webkit.org/show_bug.cgi?id=46595
+
+        Essentially implements the plumbing for the XBL2 pseudo attribute:
+        http://dev.w3.org/2006/xbl2/#the-pseudo-attribute
+
+        Test: fast/css/unknown-pseudo-element-matching.html
+
+        * css/CSSGrammar.y: Changed to handle specifier_list structure with the
+            CSSParser::updateSpecifierWithElementName helper, added logic to
+            keep unknown pseudo-element selectors at the top of the selector chain,
+            so that we can easily check for them and grab them, and also because
+            they would either not match anything or act as a descendant selector
+            (descendant into a shadow DOM subtree that is), not a specifier.
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::updateSpecifiersWithElementName): Generalized/combined
+            the logic adding element name to selectors and added the special case
+            to handle unknown pseudo-element selectors.
+        * css/CSSParser.h: Added def.
+        * css/CSSSelector.cpp:
+        (WebCore::CSSSelector::pseudoId): Removed any mention of PseudoSliderThumb/SLIDER_THUMB.
+        (WebCore::nameToPseudoTypeMap): Ditto.
+        (WebCore::CSSSelector::extractPseudoType): Ditto.
+        * css/CSSSelector.h: Added a new ShadowDescendant relation type,
+            removed PseudoSliderThumb def.
+        (WebCore::CSSSelector::isUnknownPseudoElement): Added a helper method.
+        * css/CSSSelectorList.cpp:
+        (WebCore::SelectorHasUnknownPseudoElementFunctor::operator()): Added a functor
+            to check for an unknown pseudo-element in the list.
+        (WebCore::CSSSelectorList::hasUnknownPseudoElements): Added.
+        * css/CSSSelectorList.h: Added a def.
+        * css/CSSStyleSelector.cpp:
+        (WebCore::CSSRuleSet::getPseudoRules): Added accessor to pseudo-element hash.
+        (WebCore::CSSStyleSelector::matchRules): Added matching pseudo elements.
+        (WebCore::CSSStyleSelector::SelectorChecker::checkSelector): Added handling
+            of ShadowDescendant relation.
+        (WebCore::CSSStyleSelector::SelectorChecker::checkOneSelector): Enabled handling
+            of unknown pseudo-element selectors.
+        (WebCore::CSSRuleSet::addRule): Added populating unknown pseudo-element hash.
+        * css/html.css:
+        (input[type="range"]::-webkit-slider-thumb): Added previously-hard-coded
+            display:block.
+        * dom/Element.h:
+        (WebCore::Element::shadowPseudoId): Added new virtual method to allow
+            elements to provide the value of pseudo-element selector they would match.
+        * dom/Node.cpp:
+        (WebCore::Node::querySelector): Added checking for unknown pseudo-element selectors,
+            so that we can throw a SYNTAX_ERR if found.
+        (WebCore::Node::querySelectorAll): Ditto.
+        * html/shadow/SliderThumbElement.h:
+        (WebCore::SliderThumbElement::shadowPseudoId): Added to return "-webkit-slider-thumb";
+        * rendering/RenderSlider.cpp:
+        (WebCore::RenderSlider::createThumbStyle): Changed to use the new styleForElement logic.
+        * rendering/style/RenderStyleConstants.h: Removed SLIDER_THUMB.
+
 2011-01-11  Dean Jackson  <dino@apple.com>
 
         Reviewed by Simon Fraser.
index ba5855d..a5fe795 100644 (file)
@@ -901,16 +901,13 @@ simple_selector:
     }
     | element_name specifier_list {
         $$ = $2;
-        if ($$) {
-            CSSParser* p = static_cast<CSSParser*>(parser);
-            $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
-        }
+        if ($$)
+            static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName(nullAtom, $1, $$);
     }
     | specifier_list {
         $$ = $1;
-        CSSParser* p = static_cast<CSSParser*>(parser);
-        if ($$ && p->m_defaultNamespace != starAtom)
-            $$->m_tag = QualifiedName(nullAtom, starAtom, p->m_defaultNamespace);
+        if ($$)
+            static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName(nullAtom, starAtom, $$);
     }
     | namespace_selector element_name {
         AtomicString namespacePrefix = $1;
@@ -924,25 +921,13 @@ simple_selector:
     }
     | namespace_selector element_name specifier_list {
         $$ = $3;
-        if ($$) {
-            AtomicString namespacePrefix = $1;
-            CSSParser* p = static_cast<CSSParser*>(parser);
-            if (p->m_styleSheet)
-                $$->m_tag = QualifiedName(namespacePrefix, $2,
-                                          p->m_styleSheet->determineNamespace(namespacePrefix));
-            else // FIXME: Shouldn't this case be an error?
-                $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
-        }
+        if ($$)
+            static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName($1, $2, $$);
     }
     | namespace_selector specifier_list {
         $$ = $2;
-        if ($$) {
-            AtomicString namespacePrefix = $1;
-            CSSParser* p = static_cast<CSSParser*>(parser);
-            if (p->m_styleSheet)
-                $$->m_tag = QualifiedName(namespacePrefix, starAtom,
-                                          p->m_styleSheet->determineNamespace(namespacePrefix));
-        }
+        if ($$)
+            static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName($1, starAtom, $$);
     }
   ;
 
@@ -970,13 +955,22 @@ specifier_list:
         if (!$2)
             $$ = 0;
         else if ($1) {
-            $$ = $1;
             CSSParser* p = static_cast<CSSParser*>(parser);
-            CSSSelector* end = $1;
-            while (end->tagHistory())
+            CSSSelector* end;
+            CSSSelector* history;
+            // Ensure that unknown pseudo element always stays at the top of selector chain.
+            if ($2->isUnknownPseudoElement()) {
+                end = $2;
+                history = $1;
+            } else {
+                end = $1;
+                history = $2;
+            }
+            $$ = end;
+            while(end->tagHistory())
                 end = end->tagHistory();
             end->m_relation = CSSSelector::SubSelector;
-            end->setTagHistory(p->sinkFloatingSelector($2));
+            end->setTagHistory(p->sinkFloatingSelector(history));
         }
     }
     | specifier_list error {
@@ -1141,9 +1135,7 @@ pseudo:
         $3.lower();
         $$->m_value = $3;
         CSSSelector::PseudoType type = $$->pseudoType();
-        if (type == CSSSelector::PseudoUnknown)
-            $$ = 0;
-        else if (type == CSSSelector::PseudoFirstLine) {
+        if (type == CSSSelector::PseudoFirstLine) {
             CSSParser* p = static_cast<CSSParser*>(parser);
             if (Document* doc = p->document())
                 doc->setUsesFirstLineRules(true);
index 0c03b93..ff7c34d 100644 (file)
@@ -5933,6 +5933,35 @@ void CSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri
     m_styleSheet->addNamespace(this, prefix, uri);
 }
 
+void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSSelector* specifiers)
+{
+    AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
+    QualifiedName tag = QualifiedName(namespacePrefix, elementName, determinedNamespace);
+    if (!specifiers->isUnknownPseudoElement()) {
+        specifiers->m_tag = tag;
+        return;
+    }
+
+    if (Document* doc = document())
+        doc->setUsesDescendantRules(true);
+
+    specifiers->m_relation = CSSSelector::ShadowDescendant;
+    if (CSSSelector* history = specifiers->tagHistory()) {
+        history->m_tag = tag;
+        return;
+    }
+
+    // No need to create an extra element name selector if we are matching any element
+    // in any namespace.
+    if (elementName == starAtom && m_defaultNamespace == starAtom)
+        return;
+
+    CSSSelector* elementNameSelector = fastNew<CSSSelector>();
+    elementNameSelector->m_tag = tag;
+    specifiers->setTagHistory(elementNameSelector);
+}
+
+
 CSSRule* CSSParser::createPageRule(CSSSelector* pageSelector)
 {
     // FIXME: Margin at-rules are ignored.
index e60519e..a196e58 100644 (file)
@@ -203,6 +203,7 @@ namespace WebCore {
         PassOwnPtr<MediaQuery> sinkFloatingMediaQuery(MediaQuery*);
 
         void addNamespace(const AtomicString& prefix, const AtomicString& uri);
+        void updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSSelector*);
 
         void invalidBlockHit();
 
index 90fa17e..400dd40 100644 (file)
@@ -151,8 +151,6 @@ PseudoId CSSSelector::pseudoId(PseudoType type)
     case PseudoInputSpeechButton:
         return INPUT_SPEECH_BUTTON;
 #endif
-    case PseudoSliderThumb:
-        return SLIDER_THUMB;
     case PseudoSearchCancelButton:
         return SEARCH_CANCEL_BUTTON;
     case PseudoSearchDecoration:
@@ -420,7 +418,6 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap(
     DEFINE_STATIC_LOCAL(AtomicString, searchResultsDecoration, ("-webkit-search-results-decoration"));
     DEFINE_STATIC_LOCAL(AtomicString, searchResultsButton, ("-webkit-search-results-button"));
     DEFINE_STATIC_LOCAL(AtomicString, selection, ("selection"));
-    DEFINE_STATIC_LOCAL(AtomicString, sliderThumb, ("-webkit-slider-thumb"));
     DEFINE_STATIC_LOCAL(AtomicString, target, ("target"));
     DEFINE_STATIC_LOCAL(AtomicString, visited, ("visited"));
     DEFINE_STATIC_LOCAL(AtomicString, windowInactive, ("window-inactive"));
@@ -549,7 +546,6 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap(
         nameToPseudoType->set(searchResultsDecoration.impl(), CSSSelector::PseudoSearchResultsDecoration);
         nameToPseudoType->set(searchResultsButton.impl(), CSSSelector::PseudoSearchResultsButton);
         nameToPseudoType->set(selection.impl(), CSSSelector::PseudoSelection);
-        nameToPseudoType->set(sliderThumb.impl(), CSSSelector::PseudoSliderThumb);
         nameToPseudoType->set(target.impl(), CSSSelector::PseudoTarget);
         nameToPseudoType->set(visited.impl(), CSSSelector::PseudoVisited);
         nameToPseudoType->set(firstPage.impl(), CSSSelector::PseudoFirstPage);
@@ -637,7 +633,6 @@ void CSSSelector::extractPseudoType() const
     case PseudoSearchResultsDecoration:
     case PseudoSearchResultsButton:
     case PseudoSelection:
-    case PseudoSliderThumb:
         element = true;
         break;
     case PseudoUnknown:
index 353fb5e..1101eed 100644 (file)
@@ -109,7 +109,8 @@ namespace WebCore {
             Child,
             DirectAdjacent,
             IndirectAdjacent,
-            SubSelector
+            SubSelector,
+            ShadowDescendant
         };
 
         enum PseudoType {
@@ -177,7 +178,6 @@ namespace WebCore {
             PseudoNoButton,
             PseudoSelection,
             PseudoFileUploadButton,
-            PseudoSliderThumb,
             PseudoSearchCancelButton,
             PseudoSearchDecoration,
             PseudoSearchResultsDecoration,
@@ -277,6 +277,7 @@ namespace WebCore {
                 extractPseudoType();
             return m_match == PseudoElement;
         }
+        bool isUnknownPseudoElement() const;
 
         Relation relation() const { return static_cast<Relation>(m_relation); }
 
@@ -344,6 +345,11 @@ namespace WebCore {
         QualifiedName m_tag;
     };
 
+inline bool CSSSelector::isUnknownPseudoElement() const
+{
+    return m_match == PseudoElement && m_pseudoType == PseudoUnknown;
+}
+
 } // namespace WebCore
 
 #endif // CSSSelector_h
index 7f82ca4..7cb4df4 100644 (file)
@@ -136,4 +136,20 @@ bool CSSSelectorList::selectorsNeedNamespaceResolution()
     return forEachSelector(functor, this);
 }
 
+class SelectorHasUnknownPseudoElementFunctor {
+public:
+    bool operator()(CSSSelector* selector)
+    {
+        return selector->isUnknownPseudoElement();
+    }
+};
+
+bool CSSSelectorList::hasUnknownPseudoElements() const
+{
+    SelectorHasUnknownPseudoElementFunctor functor;
+    return forEachSelector(functor, this);
+}
+
+
+
 } // namespace WebCore
index 9e40ef8..7adc6b9 100644 (file)
@@ -44,6 +44,7 @@ public:
     bool hasOneSelector() const { return m_selectorArray ? m_selectorArray->isLastInSelectorList() : false; }
 
     bool selectorsNeedNamespaceResolution();
+    bool hasUnknownPseudoElements() const;
 
 private:
     void deleteSelectors();
index 96da74c..e1e6393 100644 (file)
@@ -424,6 +424,7 @@ public:
     CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); }
     CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); }
     CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); }
+    CSSRuleDataList* getPseudoRules(AtomicStringImpl* key) { return m_pseudoRules.get(key); }
     CSSRuleDataList* getUniversalRules() { return m_universalRules.get(); }
     CSSRuleDataList* getPageRules() { return m_pageRules.get(); }
     
@@ -431,6 +432,7 @@ public:
     AtomRuleMap m_idRules;
     AtomRuleMap m_classRules;
     AtomRuleMap m_tagRules;
+    AtomRuleMap m_pseudoRules;
     OwnPtr<CSSRuleDataList> m_universalRules;
     OwnPtr<CSSRuleDataList> m_pageRules;
     unsigned m_ruleCount;
@@ -658,6 +660,10 @@ void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& l
         for (size_t i = 0; i < size; ++i)
             matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
     }
+    if (!m_element->shadowPseudoId().isEmpty()) {
+        ASSERT(m_styledElement);
+        matchRulesForList(rules->getPseudoRules(m_element->shadowPseudoId().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
+    }
     matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
     matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
     
@@ -2051,6 +2057,14 @@ CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector
                 !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass))
                 return SelectorFailsCompletely;
             return checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle);
+        case CSSSelector::ShadowDescendant:
+        {
+            Node* shadowHostNode = e->shadowAncestorNode();
+            if (shadowHostNode == e || !shadowHostNode->isElementNode())
+                return SelectorFailsCompletely;
+            e = static_cast<Element*>(shadowHostNode);
+            return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
+        }
     }
 
     return SelectorFailsCompletely;
@@ -2703,12 +2717,8 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
             if (Document* document = e->document())
                 document->setUsesFirstLetterRules(true);
         }
-        if (pseudoId != NOPSEUDO) {
+        if (pseudoId != NOPSEUDO)
             dynamicPseudo = pseudoId;
-            return true;
-        }
-        ASSERT_NOT_REACHED();
-        return false;
     }
     // ### add the rest of the checks...
     return true;
@@ -2829,12 +2839,17 @@ void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
         return;
     }
      
+    if (sel->isUnknownPseudoElement()) {
+        addToRuleSet(sel->m_value.impl(), m_pseudoRules, rule, sel);
+        return;
+    }
+
     const AtomicString& localName = sel->m_tag.localName();
     if (localName != starAtom) {
         addToRuleSet(localName.impl(), m_tagRules, rule, sel);
         return;
     }
-    
+
     // Just put it in the universal rule set.
     if (!m_universalRules)
         m_universalRules = adoptPtr(new CSSRuleDataList(m_ruleCount++, rule, sel));
index 823f5f3..d6fbbdf 100644 (file)
@@ -474,6 +474,7 @@ input[type="range"] {
 
 input[type="range"]::-webkit-slider-thumb {
     -webkit-appearance: sliderthumb-horizontal;
+    display: block;
 }
 
 input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled,
index e552376..5e6c047 100644 (file)
@@ -230,6 +230,7 @@ public:
 
     Node* shadowRoot();
     void setShadowRoot(PassRefPtr<Node>);
+    virtual AtomicString shadowPseudoId() const;
 
     RenderStyle* computedStyle(PseudoId = NOPSEUDO);
 
@@ -507,6 +508,11 @@ inline void Element::setIdAttribute(const AtomicString& value)
     setAttribute(document()->idAttributeName(), value);
 }
 
+inline AtomicString Element::shadowPseudoId() const
+{
+    return AtomicString();
+}
+
 } // namespace
 
 #endif
index 26e8187..4d50ef2 100644 (file)
@@ -1612,7 +1612,7 @@ PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode&
     CSSSelectorList querySelectorList;
     p.parseSelector(selectors, document(), querySelectorList);
 
-    if (!querySelectorList.first()) {
+    if (!querySelectorList.first() || querySelectorList.hasUnknownPseudoElements()) {
         ec = SYNTAX_ERR;
         return 0;
     }
@@ -1659,7 +1659,7 @@ PassRefPtr<NodeList> Node::querySelectorAll(const String& selectors, ExceptionCo
     CSSSelectorList querySelectorList;
     p.parseSelector(selectors, document(), querySelectorList);
 
-    if (!querySelectorList.first()) {
+    if (!querySelectorList.first() || querySelectorList.hasUnknownPseudoElements()) {
         ec = SYNTAX_ERR;
         return 0;
     }
index 8205746..5220f2b 100644 (file)
@@ -33,6 +33,7 @@
 #define SliderThumbElement_h
 
 #include "FloatPoint.h"
+#include "RenderStyleConstants.h"
 #include "ShadowElement.h"
 #include <wtf/Forward.h>
 
@@ -50,6 +51,7 @@ public:
 
     virtual void defaultEventHandler(Event*);
     virtual void detach();
+    virtual AtomicString shadowPseudoId() const;
 
 private:        
     SliderThumbElement(HTMLElement* shadowParent);
@@ -69,6 +71,12 @@ inline PassRefPtr<SliderThumbElement> SliderThumbElement::create(HTMLElement* sh
     return adoptRef(new SliderThumbElement(shadowParent));
 }
 
+inline AtomicString SliderThumbElement::shadowPseudoId() const
+{
+    DEFINE_STATIC_LOCAL(AtomicString, sliderThumb, ("-webkit-slider-thumb"));
+    return sliderThumb;
+}
+
 }
 
 
index ef88c1d..5eff826 100644 (file)
@@ -22,6 +22,7 @@
 #include "RenderSlider.h"
 
 #include "CSSPropertyNames.h"
+#include "CSSStyleSelector.h"
 #include "Document.h"
 #include "Event.h"
 #include "EventHandler.h"
@@ -110,29 +111,18 @@ void RenderSlider::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
 
 PassRefPtr<RenderStyle> RenderSlider::createThumbStyle(const RenderStyle* parentStyle)
 {
-    RefPtr<RenderStyle> style;
-    RenderStyle* pseudoStyle = getCachedPseudoStyle(SLIDER_THUMB);
-    if (pseudoStyle)
-        // We may be sharing style with another slider, but we must not share the thumb style.
-        style = RenderStyle::clone(pseudoStyle);
-    else
-        style = RenderStyle::create();
-
-    if (parentStyle)
-        style->inheritFrom(parentStyle);
-
-    style->setDisplay(BLOCK);
+    RefPtr<RenderStyle> thumbStyle = document()->styleSelector()->styleForElement(m_thumb.get(), style(), false);
 
     if (parentStyle->appearance() == SliderVerticalPart)
-        style->setAppearance(SliderThumbVerticalPart);
+        thumbStyle->setAppearance(SliderThumbVerticalPart);
     else if (parentStyle->appearance() == SliderHorizontalPart)
-        style->setAppearance(SliderThumbHorizontalPart);
+        thumbStyle->setAppearance(SliderThumbHorizontalPart);
     else if (parentStyle->appearance() == MediaSliderPart)
-        style->setAppearance(MediaSliderThumbPart);
+        thumbStyle->setAppearance(MediaSliderThumbPart);
     else if (parentStyle->appearance() == MediaVolumeSliderPart)
-        style->setAppearance(MediaVolumeSliderThumbPart);
+        thumbStyle->setAppearance(MediaVolumeSliderThumbPart);
 
-    return style.release();
+    return thumbStyle.release();
 }
 
 IntRect RenderSlider::thumbRect()
index 0839864..7cd4903 100644 (file)
@@ -68,7 +68,7 @@ enum StyleDifferenceContextSensitiveProperty {
 enum PseudoId {
     // The order must be NOP ID, public IDs, and then internal IDs.
     NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR, FILE_UPLOAD_BUTTON, INPUT_PLACEHOLDER,
-    SLIDER_THUMB, SEARCH_CANCEL_BUTTON, SEARCH_DECORATION, SEARCH_RESULTS_DECORATION, SEARCH_RESULTS_BUTTON, MEDIA_CONTROLS_PANEL,
+    SEARCH_CANCEL_BUTTON, SEARCH_DECORATION, SEARCH_RESULTS_DECORATION, SEARCH_RESULTS_BUTTON, MEDIA_CONTROLS_PANEL,
     MEDIA_CONTROLS_PLAY_BUTTON, MEDIA_CONTROLS_MUTE_BUTTON, MEDIA_CONTROLS_TIMELINE, MEDIA_CONTROLS_TIMELINE_CONTAINER,
     MEDIA_CONTROLS_VOLUME_SLIDER, MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER, MEDIA_CONTROLS_VOLUME_SLIDER_MUTE_BUTTON, 
     MEDIA_CONTROLS_CURRENT_TIME_DISPLAY, MEDIA_CONTROLS_TIME_REMAINING_DISPLAY,