Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: Source/devtools/front_end/components/EventListenersUtils.js

Issue 1268353005: [DevTools] Support JQuery event listeners (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698