<!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>[169585] trunk</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/169585">169585</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2014-06-04 00:25:29 -0700 (Wed, 04 Jun 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Fix some corner cases of :hover and :active in quirks mode
https://bugs.webkit.org/show_bug.cgi?id=133493

Reviewed by Andreas Kling.


Source/WebCore: 
Previously, the quirks mode of :hover and :active were evaluated from the SelectorFragment
in fragmentOnlyMatchesLinksInQuirksMode(). There were two problems with that approach:
1) The FragmentGenerator optimizes out some filter when they always match or can never match.
   Those fragment should still qualify :hover and :active, but they were lost
   for fragmentOnlyMatchesLinksInQuirksMode().
2) Explicitely listing every attribute of SelectorFragment in fragmentOnlyMatchesLinksInQuirksMode()
   was extremly fragile. When :not() and :-webkit-any() were added, we forgot to update the quirks
   exceptions.

This patch moves the quirks mode exception code from the code generator to the Fragment generator.
The useless filters are no longer ignored for the quirks, and we don't need to update the quirks mode detection
with every change of SelectorFragment.

It is inefficient and ugly, but that is how that quirks is defined. It is only a problem for compilation,
execution time remains unchanged.

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorFragment::SelectorFragment):
(WebCore::SelectorCompiler::addPseudoClassType):
(WebCore::SelectorCompiler::SelectorCodeGenerator::SelectorCodeGenerator):
(WebCore::SelectorCompiler::pseudoClassOnlyMatchesLinksInQuirksMode):
(WebCore::SelectorCompiler::constructFragments):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded):
(WebCore::SelectorCompiler::fragmentOnlyMatchesLinksInQuirksMode): Deleted.

LayoutTests: 
Add test case for the corner cases.

