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.PageEventListener; | |
pfeldman
2015/09/03 18:56:35
Still don't get which is what.
kozy
2015/09/03 22:17:25
Renamed to WebInspector.EventListenerObjectInInspe
| |
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.EventListenerRawResult; | |
pfeldman
2015/09/03 20:22:45
This should be entirely encapsulated into the func
kozy
2015/09/03 22:17:25
It looks like I can't encapsulate typedef: https:/
| |
19 | |
20 /** | |
21 * @typedef {{eventListeners:!Array<!WebInspector.EventListener>, internalHandle rs:?WebInspector.RemoteArray}} | |
22 */ | |
23 WebInspector.PageEventListenersResult; | |
24 | |
25 /** | |
26 * @param {!WebInspector.RemoteObject} object | |
27 * @return {!Promise<!WebInspector.PageEventListenersResult>} | |
28 */ | |
29 WebInspector.EventListener.frameworkEventListeners = function(object) | |
30 { | |
31 var listenersResult = /** @type {!WebInspector.PageEventListenersResult} */( {eventListeners: []}); | |
32 return object.callFunctionPromise(frameworkEventListeners, undefined) | |
33 .then(assertCallFunctionResult) | |
34 .then(getOwnProperties) | |
35 .then(createEventListeners) | |
36 .then(returnResult) | |
37 .catchException(listenersResult); | |
38 | |
39 /** | |
40 * @param {!WebInspector.RemoteObject} object | |
41 * @return {!Promise<!{properties: ?Array.<!WebInspector.RemoteObjectPropert y>, internalProperties: ?Array.<!WebInspector.RemoteObjectProperty>}>} | |
42 */ | |
43 function getOwnProperties(object) | |
44 { | |
45 return object.getOwnPropertiesPromise(); | |
46 } | |
47 | |
48 /** | |
49 * @param {!{properties: ?Array<!WebInspector.RemoteObjectProperty>, interna lProperties: ?Array<!WebInspector.RemoteObjectProperty>}} result | |
50 * @return {!Promise<undefined>} | |
51 */ | |
52 function createEventListeners(result) | |
53 { | |
54 if (!result.properties) | |
55 throw new Error("Object properties is empty"); | |
56 var promises = []; | |
57 for (var property of result.properties) { | |
58 if (property.name === "eventListeners" && property.value) | |
59 promises.push(convertToEventListeners(property.value).then(store EventListeners)); | |
60 if (property.name === "internalHandlers" && property.value) | |
61 promises.push(convertToInternalHandlers(property.value).then(sto reInternalHandlers)); | |
62 } | |
63 return /** @type {!Promise<undefined>} */(Promise.all(promises)); | |
64 } | |
65 | |
66 /** | |
67 * @param {!WebInspector.RemoteObject} pageEventListenersObject | |
68 * @return {!Promise<!Array<!WebInspector.EventListener>>} | |
69 */ | |
70 function convertToEventListeners(pageEventListenersObject) | |
71 { | |
72 return WebInspector.RemoteArray.objectAsArray(pageEventListenersObject) | |
73 .map(toEventListener) | |
74 .then(filterOutEmptyObjects); | |
75 | |
76 /** | |
77 * @param {!WebInspector.RemoteObject} listenerObject | |
78 * @return {!Promise<?WebInspector.EventListener>} | |
79 */ | |
80 function toEventListener(listenerObject) | |
81 { | |
82 var eventListenerData = /** @type {!WebInspector.EventListenerData} */({}); | |
83 var promises = []; | |
84 | |
85 promises.push(listenerObject.callFunctionJSONPromise(truncatePageEve ntListener, undefined).then(storeTrunkatedListener)); | |
86 | |
87 /** | |
88 * @suppressReceiverCheck | |
89 * @this {WebInspector.PageEventListener} | |
90 * @return {!{type:string, useCapture:boolean}} | |
91 */ | |
92 function truncatePageEventListener() | |
93 { | |
94 return {type: this.type, useCapture: this.useCapture}; | |
95 } | |
96 | |
97 /** | |
98 * @param {!{type:string, useCapture: boolean}} truncatedListener | |
99 * @return {undefined} | |
pfeldman
2015/09/03 18:56:35
return {undefined}?
kozy
2015/09/03 22:17:25
Removed.
| |
100 */ | |
101 function storeTrunkatedListener(truncatedListener) | |
102 { | |
103 eventListenerData.type = truncatedListener.type; | |
104 eventListenerData.useCapture = truncatedListener.useCapture; | |
105 return undefined; | |
106 } | |
107 | |
108 promises.push(listenerObject.callFunctionPromise(handlerFunction).th en(assertCallFunctionResult) | |
pfeldman
2015/09/03 18:56:35
stack them?
kozy
2015/09/03 22:17:25
Done.
| |
109 .then(toTargetFunction) | |
110 .then(storeFunctionWithDetails)); | |
111 | |
112 /** | |
113 * @suppressReceiverCheck | |
114 * @return {function()} | |
115 * @this {WebInspector.PageEventListener} | |
116 */ | |
117 function handlerFunction() | |
118 { | |
119 return this.handler; | |
120 } | |
121 | |
122 /** | |
123 * @param {!WebInspector.RemoteObject} functionObject | |
124 * @return {!Promise<undefined>} | |
125 */ | |
126 function storeFunctionWithDetails(functionObject) | |
127 { | |
128 eventListenerData.handler = functionObject; | |
129 return /** @type {!Promise<undefined>} */(functionObject.functio nDetailsPromise().then(storeFunctionDetails)); | |
130 } | |
131 | |
132 /** | |
133 * @param {?WebInspector.DebuggerModel.FunctionDetails} functionDeta ils | |
134 */ | |
135 function storeFunctionDetails(functionDetails) | |
136 { | |
137 if (!functionDetails || !functionDetails.location) | |
138 throw new Error("Empty function details or function details location"); | |
139 eventListenerData.location = functionDetails.location; | |
140 } | |
141 | |
142 return Promise.all(promises).then(createEventListener).catchExceptio n(/** @type {?WebInspector.EventListener} */(null)); | |
143 | |
144 /** | |
145 * @return {!WebInspector.EventListener} | |
146 */ | |
147 function createEventListener() | |
148 { | |
149 return new WebInspector.EventListener(eventListenerData.handler. _target, | |
pfeldman
2015/09/03 18:56:35
So you did not need this object, you could have us
kozy
2015/09/03 22:17:25
Done.
| |
150 eventListenerData.type, | |
151 eventListenerData.useCaptu re, | |
152 eventListenerData.handler, | |
153 eventListenerData.location , | |
154 "frameworkUser"); | |
155 } | |
156 } | |
157 } | |
158 | |
159 /** | |
160 * @param {!WebInspector.RemoteObject} pageInternalHandlersObject | |
161 * @return {!Promise<!WebInspector.RemoteArray>} | |
162 */ | |
163 function convertToInternalHandlers(pageInternalHandlersObject) | |
164 { | |
165 return WebInspector.RemoteArray.objectAsArray(pageInternalHandlersObject ).map(toTargetFunction) | |
166 .then(WebInspector.RemoteArray.createFrom RemoteObjects); | |
167 } | |
168 | |
169 /** | |
170 * @param {!WebInspector.RemoteObject} functionObject | |
171 * @return {!Promise<!WebInspector.RemoteObject>} | |
172 */ | |
173 function toTargetFunction(functionObject) | |
174 { | |
175 return WebInspector.RemoteFunction.objectAsFunction(functionObject).targ etFunction(); | |
176 } | |
177 | |
178 /** | |
179 * @param {!Array<!WebInspector.EventListener>} eventListeners | |
180 */ | |
181 function storeEventListeners(eventListeners) | |
182 { | |
183 listenersResult.eventListeners = eventListeners; | |
184 } | |
185 | |
186 /** | |
187 * @param {!WebInspector.RemoteArray} internalHandlers | |
188 */ | |
189 function storeInternalHandlers(internalHandlers) | |
190 { | |
191 listenersResult.internalHandlers = internalHandlers; | |
192 } | |
193 | |
194 /** | |
195 * @return {!WebInspector.PageEventListenersResult} | |
196 */ | |
197 function returnResult() | |
198 { | |
199 return listenersResult; | |
200 } | |
201 | |
202 /** | |
203 * @param {!WebInspector.CallFunctionResult} result | |
204 * @return {!WebInspector.RemoteObject} | |
205 */ | |
206 function assertCallFunctionResult(result) | |
207 { | |
208 if (result.wasThrown || !result.object) | |
209 throw new Error("Exception in callFunction or empty result"); | |
210 return result.object; | |
211 } | |
212 | |
213 /** | |
214 * @param {!Array<?T>} objects | |
215 * @return {!Array<!T>} | |
216 * @template T | |
217 */ | |
218 function filterOutEmptyObjects(objects) | |
219 { | |
220 return objects.filter(filterOutEmpty); | |
221 | |
222 /** | |
223 * @param {?T} object | |
224 * @return {boolean} | |
225 * @template T | |
226 */ | |
227 function filterOutEmpty(object) | |
228 { | |
229 return !!object; | |
230 } | |
231 } | |
232 | |
233 /* | |
234 frameworkEventListeners fetcher functions should produce following output: | |
235 { | |
236 // framework event listeners | |
237 "eventListeners": [ | |
238 { | |
239 "handler": function(), | |
240 "useCapture": true, | |
241 "type": "change" | |
242 }, | |
243 ... | |
244 ], | |
245 // internal framework event handlers | |
246 "internalHandlers": [ | |
247 function(), | |
248 function(), | |
249 ... | |
250 ] | |
251 } | |
252 */ | |
253 /** | |
254 * @suppressReceiverCheck | |
255 * @return {!WebInspector.EventListenerRawResult} | |
256 * @this {Object} | |
257 */ | |
258 function frameworkEventListeners() | |
259 { | |
260 var eventListeners = []; | |
261 var internalHandlers = []; | |
262 var fetchers = [jQueryFetcher]; | |
263 try { | |
264 if (self.devtoolsPageEventListeners && isArrayLike(self.devtoolsPage EventListeners)) | |
265 fetchers = fetchers.concat(self.devtoolsPageEventListeners); | |
266 } catch (e) { | |
267 } | |
268 | |
269 for (var i = 0; i < fetchers.length; ++i) { | |
270 try { | |
271 var fetcherResult = fetchers[i](this); | |
272 eventListeners = eventListeners.concat(fetcherResult.eventListen ers); | |
273 if (fetcherResult.internalHandlers) | |
274 internalHandlers = internalHandlers.concat(fetcherResult.int ernalHandlers); | |
275 } catch (e) { | |
276 } | |
277 } | |
278 var result = {eventListeners: eventListeners}; | |
279 if (internalHandlers.length) | |
280 result.internalHandlers = internalHandlers; | |
281 return result; | |
282 | |
283 /** | |
284 * @param {?Object} obj | |
285 * @return {boolean} | |
286 */ | |
287 function isArrayLike(obj) | |
288 { | |
289 if (!obj || typeof obj !== "object") | |
290 return false; | |
291 try { | |
292 if (typeof obj.splice === "function") { | |
293 var len = obj.length; | |
294 return typeof len === "number" && (len >>> 0 === len && (len > 0 || 1 / len > 0)); | |
295 } | |
296 } catch (e) { | |
297 } | |
298 return false; | |
299 } | |
300 | |
301 function jQueryFetcher(node) | |
302 { | |
303 if (!node || !(node instanceof Node)) | |
304 return {eventListeners: []}; | |
305 var jQuery = /** @type {?{fn,data,_data}}*/(window["jQuery"]); | |
306 if (!jQuery || !jQuery.fn) | |
307 return {eventListeners: []}; | |
308 var jQueryFunction = /** @type {function(!Node)} */(jQuery); | |
309 var data = jQuery._data || jQuery.data; | |
310 | |
311 var eventListeners = []; | |
312 var internalHandlers = []; | |
313 | |
314 if (typeof data === "function") { | |
315 var events = data(node, "events"); | |
316 for (var type in events) { | |
317 for (var key in events[type]) { | |
318 var frameworkListener = events[type][key]; | |
319 if (typeof frameworkListener === "object" || typeof fram eworkListener === "function") { | |
320 var listener = { | |
321 handler: frameworkListener.handler || frameworkL istener, | |
322 useCapture: true, | |
323 type: type | |
324 }; | |
325 eventListeners.push(listener); | |
326 } | |
327 } | |
328 } | |
329 var nodeData = data(node); | |
330 if (typeof nodeData.handle === "function") | |
331 internalHandlers.push(nodeData.handle); | |
332 } | |
333 var entry = jQueryFunction(node)[0]; | |
334 if (entry) { | |
335 var entryEvents = entry["$events"]; | |
336 for (var type in entryEvents) { | |
337 var events = entryEvents[type]; | |
338 for (var key in events) { | |
339 if (typeof events[key] === "function") { | |
340 var listener = { | |
341 handler: events[key], | |
342 useCapture: true, | |
343 type: type | |
344 }; | |
345 eventListeners.push(listener); | |
346 } | |
347 } | |
348 } | |
349 if (entry && entry["$handle"]) | |
350 internalHandlers.push(entry["$handle"]); | |
351 } | |
352 return {eventListeners: eventListeners, internalHandlers: internalHa ndlers}; | |
353 } | |
354 } | |
355 } | |
OLD | NEW |