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|!Common.Emittable), !Array<!Common.Object._listener
CallbackTuple>>|undefined)} */ |
| 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 = new Map(); |
| 47 |
43 if (!this._listeners.has(eventType)) | 48 if (!this._listeners.has(eventType)) |
44 this._listeners.set(eventType, []); | 49 this._listeners.set(eventType, []); |
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 |
(...skipping 13 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:Common.Emittable, ...)} 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) |
104 this._listeners = new Map(); | 109 this._listeners = 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:Common.Emittable, ...)} eventType |
115 * @param {function(!T)} listener | 119 * @param {function(!Common.Emittable)} listener |
116 * @param {!Object=} thisObject | 120 * @param {!Object=} thisObject |
117 */ | 121 */ |
118 off(eventType, listener, thisObject) { | 122 off(eventType, listener, thisObject) { |
119 if (!this._listeners || !this._listeners.has(eventType)) | 123 if (!this._listeners || !this._listeners.has(eventType)) |
120 return; | 124 return; |
121 var listeners = this._listeners.get(eventType); | 125 var listeners = this._listeners.get(eventType); |
122 for (var i = 0; i < listeners.length; ++i) { | 126 for (var i = 0; i < listeners.length; ++i) { |
123 if (listeners[i].listener === listener && listeners[i].thisObject === this
Object) | 127 if (listeners[i].listener === listener && listeners[i].thisObject === this
Object) |
124 listeners.splice(i--, 1); | 128 listeners.splice(i--, 1); |
125 } | 129 } |
126 if (!listeners.length) | 130 if (!listeners.length) |
127 this._listeners.delete(eventType); | 131 this._listeners.delete(eventType); |
128 } | 132 } |
129 | 133 |
130 /** | 134 /** |
131 * @template T | |
132 * @override | 135 * @override |
133 * @param {!T} event | 136 * @param {!Common.Emittable} event |
134 */ | 137 */ |
135 emit(event) { | 138 emit(event) { |
136 var eventType = event.constructor; | 139 var eventType = event.constructor; |
137 if (!this._listeners || !this._listeners.has(eventType)) | 140 if (!this._listeners || !this._listeners.has(eventType)) |
138 return; | 141 return; |
139 var listeners = this._listeners.get(eventType).slice(0); | 142 var listeners = this._listeners.get(eventType).slice(0); |
140 for (var i = 0; i < listeners.length; ++i) | 143 for (var i = 0; i < listeners.length; ++i) |
141 listeners[i].listener.call(listeners[i].thisObject, event); | 144 listeners[i].listener.call(listeners[i].thisObject, event); |
142 } | 145 } |
143 }; | 146 }; |
144 | 147 |
145 /** | 148 /** |
| 149 * @interface |
| 150 */ |
| 151 Common.Emittable = function() {}; |
| 152 |
| 153 /** |
| 154 * @typedef {!{thisObject: (!Object|undefined), listener: function(!Common.Emitt
able)}} |
| 155 */ |
| 156 Common.Object._listenerCallbackTuple; |
| 157 |
| 158 /** |
| 159 * @implements {Common.Emittable} |
146 * @unrestricted | 160 * @unrestricted |
147 */ | 161 */ |
148 Common.Event = class { | 162 Common.Event = class { |
149 /** | 163 /** |
150 * @param {*=} data | 164 * @param {*=} data |
151 */ | 165 */ |
152 constructor(data) { | 166 constructor(data) { |
153 this.data = data; | 167 this.data = data; |
154 } | 168 } |
155 }; | 169 }; |
156 | 170 |
157 /** | 171 /** |
158 * @interface | 172 * @interface |
159 */ | 173 */ |
160 Common.EventTarget = function() {}; | 174 Common.EventTarget = function() {}; |
161 | 175 |
162 /** | 176 /** |
163 * @param {!Array<!Common.EventTarget.EventDescriptor|!Common.EventTarget.TypedE
ventDescriptor>} eventList | 177 * @record |
| 178 * @template T |
| 179 */ |
| 180 Common.EventTarget.EventDescriptorStruct = class { |
| 181 constructor() { |
| 182 /** @type {!Common.EventTarget} */ |
| 183 this.eventTarget; |
| 184 /** @type {!T} */ |
| 185 this.eventType; |
| 186 /** @type {(!Object|undefined)} */ |
| 187 this.receiver; |
| 188 /** @type {function(!Common.Emittable)} */ |
| 189 this.method; |
| 190 } |
| 191 }; |
| 192 |
| 193 /** |
| 194 * @implements {Common.EventTarget.EventDescriptorStruct<symbol>} |
| 195 * @unrestricted |
| 196 */ |
| 197 Common.EventTarget.EventDescriptor = class { |
| 198 /** |
| 199 * @param {!Common.EventTarget} eventTarget |
| 200 * @param {symbol} eventType |
| 201 * @param {(!Object|undefined)} receiver |
| 202 * @param {function(!Common.Event)} method |
| 203 */ |
| 204 constructor(eventTarget, eventType, receiver, method) { |
| 205 this.eventTarget = eventTarget; |
| 206 this.eventType = eventType; |
| 207 this.receiver = receiver; |
| 208 this.method = method; |
| 209 } |
| 210 }; |
| 211 |
| 212 /** |
| 213 * @implements {Common.EventTarget.EventDescriptorStruct<function(new:Common.Emi
ttable)>} |
| 214 * @unrestricted |
| 215 */ |
| 216 Common.EventTarget.TypedEventDescriptor = class { |
| 217 /** |
| 218 * @param {!Common.EventTarget} eventTarget |
| 219 * @param {function(new:Common.Emittable, ...)} eventType |
| 220 * @param {(!Object|undefined)} receiver |
| 221 * @param {function(!Common.Emittable)} method |
| 222 */ |
| 223 constructor(eventTarget, eventType, receiver, method) { |
| 224 this.eventTarget = eventTarget; |
| 225 this.eventType = eventType; |
| 226 this.receiver = receiver; |
| 227 this.method = method; |
| 228 } |
| 229 }; |
| 230 |
| 231 /** |
| 232 * @param {!Array<!Common.EventTarget.EventDescriptorStruct>} eventList |
164 */ | 233 */ |
165 Common.EventTarget.removeEventListeners = function(eventList) { | 234 Common.EventTarget.removeEventListeners = function(eventList) { |
166 for (var i = 0; i < eventList.length; ++i) { | 235 for (var i = 0; i < eventList.length; ++i) { |
167 var eventInfo = eventList[i]; | 236 if (eventList[i] instanceof Common.EventTarget.EventDescriptor) { |
168 if (eventInfo instanceof Common.EventTarget.EventDescriptor) | 237 var eventInfo = /** @type {!Common.EventTarget.EventDescriptor} */ (eventL
ist[i]); |
169 eventInfo.eventTarget.removeEventListener(eventInfo.eventType, eventInfo.m
ethod, eventInfo.receiver); | 238 eventInfo.eventTarget.removeEventListener(eventInfo.eventType, eventInfo.m
ethod, eventInfo.receiver); |
170 else | 239 } else { |
| 240 var eventInfo = /** @type {!Common.EventTarget.TypedEventDescriptor} */ (e
ventList[i]); |
171 eventInfo.eventTarget.off(eventInfo.eventType, eventInfo.method, eventInfo
.receiver); | 241 eventInfo.eventTarget.off(eventInfo.eventType, eventInfo.method, eventInfo
.receiver); |
| 242 } |
172 } | 243 } |
173 // Do not hold references on unused event descriptors. | 244 // Do not hold references on unused event descriptors. |
174 eventList.splice(0, eventList.length); | 245 eventList.splice(0, eventList.length); |
175 }; | 246 }; |
176 | 247 |
177 Common.EventTarget.prototype = { | 248 Common.EventTarget.prototype = { |
178 /** | 249 /** |
179 * @param {symbol} eventType | 250 * @param {symbol} eventType |
180 * @param {function(!Common.Event)} listener | 251 * @param {function(!Common.Event)} listener |
181 * @param {!Object=} thisObject | 252 * @param {!Object=} thisObject |
(...skipping 14 matching lines...) Expand all Loading... |
196 */ | 267 */ |
197 hasEventListeners(eventType) {}, | 268 hasEventListeners(eventType) {}, |
198 | 269 |
199 /** | 270 /** |
200 * @param {symbol} eventType | 271 * @param {symbol} eventType |
201 * @param {*=} eventData | 272 * @param {*=} eventData |
202 */ | 273 */ |
203 dispatchEventToListeners(eventType, eventData) {}, | 274 dispatchEventToListeners(eventType, eventData) {}, |
204 | 275 |
205 /** | 276 /** |
206 * @template T | 277 * @param {function(new:Common.Emittable, ...)} eventType |
207 * @param {function(new:T, ...)} eventType | |
208 * @param {function(!T)} listener | 278 * @param {function(!T)} listener |
209 * @param {!Object=} thisObject | 279 * @param {!Object=} thisObject |
210 * @return {!Common.EventTarget.TypedEventDescriptor} | 280 * @return {!Common.EventTarget.TypedEventDescriptor} |
| 281 * @template T |
211 */ | 282 */ |
212 on(eventType, listener, thisObject) {}, | 283 on(eventType, listener, thisObject) {}, |
213 | 284 |
214 /** | 285 /** |
215 * @template T | 286 * @param {function(new:Common.Emittable, ...)} eventType |
216 * @param {function(new:T, ...)} eventType | 287 * @param {function(!Common.Emittable)} listener |
217 * @param {function(!T)} listener | |
218 * @param {!Object=} thisObject | 288 * @param {!Object=} thisObject |
219 */ | 289 */ |
220 off(eventType, listener, thisObject) {}, | 290 off(eventType, listener, thisObject) {}, |
221 | 291 |
222 /** | 292 /** |
223 * @template T | 293 * @param {!Common.Emittable} event |
224 * @param {!T} event | |
225 */ | 294 */ |
226 emit(event) {}, | 295 emit(event) {}, |
227 }; | 296 }; |
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 |