* fast/selectors/active-hover-quirks-expected.txt:
* fast/selectors/active-quirks-expected.txt:
* fast/selectors/hover-quirks-expected.txt:
* fast/selectors/resources/hover-active-quirks-utility.js:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastselectorsactivehoverquirksexpectedtxt">trunk/LayoutTests/fast/selectors/active-hover-quirks-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsactivequirksexpectedtxt">trunk/LayoutTests/fast/selectors/active-quirks-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorshoverquirksexpectedtxt">trunk/LayoutTests/fast/selectors/hover-quirks-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsresourceshoveractivequirksutilityjs">trunk/LayoutTests/fast/selectors/resources/hover-active-quirks-utility.js</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssjitSelectorCompilercpp">trunk/Source/WebCore/cssjit/SelectorCompiler.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (169584 => 169585)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-06-04 04:47:43 UTC (rev 169584)
+++ trunk/LayoutTests/ChangeLog        2014-06-04 07:25:29 UTC (rev 169585)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2014-06-03  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        Fix some corner cases of :hover and :active in quirks mode
+        https://bugs.webkit.org/show_bug.cgi?id=133493
+
+        Reviewed by Andreas Kling.
+
+        Add test case for the corner cases.
+
+        * fast/selectors/active-hover-quirks-expected.txt:
+        * fast/selectors/active-quirks-expected.txt:
+        * fast/selectors/hover-quirks-expected.txt:
+        * fast/selectors/resources/hover-active-quirks-utility.js:
+
</ins><span class="cx"> 2014-06-03  Gyuyoung Kim  &lt;gyuyoung.kim@samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Need to check invalid scheme in navigator content utils 
</span></span></pre></div>
<a id="trunkLayoutTestsfastselectorsactivehoverquirksexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/selectors/active-hover-quirks-expected.txt (169584 => 169585)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/active-hover-quirks-expected.txt        2014-06-04 04:47:43 UTC (rev 169584)
+++ trunk/LayoutTests/fast/selectors/active-hover-quirks-expected.txt        2014-06-04 07:25:29 UTC (rev 169585)
</span><span class="lines">@@ -93,8 +93,28 @@
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><span class="cx"> PASS document.querySelectorAll(&quot;:nth-child(n):active:hover:nth-child(n) #target&quot;).length is 1
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><ins>+PASS document.querySelectorAll(&quot;:active:hover:-webkit-any(*) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</ins><span class="cx"> PASS document.querySelectorAll(&quot;:-webkit-any(:active:hover) #target&quot;).length is 1
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><ins>+PASS document.querySelectorAll(&quot;:-webkit-any(*):active:hover #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:-webkit-any(*):active:hover:-webkit-any(*) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:active:hover:not(gecko) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not(gecko):active:hover #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not(gecko):active:hover:not(gecko) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:active:hover:not([webkit^=\&quot;\&quot;]) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not([webkit^=\&quot;\&quot;]):active:hover #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:active:hover:not(:nth-child(-1)) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not(:nth-child(-1)):active:hover #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsfastselectorsactivequirksexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/selectors/active-quirks-expected.txt (169584 => 169585)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/active-quirks-expected.txt        2014-06-04 04:47:43 UTC (rev 169584)
+++ trunk/LayoutTests/fast/selectors/active-quirks-expected.txt        2014-06-04 07:25:29 UTC (rev 169585)
</span><span class="lines">@@ -93,8 +93,28 @@
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><span class="cx"> PASS document.querySelectorAll(&quot;:nth-child(n):active:nth-child(n) #target&quot;).length is 1
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><ins>+PASS document.querySelectorAll(&quot;:active:-webkit-any(*) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</ins><span class="cx"> PASS document.querySelectorAll(&quot;:-webkit-any(:active) #target&quot;).length is 1
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><ins>+PASS document.querySelectorAll(&quot;:-webkit-any(*):active #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:-webkit-any(*):active:-webkit-any(*) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:active:not(gecko) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not(gecko):active #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not(gecko):active:not(gecko) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:active:not([webkit^=\&quot;\&quot;]) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not([webkit^=\&quot;\&quot;]):active #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:active:not(:nth-child(-1)) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not(:nth-child(-1)):active #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsfastselectorshoverquirksexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/selectors/hover-quirks-expected.txt (169584 => 169585)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/hover-quirks-expected.txt        2014-06-04 04:47:43 UTC (rev 169584)
+++ trunk/LayoutTests/fast/selectors/hover-quirks-expected.txt        2014-06-04 07:25:29 UTC (rev 169585)
</span><span class="lines">@@ -93,8 +93,28 @@
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><span class="cx"> PASS document.querySelectorAll(&quot;:nth-child(n):hover:nth-child(n) #target&quot;).length is 1
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><ins>+PASS document.querySelectorAll(&quot;:hover:-webkit-any(*) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</ins><span class="cx"> PASS document.querySelectorAll(&quot;:-webkit-any(:hover) #target&quot;).length is 1
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><ins>+PASS document.querySelectorAll(&quot;:-webkit-any(*):hover #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:-webkit-any(*):hover:-webkit-any(*) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:hover:not(gecko) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not(gecko):hover #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not(gecko):hover:not(gecko) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:hover:not([webkit^=\&quot;\&quot;]) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not([webkit^=\&quot;\&quot;]):hover #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:hover:not(:nth-child(-1)) #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS document.querySelectorAll(&quot;:not(:nth-child(-1)):hover #target&quot;).length is 1
+PASS getComputedStyle(document.getElementById(&quot;target&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsfastselectorsresourceshoveractivequirksutilityjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/selectors/resources/hover-active-quirks-utility.js (169584 => 169585)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/resources/hover-active-quirks-utility.js        2014-06-04 04:47:43 UTC (rev 169584)
+++ trunk/LayoutTests/fast/selectors/resources/hover-active-quirks-utility.js        2014-06-04 07:25:29 UTC (rev 169585)
</span><span class="lines">@@ -66,7 +66,20 @@
</span><span class="cx">     [&quot;PLACEHOLDER:nth-child(n) #target&quot;, true],
</span><span class="cx">     [&quot;:nth-child(n)PLACEHOLDER:nth-child(n) #target&quot;, true],
</span><span class="cx"> 
</span><ins>+    [&quot;PLACEHOLDER:-webkit-any(*) #target&quot;, true],
</ins><span class="cx">     [&quot;:-webkit-any(PLACEHOLDER) #target&quot;, true],
</span><ins>+    [&quot;:-webkit-any(*)PLACEHOLDER #target&quot;, true],
+    [&quot;:-webkit-any(*)PLACEHOLDER:-webkit-any(*) #target&quot;, true],
+
+    [&quot;PLACEHOLDER:not(gecko) #target&quot;, true],
+    [&quot;:not(gecko)PLACEHOLDER #target&quot;, true],
+    [&quot;:not(gecko)PLACEHOLDER:not(gecko) #target&quot;, true],
+
+    // A :not() functional pseudo class that cannot match anything should still qualify.
+    [&quot;PLACEHOLDER:not([webkit^=\\\&quot;\\\&quot;]) #target&quot;, true],
+    [&quot;:not([webkit^=\\\&quot;\\\&quot;])PLACEHOLDER #target&quot;, true],
+    [&quot;PLACEHOLDER:not(:nth-child(-1)) #target&quot;, true],
+    [&quot;:not(:nth-child(-1))PLACEHOLDER #target&quot;, true],
</ins><span class="cx"> ];
</span><span class="cx"> 
</span><span class="cx"> function testQuerySelector(selector, shouldMatch) {
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (169584 => 169585)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-06-04 04:47:43 UTC (rev 169584)
+++ trunk/Source/WebCore/ChangeLog        2014-06-04 07:25:29 UTC (rev 169585)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2014-06-03  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        Fix some corner cases of :hover and :active in quirks mode
+        https://bugs.webkit.org/show_bug.cgi?id=133493
+
+        Reviewed by Andreas Kling.
+
+        Previously, the quirks mode of :hover and :active were evaluated from the SelectorFragment
+        in fragmentOnlyMatchesLinksInQuirksMode(). There were two problems with that approach:
+        1) The FragmentGenerator optimizes out some filter when they always match or can never match.
+           Those fragment should still qualify :hover and :active, but they were lost
+           for fragmentOnlyMatchesLinksInQuirksMode().
+        2) Explicitely listing every attribute of SelectorFragment in fragmentOnlyMatchesLinksInQuirksMode()
+           was extremly fragile. When :not() and :-webkit-any() were added, we forgot to update the quirks
+           exceptions.
+
+        This patch moves the quirks mode exception code from the code generator to the Fragment generator.
+        The useless filters are no longer ignored for the quirks, and we don't need to update the quirks mode detection
+        with every change of SelectorFragment.
+
+        It is inefficient and ugly, but that is how that quirks is defined. It is only a problem for compilation,
+        execution time remains unchanged.
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::SelectorFragment::SelectorFragment):
+        (WebCore::SelectorCompiler::addPseudoClassType):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::SelectorCodeGenerator):
+        (WebCore::SelectorCompiler::pseudoClassOnlyMatchesLinksInQuirksMode):
+        (WebCore::SelectorCompiler::constructFragments):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded):
+        (WebCore::SelectorCompiler::fragmentOnlyMatchesLinksInQuirksMode): Deleted.
+
</ins><span class="cx"> 2014-06-03  Gyuyoung Kim  &lt;gyuyoung.kim@samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Need to check invalid scheme in navigator content utils 
</span></span></pre></div>
<a id="trunkSourceWebCorecssjitSelectorCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (169584 => 169585)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2014-06-04 04:47:43 UTC (rev 169584)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2014-06-04 07:25:29 UTC (rev 169585)
</span><span class="lines">@@ -132,7 +132,7 @@
</span><span class="cx">         , widthFromIndirectAdjacent(0)
</span><span class="cx">         , tagName(nullptr)
</span><span class="cx">         , id(nullptr)
</span><del>-        , inFunctionalPseudoClass(false)
</del><ins>+        , onlyMatchesLinksInQuirksMode(true)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     FragmentRelation relationToLeftFragment;
</span><span class="lines">@@ -159,7 +159,18 @@
</span><span class="cx">     Vector&lt;SelectorFragment&gt; notFilters;
</span><span class="cx">     Vector&lt;Vector&lt;SelectorFragment&gt;&gt; anyFilters;
</span><span class="cx"> 
</span><del>-    bool inFunctionalPseudoClass;
</del><ins>+    // For quirks mode, follow this: http://quirks.spec.whatwg.org/#the-:active-and-:hover-quirk
+    // In quirks mode, a compound selector 'selector' that matches the following conditions must not match elements that would not also match the ':any-link' selector.
+    //
+    //    selector uses the ':active' or ':hover' pseudo-classes.
+    //    selector does not use a type selector.
+    //    selector does not use an attribute selector.
+    //    selector does not use an ID selector.
+    //    selector does not use a class selector.
+    //    selector does not use a pseudo-class selector other than ':active' and ':hover'.
+    //    selector does not use a pseudo-element selector.
+    //    selector is not part of an argument to a functional pseudo-class or pseudo-element.
+    bool onlyMatchesLinksInQuirksMode;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct TagNamePattern {
</span><span class="lines">@@ -278,8 +289,13 @@
</span><span class="cx"> const Assembler::RegisterID SelectorCodeGenerator::checkingContextRegister = JSC::GPRInfo::argumentGPR1;
</span><span class="cx"> const Assembler::RegisterID SelectorCodeGenerator::callFrameRegister = JSC::GPRInfo::callFrameRegister;
</span><span class="cx"> 
</span><del>-static FunctionType constructFragments(const CSSSelector* rootSelector, SelectorContext, SelectorFragmentList&amp; selectorFragments);
</del><ins>+enum class FragmentsLevel {
+    Root = 0,
+    InFunctionalPseudoType = 1
+};
</ins><span class="cx"> 
</span><ins>+static FunctionType constructFragments(const CSSSelector* rootSelector, SelectorContext, SelectorFragmentList&amp; selectorFragments, FragmentsLevel);
+
</ins><span class="cx"> static void computeBacktrackingInformation(SelectorFragmentList&amp; selectorFragments, bool&amp; needsAdjacentBacktrackingStart);
</span><span class="cx"> 
</span><span class="cx"> SelectorCompilationStatus compileSelector(const CSSSelector* lastSelector, JSC::VM* vm, SelectorContext selectorContext, JSC::MacroAssemblerCodeRef&amp; codeRef)
</span><span class="lines">@@ -419,7 +435,7 @@
</span><span class="cx">                 return FunctionType::CannotMatchAnything;
</span><span class="cx"> 
</span><span class="cx">             SelectorFragmentList notFragments;
</span><del>-            FunctionType functionType = constructFragments(selectorList-&gt;first(), selectorContext, notFragments);
</del><ins>+            FunctionType functionType = constructFragments(selectorList-&gt;first(), selectorContext, notFragments, FragmentsLevel::InFunctionalPseudoType);
</ins><span class="cx"> 
</span><span class="cx">             // Since this is not pseudo class filter, CannotMatchAnything implies this filter always passes.
</span><span class="cx">             if (functionType == FunctionType::CannotMatchAnything)
</span><span class="lines">@@ -432,8 +448,7 @@
</span><span class="cx">             if (notFragments.size() != 1)
</span><span class="cx">                 return FunctionType::CannotCompile;
</span><span class="cx"> 
</span><del>-            SelectorFragment subFragment = notFragments.first();
-            subFragment.inFunctionalPseudoClass = true;
</del><ins>+            const SelectorFragment&amp; subFragment = notFragments.first();
</ins><span class="cx"> 
</span><span class="cx">             // FIXME: Currently we don't support visitedMatchType.
</span><span class="cx">             if (subFragment.pseudoClasses.contains(CSSSelector::PseudoClassLink))
</span><span class="lines">@@ -449,7 +464,7 @@
</span><span class="cx">             FunctionType functionType = FunctionType::SimpleSelectorChecker;
</span><span class="cx">             for (const CSSSelector* rootSelector = selector.selectorList()-&gt;first(); rootSelector; rootSelector = CSSSelectorList::next(rootSelector)) {
</span><span class="cx">                 SelectorFragmentList fragmentList;
</span><del>-                FunctionType subFunctionType = constructFragments(rootSelector, selectorContext, fragmentList);
</del><ins>+                FunctionType subFunctionType = constructFragments(rootSelector, selectorContext, fragmentList, FragmentsLevel::InFunctionalPseudoType);
</ins><span class="cx"> 
</span><span class="cx">                 // Since this fragment always unmatch against the element, don't insert it to anyFragments.
</span><span class="cx">                 if (subFunctionType == FunctionType::CannotMatchAnything)
</span><span class="lines">@@ -463,8 +478,7 @@
</span><span class="cx">                 if (fragmentList.size() != 1)
</span><span class="cx">                     return FunctionType::CannotCompile;
</span><span class="cx"> 
</span><del>-                SelectorFragment subFragment = fragmentList.first();
-                subFragment.inFunctionalPseudoClass = true;
</del><ins>+                const SelectorFragment&amp; subFragment = fragmentList.first();
</ins><span class="cx">                 anyFragments.append(subFragment);
</span><span class="cx">                 functionType = mostRestrictiveFunctionType(functionType, subFunctionType);
</span><span class="cx">             }
</span><span class="lines">@@ -498,13 +512,19 @@
</span><span class="cx">     dataLogF(&quot;Compiling \&quot;%s\&quot;\n&quot;, m_originalSelector-&gt;selectorText().utf8().data());
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    m_functionType = constructFragments(rootSelector, m_selectorContext, m_selectorFragments);
</del><ins>+    m_functionType = constructFragments(rootSelector, m_selectorContext, m_selectorFragments, FragmentsLevel::Root);
</ins><span class="cx">     if (m_functionType != FunctionType::CannotCompile &amp;&amp; m_functionType != FunctionType::CannotMatchAnything)
</span><span class="cx">         computeBacktrackingInformation(m_selectorFragments, m_needsAdjacentBacktrackingStart);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static FunctionType constructFragments(const CSSSelector* rootSelector, SelectorContext selectorContext, SelectorFragmentList&amp; selectorFragments)
</del><ins>+static bool pseudoClassOnlyMatchesLinksInQuirksMode(const CSSSelector&amp; selector)
</ins><span class="cx"> {
</span><ins>+    CSSSelector::PseudoClassType pseudoClassType = selector.pseudoClassType();
+    return pseudoClassType == CSSSelector::PseudoClassHover || pseudoClassType == CSSSelector::PseudoClassActive;
+}
+
+static FunctionType constructFragments(const CSSSelector* rootSelector, SelectorContext selectorContext, SelectorFragmentList&amp; selectorFragments, FragmentsLevel fragmentLevel)
+{
</ins><span class="cx">     SelectorFragment fragment;
</span><span class="cx">     FragmentRelation relationToPreviousFragment = FragmentRelation::Rightmost;
</span><span class="cx">     FunctionType functionType = FunctionType::SimpleSelectorChecker;
</span><span class="lines">@@ -513,51 +533,60 @@
</span><span class="cx">         case CSSSelector::Tag:
</span><span class="cx">             ASSERT(!fragment.tagName);
</span><span class="cx">             fragment.tagName = &amp;(selector-&gt;tagQName());
</span><ins>+            if (*fragment.tagName != anyQName())
+                fragment.onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             break;
</span><span class="cx">         case CSSSelector::Id: {
</span><span class="cx">             const AtomicString&amp; id = selector-&gt;value();
</span><span class="cx">             if (fragment.id) {
</span><del>-                if (id != *fragment.id) {
</del><ins>+                if (id != *fragment.id)
</ins><span class="cx">                     return FunctionType::CannotMatchAnything;
</span><del>-                }
</del><span class="cx">             } else
</span><span class="cx">                 fragment.id = &amp;(selector-&gt;value());
</span><ins>+            fragment.onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case CSSSelector::Class:
</span><span class="cx">             fragment.classNames.append(selector-&gt;value().impl());
</span><ins>+            fragment.onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PseudoClass:
</span><span class="cx">             functionType = mostRestrictiveFunctionType(functionType, addPseudoClassType(*selector, fragment, selectorContext));
</span><ins>+            if (!pseudoClassOnlyMatchesLinksInQuirksMode(*selector))
+                fragment.onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             if (functionType == FunctionType::CannotCompile || functionType == FunctionType::CannotMatchAnything)
</span><span class="cx">                 return functionType;
</span><span class="cx">             break;
</span><ins>+
</ins><span class="cx">         case CSSSelector::List:
</span><del>-            if (selector-&gt;value().contains(' ')) {
</del><ins>+            if (selector-&gt;value().contains(' '))
</ins><span class="cx">                 return FunctionType::CannotMatchAnything;
</span><del>-            }
</del><span class="cx">             FALLTHROUGH;
</span><span class="cx">         case CSSSelector::Begin:
</span><span class="cx">         case CSSSelector::End:
</span><span class="cx">         case CSSSelector::Contain:
</span><del>-            if (selector-&gt;value().isEmpty()) {
</del><ins>+            if (selector-&gt;value().isEmpty())
</ins><span class="cx">                 return FunctionType::CannotMatchAnything;
</span><del>-            }
</del><span class="cx">             FALLTHROUGH;
</span><span class="cx">         case CSSSelector::Exact:
</span><span class="cx">         case CSSSelector::Hyphen:
</span><ins>+            fragment.onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             fragment.attributes.append(AttributeMatchingInfo(selector, HTMLDocument::isCaseSensitiveAttribute(selector-&gt;attribute())));
</span><span class="cx">             break;
</span><ins>+
</ins><span class="cx">         case CSSSelector::Set:
</span><ins>+            fragment.onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             fragment.attributes.append(AttributeMatchingInfo(selector, true));
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PagePseudoClass:
</span><ins>+            fragment.onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             // Pseudo page class are only relevant for style resolution, they are ignored for matching.
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::Unknown:
</span><span class="cx">             ASSERT_NOT_REACHED();
</span><span class="cx">             return FunctionType::CannotMatchAnything;
</span><span class="cx">         case CSSSelector::PseudoElement:
</span><ins>+            fragment.onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             return FunctionType::CannotCompile;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -579,6 +608,8 @@
</span><span class="cx">         fragment.relationToRightFragment = relationToPreviousFragment;
</span><span class="cx">         relationToPreviousFragment = fragment.relationToLeftFragment;
</span><span class="cx"> 
</span><ins>+        if (fragmentLevel == FragmentsLevel::InFunctionalPseudoType)
+            fragment.onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">         selectorFragments.append(fragment);
</span><span class="cx">         fragment = SelectorFragment();
</span><span class="cx">     }
</span><span class="lines">@@ -1371,45 +1402,6 @@
</span><span class="cx">     return m_assembler.branch8(Assembler::NotEqual, Assembler::Address(checkingContext, OBJECT_OFFSETOF(CheckingContext, resolvingMode)), Assembler::TrustedImm32(SelectorChecker::ResolvingStyle));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool fragmentOnlyMatchesLinksInQuirksMode(const SelectorFragment&amp; fragment)
-{
-    // For quirks mode, follow this: http://quirks.spec.whatwg.org/#the-:active-and-:hover-quirk
-    // In quirks mode, a compound selector 'selector' that matches the following conditions must not match elements that would not also match the ':any-link' selector.
-    //
-    //    selector uses the ':active' or ':hover' pseudo-classes.
-    //    selector does not use a type selector.
-    //    selector does not use an attribute selector.
-    //    selector does not use an ID selector.
-    //    selector does not use a class selector.
-    //    selector does not use a pseudo-class selector other than ':active' and ':hover'.
-    //    selector does not use a pseudo-element selector.
-    //    selector is not part of an argument to a functional pseudo-class or pseudo-element.
-    if (fragment.tagName &amp;&amp; *fragment.tagName != anyQName())
-        return false;
-
-    if (!fragment.attributes.isEmpty())
-        return false;
-
-    if (fragment.id)
-        return false;
-
-    if (!fragment.classNames.isEmpty())
-        return false;
-
-    if (!fragment.unoptimizedPseudoClasses.isEmpty() || !fragment.nthChildFilters.isEmpty())
-        return false;
-
-    for (unsigned pseudoClassType : fragment.pseudoClasses) {
-        if (pseudoClassType != CSSSelector::PseudoClassHover &amp;&amp; pseudoClassType != CSSSelector::PseudoClassActive)
-            return false;
-    }
-
-    if (fragment.inFunctionalPseudoClass)
-        return false;
-
-    return true;
-}
-
</del><span class="cx"> static void getDocument(Assembler&amp; assembler, Assembler::RegisterID element, Assembler::RegisterID output)
</span><span class="cx"> {
</span><span class="cx">     assembler.loadPtr(Assembler::Address(element, Node::treeScopeMemoryOffset()), output);
</span><span class="lines">@@ -1418,7 +1410,7 @@
</span><span class="cx"> 
</span><span class="cx"> void SelectorCodeGenerator::generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</span><span class="cx"> {
</span><del>-    if (fragmentOnlyMatchesLinksInQuirksMode(fragment)) {
</del><ins>+    if (fragment.onlyMatchesLinksInQuirksMode) {
</ins><span class="cx">         // If the element is a link, it can always match :hover or :active.
</span><span class="cx">         Assembler::Jump isLink = m_assembler.branchTest32(Assembler::NonZero, Assembler::Address(elementAddressRegister, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagIsLink()));
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>