<!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>[210267] 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/210267">210267</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2017-01-03 19:39:39 -0800 (Tue, 03 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>label element with tabindex &gt;= 0 is not focusable
https://bugs.webkit.org/show_bug.cgi?id=102780
&lt;rdar://problem/29796608&gt;

Reviewed by Darin Adler.

Source/WebCore:

Fixed the bug by removing the override for HTMLLabelElement::isFocusable which always returned false.

This is a behavior from <a href="http://trac.webkit.org/projects/webkit/changeset/5532">r5532</a> but it doesn't match the latest HTML specification or that of Chrome
and Firefox.

Also fixed an existing bug in HTMLLabelElement::focus and HTMLLegendElement::focus which focused
the associated form control when there is one even if the element itself is focusable. Without this fix,
traversing from control with shift+tab would break since focusing the label would move the focus back
to the input element inside the label element.

Finally, fixed a bug in HTMLLegendElement::focus that we can call inFocus without updating layout first.

The fix was inspired by https://chromium.googlesource.com/chromium/src/+/085ad8697b1be50c4f93e296797a25a43a79bcfb

Test: fast/events/focus-label-legend-elements-with-tabindex.html

* html/HTMLLabelElement.cpp:
(WebCore::HTMLLabelElement::focus):
(WebCore::HTMLLabelElement::isFocusable): Deleted.
* html/HTMLLabelElement.h:
* html/HTMLLegendElement.cpp:
(WebCore::HTMLLegendElement::focus):

LayoutTests:

Added a regression test for traversing label and legend elements by tabbing.
A native merge of the blink fix would have regressed this for the label element
while the bug in the legend element had always existed.

Also added a regression test for focusing label and legend elements with tabindex.
We should be able to focus either element. New behavior matches that of Chrome.
Firefox moves the focus to the label element like we used to before this patch.

Also merge the test fix from https://chromium.googlesource.com/chromium/src/+/085ad8697b1be50c4f93e296797a25a43a79bcfb

