<!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>[202470] 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/202470">202470</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2016-06-25 21:34:23 -0700 (Sat, 25 Jun 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>The active state of elements can break when focus changes
https://bugs.webkit.org/show_bug.cgi?id=159112

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2016-06-25
Reviewed by Antti Koivisto.

Source/WebCore:

The pseudo class :active was behaving weirdly when used
with label elements with an associated form element.
The form element would get the :active state on the first click
then no longer get the state until the focus changes.

What was happenning is setFocusedElement() was clearing active
for some unknown reason. When you really do that on an active element,
you end up in an inconsistent state where no invalidation works.

The two tests illustrates 2 ways this breaks.

The test &quot;pseudo-active-on-labeled-element-not-canceled-by-focus&quot; clicks
several time on a lable element. The first time, the input element gets
the focus. The second time, it already has the focus, setFocusedElement()
clears :active before finding the focusable element and end up clearing
the active state on a target in the active chain.

The test &quot;pseudo-active-with-programmatic-focus.html&quot; shows how to invalidate
arbitrary elements using JavaScript. This can cause severely broken active
chains where invalidation never cleans some ancestors.

Tests: fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus.html
       fast/css/pseudo-active-with-programmatic-focus.html

* dom/Document.cpp:
(WebCore::Document::setFocusedElement): Deleted.

* page/EventHandler.cpp:
(WebCore::EventHandler::handleMouseDoubleClickEvent):
This is WebKit1 specific. The double click event was dispatching
the mouseUp and Click with after doing an Active hit test.
This causes us to have :active state in and after mouseUp in WebKit1.

LayoutTests:

* fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus-expected.txt: Added.
* fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus.html: Added.
* fast/css/pseudo-active-with-programmatic-focus-expected.txt: Added.
* fast/css/pseudo-active-with-programmatic-focus.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorTestExpectations">trunk/LayoutTests/platform/ios-simulator/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCorepageEventHandlercpp">trunk/Source/WebCore/page/EventHandler.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastcsspseudoactiveonlabeledelementnotcanceledbyfocusexpectedtxt">trunk/LayoutTests/fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcsspseudoactiveonlabeledelementnotcanceledbyfocushtml">trunk/LayoutTests/fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus.html</a></li>
<li><a href="#trunkLayoutTestsfastcsspseudoactivewithprogrammaticfocusexpectedtxt">trunk/LayoutTests/fast/css/pseudo-active-with-programmatic-focus-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcsspseudoactivewithprogrammaticfocushtml">trunk/LayoutTests/fast/css/pseudo-active-with-programmatic-focus.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (202469 => 202470)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-06-25 19:07:15 UTC (rev 202469)
+++ trunk/LayoutTests/ChangeLog        2016-06-26 04:34:23 UTC (rev 202470)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-06-25  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        The active state of elements can break when focus changes
+        https://bugs.webkit.org/show_bug.cgi?id=159112
+
+        Reviewed by Antti Koivisto.
+
+        * fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus-expected.txt: Added.
+        * fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus.html: Added.
+        * fast/css/pseudo-active-with-programmatic-focus-expected.txt: Added.
+        * fast/css/pseudo-active-with-programmatic-focus.html: Added.
+
</ins><span class="cx"> 2016-06-24  Jer Noble  &lt;jer.noble@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Consider exposing or hiding knowledge of a redirect from clients of WebCoreNSURLSession
</span></span></pre></div>
<a id="trunkLayoutTestsfastcsspseudoactiveonlabeledelementnotcanceledbyfocusexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus-expected.txt (0 => 202470)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus-expected.txt        2016-06-26 04:34:23 UTC (rev 202470)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+Verify that indirect :active on a labeled element is not affected when the element gets focus from the click.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+
+    Initial state
+PASS elementsWithActiveStyle() is []
+PASS elementsMatchingActiveSelector() is []
+On Mouse Down
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;, &quot;sibling5&quot;]
+PASS elementsMatchingActiveSelector() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;]
+After Mouse Down
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;, &quot;sibling5&quot;]
+PASS elementsMatchingActiveSelector() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;]
+On Mouse Up
+PASS elementsWithActiveStyle() is []
+PASS elementsMatchingActiveSelector() is []
+After Mouse Up
+PASS elementsWithActiveStyle() is []
+PASS elementsMatchingActiveSelector() is []
+On Mouse Down
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;, &quot;sibling5&quot;]
+PASS elementsMatchingActiveSelector() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;]
+After Mouse Down
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;, &quot;sibling5&quot;]
+PASS elementsMatchingActiveSelector() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;]
+On Mouse Up
+PASS elementsWithActiveStyle() is []
+PASS elementsMatchingActiveSelector() is []
+After Mouse Up
+PASS elementsWithActiveStyle() is []
+PASS elementsMatchingActiveSelector() is []
+On Mouse Down
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;, &quot;sibling5&quot;]
+PASS elementsMatchingActiveSelector() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;]
+After Mouse Down
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;, &quot;sibling5&quot;]
+PASS elementsMatchingActiveSelector() is [&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;]
+On Mouse Up
+PASS elementsWithActiveStyle() is []
+PASS elementsMatchingActiveSelector() is []
+After Mouse Up
+PASS elementsWithActiveStyle() is []
+PASS elementsMatchingActiveSelector() is []
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcsspseudoactiveonlabeledelementnotcanceledbyfocushtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus.html (0 => 202470)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus.html                                (rev 0)
+++ trunk/LayoutTests/fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus.html        2016-06-26 04:34:23 UTC (rev 202470)
</span><span class="lines">@@ -0,0 +1,126 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html id=&quot;html&quot;&gt;
+&lt;head&gt;
+&lt;style id=&quot;custom-style&quot;&gt;
+    * {
+        background-color: white;
+        margin: 0;
+        padding: 0;
+    }
+    :active, input:active + * + * + * {
+        background-color: rgb(50, 100, 150) !important;
+    }
+    #target {
+        display: block;
+        width: 100px;
+        height: 100px;
+        background-color: green;
+    }
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;body id=&quot;body&quot;&gt;
+    &lt;div id=&quot;prime-ancestor&quot;&gt;
+        &lt;div id=&quot;labelable-ancestor&quot;&gt;
+            &lt;div id=&quot;labelable-parent&quot;&gt;
+                &lt;label for=&quot;labelable&quot; id=&quot;target&quot;&gt;Label&lt;/label&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+        &lt;div id=&quot;next-group&quot; style=&quot;display:block&quot;&gt;
+            &lt;div id=&quot;sibling1&quot;&gt;Sibling1&lt;/div&gt;
+            &lt;div id=&quot;sibling2&quot;&gt;Sibling2&lt;/div&gt;
+            &lt;input id=&quot;labelable&quot; value=&quot;Labelable Input&quot;&gt;
+            &lt;div id=&quot;sibling3&quot;&gt;Sibling3&lt;/div&gt;
+            &lt;div id=&quot;sibling4&quot;&gt;Sibling4&lt;/div&gt;
+            &lt;div id=&quot;sibling5&quot;&gt;Sibling5&lt;/div&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+    &lt;div id=&quot;console&quot;&gt;
+    &lt;/div&gt;
+    &lt;script&gt;
+    description(&quot;Verify that indirect :active on a labeled element is not affected when the element gets focus from the click.&quot;);
+    window.jsTestIsAsync = true;
+
+    function elementsWithActiveStyle() {
+        let elements = [];
+        for (let element of document.querySelectorAll(&quot;*&quot;)) {
+            if (getComputedStyle(element).backgroundColor === &quot;rgb(50, 100, 150)&quot;)
+                elements.push(element.id);
+        }
+        return elements;
+    }
+    function elementsMatchingActiveSelector() {
+        let elements = [];
+        for (let element of document.querySelectorAll(&quot;:active&quot;)) {
+            elements.push(element.id);
+        }
+        return elements;
+    }
+
+    if (window.eventSender) {
+        eventSender.mouseMoveTo(50, 50);
+    } else {
+        debug(&quot;&quot;);
+        debug(&quot;To run Manually, click-hold-release 3 times on the green rect. The rect and the input element should change color. All the results below should say PASS.&quot;)
+        debug(&quot;&quot;);
+    }
+
+    function sendMouseDown() {
+        if (window.eventSender) {
+            eventSender.mouseDown();
+        }
+    }
+
+    function sendMouseUp() {
+        if (window.eventSender) {
+            eventSender.mouseUp();
+        }
+    }
+
+    function mouseDownHandler(event, delayed = false) {
+        debug(delayed ? &quot;After Mouse Down&quot; : &quot;On Mouse Down&quot;);
+        shouldBe('elementsWithActiveStyle()', '[&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;, &quot;sibling5&quot;]');
+        shouldBe('elementsMatchingActiveSelector()', '[&quot;html&quot;, &quot;body&quot;, &quot;prime-ancestor&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;, &quot;labelable&quot;]');
+
+        // The current spec does not defined the order in which elements are activated.
+        // It is reasonable to have the activation after the mouseDown dispatch. That's what Firefox does at this time.
+        // This delayed handler ensure we cover both possibilities. The first handler fails on Firefox but that's not
+        // necessarily wrong, just undefined. The result is fine as long as one of the two handler succeed.
+        if (!delayed) {
+            setTimeout(function() { mouseDownHandler(event, true); }, 0);
+        } else {
+            sendMouseUp();
+        }
+    }
+    var target = document.getElementById('target');
+    target.addEventListener('mousedown', mouseDownHandler);
+
+    let mouseUpCount = 0;
+    function mouseUpHandler(event, delayed = false) {
+        debug(delayed ? &quot;After Mouse Up&quot; : &quot;On Mouse Up&quot;);
+        shouldBe('elementsWithActiveStyle()', '[]');
+        shouldBe('elementsMatchingActiveSelector()', '[]');
+        if (++mouseUpCount === 6) {
+            document.getElementById(&quot;prime-ancestor&quot;).style.display = &quot;none&quot;;
+            document.getElementById(&quot;custom-style&quot;).innerText = &quot;&quot;;
+            finishJSTest();
+        } else {
+            if (!delayed) {
+                setTimeout(function() { mouseUpHandler(event, true); }, 0);
+            } else {
+                sendMouseDown();
+            }
+        }
+    }
+    target.addEventListener('mouseup', mouseUpHandler);
+
+
+    debug(&quot;Initial state&quot;);
+    shouldBe('elementsWithActiveStyle()', '[]');
+    shouldBe('elementsMatchingActiveSelector()', '[]');
+
+    sendMouseDown();
+    &lt;/script&gt;
+    &lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcsspseudoactivewithprogrammaticfocusexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/pseudo-active-with-programmatic-focus-expected.txt (0 => 202470)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/pseudo-active-with-programmatic-focus-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/css/pseudo-active-with-programmatic-focus-expected.txt        2016-06-26 04:34:23 UTC (rev 202470)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+
+    
+Verify that :active remain consistent when the focus is changing.
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+    Initial state
+PASS elementsWithActiveStyle() is []
+PASS elementsMatchingSelector(&quot;:active&quot;) is []
+PASS elementsMatchingSelector(&quot;:focus&quot;) is []
+On Mouse Down
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+PASS elementsMatchingSelector(&quot;:active&quot;) is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+After Mouse Down
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+PASS elementsMatchingSelector(&quot;:active&quot;) is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+Focus the target
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+PASS elementsMatchingSelector(&quot;:active&quot;) is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+PASS elementsMatchingSelector(&quot;:focus&quot;) is [&quot;target&quot;]
+Focus input2
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+PASS elementsMatchingSelector(&quot;:active&quot;) is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+PASS elementsMatchingSelector(&quot;:focus&quot;) is [&quot;input2&quot;]
+Focus the target
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+PASS elementsMatchingSelector(&quot;:active&quot;) is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+PASS elementsMatchingSelector(&quot;:focus&quot;) is [&quot;target&quot;]
+Focus input1
+PASS elementsWithActiveStyle() is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+PASS elementsMatchingSelector(&quot;:active&quot;) is [&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]
+PASS elementsMatchingSelector(&quot;:focus&quot;) is [&quot;input1&quot;]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcsspseudoactivewithprogrammaticfocushtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/pseudo-active-with-programmatic-focus.html (0 => 202470)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/pseudo-active-with-programmatic-focus.html                                (rev 0)
+++ trunk/LayoutTests/fast/css/pseudo-active-with-programmatic-focus.html        2016-06-26 04:34:23 UTC (rev 202470)
</span><span class="lines">@@ -0,0 +1,127 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html id=&quot;html&quot;&gt;
+&lt;head&gt;
+&lt;style id=&quot;custom-style&quot;&gt;
+    * {
+        background-color: white;
+        margin: 0;
+        padding: 0;
+    }
+    :active {
+        background-color: rgb(50, 100, 150) !important;
+    }
+    #target {
+        display: block;
+        width: 100px;
+        height: 100px;
+        background-color: green;
+    }
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;body id=&quot;body&quot;&gt;
+    &lt;div id=&quot;webkit-test&quot;&gt;
+        &lt;div id=&quot;labelable-ancestor&quot;&gt;
+            &lt;div id=&quot;labelable-parent&quot;&gt;
+                &lt;textarea id=&quot;target&quot;&gt;Label&lt;/textarea&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+        &lt;div id=&quot;next-group&quot; style=&quot;display:block&quot;&gt;
+            &lt;input id=&quot;input1&quot; value=&quot;Input1&quot;&gt;
+            &lt;input id=&quot;input2&quot; value=&quot;Input2&quot;&gt;
+            &lt;input id=&quot;input3&quot; value=&quot;Input3&quot;&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+    &lt;div id=&quot;console&quot;&gt;
+    &lt;/div&gt;
+    &lt;script&gt;
+    description(&quot;Verify that :active remain consistent when the focus is changing.&quot;);
+    window.jsTestIsAsync = true;
+
+    function elementsWithActiveStyle() {
+        let elements = [];
+        for (let element of document.querySelectorAll(&quot;*&quot;)) {
+            if (getComputedStyle(element).backgroundColor === &quot;rgb(50, 100, 150)&quot;)
+                elements.push(element.id);
+        }
+        return elements;
+    }
+    function elementsMatchingSelector(selector) {
+        let elements = [];
+        for (let element of document.querySelectorAll(selector)) {
+            elements.push(element.id);
+        }
+        return elements;
+    }
+
+    if (window.eventSender) {
+        eventSender.mouseMoveTo(50, 50);
+    } else {
+        debug(&quot;&quot;);
+        debug(&quot;To run Manually, click-hold-release on the green rect. All the results below should say PASS.&quot;)
+        debug(&quot;&quot;);
+    }
+
+    function sendMouseDown() {
+        if (window.eventSender) {
+            eventSender.mouseDown();
+        }
+    }
+
+    function sendMouseUp() {
+        if (window.eventSender) {
+            eventSender.mouseUp();
+        }
+    }
+
+    var target = document.getElementById('target');
+    function afterMouseDown(event) {
+        debug(&quot;After Mouse Down&quot;);
+        shouldBe('elementsWithActiveStyle()', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+        shouldBe('elementsMatchingSelector(&quot;:active&quot;)', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+        debug(&quot;Focus the target&quot;);
+        target.focus();
+        shouldBe('elementsWithActiveStyle()', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+        shouldBe('elementsMatchingSelector(&quot;:active&quot;)', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+        shouldBe('elementsMatchingSelector(&quot;:focus&quot;)', '[&quot;target&quot;]');
+        debug(&quot;Focus input2&quot;);
+        let input2 = document.getElementById(&quot;input2&quot;);
+        input2.focus();
+        shouldBe('elementsWithActiveStyle()', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+        shouldBe('elementsMatchingSelector(&quot;:active&quot;)', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+        shouldBe('elementsMatchingSelector(&quot;:focus&quot;)', '[&quot;input2&quot;]');
+        debug(&quot;Focus the target&quot;);
+        target.focus();
+        shouldBe('elementsWithActiveStyle()', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+        shouldBe('elementsMatchingSelector(&quot;:active&quot;)', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+        shouldBe('elementsMatchingSelector(&quot;:focus&quot;)', '[&quot;target&quot;]');
+        debug(&quot;Focus input1&quot;);
+        let input1 = document.getElementById(&quot;input1&quot;);
+        input1.focus();
+        shouldBe('elementsWithActiveStyle()', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+        shouldBe('elementsMatchingSelector(&quot;:active&quot;)', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+        shouldBe('elementsMatchingSelector(&quot;:focus&quot;)', '[&quot;input1&quot;]');
+
+        finishJSTest();
+    }
+    function mouseDownHandler(event) {
+        debug(&quot;On Mouse Down&quot;);
+        shouldBe('elementsWithActiveStyle()', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+        shouldBe('elementsMatchingSelector(&quot;:active&quot;)', '[&quot;html&quot;, &quot;body&quot;, &quot;webkit-test&quot;, &quot;labelable-ancestor&quot;, &quot;labelable-parent&quot;, &quot;target&quot;]');
+
+        setTimeout(function() { afterMouseDown(event); }, 0);
+    }
+
+    target.addEventListener('mousedown', mouseDownHandler);
+
+
+    debug(&quot;Initial state&quot;);
+    shouldBe('elementsWithActiveStyle()', '[]');
+    shouldBe('elementsMatchingSelector(&quot;:active&quot;)', '[]');
+    shouldBe('elementsMatchingSelector(&quot;:focus&quot;)', '[]');
+
+    sendMouseDown();
+    &lt;/script&gt;
+    &lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (202469 => 202470)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator/TestExpectations        2016-06-25 19:07:15 UTC (rev 202469)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations        2016-06-26 04:34:23 UTC (rev 202470)
</span><span class="lines">@@ -1435,6 +1435,8 @@
</span><span class="cx"> fast/css/negative-text-indent-in-inline-block.html [ ImageOnlyFailure ]
</span><span class="cx"> fast/css/object-fit/object-fit-input-image.html [ ImageOnlyFailure ]
</span><span class="cx"> fast/css/outline-auto-empty-rects.html [ Failure ]
</span><ins>+fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus.html [ Failure ]
+fast/css/pseudo-active-with-programmatic-focus.html [ Failure ]
</ins><span class="cx"> fast/css/pseudo-first-line-border-width.html [ Failure ]
</span><span class="cx"> fast/css/read-only-read-write-input-basics.html [ ImageOnlyFailure ]
</span><span class="cx"> fast/css/replaced-element-implicit-size.html [ Failure ]
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (202469 => 202470)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-06-25 19:07:15 UTC (rev 202469)
+++ trunk/Source/WebCore/ChangeLog        2016-06-26 04:34:23 UTC (rev 202470)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2016-06-25  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        The active state of elements can break when focus changes
+        https://bugs.webkit.org/show_bug.cgi?id=159112
+
+        Reviewed by Antti Koivisto.
+
+        The pseudo class :active was behaving weirdly when used
+        with label elements with an associated form element.
+        The form element would get the :active state on the first click
+        then no longer get the state until the focus changes.
+
+        What was happenning is setFocusedElement() was clearing active
+        for some unknown reason. When you really do that on an active element,
+        you end up in an inconsistent state where no invalidation works.
+
+        The two tests illustrates 2 ways this breaks.
+
+        The test &quot;pseudo-active-on-labeled-element-not-canceled-by-focus&quot; clicks
+        several time on a lable element. The first time, the input element gets
+        the focus. The second time, it already has the focus, setFocusedElement()
+        clears :active before finding the focusable element and end up clearing
+        the active state on a target in the active chain.
+
+        The test &quot;pseudo-active-with-programmatic-focus.html&quot; shows how to invalidate
+        arbitrary elements using JavaScript. This can cause severely broken active
+        chains where invalidation never cleans some ancestors.
+
+        Tests: fast/css/pseudo-active-on-labeled-element-not-canceled-by-focus.html
+               fast/css/pseudo-active-with-programmatic-focus.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::setFocusedElement): Deleted.
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::handleMouseDoubleClickEvent):
+        This is WebKit1 specific. The double click event was dispatching
+        the mouseUp and Click with after doing an Active hit test.
+        This causes us to have :active state in and after mouseUp in WebKit1.
+
</ins><span class="cx"> 2016-06-24  Jer Noble  &lt;jer.noble@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Consider exposing or hiding knowledge of a redirect from clients of WebCoreNSURLSession
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (202469 => 202470)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2016-06-25 19:07:15 UTC (rev 202469)
+++ trunk/Source/WebCore/dom/Document.cpp        2016-06-26 04:34:23 UTC (rev 202470)
</span><span class="lines">@@ -3777,9 +3777,6 @@
</span><span class="cx"> 
</span><span class="cx">     // Remove focus from the existing focus node (if any)
</span><span class="cx">     if (oldFocusedElement) {
</span><del>-        if (oldFocusedElement-&gt;active())
-            oldFocusedElement-&gt;setActive(false);
-
</del><span class="cx">         oldFocusedElement-&gt;setFocus(false);
</span><span class="cx">         setFocusNavigationStartingNode(nullptr);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepageEventHandlercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/EventHandler.cpp (202469 => 202470)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/EventHandler.cpp        2016-06-25 19:07:15 UTC (rev 202469)
+++ trunk/Source/WebCore/page/EventHandler.cpp        2016-06-26 04:34:23 UTC (rev 202470)
</span><span class="lines">@@ -1752,7 +1752,7 @@
</span><span class="cx">     m_mousePressed = false;
</span><span class="cx">     setLastKnownMousePosition(platformMouseEvent);
</span><span class="cx"> 
</span><del>-    HitTestRequest request(HitTestRequest::Active | HitTestRequest::DisallowUserAgentShadowContent);
</del><ins>+    HitTestRequest request(HitTestRequest::Release | HitTestRequest::DisallowUserAgentShadowContent);
</ins><span class="cx">     MouseEventWithHitTestResults mouseEvent = prepareMouseEvent(request, platformMouseEvent);
</span><span class="cx">     Frame* subframe = subframeForHitTestResult(mouseEvent);
</span><span class="cx">     if (m_eventHandlerWillResetCapturingMouseEventsElement)
</span></span></pre>
</div>
</div>

</body>
</html>