<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[207854] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/207854">207854</a></dd>
<dt>Author</dt> <dd>hyatt@apple.com</dd>
<dt>Date</dt> <dd>2016-10-25 16:21:03 -0700 (Tue, 25 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[CSS Parser] Improvements to selector parsing
https://bugs.webkit.org/show_bug.cgi?id=163964

Reviewed by Zalan Bujtas.

* css/CSSSelector.cpp:
(WebCore::CSSSelector::setAttribute):
(WebCore::CSSSelector::setNth):
* css/CSSSelector.h:
(WebCore::CSSSelector::setAttributeValueMatchingIsCaseInsensitive):
* css/StyleSheetContents.cpp:
(WebCore::StyleSheetContents::StyleSheetContents):
(WebCore::StyleSheetContents::parserAppendRule):
(WebCore::StyleSheetContents::ruleAt):
(WebCore::StyleSheetContents::ruleCount):
(WebCore::StyleSheetContents::clearRules):
(WebCore::StyleSheetContents::wrapperInsertRule):
(WebCore::StyleSheetContents::wrapperDeleteRule):
* css/StyleSheetContents.h:
* css/parser/CSSParser.cpp:
(WebCore::CSSParserContext::CSSParserContext):
(WebCore::CSSParser::parseSelector):
* css/parser/CSSParserValues.h:
(WebCore::CSSParserSelector::setAttribute):
(WebCore::CSSParserSelector::setArgument):
(WebCore::CSSParserSelector::setNth):
* css/parser/CSSSelectorParser.cpp:
(WebCore::consumeLangArgumentList):
(WebCore::CSSSelectorParser::consumeCompoundSelector):
(WebCore::CSSSelectorParser::consumeAttribute):
(WebCore::isPseudoClassFunction):
(WebCore::isPseudoElementFunction):
(WebCore::CSSSelectorParser::consumePseudo):
(WebCore::CSSSelectorParser::consumeCombinator):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssCSSSelectorcpp">trunk/Source/WebCore/css/CSSSelector.cpp</a></li>
<li><a href="#trunkSourceWebCorecssCSSSelectorh">trunk/Source/WebCore/css/CSSSelector.h</a></li>
<li><a href="#trunkSourceWebCorecssStyleSheetContentscpp">trunk/Source/WebCore/css/StyleSheetContents.cpp</a></li>
<li><a href="#trunkSourceWebCorecssStyleSheetContentsh">trunk/Source/WebCore/css/StyleSheetContents.h</a></li>
<li><a href="#trunkSourceWebCorecssparserCSSParsercpp">trunk/Source/WebCore/css/parser/CSSParser.cpp</a></li>
<li><a href="#trunkSourceWebCorecssparserCSSParserValuescpp">trunk/Source/WebCore/css/parser/CSSParserValues.cpp</a></li>
<li><a href="#trunkSourceWebCorecssparserCSSParserValuesh">trunk/Source/WebCore/css/parser/CSSParserValues.h</a></li>
<li><a href="#trunkSourceWebCorecssparserCSSSelectorParsercpp">trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (207853 => 207854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/ChangeLog        2016-10-25 23:21:03 UTC (rev 207854)
</span><span class="lines">@@ -1,3 +1,40 @@
</span><ins>+2016-10-25  Dave Hyatt  &lt;hyatt@apple.com&gt;
+
+        [CSS Parser] Improvements to selector parsing
+        https://bugs.webkit.org/show_bug.cgi?id=163964
+
+        Reviewed by Zalan Bujtas.
+
+        * css/CSSSelector.cpp:
+        (WebCore::CSSSelector::setAttribute):
+        (WebCore::CSSSelector::setNth):
+        * css/CSSSelector.h:
+        (WebCore::CSSSelector::setAttributeValueMatchingIsCaseInsensitive):
+        * css/StyleSheetContents.cpp:
+        (WebCore::StyleSheetContents::StyleSheetContents):
+        (WebCore::StyleSheetContents::parserAppendRule):
+        (WebCore::StyleSheetContents::ruleAt):
+        (WebCore::StyleSheetContents::ruleCount):
+        (WebCore::StyleSheetContents::clearRules):
+        (WebCore::StyleSheetContents::wrapperInsertRule):
+        (WebCore::StyleSheetContents::wrapperDeleteRule):
+        * css/StyleSheetContents.h:
+        * css/parser/CSSParser.cpp:
+        (WebCore::CSSParserContext::CSSParserContext):
+        (WebCore::CSSParser::parseSelector):
+        * css/parser/CSSParserValues.h:
+        (WebCore::CSSParserSelector::setAttribute):
+        (WebCore::CSSParserSelector::setArgument):
+        (WebCore::CSSParserSelector::setNth):
+        * css/parser/CSSSelectorParser.cpp:
+        (WebCore::consumeLangArgumentList):
+        (WebCore::CSSSelectorParser::consumeCompoundSelector):
+        (WebCore::CSSSelectorParser::consumeAttribute):
+        (WebCore::isPseudoClassFunction):
+        (WebCore::isPseudoElementFunction):
+        (WebCore::CSSSelectorParser::consumePseudo):
+        (WebCore::CSSSelectorParser::consumeCombinator):
+
</ins><span class="cx"> 2016-10-25  Beth Dakin  &lt;bdakin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Numbered list should be represented without ‘…’
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSSelectorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSSelector.cpp (207853 => 207854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSSelector.cpp        2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/CSSSelector.cpp        2016-10-25 23:21:03 UTC (rev 207854)
</span><span class="lines">@@ -763,6 +763,14 @@
</span><span class="cx">     m_data.m_rareData-&gt;m_attributeCanonicalLocalName = isCaseInsensitive ? value.localName().convertToASCIILowercase() : value.localName();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CSSSelector::setAttribute(const QualifiedName&amp; value, bool convertToLowercase, AttributeMatchType matchType)
+{
+    createRareData();
+    m_data.m_rareData-&gt;m_attribute = value;
+    m_data.m_rareData-&gt;m_attributeCanonicalLocalName = convertToLowercase ? value.localName().convertToASCIILowercase() : value.localName();
+    m_caseInsensitiveAttributeValueMatching = matchType == CaseInsensitive;
+}
+    
</ins><span class="cx"> void CSSSelector::setArgument(const AtomicString&amp; value)
</span><span class="cx"> {
</span><span class="cx">     createRareData();
</span><span class="lines">@@ -781,6 +789,16 @@
</span><span class="cx">     m_data.m_rareData-&gt;m_selectorList = WTFMove(selectorList);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CSSSelector::setNth(int a, int b)
+{
+    createRareData();
+    m_parsedNth = true; // FIXME-NEWPARSER: Can remove this parsed boolean once old parser is gone.
+    m_data.m_rareData-&gt;m_a = a;
+    m_data.m_rareData-&gt;m_b = b;
+}
+    
+// FIXME-NEWPARSER: All the code to parse nth-child stuff can be removed when
+// the new parser is enabled.
</ins><span class="cx"> bool CSSSelector::parseNth() const
</span><span class="cx"> {
</span><span class="cx">     if (!m_hasRareData)
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSSelectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSSelector.h (207853 => 207854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSSelector.h        2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/CSSSelector.h        2016-10-25 23:21:03 UTC (rev 207854)
</span><span class="lines">@@ -244,9 +244,13 @@
</span><span class="cx">         const CSSSelectorList* selectorList() const { return m_hasRareData ? m_data.m_rareData-&gt;m_selectorList.get() : nullptr; }
</span><span class="cx"> 
</span><span class="cx">         void setValue(const AtomicString&amp;);
</span><del>-        void setAttribute(const QualifiedName&amp;, bool isCaseInsensitive);
</del><ins>+        
+        // FIXME-NEWPARSER: These two methods can go away once the old parser is gone.
+        void setAttribute(const QualifiedName&amp;, bool);
+        void setAttributeValueMatchingIsCaseInsensitive(bool);
+        void setAttribute(const QualifiedName&amp;, bool convertToLowercase, AttributeMatchType);
+        void setNth(int a, int b);
</ins><span class="cx">         void setArgument(const AtomicString&amp;);
</span><del>-        void setAttributeValueMatchingIsCaseInsensitive(bool);
</del><span class="cx">         void setLangArgumentList(std::unique_ptr&lt;Vector&lt;AtomicString&gt;&gt;);
</span><span class="cx">         void setSelectorList(std::unique_ptr&lt;CSSSelectorList&gt;);
</span><span class="cx"> 
</span><span class="lines">@@ -585,7 +589,7 @@
</span><span class="cx">     ASSERT(isAttributeSelector() &amp;&amp; match() != CSSSelector::Set);
</span><span class="cx">     m_caseInsensitiveAttributeValueMatching = isCaseInsensitive;
</span><span class="cx"> }
</span><del>-
</del><ins>+    
</ins><span class="cx"> inline bool CSSSelector::attributeValueMatchingIsCaseInsensitive() const
</span><span class="cx"> {
</span><span class="cx">     return m_caseInsensitiveAttributeValueMatching;
</span></span></pre></div>
<a id="trunkSourceWebCorecssStyleSheetContentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/StyleSheetContents.cpp (207853 => 207854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/StyleSheetContents.cpp        2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/StyleSheetContents.cpp        2016-10-25 23:21:03 UTC (rev 207854)
</span><span class="lines">@@ -80,6 +80,7 @@
</span><span class="cx">     , m_originalURL(o.m_originalURL)
</span><span class="cx">     , m_encodingFromCharsetRule(o.m_encodingFromCharsetRule)
</span><span class="cx">     , m_importRules(o.m_importRules.size())
</span><ins>+    , m_namespaceRules(o.m_namespaceRules.size())
</ins><span class="cx">     , m_childRules(o.m_childRules.size())
</span><span class="cx">     , m_namespaces(o.m_namespaces)
</span><span class="cx">     , m_defaultNamespace(o.m_defaultNamespace)
</span><span class="lines">@@ -142,6 +143,16 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (is&lt;StyleRuleNamespace&gt;(rule)) {
+        // Parser enforces that @namespace rules come before all rules other than
+        // import/charset rules
+        ASSERT(m_childRules.isEmpty());
+        StyleRuleNamespace&amp; namespaceRule = downcast&lt;StyleRuleNamespace&gt;(rule.get());
+        parserAddNamespace(namespaceRule.prefix(), namespaceRule.uri());
+        m_namespaceRules.append(downcast&lt;StyleRuleNamespace&gt;(rule.ptr()));
+        return;
+    }
+
</ins><span class="cx">     if (is&lt;StyleRuleMedia&gt;(rule))
</span><span class="cx">         reportMediaQueryWarningIfNeeded(singleOwnerDocument(), downcast&lt;StyleRuleMedia&gt;(rule.get()).mediaQueries());
</span><span class="cx"> 
</span><span class="lines">@@ -164,6 +175,12 @@
</span><span class="cx">         return m_importRules[childVectorIndex].get();
</span><span class="cx"> 
</span><span class="cx">     childVectorIndex -= m_importRules.size();
</span><ins>+    
+    if (childVectorIndex &lt; m_namespaceRules.size())
+        return m_namespaceRules[childVectorIndex].get();
+    
+    childVectorIndex -= m_namespaceRules.size();
+    
</ins><span class="cx">     return m_childRules[childVectorIndex].get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -171,6 +188,7 @@
</span><span class="cx"> {
</span><span class="cx">     unsigned result = 0;
</span><span class="cx">     result += m_importRules.size();
</span><ins>+    result += m_namespaceRules.size();
</ins><span class="cx">     result += m_childRules.size();
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="lines">@@ -187,6 +205,7 @@
</span><span class="cx">         m_importRules[i]-&gt;clearParentStyleSheet();
</span><span class="cx">     }
</span><span class="cx">     m_importRules.clear();
</span><ins>+    m_namespaceRules.clear();
</ins><span class="cx">     m_childRules.clear();
</span><span class="cx">     clearCharsetRule();
</span><span class="cx"> }
</span><span class="lines">@@ -221,6 +240,31 @@
</span><span class="cx">         return false;
</span><span class="cx">     childVectorIndex -= m_importRules.size();
</span><span class="cx"> 
</span><ins>+    
+    if (childVectorIndex &lt; m_namespaceRules.size() || (childVectorIndex == m_namespaceRules.size() &amp;&amp; rule-&gt;isNamespaceRule())) {
+        // Inserting non-namespace rules other than import rule before @namespace is
+        // not allowed.
+        if (!is&lt;StyleRuleNamespace&gt;(rule))
+            return false;
+        // Inserting @namespace rule when rules other than import/namespace/charset
+        // are present is not allowed.
+        if (!m_childRules.isEmpty())
+            return false;
+        
+        StyleRuleNamespace&amp; namespaceRule = downcast&lt;StyleRuleNamespace&gt;(rule.get());
+        m_namespaceRules.insert(index, downcast&lt;StyleRuleNamespace&gt;(rule.ptr()));
+        
+        // For now to be compatible with IE and Firefox if a namespace rule with the same
+        // prefix is added, it overwrites previous ones.
+        // FIXME: The eventual correct behavior would be to ensure that the last value in
+        // the list wins.
+        parserAddNamespace(namespaceRule.prefix(), namespaceRule.uri());
+        return true;
+    }
+    if (is&lt;StyleRuleNamespace&gt;(rule))
+        return false;
+    childVectorIndex -= m_namespaceRules.size();
+
</ins><span class="cx">     // If the number of selectors would overflow RuleData, we drop the operation.
</span><span class="cx">     if (is&lt;StyleRule&gt;(rule) &amp;&amp; downcast&lt;StyleRule&gt;(rule.get()).selectorList().componentCount() &gt; RuleData::maximumSelectorComponentCount)
</span><span class="cx">         return false;
</span><span class="lines">@@ -242,6 +286,14 @@
</span><span class="cx">     }
</span><span class="cx">     childVectorIndex -= m_importRules.size();
</span><span class="cx"> 
</span><ins>+    if (childVectorIndex &lt; m_namespaceRules.size()) {
+        if (!m_childRules.isEmpty())
+            return;
+        m_namespaceRules.remove(childVectorIndex);
+        return;
+    }
+    childVectorIndex -= m_namespaceRules.size();
+
</ins><span class="cx">     m_childRules.remove(childVectorIndex);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorecssStyleSheetContentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/StyleSheetContents.h (207853 => 207854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/StyleSheetContents.h        2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/StyleSheetContents.h        2016-10-25 23:21:03 UTC (rev 207854)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> class SecurityOrigin;
</span><span class="cx"> class StyleRuleBase;
</span><span class="cx"> class StyleRuleImport;
</span><ins>+class StyleRuleNamespace;
</ins><span class="cx"> 
</span><span class="cx"> class StyleSheetContents final : public RefCounted&lt;StyleSheetContents&gt; {
</span><span class="cx"> public:
</span><span class="lines">@@ -104,6 +105,7 @@
</span><span class="cx">     // Rules other than @charset and @import.
</span><span class="cx">     const Vector&lt;RefPtr&lt;StyleRuleBase&gt;&gt;&amp; childRules() const { return m_childRules; }
</span><span class="cx">     const Vector&lt;RefPtr&lt;StyleRuleImport&gt;&gt;&amp; importRules() const { return m_importRules; }
</span><ins>+    const Vector&lt;RefPtr&lt;StyleRuleNamespace&gt;&gt;&amp; namespaceRules() const { return m_namespaceRules; }
</ins><span class="cx"> 
</span><span class="cx">     void notifyLoadedSheet(const CachedCSSStyleSheet*);
</span><span class="cx">     
</span><span class="lines">@@ -154,6 +156,7 @@
</span><span class="cx"> 
</span><span class="cx">     String m_encodingFromCharsetRule;
</span><span class="cx">     Vector&lt;RefPtr&lt;StyleRuleImport&gt;&gt; m_importRules;
</span><ins>+    Vector&lt;RefPtr&lt;StyleRuleNamespace&gt;&gt; m_namespaceRules;
</ins><span class="cx">     Vector&lt;RefPtr&lt;StyleRuleBase&gt;&gt; m_childRules;
</span><span class="cx">     typedef HashMap&lt;AtomicString, AtomicString&gt; PrefixNamespaceURIMap;
</span><span class="cx">     PrefixNamespaceURIMap m_namespaces;
</span></span></pre></div>
<a id="trunkSourceWebCorecssparserCSSParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/parser/CSSParser.cpp (207853 => 207854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/parser/CSSParser.cpp        2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/parser/CSSParser.cpp        2016-10-25 23:21:03 UTC (rev 207854)
</span><span class="lines">@@ -64,9 +64,11 @@
</span><span class="cx"> #include &quot;CSSReflectValue.h&quot;
</span><span class="cx"> #include &quot;CSSRevertValue.h&quot;
</span><span class="cx"> #include &quot;CSSSelector.h&quot;
</span><ins>+#include &quot;CSSSelectorParser.h&quot;
</ins><span class="cx"> #include &quot;CSSShadowValue.h&quot;
</span><span class="cx"> #include &quot;CSSStyleSheet.h&quot;
</span><span class="cx"> #include &quot;CSSTimingFunctionValue.h&quot;
</span><ins>+#include &quot;CSSTokenizer.h&quot;
</ins><span class="cx"> #include &quot;CSSUnicodeRangeValue.h&quot;
</span><span class="cx"> #include &quot;CSSUnsetValue.h&quot;
</span><span class="cx"> #include &quot;CSSValueKeywords.h&quot;
</span><span class="lines">@@ -1411,8 +1413,14 @@
</span><span class="cx"> 
</span><span class="cx"> void CSSParser::parseSelector(const String&amp; string, CSSSelectorList&amp; selectorList)
</span><span class="cx"> {
</span><ins>+    if (m_context.useNewParser &amp;&amp; m_context.mode != UASheetMode) {
+        CSSTokenizer::Scope scope(string);
+        selectorList = CSSSelectorParser::parseSelector(scope.tokenRange(), m_context, nullptr);
+        return;
+    }
+
</ins><span class="cx">     m_selectorListForParseSelector = &amp;selectorList;
</span><del>-
</del><ins>+    
</ins><span class="cx">     setupParser(&quot;@-webkit-selector{&quot;, string, &quot;}&quot;);
</span><span class="cx"> 
</span><span class="cx">     cssyyparse(this);
</span></span></pre></div>
<a id="trunkSourceWebCorecssparserCSSParserValuescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/parser/CSSParserValues.cpp (207853 => 207854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/parser/CSSParserValues.cpp        2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/parser/CSSParserValues.cpp        2016-10-25 23:21:03 UTC (rev 207854)
</span><span class="lines">@@ -410,7 +410,13 @@
</span><span class="cx">         argumentList-&gt;append(languageArgument);
</span><span class="cx">     m_selector-&gt;setLangArgumentList(WTFMove(argumentList));
</span><span class="cx"> }
</span><del>-    
</del><ins>+
+void CSSParserSelector::setLangArgumentList(std::unique_ptr&lt;Vector&lt;AtomicString&gt;&gt; argumentList)
+{
+    ASSERT_WITH_MESSAGE(!argumentList-&gt;isEmpty(), &quot;No CSS Selector takes an empty argument list.&quot;);
+    m_selector-&gt;setLangArgumentList(WTFMove(argumentList));
+}
+
</ins><span class="cx"> void CSSParserSelector::setSelectorList(std::unique_ptr&lt;CSSSelectorList&gt; selectorList)
</span><span class="cx"> {
</span><span class="cx">     m_selector-&gt;setSelectorList(WTFMove(selectorList));
</span></span></pre></div>
<a id="trunkSourceWebCorecssparserCSSParserValuesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/parser/CSSParserValues.h (207853 => 207854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/parser/CSSParserValues.h        2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/parser/CSSParserValues.h        2016-10-25 23:21:03 UTC (rev 207854)
</span><span class="lines">@@ -222,9 +222,15 @@
</span><span class="cx">     std::unique_ptr&lt;CSSSelector&gt; releaseSelector() { return WTFMove(m_selector); }
</span><span class="cx"> 
</span><span class="cx">     void setValue(const AtomicString&amp; value) { m_selector-&gt;setValue(value); }
</span><ins>+    
+    // FIXME-NEWPARSER: These two methods can go away once old parser is gone.
</ins><span class="cx">     void setAttribute(const QualifiedName&amp; value, bool isCaseInsensitive) { m_selector-&gt;setAttribute(value, isCaseInsensitive); }
</span><ins>+    void setAttributeValueMatchingIsCaseInsensitive(bool isCaseInsensitive) { m_selector-&gt;setAttributeValueMatchingIsCaseInsensitive(isCaseInsensitive); }
+    
+    void setAttribute(const QualifiedName&amp; value, bool convertToLowercase, CSSSelector::AttributeMatchType type) { m_selector-&gt;setAttribute(value, convertToLowercase, type); }
+    
</ins><span class="cx">     void setArgument(const AtomicString&amp; value) { m_selector-&gt;setArgument(value); }
</span><del>-    void setAttributeValueMatchingIsCaseInsensitive(bool isCaseInsensitive) { m_selector-&gt;setAttributeValueMatchingIsCaseInsensitive(isCaseInsensitive); }
</del><ins>+    void setNth(int a, int b) { m_selector-&gt;setNth(a, b); }
</ins><span class="cx">     void setMatch(CSSSelector::Match value) { m_selector-&gt;setMatch(value); }
</span><span class="cx">     void setRelation(CSSSelector::RelationType value) { m_selector-&gt;setRelation(value); }
</span><span class="cx">     void setForPage() { m_selector-&gt;setForPage(); }
</span><span class="lines">@@ -235,6 +241,7 @@
</span><span class="cx"> 
</span><span class="cx">     void adoptSelectorVector(Vector&lt;std::unique_ptr&lt;CSSParserSelector&gt;&gt;&amp; selectorVector);
</span><span class="cx">     void setLangArgumentList(const Vector&lt;CSSParserString&gt;&amp; stringVector);
</span><ins>+    void setLangArgumentList(std::unique_ptr&lt;Vector&lt;AtomicString&gt;&gt;);
</ins><span class="cx">     void setSelectorList(std::unique_ptr&lt;CSSSelectorList&gt;);
</span><span class="cx"> 
</span><span class="cx">     void setPseudoClassValue(const CSSParserString&amp; pseudoClassString);
</span></span></pre></div>
<a id="trunkSourceWebCorecssparserCSSSelectorParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp (207853 => 207854)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp        2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp        2016-10-25 23:21:03 UTC (rev 207854)
</span><span class="lines">@@ -100,6 +100,28 @@
</span><span class="cx">     return list;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static bool consumeLangArgumentList(std::unique_ptr&lt;Vector&lt;AtomicString&gt;&gt;&amp; argumentList, CSSParserTokenRange&amp; range)
+{
+    const CSSParserToken&amp; ident = range.consumeIncludingWhitespace();
+    if (ident.type() != IdentToken &amp;&amp; ident.type() != StringToken)
+        return false;
+    StringView string = ident.value();
+    if (string.startsWith(&quot;--&quot;))
+        return false;
+    argumentList-&gt;append(string.toAtomicString());
+    while (!range.atEnd() &amp;&amp; range.peek().type() == CommaToken) {
+        range.consumeIncludingWhitespace();
+        const CSSParserToken&amp; ident = range.consumeIncludingWhitespace();
+        if (ident.type() != IdentToken &amp;&amp; ident.type() != StringToken)
+            return false;
+        StringView string = ident.value();
+        if (string.startsWith(&quot;--&quot;))
+            return false;
+        argumentList-&gt;append(string.toAtomicString());
+    }
+    return range.atEnd();
+}
+
</ins><span class="cx"> namespace {
</span><span class="cx"> 
</span><span class="cx"> enum CompoundSelectorFlags {
</span><span class="lines">@@ -257,8 +279,6 @@
</span><span class="cx">         if (compoundSelector-&gt;match() == CSSSelector::PseudoElement)
</span><span class="cx">             compoundPseudoElement = compoundSelector-&gt;pseudoElementType();
</span><span class="cx">     }
</span><del>-    if (m_context.isHTMLDocument)
-        elementName = elementName.convertToASCIILowercase();
</del><span class="cx"> 
</span><span class="cx">     while (std::unique_ptr&lt;CSSParserSelector&gt; simpleSelector = consumeSimpleSelector(range)) {
</span><span class="cx">         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=161747
</span><span class="lines">@@ -400,9 +420,6 @@
</span><span class="cx">         return nullptr;
</span><span class="cx">     block.consumeWhitespace();
</span><span class="cx"> 
</span><del>-    if (m_context.isHTMLDocument)
-        attributeName = attributeName.convertToASCIILowercase();
-
</del><span class="cx">     AtomicString namespaceURI = determineNamespace(namespacePrefix);
</span><span class="cx">     if (namespaceURI.isNull())
</span><span class="cx">         return nullptr;
</span><span class="lines">@@ -414,7 +431,7 @@
</span><span class="cx">     std::unique_ptr&lt;CSSParserSelector&gt; selector = std::unique_ptr&lt;CSSParserSelector&gt;(new CSSParserSelector());
</span><span class="cx"> 
</span><span class="cx">     if (block.atEnd()) {
</span><del>-        selector-&gt;setAttribute(qualifiedName, CSSSelector::CaseSensitive);
</del><ins>+        selector-&gt;setAttribute(qualifiedName, m_context.isHTMLDocument, CSSSelector::CaseSensitive);
</ins><span class="cx">         selector-&gt;setMatch(CSSSelector::Set);
</span><span class="cx">         return selector;
</span><span class="cx">     }
</span><span class="lines">@@ -425,7 +442,8 @@
</span><span class="cx">     if (attributeValue.type() != IdentToken &amp;&amp; attributeValue.type() != StringToken)
</span><span class="cx">         return nullptr;
</span><span class="cx">     selector-&gt;setValue(attributeValue.value().toAtomicString());
</span><del>-    selector-&gt;setAttribute(qualifiedName, consumeAttributeFlags(block));
</del><ins>+    
+    selector-&gt;setAttribute(qualifiedName, m_context.isHTMLDocument, consumeAttributeFlags(block));
</ins><span class="cx"> 
</span><span class="cx">     if (!block.atEnd())
</span><span class="cx">         return nullptr;
</span><span class="lines">@@ -432,6 +450,41 @@
</span><span class="cx">     return selector;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static bool isPseudoClassFunction(CSSSelector::PseudoClassType pseudoClassType)
+{
+    switch (pseudoClassType) {
+    case CSSSelector::PseudoClassNot:
+    case CSSSelector::PseudoClassMatches:
+    case CSSSelector::PseudoClassNthChild:
+    case CSSSelector::PseudoClassNthLastChild:
+    case CSSSelector::PseudoClassNthOfType:
+    case CSSSelector::PseudoClassNthLastOfType:
+    case CSSSelector::PseudoClassLang:
+    case CSSSelector::PseudoClassAny:
+    case CSSSelector::PseudoClassHost:
+#if ENABLE_CSS_SELECTORS_LEVEL4
+    case CSSSelector::PseudoClassDir:
+    case CSSSelector::PseudoClassRole:
+#endif
+        return true;
+    default:
+        break;
+    }
+    return false;
+}
+    
+static bool isPseudoElementFunction(CSSSelector::PseudoElementType pseudoElementType)
+{
+    switch (pseudoElementType) {
+    case CSSSelector::PseudoElementCue:
+    case CSSSelector::PseudoElementSlotted:
+        return true;
+    default:
+        break;
+    }
+    return false;
+}
+
</ins><span class="cx"> std::unique_ptr&lt;CSSParserSelector&gt; CSSSelectorParser::consumePseudo(CSSParserTokenRange&amp; range)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(range.peek().type() == ColonToken);
</span><span class="lines">@@ -459,7 +512,8 @@
</span><span class="cx"> 
</span><span class="cx">     if (token.type() == IdentToken) {
</span><span class="cx">         range.consume();
</span><del>-        if ((selector-&gt;match() == CSSSelector::PseudoElement &amp;&amp; selector-&gt;pseudoElementType() == CSSSelector::PseudoElementUnknown) || (selector-&gt;match() == CSSSelector::PseudoClass &amp;&amp; selector-&gt;pseudoClassType() == CSSSelector::PseudoClassUnknown))
</del><ins>+        if ((selector-&gt;match() == CSSSelector::PseudoElement &amp;&amp; (selector-&gt;pseudoElementType() == CSSSelector::PseudoElementUnknown || isPseudoElementFunction(selector-&gt;pseudoElementType())))
+            || (selector-&gt;match() == CSSSelector::PseudoClass &amp;&amp; (selector-&gt;pseudoClassType() == CSSSelector::PseudoClassUnknown || isPseudoClassFunction(selector-&gt;pseudoClassType()))))
</ins><span class="cx">             return nullptr;
</span><span class="cx">         return selector;
</span><span class="cx">     }
</span><span class="lines">@@ -469,78 +523,112 @@
</span><span class="cx">     if (token.type() != FunctionToken)
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    switch (selector-&gt;pseudoClassType()) {
-    case CSSSelector::PseudoClassNot: {
-        std::unique_ptr&lt;CSSParserSelector&gt; innerSelector = consumeCompoundSelector(block);
-        block.consumeWhitespace();
-        if (!innerSelector || !block.atEnd())
-            return nullptr;
-        Vector&lt;std::unique_ptr&lt;CSSParserSelector&gt;&gt; selectorVector;
-        selectorVector.append(WTFMove(innerSelector));
-        selector-&gt;adoptSelectorVector(selectorVector);
-        return selector;
-    }
-    case CSSSelector::PseudoClassNthChild:
-    case CSSSelector::PseudoClassNthLastChild:
-    case CSSSelector::PseudoClassNthOfType:
-    case CSSSelector::PseudoClassNthLastOfType: {
-        std::pair&lt;int, int&gt; ab;
-        if (!consumeANPlusB(block, ab))
-            return nullptr;
-        block.consumeWhitespace();
-        if (!block.atEnd())
-            return nullptr;
-        selector-&gt;setArgument(AtomicString::number(ab.first * ab.second));
-        return selector;
-    }
-    case CSSSelector::PseudoClassLang: {
-        // FIXME: CSS Selectors Level 4 allows :lang(*-foo)
-        const CSSParserToken&amp; ident = block.consumeIncludingWhitespace();
-        if (ident.type() != IdentToken || !block.atEnd())
-            return nullptr;
-        selector-&gt;setArgument(ident.value().toAtomicString());
-        return selector;
-    }
-    // FIXME-NEWPARSER: Support :host-context
-    case CSSSelector::PseudoClassAny:
-    case CSSSelector::PseudoClassHost: {
-        DisallowPseudoElementsScope scope(this);
-        std::unique_ptr&lt;CSSSelectorList&gt; selectorList = std::unique_ptr&lt;CSSSelectorList&gt;(new CSSSelectorList());
-        *selectorList = consumeCompoundSelectorList(block);
-        if (!selectorList-&gt;isValid() || !block.atEnd())
-            return nullptr;
-        selector-&gt;setSelectorList(WTFMove(selectorList));
-        return selector;
-    }
-    default:
-        break;
-    }
</del><ins>+    if (selector-&gt;match() == CSSSelector::PseudoClass) {
+        switch (selector-&gt;pseudoClassType()) {
+        case CSSSelector::PseudoClassNot: {
+            DisallowPseudoElementsScope scope(this);
+            std::unique_ptr&lt;CSSSelectorList&gt; selectorList = std::unique_ptr&lt;CSSSelectorList&gt;(new CSSSelectorList());
+            *selectorList = consumeComplexSelectorList(block);
+            if (!selectorList-&gt;componentCount() || !block.atEnd())
+                return nullptr;
+            selector-&gt;setSelectorList(WTFMove(selectorList));
+            return selector;
+        }
+        case CSSSelector::PseudoClassNthChild:
+        case CSSSelector::PseudoClassNthLastChild:
+        case CSSSelector::PseudoClassNthOfType:
+        case CSSSelector::PseudoClassNthLastOfType: {
+            std::pair&lt;int, int&gt; ab;
+            if (!consumeANPlusB(block, ab))
+                return nullptr;
+            block.consumeWhitespace();
+            if (!block.atEnd()) {
+                if (block.peek().type() != IdentToken)
+                    return nullptr;
+                const CSSParserToken&amp; ident = block.consume();
+                if (!equalIgnoringASCIICase(ident.value(), &quot;of&quot;))
+                    return nullptr;
+                DisallowPseudoElementsScope scope(this);
+                block.consumeWhitespace();
+                std::unique_ptr&lt;CSSSelectorList&gt; selectorList = std::unique_ptr&lt;CSSSelectorList&gt;(new CSSSelectorList());
+                *selectorList = consumeComplexSelectorList(block);
+                if (!selectorList-&gt;componentCount() || !block.atEnd())
+                    return nullptr;
+                selector-&gt;setSelectorList(WTFMove(selectorList));
+            }
+            selector-&gt;setNth(ab.first, ab.second);
+            return selector;
+        }
+        case CSSSelector::PseudoClassLang: {
+            // FIXME: CSS Selectors Level 4 allows :lang(*-foo)
+            auto argumentList = std::make_unique&lt;Vector&lt;AtomicString&gt;&gt;();
+            if (!consumeLangArgumentList(argumentList, block))
+                return nullptr;
+            selector-&gt;setLangArgumentList(WTFMove(argumentList));
+            return selector;
+        }
+        case CSSSelector::PseudoClassMatches: {
+            std::unique_ptr&lt;CSSSelectorList&gt; selectorList = std::unique_ptr&lt;CSSSelectorList&gt;(new CSSSelectorList());
+            *selectorList = consumeComplexSelectorList(block);
+            if (!selectorList-&gt;componentCount() || !block.atEnd())
+                return nullptr;
+            selector-&gt;setSelectorList(WTFMove(selectorList));
+            return selector;
+        }
+        // FIXME-NEWPARSER: Support :host-context
+        case CSSSelector::PseudoClassAny:
+        case CSSSelector::PseudoClassHost: {
+            DisallowPseudoElementsScope scope(this);
+            std::unique_ptr&lt;CSSSelectorList&gt; selectorList = std::unique_ptr&lt;CSSSelectorList&gt;(new CSSSelectorList());
+            *selectorList = consumeCompoundSelectorList(block);
+            if (!selectorList-&gt;componentCount() || !block.atEnd())
+                return nullptr;
+            selector-&gt;setSelectorList(WTFMove(selectorList));
+            return selector;
+        }
+#if ENABLE_CSS_SELECTORS_LEVEL4
+        case CSSSelector::PseudoClassDir:
+        case CSSSelector::PseudoClassRole: {
+            const CSSParserToken&amp; ident = block.consumeIncludingWhitespace();
+            if (ident.type() != IdentToken)
+                return nullptr;
+            selector-&gt;setArgument(ident.value().toAtomicString());
+            return selector;
+        }
+#endif
+        default:
+            break;
+        }
</ins><span class="cx"> 
</span><del>-    switch (selector-&gt;pseudoElementType()) {
-    case CSSSelector::PseudoElementCue: {
-        DisallowPseudoElementsScope scope(this);
-        std::unique_ptr&lt;CSSSelectorList&gt; selectorList = std::unique_ptr&lt;CSSSelectorList&gt;(new CSSSelectorList());
-        *selectorList = consumeCompoundSelectorList(block);
-        if (!selectorList-&gt;isValid() || !block.atEnd())
-            return nullptr;
-        selector-&gt;setSelectorList(WTFMove(selectorList));
-        return selector;
</del><span class="cx">     }
</span><del>-    case CSSSelector::PseudoElementSlotted: {
-        DisallowPseudoElementsScope scope(this);
</del><ins>+    
+    if (selector-&gt;match() == CSSSelector::PseudoElement) {
+        switch (selector-&gt;pseudoElementType()) {
+        case CSSSelector::PseudoElementCue: {
+            DisallowPseudoElementsScope scope(this);
+            std::unique_ptr&lt;CSSSelectorList&gt; selectorList = std::unique_ptr&lt;CSSSelectorList&gt;(new CSSSelectorList());
+            *selectorList = consumeCompoundSelectorList(block);
+            if (!selectorList-&gt;isValid() || !block.atEnd())
+                return nullptr;
+            selector-&gt;setSelectorList(WTFMove(selectorList));
+            return selector;
+        }
+        case CSSSelector::PseudoElementSlotted: {
+            DisallowPseudoElementsScope scope(this);
</ins><span class="cx"> 
</span><del>-        std::unique_ptr&lt;CSSParserSelector&gt; innerSelector = consumeCompoundSelector(block);
-        block.consumeWhitespace();
-        if (!innerSelector || !block.atEnd())
-            return nullptr;
-        Vector&lt;std::unique_ptr&lt;CSSParserSelector&gt;&gt; selectorVector;
-        selectorVector.append(WTFMove(innerSelector));
-        selector-&gt;adoptSelectorVector(selectorVector);
-        return selector;
</del><ins>+            std::unique_ptr&lt;CSSParserSelector&gt; innerSelector = consumeCompoundSelector(block);
+            block.consumeWhitespace();
+            if (!innerSelector || !block.atEnd())
+                return nullptr;
+            Vector&lt;std::unique_ptr&lt;CSSParserSelector&gt;&gt; selectorVector;
+            selectorVector.append(WTFMove(innerSelector));
+            selector-&gt;adoptSelectorVector(selectorVector);
+            return selector;
+        }
+        default:
+            break;
+        }
</ins><span class="cx">     }
</span><del>-    default:
-        break;
-    }
</del><span class="cx"> 
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="lines">@@ -564,6 +652,13 @@
</span><span class="cx">             return CSSSelector::DirectAdjacent;
</span><span class="cx">         if (delimiter == '~')
</span><span class="cx">             return CSSSelector::IndirectAdjacent;
</span><ins>+#if ENABLE_CSS_SELECTORS_LEVEL4
+        // FIXME-NEWPARSER: Need to set that this was a &gt;&gt; so serialization is correct
+        if (delimiter == '&gt;' &amp;&amp; range.peek().type() == DelimiterToken &amp;&amp; range.peek().delimiter() == '&gt;') {
+            range.consumeIncludingWhitespace();
+            return CSSSelector::Descendant;
+        }
+#endif
</ins><span class="cx">         return CSSSelector::Child;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>