Index: Source/devtools/front_end/components/EventListenersView.js |
diff --git a/Source/devtools/front_end/components/EventListenersView.js b/Source/devtools/front_end/components/EventListenersView.js |
index 0a7abf6be8a35aeba01d567696c7eea0be0409d9..be03d01b69ff235da1be4d96e6a8ffcb15d3f921 100644 |
--- a/Source/devtools/front_end/components/EventListenersView.js |
+++ b/Source/devtools/front_end/components/EventListenersView.js |
@@ -3,6 +3,11 @@ |
// found in the LICENSE file. |
/** |
+ * @typedef {Array<{object: !WebInspector.RemoteObject, eventListeners: ?Array<!WebInspector.EventListener>, frameworkEventListeners: ?Array<!WebInspector.EventListener>, frameworkInternalHandlers: ?WebInspector.RemoteSet, isInternal: ?Array<boolean>}>} |
+ */ |
+WebInspector.EventListenersResult; |
+ |
+/** |
* @constructor |
* @param {!Element} element |
*/ |
@@ -30,34 +35,85 @@ WebInspector.EventListenersView.prototype = { |
addObjects: function(objects) |
pfeldman
2015/08/27 01:30:38
I am trying to understand what it does and it is s
|
{ |
var promises = []; |
- for (var i = 0; i < objects.length; ++i) |
- promises.push(objects[i].eventListeners()); |
- return Promise.all(promises).then(listenersCallback.bind(this)); |
+ var results = []; |
+ for (var i = 0; i < objects.length; ++i) { |
+ var result = {object: objects[i]}; |
+ results.push(result); |
+ promises.push(objects[i].eventListeners().then(WebInspector.storeTo.bind(null, result, "eventListeners"))); |
pfeldman
2015/08/27 01:21:31
What's storeTo?
|
+ promises.push(objects[i].frameworkEventListeners(WebInspector.EventListenersView._frameworkEventListenersGetter) |
pfeldman
2015/08/27 01:30:38
In here we call remote objects' frameworkEventList
|
+ .then(WebInspector.storeTo.bind(null, result, "frameworkEventListeners"))); |
+ promises.push(objects[i].frameworkInternalHandlers(WebInspector.EventListenersView._frameworkInternalHandlersGetter) |
+ .then(WebInspector.storeTo.bind(null, result, "frameworkInternalHandlers"))); |
+ } |
+ return Promise.all(promises).then(listenersCallback.bind(this, results)); |
/** |
- * @param {!Array<?Array<!WebInspector.EventListener>>} listeners |
+ * @param {!WebInspector.EventListenersResult} results |
* @this {WebInspector.EventListenersView} |
*/ |
- function listenersCallback(listeners) |
+ function listenersCallback(results) |
{ |
this.reset(); |
- for (var i = 0; i < listeners.length; ++i) |
- this._addObjectEventListeners(objects[i], listeners[i]); |
+ var promises = []; |
+ for (var i = 0; i < results.length; ++i) { |
+ results[i].isInternal = []; |
+ for (var j = 0; j < results[i].eventListeners.length; ++j) { |
+ var handler = results[i].eventListeners[j].handler(); |
+ if (handler) { |
+ promises.push(results[i].frameworkInternalHandlers.has(handler) |
+ .then(WebInspector.storeTo.bind(null, results[i].isInternal, j))); |
+ } |
+ } |
+ } |
+ return Promise.all(promises).then(addResults.bind(this, results)); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.EventListenersResult} results |
+ * @this {WebInspector.EventListenersView} |
+ */ |
+ function addResults(results) |
+ { |
+ for (var i = 0; i < results.length; ++i) { |
+ this._addObjectEventListeners(results[i].object, results[i].eventListeners, "normal", results[i].isInternal); |
+ this._addObjectEventListeners(results[i].object, results[i].frameworkEventListeners, "frameworkUser", null); |
+ } |
this.addEmptyHolderIfNeeded(); |
this._eventListenersArrivedForTest(); |
} |
}, |
/** |
+ * @param {boolean} showFramework |
+ */ |
+ showFrameworkListeners: function(showFramework) |
+ { |
+ var eventTypes = this._treeOutline.rootElement().children(); |
+ for (var eventType of eventTypes) { |
+ for (var listenerElement of eventType.children()) { |
+ var listenerType = listenerElement.listenerType(); |
+ var hidden = false; |
+ if (listenerType === "frameworkUser" && !showFramework) |
+ hidden = true; |
+ if (listenerType === "frameworkInternal" && showFramework) |
+ hidden = true; |
+ listenerElement.hidden = hidden; |
+ } |
+ } |
+ }, |
+ |
+ /** |
* @param {!WebInspector.RemoteObject} object |
* @param {?Array<!WebInspector.EventListener>} eventListeners |
+ * @param {string} listenerType |
+ * @param {?Array<boolean>} isInternal |
*/ |
- _addObjectEventListeners: function(object, eventListeners) |
+ _addObjectEventListeners: function(object, eventListeners, listenerType, isInternal) |
{ |
if (!eventListeners) |
return; |
- for (var eventListener of eventListeners) { |
- var treeItem = this._getOrCreateTreeElementForType(eventListener.type()); |
- treeItem.addObjectEventListener(eventListener, object); |
+ for (var i = 0; i < eventListeners.length; ++i) { |
+ var treeItem = this._getOrCreateTreeElementForType(eventListeners[i].type()); |
+ treeItem.addObjectEventListener(eventListeners[i], object, isInternal && isInternal[i] ? "frameworkInternal" : listenerType); |
} |
}, |
@@ -124,10 +180,11 @@ WebInspector.EventListenersTreeElement.prototype = { |
/** |
* @param {!WebInspector.EventListener} eventListener |
* @param {!WebInspector.RemoteObject} object |
+ * @param {string} listenerType |
*/ |
- addObjectEventListener: function(eventListener, object) |
+ addObjectEventListener: function(eventListener, object, listenerType) |
{ |
- var treeElement = new WebInspector.ObjectEventListenerBar(eventListener, object, this._linkifier); |
+ var treeElement = new WebInspector.ObjectEventListenerBar(eventListener, object, this._linkifier, listenerType); |
this.appendChild(/** @type {!TreeElement} */ (treeElement)); |
}, |
@@ -140,14 +197,16 @@ WebInspector.EventListenersTreeElement.prototype = { |
* @param {!WebInspector.EventListener} eventListener |
* @param {!WebInspector.RemoteObject} object |
* @param {!WebInspector.Linkifier} linkifier |
+ * @param {string} listenerType |
*/ |
-WebInspector.ObjectEventListenerBar = function(eventListener, object, linkifier) |
+WebInspector.ObjectEventListenerBar = function(eventListener, object, linkifier, listenerType) |
{ |
TreeElement.call(this, "", true); |
this._eventListener = eventListener; |
this.editable = false; |
this.selectable = false; |
this._setTitle(object, linkifier); |
+ this._listenerType = listenerType; |
} |
WebInspector.ObjectEventListenerBar.prototype = { |
@@ -174,5 +233,168 @@ WebInspector.ObjectEventListenerBar.prototype = { |
title.appendChild(WebInspector.ObjectPropertiesSection.createValueElement(object, false)); |
}, |
+ /** |
+ * @return {string} |
+ */ |
+ listenerType: function() |
+ { |
+ return this._listenerType; |
+ }, |
+ |
__proto__: TreeElement.prototype |
-} |
+} |
+ |
+/** |
+ * @return {!Array<!{handler:function(), useCapture: boolean, type:string}>} |
+ * @this {Object} |
+ */ |
+WebInspector.EventListenersView._frameworkEventListenersGetter = function() |
+{ |
+ var listeners = []; |
+ var getters = [jQueryEventListeners]; |
+ try { |
+ if (self.devtoolsFrameworkEventListeners && isArrayLike(self.devtoolsFrameworkEventListeners)) |
+ getters = getters.concat(self.devtoolsFrameworkEventListeners); |
+ } catch (e) { |
+ } |
+ |
+ for (var i = 0; i < getters.length; ++i) { |
+ try { |
+ listeners = listeners.concat(getters[i](this)); |
+ } catch (e) { |
+ } |
+ } |
+ return listeners; |
+ |
+ /** |
+ * @param {?Object} obj |
+ * @return {boolean} |
+ */ |
+ function isArrayLike(obj) |
+ { |
+ if (!obj || typeof obj !== "object") |
+ return false; |
+ try { |
+ if (typeof obj.splice === "function") { |
+ var len = obj.length; |
+ return typeof len === "number" && (len >>> 0 === len && (len > 0 || 1 / len > 0)); |
+ } |
+ } catch (e) { |
+ } |
+ return false; |
+ } |
+ |
+ /** |
+ * @param {?Object} node |
+ * @return {!Array<!{handler:function(), useCapture: boolean, type:string}>} |
+ */ |
+ function jQueryEventListeners(node) |
+ { |
+ if (!node || !(node instanceof Node)) |
+ return []; |
+ var hasJQuery = (typeof jQuery !== 'undefined') && jQuery.fn; |
+ if (!hasJQuery) |
+ return []; |
+ var listeners = []; |
+ var data = jQuery._data || jQuery.data; |
+ if (typeof data === "function") { |
+ var events = data(node, "events"); |
+ for (var type in events) { |
+ for (var key in events[type]) { |
+ var frameworkListener = events[type][key]; |
+ if (typeof frameworkListener === "object" || typeof frameworkListener === "function") { |
+ var listener = { |
+ handler: frameworkListener.handler || frameworkListener, |
+ useCapture: true, |
+ type: type |
+ }; |
+ listeners.push(listener); |
+ } |
+ } |
+ } |
+ } |
+ var entry = jQuery(node)[0]; |
+ if (entry) { |
+ var entryEvents = entry["$events"]; |
+ for (var type in entryEvents) { |
+ var events = entryEvents[type]; |
+ for (var key in events) { |
+ if (typeof events[key] === "function") { |
+ var listener = { |
+ handler: events[key], |
+ useCapture: true, |
+ type: type |
+ }; |
+ listeners.push(listener); |
+ } |
+ } |
+ } |
+ } |
+ return listeners; |
+ } |
+} |
+ |
+/** |
+ * @return {!Array<function()>} |
+ * @this {Object} |
+ */ |
+WebInspector.EventListenersView._frameworkInternalHandlersGetter = function() |
pfeldman
2015/08/27 01:30:38
Can we do these two in one pass and return the str
|
+{ |
+ var handlers = []; |
+ var getters = [jQueryInternalHandlers]; |
+ try { |
+ if (self.devtoolsFrameworkInternalHandlers && isArrayLike(self.devtoolsFrameworkInternalHandlers)) |
+ getters = getters.concat(self.devtoolsFrameworkInternalHandlers); |
+ } catch (e) { |
+ } |
+ |
+ for (var i = 0; i < getters.length; ++i) { |
+ try { |
+ handlers = handlers.concat(getters[i](this)); |
+ } catch (e) { |
+ } |
+ } |
+ return handlers; |
+ |
+ /** |
+ * @param {?Object} obj |
+ * @return {boolean} |
+ */ |
+ function isArrayLike(obj) |
+ { |
+ if (!obj || typeof obj !== "object") |
+ return false; |
+ try { |
+ if (typeof obj.splice === "function") { |
+ var len = obj.length; |
+ return typeof len === "number" && (len >>> 0 === len && (len > 0 || 1 / len > 0)); |
+ } |
+ } catch (e) { |
+ } |
+ return false; |
+ } |
+ |
+ /** |
+ * @param {?Object} node |
+ * @return {!Array<function()>} |
+ */ |
+ function jQueryInternalHandlers(node) |
+ { |
+ if (!(node instanceof Node)) |
+ return []; |
+ var hasJQuery = (typeof jQuery !== 'undefined') && jQuery.fn; |
+ if (!hasJQuery) |
+ return []; |
+ var handlers = []; |
+ var data = jQuery._data || jQuery.data; |
+ if (typeof data === "function") { |
+ var nodeData = data(node); |
+ if (typeof nodeData.handle === "function") |
+ handlers.push(nodeData.handle); |
+ } |
+ var entry = jQuery(node)[0]; |
+ if (entry && entry["$handle"]) |
+ handlers.push(entry["$handle"]); |
+ return handlers; |
+ } |
+} |