Source/WebCore/ChangeLog

 12016-12-12 Ryosuke Niwa <rniwa@webkit.org>
 2
 3 :hover rule causes a single tap to not activate a slotted anchor element
 4 https://bugs.webkit.org/show_bug.cgi?id=165551
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Fixed a bug in ancestorRespondingToClickEvents that we were traversing the ancestor nodes without taking
 9 shadow roots and slots into account. This prevented tapping on a text node assigned to a slot inside
 10 an anchor element to activate the hyperlink on iOS.
 11
 12 This bug was supposed to be fixed in r206605, and it was still broken on iOS due to the bug in
 13 ancestorRespondingToClickEvents. It is now tested by click-text-inside-linked-slot.html.
 14
 15 Tests: fast/shadow-dom/click-on-slotted-anchor-with-hover.html
 16 fast/shadow-dom/click-text-inside-linked-slot.html
 17
 18 * page/ios/FrameIOS.mm:
 19 (WebCore::ancestorRespondingToClickEvents):
 20 (WebCore::Frame::qualifyingNodeAtViewportLocation):
 21
1222016-12-12 Darin Adler <darin@apple.com>
223
324 Remove bindings generation support for legacy WebCore::Dictionary
209752

Source/WebCore/page/ios/FrameIOS.mm

5959#import "RenderTextControl.h"
6060#import "RenderView.h"
6161#import "RenderedDocumentMarker.h"
 62#import "ShadowRoot.h"
6263#import "TextBoundaries.h"
6364#import "TextIterator.h"
6465#import "VisiblePosition.h"

