7 function log(msg, success)
9 logDiv.appendChild(document.createElement('div')).textContent = msg + ': ' + (success ? 'PASS' : 'FAIL');
12 function moveOver(element)
14 if (!window.eventSender)
17 var x = element.offsetLeft + element.offsetWidth / 2;
18 var y = element.offsetTop + element.offsetHeight / 2;
19 eventSender.mouseMoveTo(x, y);
22 function moveOverLeftQuarterOf(element)
24 if (!window.eventSender)
27 var x = element.offsetLeft + element.offsetWidth / 4;
28 var y = element.offsetTop + element.offsetHeight / 2;
29 eventSender.mouseMoveTo(x, y);
32 function moveOverRightQuarterOf(element)
34 if (!window.eventSender)
37 var x = element.offsetLeft + element.offsetWidth * 3 / 4;
38 var y = element.offsetTop + element.offsetHeight / 2;
39 eventSender.mouseMoveTo(x, y);
42 function clickOn(element)
45 eventSender.mouseDown();
46 eventSender.mouseUp();
49 function clickOnLeftQuarterOf(element)
51 if (!window.eventSender)
54 moveOverLeftQuarterOf(element);
55 eventSender.mouseDown();
56 eventSender.mouseUp();
59 function leapForward()
61 if (!window.eventSender)
64 eventSender.leapForward(1000);
68 mutationEventPropagation: function()
70 var textarea = document.body.appendChild(document.createElement('textarea'));
71 var mutationEventFired;
72 textarea.addEventListener('DOMSubtreeModified', function(e)
74 mutationEventFired = true;
76 textarea.value = 'test';
77 // Trigger style recalc and sadly, the actual mutation of the textarea shadow DOM.
78 textarea.offsetHeight;
79 log('Mutation events should not propagate out of the shadow DOM', !mutationEventFired);
80 textarea.parentNode.removeChild(textarea);
82 selectstartEventPropagation: function()
84 var textInput = document.body.appendChild(document.createElement('input'));
85 var selectstartEventFired = false;
86 document.selectstart = function()
88 selectstartEventFired = true;
91 log('The selectstart event should not propagate out of the shadow DOM', !selectstartEventFired);
92 textInput.parentNode.removeChild(textInput);
93 document.selectstart = null;
95 mouseOverAndOutPropagation: function()
98 var fileInput = document.body.appendChild(document.createElement('input'));
99 fileInput.setAttribute('type', 'file');
100 var countEventDispatch = function()
104 moveOverLeftQuarterOf(fileInput);
106 document.body.addEventListener('mouseover', countEventDispatch, false);
107 document.body.addEventListener('mouseout', countEventDispatch, false);
109 moveOverRightQuarterOf(fileInput);
111 log("The mouseover/mouseout event between two elements inside the same shadow subtree should not propagate out of the shadow DOM", count == 0);
113 document.body.removeEventListener('mouseover', countEventDispatch, false);
114 document.body.removeEventListener('mouseout', countEventDispatch, false);
115 fileInput.parentNode.removeChild(fileInput);
117 relatedTargetAsHost: function()
120 var relatedTarget = document.createElement('div');
121 relatedTarget.style.cssText = 'width: 50px; height: 50px; padding-left: 50px;';
122 document.body.appendChild(relatedTarget);
123 var target = document.createElement('div');
124 target.style.cssText = 'width: 50px; height: 50px';
125 relatedTarget.createShadowRoot().appendChild(target);
126 moveOverLeftQuarterOf(relatedTarget);
127 var countEventDispatch = function()
131 relatedTarget.addEventListener('mouseover', countEventDispatch, false)
132 moveOverRightQuarterOf(relatedTarget);
134 log("The mouseover event in a shadow subtree, where related target is the tree host should not escape out of shadow DOM", count == 0);
136 relatedTarget.removeEventListener('mouseover', countEventDispatch, false);
137 document.body.removeChild(relatedTarget);
139 targetAsHost: function()
142 var target = document.createElement('div');
143 target.style.cssText = 'width: 50px; height: 50px; padding-left: 50px;';
144 document.body.appendChild(target);
145 var relatedTarget = document.createElement('div');
146 relatedTarget.style.cssText = 'width: 50px; height: 50px';
147 target.createShadowRoot().appendChild(relatedTarget);
148 moveOverRightQuarterOf(target);
149 var countEventDispatch = function(evt)
153 target.addEventListener('mouseover', countEventDispatch, false)
154 moveOverLeftQuarterOf(target);
156 log("Events with relatedTarget should not escape out of shadow subtree when its host is the target", count == 0);
158 target.removeEventListener('mouseout', countEventDispatch, false);
159 document.body.removeChild(target);
161 mouseOverOnHost: function()
164 var input = document.body.appendChild(document.createElement('input'));
165 var countEventDispatch = function()
170 moveOver(document.body);
171 input.addEventListener('mouseover', countEventDispatch, false);
174 log("The mouseover/mouseout event on a shadow subtree host should propagate out of the shadow DOM", count == 1);
176 document.body.removeEventListener('mouseover', countEventDispatch, false);
177 input.parentNode.removeChild(input);
179 labelSyntheticClick: function()
182 var label = document.body.appendChild(document.createElement('label'));
183 var searchInput = label.appendChild(document.createElement('input'));
184 searchInput.setAttribute('type', 'search');
185 searchInput.setAttribute('id', 'baz');
186 label.setAttribute('for', 'baz');
187 searchInput.addEventListener('click', function(e)
191 clickOn(searchInput);
192 log("Label should look beyond shadow boundary to detect if it encloses its associated element", count == 1);
193 label.parentNode.removeChild(label);
195 /* This subtest started crashing after r89007:
196 * https://bugs.webkit.org/show_bug.cgi?id=62788
197 * I'm disabling this test for now while I ask for help understanding the problem.
198 defaultEventRetargeting: function()
201 var fileInput = document.body.appendChild(document.createElement('input'));
202 fileInput.setAttribute('type', 'file');
203 var counter = function()
207 document.body.addEventListener('DOMActivate', counter, false);
208 clickOnLeftQuarterOf(fileInput);
209 log("Events for default event handler should not be retargeted", count == 1);
210 document.body.removeEventListener('DOMActivate', counter, false);
211 fileInput.parentNode.removeChild(fileInput);
214 relatedTargetRetargeting: function()
217 var textInput = document.body.appendChild(document.createElement('input'));
218 var counter = function(evt)
220 if (evt.relatedTarget && !evt.relatedTarget.parentNode)
224 document.body.addEventListener("mouseover", counter, false);
225 moveOver(document.body);
226 document.body.removeEventListener("mouseover", counter, false);
227 log("Event's relatedTarget should be retargeted", count == 0);
228 textInput.parentNode.removeChild(textInput);
230 eventInProgress: function()
232 var textInput = document.body.appendChild(document.createElement('input'));
233 textInput.addEventListener('click', function(e)
235 log('Other events should be retargeted', e.target == textInput);
238 textInput.parentNode.removeChild(textInput);
240 finalEventObject: function()
242 var textInput = document.body.appendChild(document.createElement('input'));
244 textInput.addEventListener('click', function(e)
249 log('After event dispatch, the event object should not reveal shadow DOM', storedEvent && storedEvent.target == textInput);
250 textInput.parentNode.removeChild(textInput);
252 focusEventPropagation: function()
254 var searchInput = document.body.appendChild(document.createElement('input'));
255 searchInput.setAttribute('type', 'search');
257 searchInput.addEventListener('focus', function(evt)
261 clickOn(searchInput);
263 clickOn(searchInput);
264 log('Focusing same shadow DOM element repeatedly should not trigger multiple focus/blur events', count == 1);
265 searchInput.parentNode.removeChild(searchInput);
271 if (window.testRunner)
272 testRunner.dumpAsText();
274 logDiv = document.getElementById('log');
275 for(var testName in tests) {
282 <body onload="runTest()">
283 <p>Tests to ensure that shadow DOM boundary is not crossed during event propagation. Can only run within DRT.
284 <p>See <a href="https://bugs.webkit.org/show_bug.cgi?id=46015">bug 46015</a> for details.