* fast/events/focus-label-legend-elements-expected.txt: Added.
* fast/events/focus-label-legend-elements-with-tab-expected.txt: Added.
* fast/events/focus-label-legend-elements-with-tab.html: Added.
* fast/events/focus-label-legend-elements.html: Added.
* fast/events/resources/tabindex-focus-blur-all-frame1.html:
* fast/events/resources/tabindex-focus-blur-all-frame2.html:
* fast/events/resources/tabindex-focus-blur-all.js:
* fast/events/tabindex-focus-blur-all-expected.txt:
* platform/ios-simulator-wk2/TestExpectations:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfasteventsresourcestabindexfocusblurallframe1html">trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all-frame1.html</a></li>
<li><a href="#trunkLayoutTestsfasteventsresourcestabindexfocusblurallframe2html">trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all-frame2.html</a></li>
<li><a href="#trunkLayoutTestsfasteventsresourcestabindexfocusbluralljs">trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all.js</a></li>
<li><a href="#trunkLayoutTestsfasteventstabindexfocusblurallexpectedtxt">trunk/LayoutTests/fast/events/tabindex-focus-blur-all-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorwk2TestExpectations">trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLLabelElementcpp">trunk/Source/WebCore/html/HTMLLabelElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLLabelElementh">trunk/Source/WebCore/html/HTMLLabelElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLLegendElementcpp">trunk/Source/WebCore/html/HTMLLegendElement.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfasteventsfocuslabellegendelementsexpectedtxt">trunk/LayoutTests/fast/events/focus-label-legend-elements-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsfocuslabellegendelementswithtabexpectedtxt">trunk/LayoutTests/fast/events/focus-label-legend-elements-with-tab-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsfocuslabellegendelementswithtabhtml">trunk/LayoutTests/fast/events/focus-label-legend-elements-with-tab.html</a></li>
<li><a href="#trunkLayoutTestsfasteventsfocuslabellegendelementshtml">trunk/LayoutTests/fast/events/focus-label-legend-elements.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (210266 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-01-04 03:13:22 UTC (rev 210266)
+++ trunk/LayoutTests/ChangeLog        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -1,3 +1,31 @@
</span><ins>+2017-01-03  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        label element with tabindex &gt;= 0 is not focusable
+        https://bugs.webkit.org/show_bug.cgi?id=102780
+        &lt;rdar://problem/29796608&gt;
+
+        Reviewed by Darin Adler.
+
+        Added a regression test for traversing label and legend elements by tabbing.
+        A native merge of the blink fix would have regressed this for the label element
+        while the bug in the legend element had always existed.
+
+        Also added a regression test for focusing label and legend elements with tabindex.
+        We should be able to focus either element. New behavior matches that of Chrome.
+        Firefox moves the focus to the label element like we used to before this patch.
+
+        Also merge the test fix from https://chromium.googlesource.com/chromium/src/+/085ad8697b1be50c4f93e296797a25a43a79bcfb
+
+        * fast/events/focus-label-legend-elements-expected.txt: Added.
+        * fast/events/focus-label-legend-elements-with-tab-expected.txt: Added.
+        * fast/events/focus-label-legend-elements-with-tab.html: Added.
+        * fast/events/focus-label-legend-elements.html: Added.
+        * fast/events/resources/tabindex-focus-blur-all-frame1.html:
+        * fast/events/resources/tabindex-focus-blur-all-frame2.html:
+        * fast/events/resources/tabindex-focus-blur-all.js:
+        * fast/events/tabindex-focus-blur-all-expected.txt:
+        * platform/ios-simulator-wk2/TestExpectations:
+
</ins><span class="cx"> 2017-01-03  Tim Horton  &lt;timothy_horton@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         NSSpellChecker's recordResponse isn't called for unseen automatic corrections
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsfocuslabellegendelementsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/focus-label-legend-elements-expected.txt (0 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/focus-label-legend-elements-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/events/focus-label-legend-elements-expected.txt        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+Tests for calling focus() on a label element and a legend element. They should not move the focus to the associated element.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS testContent.querySelector(&quot;label&quot;).focus(); document.activeElement is testContent.querySelector(&quot;label&quot;)
+PASS testContent.querySelector(&quot;legend&quot;).focus(); document.activeElement is testContent.querySelector(&quot;legend&quot;)
+PASS successfullyParsed is true
+
+TEST COMPLETE
+ foo
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsfocuslabellegendelementswithtabexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/focus-label-legend-elements-with-tab-expected.txt (0 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/focus-label-legend-elements-with-tab-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/events/focus-label-legend-elements-with-tab-expected.txt        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+Tests for moving focus by pressing tab key across label and legend elements.
+To manually test, press tab key seven times then shift+tab six times.
+It should traverse focusable elements in the ascending order from 1 to 7 and then in the descending order back to 1.
+
+
+1. An input element inside a non-focusable label element
+2. A label element with an input element
+3. An input elment inside a focusable label element
+4. A label element with just text
+6. A focusable legend element inside a fieldset element
+7. An input element inside a fieldset element
+7. An input element inside a fieldset element
+6. A focusable legend element inside a fieldset element
+4. A label element with just text
+3. An input elment inside a focusable label element
+2. A label element with an input element
+1. An input element inside a non-focusable label element
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsfocuslabellegendelementswithtabhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/focus-label-legend-elements-with-tab.html (0 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/focus-label-legend-elements-with-tab.html                                (rev 0)
+++ trunk/LayoutTests/fast/events/focus-label-legend-elements-with-tab.html        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -0,0 +1,72 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;p&gt;Tests for moving focus by pressing tab key across label and legend elements.&lt;br&gt;
+To manually test, press tab key seven times then shift+tab six times.&lt;br&gt;
+It should traverse focusable elements in the ascending order from 1 to 7 and then in the descending order back to 1.&lt;/p&gt;
+&lt;/p&gt;
+&lt;input id=&quot;startingNode&quot;&gt;
+&lt;div id=&quot;test-content&quot;&gt;
+    &lt;label title=&quot;FAIL - a non-focusable label with an input should not be focused&quot;&gt;
+        &lt;input title=&quot;1. An input element inside a non-focusable label element&quot;&gt;hello
+    &lt;/label&gt;
+    &lt;label tabindex=&quot;0&quot; title=&quot;2. A label element with an input element&quot;&gt;
+        &lt;input title=&quot;3. An input elment inside a focusable label element&quot;&gt;world&lt;/label&gt;
+    &lt;label tabindex=&quot;0&quot; title=&quot;4. A label element with just text&quot;&gt;webkit&lt;/label&gt;
+    &lt;label title=&quot;FAIL - an label element without tabindex should not be focused&quot;&gt;rocks&lt;/label&gt;
+    &lt;fieldset tabindex=&quot;0&quot; title=&quot;5. A fieldset element with tabindex&quot;&gt;
+        &lt;legend tabindex=&quot;0&quot; title=&quot;6. A focusable legend element inside a fieldset element&quot;&gt;foo&lt;/legend&gt;
+        &lt;input title=&quot;7. An input element inside a fieldset element&quot;&gt;
+    &lt;/fieldset&gt;
+&lt;/div&gt;
+&lt;style&gt; :focus { background: red; } &lt;/style&gt;
+&lt;pre id=&quot;result&quot;&gt;&lt;/pre&gt;
+&lt;script&gt;
+
+function moveFocusForward(focusCount)
+{
+    setTimeout(function () {
+        if (!focusCount)
+            return moveFocusBackward(7);
+        eventSender.keyDown('\t');
+        setTimeout(function () {
+            moveFocusForward(focusCount - 1);            
+        }, 1);
+    }, 1);
+}
+
+function moveFocusBackward(focusCount)
+{
+    setTimeout(function () {
+        if (!focusCount) {
+            testContent.style.display = 'none';
+            testRunner.notifyDone();
+            return;
+        }
+        eventSender.keyDown('\t', ['shiftKey']);
+        setTimeout(function () {
+            moveFocusBackward(focusCount - 1);            
+        }, 1);
+    }, 1);
+}
+
+let testContent = document.getElementById('test-content');
+
+window.onload = () =&gt; {
+    document.getElementById('startingNode').focus();
+    if (window.eventSender) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+    moveFocusForward(7);
+}
+
+testContent.querySelectorAll('*').forEach((element) =&gt; {
+    element.onfocus = function () {
+        document.getElementById('result').textContent += (element.title || 'FAIL - focused an unexpected element') + '\n';
+    }
+});
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsfocuslabellegendelementshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/focus-label-legend-elements.html (0 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/focus-label-legend-elements.html                                (rev 0)
+++ trunk/LayoutTests/fast/events/focus-label-legend-elements.html        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/js-test.js&quot;&gt;&lt;/script&gt;
+&lt;div id=&quot;test-content&quot;&gt;
+    &lt;label tabindex=&quot;0&quot;&gt;&lt;input tabindex=&quot;0&quot;&gt;&lt;/label&gt;
+    &lt;fieldset tabindex=&quot;0&quot;&gt;
+        &lt;legend tabindex=&quot;0&quot;&gt;foo&lt;/legend&gt;
+        &lt;input tabindex=&quot;0&quot;&gt;
+    &lt;/fieldset&gt;
+&lt;/div&gt;
+&lt;script&gt;
+
+description('Tests for calling focus() on a label element and a legend element. They should not move the focus to the associated element.');
+
+let testContent = document.getElementById('test-content');
+shouldBe('testContent.querySelector(&quot;label&quot;).focus(); document.activeElement', 'testContent.querySelector(&quot;label&quot;)');
+shouldBe('testContent.querySelector(&quot;legend&quot;).focus(); document.activeElement', 'testContent.querySelector(&quot;legend&quot;)');
+
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsresourcestabindexfocusblurallframe1html"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all-frame1.html (210266 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all-frame1.html        2017-01-04 03:13:22 UTC (rev 210266)
+++ trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all-frame1.html        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -154,6 +154,7 @@
</span><span class="cx"> &lt;input type=&quot;checkbox&quot; id=&quot;checkbox1&quot;&gt;&lt;br&gt;
</span><span class="cx"> &lt;input type=&quot;radio&quot; id=&quot;radioChoice1a&quot; name=&quot;radio1&quot; tabindex=&quot;0&quot;&gt;&lt;br&gt;
</span><span class="cx"> &lt;label id=&quot;label1&quot; tabindex=&quot;-1&quot;&gt;&lt;input type=&quot;radio&quot; name=&quot;radio1&quot;&gt;label for radioChoice B&lt;/label&gt;&lt;br&gt;
</span><ins>+&lt;label id=&quot;label2&quot;&gt;&lt;input type=&quot;radio&quot; name=&quot;radio1&quot;&gt;label for radioChoice C&lt;/label&gt;&lt;br&gt;
</ins><span class="cx"> &lt;input type=&quot;file&quot; id=&quot;file1&quot; tabindex=&quot;2&quot;&gt;&lt;br&gt;
</span><span class="cx"> input type=&quot;hidden&quot;&lt;input type=&quot;hidden&quot; id=&quot;hidden1&quot; tabindex=&quot;-1&quot;&gt;&lt;br&gt;
</span><span class="cx"> input type=&quot;image&quot;&lt;input type=&quot;image&quot; id=&quot;inputImage1&quot; src=&quot;abe.png&quot; tabindex=&quot;3&quot;&gt;&lt;br&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsresourcestabindexfocusblurallframe2html"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all-frame2.html (210266 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all-frame2.html        2017-01-04 03:13:22 UTC (rev 210266)
+++ trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all-frame2.html        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -154,6 +154,7 @@
</span><span class="cx"> &lt;input type=&quot;checkbox&quot; id=&quot;checkbox3&quot; tabindex=&quot;0&quot;&gt;&lt;br&gt;
</span><span class="cx"> &lt;input type=&quot;radio&quot; id=&quot;radioChoice3a&quot; name=&quot;radio3&quot;&gt;&lt;br&gt;
</span><span class="cx"> &lt;label id=&quot;label3&quot; tabindex=&quot;2&quot;&gt;&lt;input type=&quot;radio&quot; name=&quot;radio3&quot; tabindex=&quot;0&quot;&gt;label for radio button&lt;/label&gt;&lt;br&gt;
</span><ins>+&lt;label id=&quot;label4&quot;&gt;&lt;input type=&quot;radio&quot; name=&quot;radio3&quot; tabindex=&quot;0&quot;&gt;another label for radio button&lt;/label&gt;&lt;br&gt;
</ins><span class="cx"> &lt;input type=&quot;file&quot; id=&quot;file3&quot; tabindex=&quot;-1&quot;&gt;&lt;br&gt;
</span><span class="cx"> input type=&quot;hidden&quot;&lt;input type=&quot;hidden&quot; id=&quot;hidden3&quot; tabindex=&quot;3&quot;&gt;&lt;br&gt;
</span><span class="cx"> input type=&quot;image&quot;&lt;input type=&quot;image&quot; id=&quot;inputImage3&quot; src=&quot;abe.png&quot; tabindex=&quot;-1&quot;&gt;&lt;br&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsresourcestabindexfocusbluralljs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all.js (210266 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all.js        2017-01-04 03:13:22 UTC (rev 210266)
+++ trunk/LayoutTests/fast/events/resources/tabindex-focus-blur-all.js        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -55,7 +55,7 @@
</span><span class="cx">     var homeBase = window.frames[1].document.getElementsByClassName('homebase');
</span><span class="cx">     homeBase[0].focus();
</span><span class="cx"> 
</span><del>-    var resultSummary = focusCount+&quot; focus / &quot;+blurCount+&quot; blur events dispatched, and should be 333 / 333 &quot;;
</del><ins>+    var resultSummary = focusCount+&quot; focus / &quot;+blurCount+&quot; blur events dispatched, and should be 336 / 336 &quot;;
</ins><span class="cx">     resultSummary += (focusCount==blurCount) ? &quot;&lt;span style='color:green'&gt;PASSED&lt;/span&gt;&lt;br&gt;&quot; : &quot;&lt;span style='color:red'&gt;FAILED&lt;/span&gt;&lt;br&gt;&quot;;
</span><span class="cx">     resultSummary += &quot;Total of &quot;+failedTestCount+&quot; focus test(s) failed.&quot;;
</span><span class="cx">     if (failedTestCount)
</span><span class="lines">@@ -101,7 +101,7 @@
</span><span class="cx"> function testProgrammaticFocus(elem)
</span><span class="cx"> {
</span><span class="cx">     var elemThatShouldFocus = null;
</span><del>-    var OKtoFocusOtherElement = false;
</del><ins>+    var shouldFocusOtherElement = false;
</ins><span class="cx">     focusedElem = null;
</span><span class="cx"> 
</span><span class="cx">     if (elem.tabIndex == elem.getAttribute(&quot;tabindex&quot;)) // this means tabindex was explicitly set
</span><span class="lines">@@ -117,13 +117,11 @@
</span><span class="cx">     if (elem.tabIndex == -1 &amp;&amp; elem.tagName == &quot;AREA&quot;)
</span><span class="cx">         elemThatShouldFocus = null;
</span><span class="cx"> 
</span><del>-    if (tagNamesTransferFocused.find(elem.tagName)) {
-        elemThatShouldFocus = null;
-        OKtoFocusOtherElement = true;
-    }
</del><ins>+    if (tagNamesTransferFocused.find(elem.tagName) &amp;&amp; elemThatShouldFocus == null)
+        shouldFocusOtherElement = true;
</ins><span class="cx"> 
</span><span class="cx">     elem.focus();
</span><del>-    if (elemThatShouldFocus == focusedElem || (!elemThatShouldFocus &amp;&amp; OKtoFocusOtherElement))
</del><ins>+    if ((!shouldFocusOtherElement &amp;&amp; elemThatShouldFocus == focusedElem) || (shouldFocusOtherElement &amp;&amp; elem != focusedElem))
</ins><span class="cx">         printToConsole(&quot;&lt;&quot;+elem.tagName+&quot;&gt; &quot;+elem.id+&quot; PASSED focus test&quot;);
</span><span class="cx">     else {
</span><span class="cx">         failedTestCount++;
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventstabindexfocusblurallexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/tabindex-focus-blur-all-expected.txt (210266 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/tabindex-focus-blur-all-expected.txt        2017-01-04 03:13:22 UTC (rev 210266)
+++ trunk/LayoutTests/fast/events/tabindex-focus-blur-all-expected.txt        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -1,2 +1,2 @@
</span><del>-333 focus / 333 blur events dispatched, and should be 333 / 333 PASSED
</del><ins>+336 focus / 336 blur events dispatched, and should be 336 / 336 PASSED
</ins><span class="cx"> Total of 0 focus test(s) failed. PASSED
</span></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorwk2TestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations (210266 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations        2017-01-04 03:13:22 UTC (rev 210266)
+++ trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -1766,6 +1766,7 @@
</span><span class="cx"> fast/shadow-dom/fullscreen-in-shadow-webkitCurrentFullScreenElement.html [ Skip ]
</span><span class="cx"> fast/shadow-dom/fullscreen-in-slot-fullscreenElement.html [ Skip ]
</span><span class="cx"> fast/shadow-dom/fullscreen-in-slot-webkitCurrentFullScreenElement.html [ Skip ]
</span><ins>+fast/events/focus-label-legend-elements-with-tab.html [ Skip ]
</ins><span class="cx"> 
</span><span class="cx"> # No touch events
</span><span class="cx"> fast/visual-viewport/ios/fixed-element-on-bottom-with-keyboard.html [ Skip ]
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (210266 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-01-04 03:13:22 UTC (rev 210266)
+++ trunk/Source/WebCore/ChangeLog        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2017-01-03  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        label element with tabindex &gt;= 0 is not focusable
+        https://bugs.webkit.org/show_bug.cgi?id=102780
+        &lt;rdar://problem/29796608&gt;
+
+        Reviewed by Darin Adler.
+
+        Fixed the bug by removing the override for HTMLLabelElement::isFocusable which always returned false.
+
+        This is a behavior from r5532 but it doesn't match the latest HTML specification or that of Chrome
+        and Firefox.
+
+        Also fixed an existing bug in HTMLLabelElement::focus and HTMLLegendElement::focus which focused
+        the associated form control when there is one even if the element itself is focusable. Without this fix,
+        traversing from control with shift+tab would break since focusing the label would move the focus back
+        to the input element inside the label element.
+
+        Finally, fixed a bug in HTMLLegendElement::focus that we can call inFocus without updating layout first.
+
+        The fix was inspired by https://chromium.googlesource.com/chromium/src/+/085ad8697b1be50c4f93e296797a25a43a79bcfb
+
+        Test: fast/events/focus-label-legend-elements-with-tabindex.html
+
+        * html/HTMLLabelElement.cpp:
+        (WebCore::HTMLLabelElement::focus):
+        (WebCore::HTMLLabelElement::isFocusable): Deleted.
+        * html/HTMLLabelElement.h:
+        * html/HTMLLegendElement.cpp:
+        (WebCore::HTMLLegendElement::focus):
+
</ins><span class="cx"> 2017-01-03  Tim Horton  &lt;timothy_horton@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         NSSpellChecker's recordResponse isn't called for unseen automatic corrections
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLLabelElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLLabelElement.cpp (210266 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLLabelElement.cpp        2017-01-04 03:13:22 UTC (rev 210266)
+++ trunk/Source/WebCore/html/HTMLLabelElement.cpp        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -58,11 +58,6 @@
</span><span class="cx">     return adoptRef(*new HTMLLabelElement(tagName, document));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool HTMLLabelElement::isFocusable() const
-{
-    return false;
-}
-
</del><span class="cx"> LabelableElement* HTMLLabelElement::control()
</span><span class="cx"> {
</span><span class="cx">     const AtomicString&amp; controlId = attributeWithoutSynchronization(forAttr);
</span><span class="lines">@@ -150,9 +145,18 @@
</span><span class="cx">     return (element &amp;&amp; element-&gt;willRespondToMouseClickEvents()) || HTMLElement::willRespondToMouseClickEvents();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void HTMLLabelElement::focus(bool, FocusDirection direction)
</del><ins>+void HTMLLabelElement::focus(bool restorePreviousSelection, FocusDirection direction)
</ins><span class="cx"> {
</span><del>-    // to match other browsers, always restore previous selection
</del><ins>+    if (document().haveStylesheetsLoaded()) {
+        document().updateLayout();
+        if (isFocusable()) {
+            // The value of restorePreviousSelection is not used for label elements as it doesn't override updateFocusAppearance.
+            Element::focus(restorePreviousSelection, direction);
+            return;
+        }
+    }
+
+    // To match other browsers, always restore previous selection.
</ins><span class="cx">     if (auto* element = control())
</span><span class="cx">         element-&gt;focus(true, direction);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLLabelElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLLabelElement.h (210266 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLLabelElement.h        2017-01-04 03:13:22 UTC (rev 210266)
+++ trunk/Source/WebCore/html/HTMLLabelElement.h        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -39,8 +39,6 @@
</span><span class="cx"> private:
</span><span class="cx">     HTMLLabelElement(const QualifiedName&amp;, Document&amp;);
</span><span class="cx"> 
</span><del>-    bool isFocusable() const final;
-
</del><span class="cx">     void accessKeyAction(bool sendMouseEvents) final;
</span><span class="cx"> 
</span><span class="cx">     // Overridden to update the hover/active state of the corresponding control.
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLLegendElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLLegendElement.cpp (210266 => 210267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLLegendElement.cpp        2017-01-04 03:13:22 UTC (rev 210266)
+++ trunk/Source/WebCore/html/HTMLLegendElement.cpp        2017-01-04 03:39:39 UTC (rev 210267)
</span><span class="lines">@@ -57,13 +57,17 @@
</span><span class="cx">     return descendantsOfType&lt;HTMLFormControlElement&gt;(*enclosingFieldset).first();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void HTMLLegendElement::focus(bool, FocusDirection direction)
</del><ins>+void HTMLLegendElement::focus(bool restorePreviousSelection, FocusDirection direction)
</ins><span class="cx"> {
</span><del>-    if (isFocusable())
-        Element::focus(true, direction);
-        
</del><span class="cx">     // To match other browsers' behavior, never restore previous selection.
</span><del>-    if (HTMLFormControlElement* control = associatedControl())
</del><ins>+    if (document().haveStylesheetsLoaded()) {
+        document().updateLayoutIgnorePendingStylesheets();
+        if (isFocusable()) {
+            Element::focus(restorePreviousSelection, direction);
+            return;
+        }
+    }
+    if (auto* control = associatedControl())
</ins><span class="cx">         control-&gt;focus(false, direction);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>