Chromium Code Reviews| 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 |