OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 /** | |
6 * @typedef {{type: string, useCapture: boolean, handler: function()}} | |
7 */ | |
8 WebInspector.FrameworkEventListener; | |
pfeldman
2015/09/02 22:55:34
What is the difference between all of these types?
kozy
2015/09/03 16:27:52
Rename page types to Page*
| |
9 | |
10 /** | |
11 * @typedef {{type:string, useCapture:boolean, handler:!WebInspector.RemoteObjec t, location:!WebInspector.DebuggerModel.Location}} | |
12 */ | |
13 WebInspector.EventListenerData; | |
14 | |
15 /** | |
16 * @typedef {{eventListeners:!Array<!{type:string, handler:function(), useCaptur e:boolean}>, internalHandlers:?Array<function()>}} | |
17 */ | |
18 WebInspector.FrameworkEventListenerRawResult; | |
19 | |
20 /** | |
21 * @typedef {{eventListeners:!Array<!WebInspector.EventListener>, internalHandle rs:?WebInspector.RemoteArray}} | |
22 */ | |
23 WebInspector.FrameworkEventListenersResult; | |
24 | |
25 /** | |
26 * @param {!WebInspector.RemoteObject} object | |
27 * @return {!Promise<!WebInspector.FrameworkEventListenersResult>} | |
28 */ | |
29 WebInspector.EventListener.frameworkEventListeners = function(object) | |
30 { | |
31 var listenersResult = /** @type {!WebInspector.FrameworkEventListenersResult } */({eventListeners: []}); | |
32 return object.callFunctionPromise(frameworkEventListeners, undefined) | |
33 .then(assertCallFunctionResult) | |
34 .then(frameworkEventListenersCallback) | |
35 .then(returnResult) | |
36 .catchException(listenersResult); | |
37 | |
38 /** | |
39 * @param {!WebInspector.RemoteObject} object | |
40 * @return {!Promise<undefined>} | |
41 */ | |
42 function frameworkEventListenersCallback(object) | |
pfeldman
2015/09/02 22:55:34
You should call them based on what they do, not wh
kozy
2015/09/03 16:27:52
Done.
| |
43 { | |
44 return object.getOwnPropertiesPromise().then(propertiesCallback); | |
pfeldman
2015/09/02 22:55:34
Why is propertiesCallback now here? Stack it above
kozy
2015/09/03 16:27:52
Done.
| |
45 } | |
46 | |
47 /** | |
48 * @param {!{properties: ?Array<!WebInspector.RemoteObjectProperty>, interna lProperties: ?Array<!WebInspector.RemoteObjectProperty>}} result | |
49 * @return {!Promise<undefined>} | |
50 */ | |
51 function propertiesCallback(result) | |
52 { | |
53 if (!result.properties) | |
54 throw new Error("Object properties is empty"); | |
55 var promises = []; | |
56 for (var property of result.properties) { | |
57 if (property.name === "eventListeners" && property.value) { | |
58 promises.push(WebInspector.RemoteArray.objectAsArray(property.va lue) | |
pfeldman
2015/09/02 22:55:34
Extract this into the method that returns eventLis
kozy
2015/09/03 16:27:52
Done.
| |
59 .map(toEventListener) | |
60 .then(nonEmptyObjects) | |
61 .then(eventListenersCallba ck)); | |
pfeldman
2015/09/02 22:55:34
Promise<eventListeners>
kozy
2015/09/03 16:27:52
Done.
| |
62 } | |
63 if (property.name === "internalHandlers" && property.value) { | |
64 promises.push(WebInspector.RemoteArray.objectAsArray(property.va lue) | |
pfeldman
2015/09/02 22:55:34
Extract this into the method that returns Promise<
kozy
2015/09/03 16:27:52
Done.
| |
65 .map(toTargetFunction) | |
66 .then(WebInspector.RemoteA rray.createFromRemoteObjects) | |
67 .then(internalHandlersCall back)); | |
68 } | |
69 } | |
70 return /** @type {!Promise<undefined>} */(Promise.all(promises)); | |
71 | |
72 /** | |
73 * @param {!WebInspector.RemoteObject} listenerObject | |
74 * @return {!Promise<?WebInspector.EventListener>} | |
75 */ | |
76 function toEventListener(listenerObject) | |
77 { | |
78 var eventListenerData = /** @type {!WebInspector.EventListenerData} */({}); | |
79 var promises = []; | |
80 | |
81 promises.push(listenerObject.callFunctionJSONPromise(truncateFramewo rkEventListener, undefined).then(truncateFrameworkEventListenerCallback)); | |
82 | |
83 /** | |
84 * @suppressReceiverCheck | |
85 * @this {WebInspector.FrameworkEventListener} | |
86 * @return {!{type:string, useCapture:boolean}} | |
87 */ | |
88 function truncateFrameworkEventListener() | |
89 { | |
90 return {type: this.type, useCapture: this.useCapture}; | |
91 } | |
92 | |
93 /** | |
94 * @param {!{type:string, useCapture: boolean}} truncatedListener | |
95 * @return {undefined} | |
96 */ | |
97 function truncateFrameworkEventListenerCallback(truncatedListener) | |
pfeldman
2015/09/02 22:55:34
strip the Callback suffixes in all over the place,
kozy
2015/09/03 16:27:52
Done.
| |
98 { | |
99 eventListenerData.type = truncatedListener.type; | |
100 eventListenerData.useCapture = truncatedListener.useCapture; | |
101 return undefined; | |
102 } | |
103 | |
104 promises.push(listenerObject.callFunctionPromise(handlerFunction).th en(assertCallFunctionResult) | |
105 .then(toTargetFunction) | |
106 .then(toTargetFunctionCallback)); | |
107 | |
108 /** | |
109 * @suppressReceiverCheck | |
110 * @return {function()} | |
111 * @this {WebInspector.FrameworkEventListener} | |
112 */ | |
113 function handlerFunction() | |
114 { | |
115 return this.handler; | |
116 } | |
117 | |
118 /** | |
119 * @param {!WebInspector.RemoteObject} functionObject | |
120 * @return {!Promise<undefined>} | |
121 */ | |
122 function toTargetFunctionCallback(functionObject) | |
123 { | |
124 eventListenerData.handler = functionObject; | |
125 return /** @type {!Promise<undefined>} */(functionObject.functio nDetailsPromise().then(targetFunctionDetailsCallback)); | |
126 } | |
127 | |
128 /** | |
129 * @param {?WebInspector.DebuggerModel.FunctionDetails} functionDeta ils | |
130 */ | |
131 function targetFunctionDetailsCallback(functionDetails) | |
132 { | |
133 if (!functionDetails || !functionDetails.location) | |
134 throw new Error("Empty function details or function details location"); | |
135 eventListenerData.location = functionDetails.location; | |
136 } | |
137 | |
138 return Promise.all(promises).then(createEventListener).catchExceptio n(/** @type {?WebInspector.EventListener} */(null)); | |
139 | |
140 /** | |
141 * @return {!WebInspector.EventListener} | |
142 */ | |
143 function createEventListener() | |
144 { | |
145 return new WebInspector.EventListener(eventListenerData.handler. _target, | |
146 eventListenerData.type, | |
147 eventListenerData.useCaptu re, | |
148 eventListenerData.handler, | |
149 eventListenerData.location , | |
150 "frameworkUser"); | |
151 } | |
152 } | |
153 | |
154 /** | |
155 * @param {!WebInspector.RemoteObject} functionObject | |
156 * @return {!Promise<!WebInspector.RemoteObject>} | |
157 */ | |
158 function toTargetFunction(functionObject) | |
159 { | |
160 return WebInspector.RemoteFunction.objectAsFunction(functionObject). targetFunction(); | |
161 } | |
162 | |
163 /** | |
164 * @param {!Array<?T>} objects | |
165 * @return {!Array<!T>} | |
166 * @template T | |
167 */ | |
168 function nonEmptyObjects(objects) | |
169 { | |
170 return objects.filter(filterOutEmpty); | |
171 | |
172 /** | |
173 * @param {?T} object | |
174 * @return {boolean} | |
175 * @template T | |
176 */ | |
177 function filterOutEmpty(object) | |
178 { | |
179 return !!object; | |
180 } | |
181 } | |
182 } | |
183 | |
184 /** | |
185 * @param {!Array<!WebInspector.EventListener>} eventListeners | |
186 */ | |
187 function eventListenersCallback(eventListeners) | |
188 { | |
189 listenersResult.eventListeners = eventListeners; | |
190 } | |
191 | |
192 /** | |
193 * @param {!WebInspector.RemoteArray} internalHandlers | |
194 */ | |
195 function internalHandlersCallback(internalHandlers) | |
196 { | |
197 listenersResult.internalHandlers = internalHandlers; | |
198 } | |
199 | |
200 /** | |
201 * @return {!WebInspector.FrameworkEventListenersResult} | |
202 */ | |
203 function returnResult() | |
204 { | |
205 return listenersResult; | |
206 } | |
207 | |
208 /** | |
209 * @param {!WebInspector.CallFunctionResult} result | |
210 * @return {!WebInspector.RemoteObject} | |
211 */ | |
212 function assertCallFunctionResult(result) | |
213 { | |
214 if (result.wasThrown || !result.object) | |
215 throw new Error("Exception in callFunction or empty result"); | |
216 return result.object; | |
217 } | |
218 | |
219 /* | |
220 frameworkEventListeners fetcher functions should produce following output: | |
221 { | |
222 // framework event listeners | |
223 "eventListeners": [ | |
224 { | |
225 "handler": function(), | |
226 "useCapture": true, | |
227 "type": "change" | |
228 }, | |
229 ... | |
230 ], | |
231 // internal framework event handlers | |
232 "internalHandlers": [ | |
233 function(), | |
234 function(), | |
235 ... | |
236 ] | |
237 } | |
238 */ | |
239 /** | |
240 * @suppressReceiverCheck | |
241 * @return {!WebInspector.FrameworkEventListenerRawResult} | |
242 * @this {Object} | |
243 */ | |
244 function frameworkEventListeners() | |
245 { | |
246 var eventListeners = []; | |
247 var internalHandlers = []; | |
248 var fetchers = [jQueryFetcher]; | |
249 try { | |
250 if (self.devtoolsFrameworkEventListeners && isArrayLike(self.devtool sFrameworkEventListeners)) | |
251 fetchers = fetchers.concat(self.devtoolsFrameworkEventListeners) ; | |
252 } catch (e) { | |
253 } | |
254 | |
255 for (var i = 0; i < fetchers.length; ++i) { | |
256 try { | |
257 var fetcherResult = fetchers[i](this); | |
258 eventListeners = eventListeners.concat(fetcherResult.eventListen ers); | |
259 if (fetcherResult.internalHandlers) | |
260 internalHandlers = internalHandlers.concat(fetcherResult.int ernalHandlers); | |
261 } catch (e) { | |
262 } | |
263 } | |
264 var result = {eventListeners: eventListeners}; | |
265 if (internalHandlers.length) | |
266 result.internalHandlers = internalHandlers; | |
267 return result; | |
268 | |
269 /** | |
270 * @param {?Object} obj | |
271 * @return {boolean} | |
272 */ | |
273 function isArrayLike(obj) | |
274 { | |
275 if (!obj || typeof obj !== "object") | |
276 return false; | |
277 try { | |
278 if (typeof obj.splice === "function") { | |
279 var len = obj.length; | |
280 return typeof len === "number" && (len >>> 0 === len && (len > 0 || 1 / len > 0)); | |
281 } | |
282 } catch (e) { | |
283 } | |
284 return false; | |
285 } | |
286 | |
287 function jQueryFetcher(node) | |
288 { | |
289 if (!node || !(node instanceof Node)) | |
290 return {eventListeners: []}; | |
291 var jQuery = /** @type {?{fn,data,_data}}*/(window["jQuery"]); | |
292 if (!jQuery || !jQuery.fn) | |
293 return {eventListeners: []}; | |
294 var jQueryFunction = /** @type {function(!Node)} */(jQuery); | |
295 var data = jQuery._data || jQuery.data; | |
296 | |
297 var eventListeners = []; | |
298 var internalHandlers = []; | |
299 | |
300 if (typeof data === "function") { | |
301 var events = data(node, "events"); | |
302 for (var type in events) { | |
303 for (var key in events[type]) { | |
304 var frameworkListener = events[type][key]; | |
305 if (typeof frameworkListener === "object" || typeof fram eworkListener === "function") { | |
306 var listener = { | |
307 handler: frameworkListener.handler || frameworkL istener, | |
308 useCapture: true, | |
309 type: type | |
310 }; | |
311 eventListeners.push(listener); | |
312 } | |
313 } | |
314 } | |
315 var nodeData = data(node); | |
316 if (typeof nodeData.handle === "function") | |
317 internalHandlers.push(nodeData.handle); | |
318 } | |
319 var entry = jQueryFunction(node)[0]; | |
320 if (entry) { | |
321 var entryEvents = entry["$events"]; | |
322 for (var type in entryEvents) { | |
323 var events = entryEvents[type]; | |
324 for (var key in events) { | |
325 if (typeof events[key] === "function") { | |
326 var listener = { | |
327 handler: events[key], | |
328 useCapture: true, | |
329 type: type | |
330 }; | |
331 eventListeners.push(listener); | |
332 } | |
333 } | |
334 } | |
335 if (entry && entry["$handle"]) | |
336 internalHandlers.push(entry["$handle"]); | |
337 } | |
338 return {eventListeners: eventListeners, internalHandlers: internalHa ndlers}; | |
339 } | |
340 } | |
341 } | |
OLD | NEW |