|
1 <!DOCTYPE html> |
|
2 <!-- |
|
3 Any copyright is dedicated to the Public Domain. |
|
4 http://creativecommons.org/publicdomain/zero/1.0/ |
|
5 --> |
|
6 |
|
7 <html> |
|
8 |
|
9 <head> |
|
10 <meta charset="utf8"> |
|
11 <title></title> |
|
12 |
|
13 <script type="application/javascript" |
|
14 src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> |
|
15 <link rel="stylesheet" type="text/css" |
|
16 href="chrome://mochikit/content/tests/SimpleTest/test.css"> |
|
17 </head> |
|
18 |
|
19 <body> |
|
20 |
|
21 <script type="application/javascript;version=1.8"> |
|
22 "use strict"; |
|
23 |
|
24 const { utils: Cu } = Components; |
|
25 const { Promise: promise } = |
|
26 Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {}); |
|
27 const { EventEmitter } = |
|
28 Cu.import("resource://gre/modules/devtools/event-emitter.js", {}); |
|
29 const { Task } = Cu.import("resource://gre/modules/Task.jsm", {}); |
|
30 |
|
31 SimpleTest.waitForExplicitFinish(); |
|
32 |
|
33 testEmitter(); |
|
34 testEmitter({}); |
|
35 |
|
36 Task.spawn(testPromise) |
|
37 .then(null, ok.bind(null, false)) |
|
38 .then(SimpleTest.finish); |
|
39 |
|
40 function testEmitter(aObject) { |
|
41 let emitter; |
|
42 |
|
43 if (aObject) { |
|
44 emitter = aObject; |
|
45 EventEmitter.decorate(emitter); |
|
46 } else { |
|
47 emitter = new EventEmitter(); |
|
48 } |
|
49 |
|
50 ok(emitter, "We have an event emitter"); |
|
51 |
|
52 emitter.on("next", next); |
|
53 emitter.emit("next", "abc", "def"); |
|
54 |
|
55 let beenHere1 = false; |
|
56 function next(eventName, str1, str2) { |
|
57 is(eventName, "next", "Got event"); |
|
58 is(str1, "abc", "Argument 1 is correct"); |
|
59 is(str2, "def", "Argument 2 is correct"); |
|
60 |
|
61 ok(!beenHere1, "first time in next callback"); |
|
62 beenHere1 = true; |
|
63 |
|
64 emitter.off("next", next); |
|
65 |
|
66 emitter.emit("next"); |
|
67 |
|
68 emitter.once("onlyonce", onlyOnce); |
|
69 |
|
70 emitter.emit("onlyonce"); |
|
71 emitter.emit("onlyonce"); |
|
72 } |
|
73 |
|
74 let beenHere2 = false; |
|
75 function onlyOnce() { |
|
76 ok(!beenHere2, "\"once\" listner has been called once"); |
|
77 beenHere2 = true; |
|
78 emitter.emit("onlyonce"); |
|
79 |
|
80 killItWhileEmitting(); |
|
81 } |
|
82 |
|
83 function killItWhileEmitting() { |
|
84 function c1() { |
|
85 ok(true, "c1 called"); |
|
86 } |
|
87 function c2() { |
|
88 ok(true, "c2 called"); |
|
89 emitter.off("tick", c3); |
|
90 } |
|
91 function c3() { |
|
92 ok(false, "c3 should not be called"); |
|
93 } |
|
94 function c4() { |
|
95 ok(true, "c4 called"); |
|
96 } |
|
97 |
|
98 emitter.on("tick", c1); |
|
99 emitter.on("tick", c2); |
|
100 emitter.on("tick", c3); |
|
101 emitter.on("tick", c4); |
|
102 |
|
103 emitter.emit("tick"); |
|
104 |
|
105 offAfterOnce(); |
|
106 } |
|
107 |
|
108 function offAfterOnce() { |
|
109 let enteredC1 = false; |
|
110 |
|
111 function c1() { |
|
112 enteredC1 = true; |
|
113 } |
|
114 |
|
115 emitter.once("oao", c1); |
|
116 emitter.off("oao", c1); |
|
117 |
|
118 emitter.emit("oao"); |
|
119 |
|
120 ok(!enteredC1, "c1 should not be called"); |
|
121 } |
|
122 } |
|
123 |
|
124 function testPromise() { |
|
125 let emitter = new EventEmitter(); |
|
126 let p = emitter.once("thing"); |
|
127 |
|
128 // Check that the promise is only resolved once event though we |
|
129 // emit("thing") more than once |
|
130 let firstCallbackCalled = false; |
|
131 let check1 = p.then(arg => { |
|
132 is(firstCallbackCalled, false, "first callback called only once"); |
|
133 firstCallbackCalled = true; |
|
134 is(arg, "happened", "correct arg in promise"); |
|
135 return "rval from c1"; |
|
136 }); |
|
137 |
|
138 emitter.emit("thing", "happened", "ignored"); |
|
139 |
|
140 // Check that the promise is resolved asynchronously |
|
141 let secondCallbackCalled = false; |
|
142 let check2 = p.then(arg => { |
|
143 ok(true, "second callback called"); |
|
144 is(arg, "happened", "correct arg in promise"); |
|
145 secondCallbackCalled = true; |
|
146 is(arg, "happened", "correct arg in promise (a second time)"); |
|
147 return "rval from c2"; |
|
148 }); |
|
149 |
|
150 // Shouldn't call any of the above listeners |
|
151 emitter.emit("thing", "trashinate"); |
|
152 |
|
153 // Check that we can still separate events with different names |
|
154 // and that it works with no parameters |
|
155 let pfoo = emitter.once("foo"); |
|
156 let pbar = emitter.once("bar"); |
|
157 |
|
158 let check3 = pfoo.then(arg => { |
|
159 ok(arg === undefined, "no arg for foo event"); |
|
160 return "rval from c3"; |
|
161 }); |
|
162 |
|
163 pbar.then(() => { |
|
164 ok(false, "pbar should not be called"); |
|
165 }); |
|
166 |
|
167 emitter.emit("foo"); |
|
168 |
|
169 is(secondCallbackCalled, false, "second callback not called yet"); |
|
170 |
|
171 return promise.all([ check1, check2, check3 ]).then(args => { |
|
172 is(args[0], "rval from c1", "callback 1 done good"); |
|
173 is(args[1], "rval from c2", "callback 2 done good"); |
|
174 is(args[2], "rval from c3", "callback 3 done good"); |
|
175 }); |
|
176 } |
|
177 </script> |
|
178 </body> |
|
179 </html> |