|
1 <!DOCTYPE HTML> |
|
2 <html> |
|
3 <!-- |
|
4 https://bugzilla.mozilla.org/show_bug.cgi?id=448602 |
|
5 --> |
|
6 <head> |
|
7 <title>Test for Bug 448602</title> |
|
8 <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
|
9 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> |
|
10 </head> |
|
11 <body> |
|
12 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=448602">Mozilla Bug 448602</a> |
|
13 <p id="display"></p> |
|
14 <div id="content" style="display: none"> |
|
15 |
|
16 </div> |
|
17 <pre id="test"> |
|
18 <script type="application/javascript"> |
|
19 |
|
20 /** Test for Bug 448602 **/ |
|
21 |
|
22 var els, root, l2, l3; |
|
23 |
|
24 function runTests() { |
|
25 /* |
|
26 Disabled due to lack of present support for JSD in JM |
|
27 var jsdIDebuggerService = SpecialPowers.Ci.jsdIDebuggerService; |
|
28 var jsd = SpecialPowers.Components.classes['@mozilla.org/js/jsd/debugger-service;1'] |
|
29 .getService(jsdIDebuggerService); |
|
30 */ |
|
31 els = SpecialPowers.Cc["@mozilla.org/eventlistenerservice;1"] |
|
32 .getService(SpecialPowers.Ci.nsIEventListenerService); |
|
33 |
|
34 // Event listener info tests |
|
35 root = document.getElementById("testroot"); |
|
36 var infos = els.getListenerInfoFor(root, {}); |
|
37 is(infos.length, 0, "Element shouldn't have listeners (1)"); |
|
38 |
|
39 var listenerSource = 'alert(event);'; |
|
40 root.setAttribute("onclick", listenerSource); |
|
41 infos = els.getListenerInfoFor(root, {}); |
|
42 is(infos.length, 1, "Element should have listeners (1)"); |
|
43 is(infos[0].toSource(), 'function onclick(event) {\n' + listenerSource + '\n}', |
|
44 "Unexpected serialization (1)"); |
|
45 is(infos[0].type, "click", "Wrong type (1)"); |
|
46 is(infos[0].capturing, false, "Wrong phase (1)"); |
|
47 is(infos[0].allowsUntrusted, true, "Should allow untrusted events (1)"); |
|
48 is(SpecialPowers.unwrap(infos[0].listenerObject), root.onclick, |
|
49 "Should have the right listener object (1)"); |
|
50 |
|
51 /* |
|
52 var jsdOn = jsd.isOn; |
|
53 if (!jsdOn) { |
|
54 is(infos[0].getDebugObject(), null, |
|
55 "If JSD isn't running, getDebugObject() should return null.") |
|
56 jsd.on(); |
|
57 ok(jsd.isOn, "JSD should be running."); |
|
58 } |
|
59 var jsdvalue = infos[0].getDebugObject().QueryInterface(SpecialPowers.Ci.jsdIValue); |
|
60 is(jsdvalue.jsType, 3, "Event listener should be a function! (1)"); |
|
61 */ |
|
62 |
|
63 root.removeAttribute("onclick"); |
|
64 root.setAttribute("onclick", "...invalid script..."); |
|
65 SimpleTest.expectUncaughtException(true); |
|
66 infos = els.getListenerInfoFor(root, {}); |
|
67 SimpleTest.expectUncaughtException(false); |
|
68 is(infos.length, 1); |
|
69 is(infos[0].listenerObject, null); |
|
70 |
|
71 root.removeAttribute("onclick"); |
|
72 infos = els.getListenerInfoFor(root, {}); |
|
73 is(infos.length, 0, "Element shouldn't have listeners (2)"); |
|
74 |
|
75 var l = function (e) { alert(e); }; |
|
76 root.addEventListener("foo", l, true, true); |
|
77 root.addEventListener("foo", l, false, false); |
|
78 infos = els.getListenerInfoFor(root, {}); |
|
79 is(infos.length, 2, "Element should have listeners (2)"); |
|
80 is(infos[0].toSource(), "(function (e) { alert(e); })", |
|
81 "Unexpected serialization (2)"); |
|
82 is(infos[0].type, "foo", "Wrong type (2)"); |
|
83 is(infos[0].capturing, true, "Wrong phase (2)"); |
|
84 is(infos[0].allowsUntrusted, true, "Should allow untrusted events (2)"); |
|
85 is(SpecialPowers.unwrap(infos[0].listenerObject), l, |
|
86 "Should have the right listener object (2)"); |
|
87 /* |
|
88 jsdvalue = infos[0].getDebugObject().QueryInterface(SpecialPowers.Ci.jsdIValue); |
|
89 is(jsdvalue.jsType, 3, "Event listener should be a function!(2)"); |
|
90 is(jsdvalue.getWrappedValue(), l, "Wrong JS value! (1)"); |
|
91 */ |
|
92 |
|
93 is(infos[1].toSource(), "(function (e) { alert(e); })", |
|
94 "Unexpected serialization (3)"); |
|
95 is(infos[1].type, "foo", "Wrong type (3)"); |
|
96 is(infos[1].capturing, false, "Wrong phase (3)"); |
|
97 is(infos[1].allowsUntrusted, false, "Shouldn't allow untrusted events (1)"); |
|
98 is(SpecialPowers.unwrap(infos[1].listenerObject), l, |
|
99 "Should have the right listener object (3)"); |
|
100 |
|
101 /* |
|
102 jsdvalue2 = infos[1].getDebugObject().QueryInterface(SpecialPowers.Ci.jsdIValue); |
|
103 is(jsdvalue2.jsType, 3, "Event listener should be a function! (3)"); |
|
104 is(jsdvalue2.getWrappedValue(), l, "Wrong JS value! (2)"); |
|
105 */ |
|
106 root.removeEventListener("foo", l, true); |
|
107 root.removeEventListener("foo", l, false); |
|
108 infos = els.getListenerInfoFor(root, {}); |
|
109 is(infos.length, 0, "Element shouldn't have listeners (3)"); |
|
110 |
|
111 root.onclick = l; |
|
112 infos = els.getListenerInfoFor(root, {}); |
|
113 is(infos.length, 1, "Element should have listeners (3)"); |
|
114 is(infos[0].toSource(), '(function (e) { alert(e); })', |
|
115 "Unexpected serialization (4)"); |
|
116 is(infos[0].type, "click", "Wrong type (4)"); |
|
117 is(infos[0].capturing, false, "Wrong phase (4)"); |
|
118 is(infos[0].allowsUntrusted, true, "Should allow untrusted events (3)"); |
|
119 is(SpecialPowers.unwrap(infos[0].listenerObject), l, |
|
120 "Should have the right listener object (4)"); |
|
121 |
|
122 // Event target chain tests |
|
123 l2 = document.getElementById("testlevel2"); |
|
124 l3 = document.getElementById("testlevel3"); |
|
125 var textnode = l3.firstChild; |
|
126 var chain = els.getEventTargetChainFor(textnode, {}); |
|
127 ok(chain.length > 3, "Too short event target chain."); |
|
128 ok(SpecialPowers.compare(chain[0], textnode), "Wrong chain item (1)"); |
|
129 ok(SpecialPowers.compare(chain[1], l3), "Wrong chain item (2)"); |
|
130 ok(SpecialPowers.compare(chain[2], l2), "Wrong chain item (3)"); |
|
131 ok(SpecialPowers.compare(chain[3], root), "Wrong chain item (4)"); |
|
132 |
|
133 var hasDocumentInChain = false; |
|
134 var hasWindowInChain = false; |
|
135 for (var i = 0; i < chain.length; ++i) { |
|
136 if (SpecialPowers.compare(chain[i], document)) { |
|
137 hasDocumentInChain = true; |
|
138 } else if (SpecialPowers.compare(chain[i], window)) { |
|
139 hasWindowInChain = true; |
|
140 } |
|
141 } |
|
142 |
|
143 ok(hasDocumentInChain, "Should have document in event target chain!"); |
|
144 ok(hasWindowInChain, "Should have window in event target chain!"); |
|
145 /* |
|
146 if (!jsdOn) { |
|
147 jsd.off(); |
|
148 ok(!jsd.isOn, "JSD shouldn't be running anymore."); |
|
149 } |
|
150 */ |
|
151 |
|
152 try { |
|
153 els.getListenerInfoFor(null, {}); |
|
154 ok(false, "Should have thrown an exception."); |
|
155 } catch (ex) { |
|
156 ok(true, "We should be still running."); |
|
157 } |
|
158 setTimeout(testAllListener, 0); |
|
159 } |
|
160 |
|
161 function dispatchTrusted(t, o) { |
|
162 SpecialPowers.dispatchEvent(window, t, new Event("testevent", o)); |
|
163 } |
|
164 |
|
165 function testAllListener() { |
|
166 els = SpecialPowers.wrap(els); |
|
167 var results = []; |
|
168 var expectedResults = |
|
169 [ { target: "testlevel3", phase: 3, trusted: false }, |
|
170 { target: "testlevel3", phase: 3, trusted: false }, |
|
171 { target: "testlevel3", phase: 3, trusted: true }, |
|
172 { target: "testlevel3", phase: 3, trusted: true }, |
|
173 { target: "testlevel3", phase: 3, trusted: true } |
|
174 ]; |
|
175 |
|
176 function allListener(e) { |
|
177 results.push({ |
|
178 target: e.target.id, |
|
179 phase: e.eventPhase, |
|
180 trusted: e.isTrusted |
|
181 }); |
|
182 e.stopPropagation(); |
|
183 } |
|
184 function allListenerTrustedOnly(e) { |
|
185 results.push({ |
|
186 target: e.target.id, |
|
187 phase: e.eventPhase, |
|
188 trusted: e.isTrusted |
|
189 }); |
|
190 e.stopPropagation(); |
|
191 } |
|
192 |
|
193 els.addListenerForAllEvents(root, allListener, false, true); |
|
194 var infos = els.getListenerInfoFor(root); |
|
195 var nullTypes = 0; |
|
196 for (var i = 0; i < infos.length; ++i) { |
|
197 if (infos[i].type == null) { |
|
198 ++nullTypes; |
|
199 } |
|
200 } |
|
201 is(nullTypes, 1, "Should have one all-event-listener!"); |
|
202 |
|
203 els.addListenerForAllEvents(root, allListener, false, true, true); |
|
204 els.addListenerForAllEvents(root, allListenerTrustedOnly, false, false, true); |
|
205 l3.dispatchEvent(new Event("testevent", { bubbles: true })); |
|
206 dispatchTrusted(l3, { bubbles: true }); |
|
207 els.removeListenerForAllEvents(root, allListener, false); |
|
208 els.removeListenerForAllEvents(root, allListener, false, true); |
|
209 els.removeListenerForAllEvents(root, allListenerTrustedOnly, false, true); |
|
210 // make sure removeListenerForAllEvents works. |
|
211 l3.dispatchEvent(new Event("testevent", { bubbles: true })); |
|
212 dispatchTrusted(l3, { bubbles: true }); |
|
213 |
|
214 // Test the order of event listeners. |
|
215 var clickListenerCalled = false; |
|
216 var allListenerCalled = false; |
|
217 function clickListener() { |
|
218 clickListenerCalled = true; |
|
219 ok(allListenerCalled, "Should have called '*' listener before normal listener!"); |
|
220 } |
|
221 function allListener2() { |
|
222 allListenerCalled = true; |
|
223 notok(clickListenerCalled, "Shouldn't have called click listener before '*' listener!"); |
|
224 } |
|
225 root.onclick = null; // Remove the listener added in earlier tests. |
|
226 root.addEventListener("click", clickListener); |
|
227 els.addListenerForAllEvents(root, allListener2, false, true); |
|
228 l3.dispatchEvent(new MouseEvent("click", { bubbles: true })); |
|
229 root.removeEventListener("click", clickListener); |
|
230 els.removeListenerForAllEvents(root, allListener2, false); |
|
231 ok(allListenerCalled, "Should have called '*' listener"); |
|
232 ok(clickListenerCalled, "Should have called click listener"); |
|
233 |
|
234 is(results.length, expectedResults.length, "count"); |
|
235 for (var i = 0; i < expectedResults.length; ++i) { |
|
236 for (var p in expectedResults[i]) { |
|
237 is(results[i][p], expectedResults[i][p], p); |
|
238 } |
|
239 } |
|
240 SimpleTest.finish(); |
|
241 } |
|
242 |
|
243 SimpleTest.waitForExplicitFinish(); |
|
244 addLoadEvent(runTests); |
|
245 </script> |
|
246 </pre> |
|
247 <div id="testroot"> |
|
248 <div id="testlevel2"> |
|
249 <div id="testlevel3"> |
|
250 Test |
|
251 </div> |
|
252 </div> |
|
253 </div> |
|
254 </body> |
|
255 </html> |