@@static Node* ancestorRespondingToClickEv
258259 *nodeBounds = IntRect();
259260
260261 Node* pointerCursorNode = nullptr;
261  for (Node* node = hitTestResult.innerNode(); node && node != terminationNode; node = node->parentNode()) {
262  ASSERT(!node->isInShadowTree());
 262 for (Node* node = hitTestResult.innerNode(); node && node != terminationNode; node = node->parentInComposedTree()) {
 263 ASSERT(!node->isInShadowTree() || node->containingShadowRoot()->mode() != ShadowRootMode::UserAgent);
263264
264265 // We only accept pointer nodes before reaching the body tag.
265266 if (node->hasTagName(HTMLNames::bodyTag)) {

@@Node* Frame::qualifyingNodeAtViewportLoc
405406 Node* failedNode = candidate;
406407
407408 while (candidate && !candidate->isElementNode())
408  candidate = candidate->parentNode();
 409 candidate = candidate->parentInComposedTree();
409410
410411 if (candidate)
411412 failedNode = candidate;
209064

LayoutTests/ChangeLog

 12016-12-12 Ryosuke Niwa <rniwa@webkit.org>
 2
 3 :hover rule causes a single tap to not activate a slotted anchor element
 4 https://bugs.webkit.org/show_bug.cgi?id=165551
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Added a test for tapping on an anchor element assigned to a slot, which has been fixed in r209065.
 9
 10 Also added a new helper JS wrapepr, UIHelper, defined inside LayoutTests/resources/js-helper.js
 11 to provide an abstraction around EventSender and UIScriptController.
 12
 13 Fixed click-text-inside-linked-slot.html on iOS using UIHelper.
 14
 15 * fast/shadow-dom/click-on-slotted-anchor-with-hover-expected.txt: Added.
 16 * fast/shadow-dom/click-on-slotted-anchor-with-hover.html: Added.
 17 * fast/shadow-dom/click-text-inside-linked-slot.html:
 18 * platform/ios-simulator/fast/shadow-dom/click-text-inside-linked-slot-expected.txt: Added.
 19 * resources/ui-helper.js: Added.
 20 (window.UIHelper.isIOS):
 21 (window.UIHelper.activateAt.return.new.Promise):
 22 (window.UIHelper.activateAt):
 23 (window.UIHelper.wait):
 24 (window.UIHelper):
 25
1262016-12-12 Chris Dumez <cdumez@apple.com>
227
328 Add Document.onvisibilitychange event handler attribute
209750

LayoutTests/fast/shadow-dom/click-on-slotted-anchor-with-hover-expected.txt

 1Tests for tapping or clicking on an anchor element assigned to a slot with :hover rule.
 2Tapping on "Tap me" below exactly once should activate the hyperlink.
 3
 4Tap me
 5PASS
nonexistent

LayoutTests/fast/shadow-dom/click-on-slotted-anchor-with-hover.html

 1<!DOCTYPE html>
 2<html>
 3<body>
 4<p>Tests for tapping or clicking on an anchor element assigned to a slot with :hover rule.<br>
 5Tapping on "Tap me" below exactly once should activate the hyperlink.</p>
 6<div id="host"><a href="#" onclick="activated();">Tap me</a></div>
 7<div id="result">FAIL</div>
 8<script src="../../resources/ui-helper.js"></script>
 9<script>
 10
 11let shadowHost = document.getElementById('host');
 12shadowHost.attachShadow({mode: 'closed'}).innerHTML = '<slot></slot>';
 13
 14function activated() {
 15 document.getElementById('result').textContent = 'PASS';
 16}
 17
 18document.onclick = function () {
 19 document.getElementById('result').style.display = null;
 20}
 21
 22if (window.testRunner) {
 23 testRunner.dumpAsText();
 24 UIHelper.wait(UIHelper.activateAt(shadowHost.offsetLeft + 5, shadowHost.offsetTop + 5));
 25} else
 26 document.getElementById('result').style.display = 'none';
 27
 28</script>
 29</body>
 30</html>
nonexistent

LayoutTests/fast/shadow-dom/click-text-inside-linked-slot.html

33<body>
44<p>This tests clicking on a Text node assigned to a slot inside an anchor element. The link should be activated.<br>
55To manually test, click "here" below and you should see "PASS" and the mouse cursor should indicate it's a hyperlink, not text:</p>
 6<script src="../../resources/ui-helper.js"></script>
67<script>
78
89var shadowHost = document.createElement('div');

@@if (window.internals) {
2425 testRunner.dumpAsText();
2526 document.getElementById('activation').textContent = 'FAIL';
2627 document.write('<div>Cursor: <span id="cursor">FAIL<span></div>');
27  eventSender.mouseMoveTo(shadowHost.offsetLeft + 5, shadowHost.offsetTop + 5);
28  eventSender.mouseDown();
29  eventSender.mouseUp();
 28 UIHelper.wait(UIHelper.activateAt(shadowHost.offsetLeft + 5, shadowHost.offsetTop + 5));
3029}
3130
3231</script>
209064

LayoutTests/platform/ios-simulator/fast/shadow-dom/click-text-inside-linked-slot-expected.txt

 1This tests clicking on a Text node assigned to a slot inside an anchor element. The link should be activated.
 2To manually test, click "here" below and you should see "PASS" and the mouse cursor should indicate it's a hyperlink, not text:
 3
 4click here
 5Activation: PASS
 6Cursor: FAIL: Cursor details not available on this platform.
nonexistent

LayoutTests/resources/ui-helper.js

 1
 2window.UIHelper = class UIHelper {
 3 static isIOS()
 4 {
 5 return navigator.userAgent.includes('iPhone');
 6 }
 7
 8 static activateAt(x, y)
 9 {
 10 if (!testRunner.runUIScript || !this.isIOS()) {
 11 eventSender.mouseMoveTo(x, y);
 12 eventSender.mouseDown();
 13 eventSender.mouseUp();
 14 return Promise.resolve();
 15 }
 16
 17 return new Promise((resolve) => {
 18 testRunner.runUIScript(`
 19 uiController.singleTapAtPoint(${x}, ${y}, function() {
 20 uiController.uiScriptComplete('Done');
 21 });`, resolve);
 22 });
 23 }
 24
 25 static wait(promise)
 26 {
 27 testRunner.waitUntilDone();
 28 return promise.then(
 29 function () { testRunner.notifyDone(); },
 30 function (error) { testRunner.notifyDone(); return Promise.reject(error); });
 31 }
 32}
nonexistent