OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 /** | 25 /** |
26 * @implements {Common.EventTarget} | 26 * @implements {Common.EventTarget} |
27 * @unrestricted | 27 * @unrestricted |
28 */ | 28 */ |
29 Common.Object = class { | 29 Common.Object = class { |
30 constructor() { | |
31 /** @type {(!Map<symbol, !Array<!Common.Object._listenerCallbackTuple>>|unde fined)} */ | |
32 this._listeners; | |
33 } | |
30 /** | 34 /** |
31 * @override | 35 * @override |
32 * @param {symbol} eventType | 36 * @param {symbol} eventType |
33 * @param {function(!Common.Event)} listener | 37 * @param {function(!Common.Event)} listener |
34 * @param {!Object=} thisObject | 38 * @param {!Object=} thisObject |
35 * @return {!Common.EventTarget.EventDescriptor} | 39 * @return {!Common.EventTarget.EventDescriptor} |
36 */ | 40 */ |
37 addEventListener(eventType, listener, thisObject) { | 41 addEventListener(eventType, listener, thisObject) { |
38 if (!listener) | 42 if (!listener) |
39 console.assert(false); | 43 console.assert(false); |
40 | 44 |
41 if (!this._listeners) | 45 if (!this._listeners) |
42 this._listeners = new Map(); | 46 this._listeners = /** @type {!Map<symbol, !Array<!Common.Object._listenerC allbackTuple>>} */ (new Map()); |
dgozman
2017/01/04 18:07:53
I'm surprised you have to cast here.
allada
2017/01/04 21:47:25
There are no side affects, but closure silently do
| |
47 | |
43 if (!this._listeners.has(eventType)) | 48 if (!this._listeners.has(eventType)) |
44 this._listeners.set(eventType, []); | 49 this._listeners.set(eventType, /** @type {!Array<!Common.Object._listenerC allbackTuple>} */ ([])); |
45 this._listeners.get(eventType).push({thisObject: thisObject, listener: liste ner}); | 50 this._listeners.get(eventType).push({thisObject: thisObject, listener: liste ner}); |
46 return new Common.EventTarget.EventDescriptor(this, eventType, thisObject, l istener); | 51 return new Common.EventTarget.EventDescriptor(this, eventType, thisObject, l istener); |
47 } | 52 } |
48 | 53 |
49 /** | 54 /** |
50 * @override | 55 * @override |
51 * @param {symbol} eventType | 56 * @param {symbol} eventType |
52 * @param {function(!Common.Event)} listener | 57 * @param {function(!Common.Event)} listener |
53 * @param {!Object=} thisObject | 58 * @param {!Object=} thisObject |
54 */ | 59 */ |
(...skipping 11 matching lines...) Expand all Loading... | |
66 if (!listeners.length) | 71 if (!listeners.length) |
67 this._listeners.delete(eventType); | 72 this._listeners.delete(eventType); |
68 } | 73 } |
69 | 74 |
70 /** | 75 /** |
71 * @override | 76 * @override |
72 * @param {symbol} eventType | 77 * @param {symbol} eventType |
73 * @return {boolean} | 78 * @return {boolean} |
74 */ | 79 */ |
75 hasEventListeners(eventType) { | 80 hasEventListeners(eventType) { |
76 return this._listeners && this._listeners.has(eventType); | 81 return !!(this._listeners && this._listeners.has(eventType)); |
77 } | 82 } |
78 | 83 |
79 /** | 84 /** |
80 * @override | 85 * @override |
81 * @param {symbol} eventType | 86 * @param {symbol} eventType |
82 * @param {*=} eventData | 87 * @param {*=} eventData |
83 */ | 88 */ |
84 dispatchEventToListeners(eventType, eventData) { | 89 dispatchEventToListeners(eventType, eventData) { |
85 if (!this._listeners || !this._listeners.has(eventType)) | 90 if (!this._listeners || !this._listeners.has(eventType)) |
86 return; | 91 return; |
87 | 92 |
88 var event = new Common.Event(eventData); | 93 var event = new Common.Event(eventData); |
89 var listeners = this._listeners.get(eventType).slice(0); | 94 var listeners = this._listeners.get(eventType).slice(0); |
90 for (var i = 0; i < listeners.length; ++i) | 95 for (var i = 0; i < listeners.length; ++i) |
91 listeners[i].listener.call(listeners[i].thisObject, event); | 96 listeners[i].listener.call(listeners[i].thisObject, event); |
92 } | 97 } |
93 | 98 |
94 /** | 99 /** |
95 * @template T | |
96 * @override | 100 * @override |
97 * @param {function(new:T, ...)} eventType | 101 * @param {function(new:T, ...)} eventType |
98 * @param {function(!T)} listener | 102 * @param {function(!T)} listener |
99 * @param {!Object=} thisObject | 103 * @param {!Object=} thisObject |
100 * @return {!Common.EventTarget.TypedEventDescriptor} | 104 * @return {!Common.EventTarget.TypedEventDescriptor} |
105 * @template T | |
101 */ | 106 */ |
102 on(eventType, listener, thisObject) { | 107 on(eventType, listener, thisObject) { |
103 if (!this._listeners) | 108 if (!this._listeners) |
dgozman
2017/01/04 18:07:53
Let's add a line here
var emitableListener = /** @
allada
2017/01/04 21:47:25
Done.
| |
104 this._listeners = new Map(); | 109 this._listeners = /** @type {!Map<symbol, !Array<!Common.Object._listenerC allbackTuple>>} */ (new Map()); |
105 if (!this._listeners.has(eventType)) | 110 if (!this._listeners.has(eventType)) |
106 this._listeners.set(eventType, []); | 111 this._listeners.set(eventType, []); |
107 this._listeners.get(eventType).push({thisObject: thisObject, listener: liste ner}); | 112 this._listeners.get(eventType).push({thisObject: thisObject, listener: liste ner}); |
108 return new Common.EventTarget.TypedEventDescriptor(this, eventType, thisObje ct, listener); | 113 return new Common.EventTarget.TypedEventDescriptor(this, eventType, thisObje ct, listener); |
109 } | 114 } |
110 | 115 |
111 /** | 116 /** |
112 * @template T | |
113 * @override | 117 * @override |
114 * @param {function(new:T, ...)} eventType | 118 * @param {function(new:T, ...)} eventType |
115 * @param {function(!T)} listener | 119 * @param {function(!T)} listener |
116 * @param {!Object=} thisObject | 120 * @param {!Object=} thisObject |
121 * @template T | |
117 */ | 122 */ |
118 off(eventType, listener, thisObject) { | 123 off(eventType, listener, thisObject) { |
dgozman
2017/01/04 18:07:53
ditto
allada
2017/01/04 21:47:25
Done.
| |
119 if (!this._listeners || !this._listeners.has(eventType)) | 124 if (!this._listeners || !this._listeners.has(eventType)) |
120 return; | 125 return; |
121 var listeners = this._listeners.get(eventType); | 126 var listeners = this._listeners.get(eventType); |
122 for (var i = 0; i < listeners.length; ++i) { | 127 for (var i = 0; i < listeners.length; ++i) { |
123 if (listeners[i].listener === listener && listeners[i].thisObject === this Object) | 128 if (listeners[i].listener === listener && listeners[i].thisObject === this Object) |
124 listeners.splice(i--, 1); | 129 listeners.splice(i--, 1); |
125 } | 130 } |
126 if (!listeners.length) | 131 if (!listeners.length) |
127 this._listeners.delete(eventType); | 132 this._listeners.delete(eventType); |
128 } | 133 } |
129 | 134 |
130 /** | 135 /** |
131 * @template T | |
132 * @override | 136 * @override |
133 * @param {!T} event | 137 * @param {!Common.Emitable} event |
134 */ | 138 */ |
135 emit(event) { | 139 emit(event) { |
136 var eventType = event.constructor; | 140 var eventType = event.constructor; |
137 if (!this._listeners || !this._listeners.has(eventType)) | 141 if (!this._listeners || !this._listeners.has(eventType)) |
138 return; | 142 return; |
139 var listeners = this._listeners.get(eventType).slice(0); | 143 var listeners = this._listeners.get(eventType).slice(0); |
140 for (var i = 0; i < listeners.length; ++i) | 144 for (var i = 0; i < listeners.length; ++i) |
141 listeners[i].listener.call(listeners[i].thisObject, event); | 145 listeners[i].listener.call(listeners[i].thisObject, event); |
142 } | 146 } |
143 }; | 147 }; |
144 | 148 |
145 /** | 149 /** |
150 * @interface | |
151 */ | |
152 Common.Emitable = function() {}; | |
153 | |
154 /** | |
155 * @typedef {!{thisObject: (!Object|undefined), listener: function(!Common.Emita ble)}} | |
156 */ | |
157 Common.Object._listenerCallbackTuple; | |
158 | |
159 /** | |
160 * @implements {Common.Emitable} | |
146 * @unrestricted | 161 * @unrestricted |
147 */ | 162 */ |
148 Common.Event = class { | 163 Common.Event = class { |
149 /** | 164 /** |
150 * @param {*=} data | 165 * @param {*=} data |
151 */ | 166 */ |
152 constructor(data) { | 167 constructor(data) { |
153 this.data = data; | 168 this.data = data; |
154 } | 169 } |
155 }; | 170 }; |
156 | 171 |
157 /** | 172 /** |
158 * @interface | 173 * @interface |
159 */ | 174 */ |
160 Common.EventTarget = function() {}; | 175 Common.EventTarget = function() {}; |
161 | 176 |
162 /** | 177 /** |
163 * @param {!Array<!Common.EventTarget.EventDescriptor|!Common.EventTarget.TypedE ventDescriptor>} eventList | 178 * @unrestricted |
179 */ | |
180 Common.EventTarget.EventDescriptor = class { | |
181 /** | |
182 * @param {!Common.EventTarget} eventTarget | |
183 * @param {symbol} eventType | |
184 * @param {(!Object|undefined)} receiver | |
185 * @param {function(?):?} method | |
186 */ | |
187 constructor(eventTarget, eventType, receiver, method) { | |
188 this.eventTarget = eventTarget; | |
189 this.eventType = eventType; | |
190 this.receiver = receiver; | |
191 this.method = method; | |
192 } | |
193 }; | |
194 | |
195 /** | |
196 * @template T | |
197 * @unrestricted | |
198 */ | |
199 Common.EventTarget.TypedEventDescriptor = class { | |
200 /** | |
201 * @param {!Common.EventTarget} eventTarget | |
202 * @param {function(new:T, ...)} eventType | |
203 * @param {(!Object|undefined)} receiver | |
204 * @param {function(!T)} method | |
205 */ | |
206 constructor(eventTarget, eventType, receiver, method) { | |
207 this.eventTarget = eventTarget; | |
208 this.eventType = eventType; | |
209 this.receiver = receiver; | |
210 this.method = method; | |
211 } | |
212 }; | |
213 | |
214 /** | |
215 * @param {!Array<!Common.EventTarget.EventDescriptor>} eventList | |
164 */ | 216 */ |
165 Common.EventTarget.removeEventListeners = function(eventList) { | 217 Common.EventTarget.removeEventListeners = function(eventList) { |
166 for (var i = 0; i < eventList.length; ++i) { | 218 for (var i = 0; i < eventList.length; ++i) { |
167 var eventInfo = eventList[i]; | 219 var eventInfo = eventList[i]; |
168 if (eventInfo instanceof Common.EventTarget.EventDescriptor) | 220 eventInfo.eventTarget.removeEventListener(eventInfo.eventType, eventInfo.met hod, eventInfo.receiver); |
169 eventInfo.eventTarget.removeEventListener(eventInfo.eventType, eventInfo.m ethod, eventInfo.receiver); | |
170 else | |
171 eventInfo.eventTarget.off(eventInfo.eventType, eventInfo.method, eventInfo .receiver); | |
dgozman
2017/01/04 18:07:53
Removing this is incorrect.
| |
172 } | 221 } |
173 // Do not hold references on unused event descriptors. | 222 // Do not hold references on unused event descriptors. |
174 eventList.splice(0, eventList.length); | 223 eventList.splice(0, eventList.length); |
175 }; | 224 }; |
176 | 225 |
177 Common.EventTarget.prototype = { | 226 Common.EventTarget.prototype = { |
178 /** | 227 /** |
179 * @param {symbol} eventType | 228 * @param {symbol} eventType |
180 * @param {function(!Common.Event)} listener | 229 * @param {function(!Common.Event)} listener |
181 * @param {!Object=} thisObject | 230 * @param {!Object=} thisObject |
(...skipping 14 matching lines...) Expand all Loading... | |
196 */ | 245 */ |
197 hasEventListeners(eventType) {}, | 246 hasEventListeners(eventType) {}, |
198 | 247 |
199 /** | 248 /** |
200 * @param {symbol} eventType | 249 * @param {symbol} eventType |
201 * @param {*=} eventData | 250 * @param {*=} eventData |
202 */ | 251 */ |
203 dispatchEventToListeners(eventType, eventData) {}, | 252 dispatchEventToListeners(eventType, eventData) {}, |
204 | 253 |
205 /** | 254 /** |
206 * @template T | |
207 * @param {function(new:T, ...)} eventType | 255 * @param {function(new:T, ...)} eventType |
208 * @param {function(!T)} listener | 256 * @param {function(!T)} listener |
209 * @param {!Object=} thisObject | 257 * @param {!Object=} thisObject |
210 * @return {!Common.EventTarget.TypedEventDescriptor} | 258 * @return {!Common.EventTarget.TypedEventDescriptor} |
259 * @template T | |
211 */ | 260 */ |
212 on(eventType, listener, thisObject) {}, | 261 on(eventType, listener, thisObject) {}, |
213 | 262 |
214 /** | 263 /** |
215 * @template T | |
216 * @param {function(new:T, ...)} eventType | 264 * @param {function(new:T, ...)} eventType |
217 * @param {function(!T)} listener | 265 * @param {function(!T)} listener |
218 * @param {!Object=} thisObject | 266 * @param {!Object=} thisObject |
267 * @template T | |
219 */ | 268 */ |
220 off(eventType, listener, thisObject) {}, | 269 off(eventType, listener, thisObject) {}, |
221 | 270 |
222 /** | 271 /** |
223 * @template T | 272 * @param {!Common.Emitable} event |
224 * @param {!T} event | |
225 */ | 273 */ |
226 emit(event) {}, | 274 emit(event) {}, |
227 }; | 275 }; |
228 | |
229 /** | |
230 * @unrestricted | |
231 */ | |
232 Common.EventTarget.EventDescriptor = class { | |
233 /** | |
234 * @param {!Common.EventTarget} eventTarget | |
235 * @param {symbol} eventType | |
236 * @param {(!Object|undefined)} receiver | |
237 * @param {function(?):?} method | |
238 */ | |
239 constructor(eventTarget, eventType, receiver, method) { | |
240 this.eventTarget = eventTarget; | |
241 this.eventType = eventType; | |
242 this.receiver = receiver; | |
243 this.method = method; | |
244 } | |
245 }; | |
246 | |
247 /** | |
248 * @template T | |
249 * @unrestricted | |
250 */ | |
251 Common.EventTarget.TypedEventDescriptor = class { | |
252 /** | |
253 * @param {!Common.EventTarget} eventTarget | |
254 * @param {function(new:T, ...)} eventType | |
255 * @param {(!Object|undefined)} receiver | |
256 * @param {function(!T)} method | |
257 */ | |
258 constructor(eventTarget, eventType, receiver, method) { | |
259 this.eventTarget = eventTarget; | |
260 this.eventType = eventType; | |
261 this.receiver = receiver; | |
262 this.method = method; | |
263 } | |
264 }; | |
OLD | NEW |