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

Unified Diff: Source/devtools/front_end/sdk/EventListenerUtils.js

Issue 1268353005: [DevTools] Support JQuery event listeners (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Implemented in frontend code Created 5 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: Source/devtools/front_end/sdk/EventListenerUtils.js
diff --git a/Source/devtools/front_end/sdk/EventListenerUtils.js b/Source/devtools/front_end/sdk/EventListenerUtils.js
new file mode 100644
index 0000000000000000000000000000000000000000..48ef66eccc3e46542338667aa46191e379cface3
--- /dev/null
+++ b/Source/devtools/front_end/sdk/EventListenerUtils.js
@@ -0,0 +1,342 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @param {!WebInspector.RemoteObject} functionObject
+ * @return {!Promise<!WebInspector.RemoteObject>}
+ */
+WebInspector.targetFunction = function(functionObject)
+{
+ return new Promise(promiseConstructor);
+
+ /**
+ * @param {function(?)} fulfill
+ * @param {function(*)} reject
+ */
+ function promiseConstructor(fulfill, reject)
+ {
+ functionObject.getOwnProperties(ownPropertiesCallback);
pfeldman 2015/08/24 23:29:44 You should promisify the getOwnProperties instead,
+ function ownPropertiesCallback(properties, internalProperties)
+ {
+ if (internalProperties) {
+ for (var i = 0; i < internalProperties.length; ++i) {
+ if (internalProperties[i].name === "[[TargetFunction]]") {
+ fulfill(internalProperties[i].value);
+ return;
+ }
+ }
+ }
+ fulfill(functionObject);
+ }
+ }
+}
+
+/**
+ * @param {!WebInspector.RemoteObject} functionObject
+ * @return {!Promise<{functionObject: !WebInspector.RemoteObject, functionDetails: ?WebInspector.DebuggerModel.FunctionDetails}>}
+ */
+WebInspector.functionDetails = function(functionObject)
+{
+ return new Promise(promiseConstructor);
+
+ /**
+ * @param {function(?)} fulfill
+ * @param {function(*)} reject
+ */
+ function promiseConstructor(fulfill, reject)
+ {
+ if (!functionObject) {
+ fulfill({functionObject: null, functionDetails: null});
+ return;
+ }
+ functionObject.functionDetails(functionDetailsCallback);
pfeldman 2015/08/24 23:29:44 ditto, pure promisification required.
+ /**
+ * @param {?WebInspector.DebuggerModel.FunctionDetails} functionDetails
+ */
+ function functionDetailsCallback(functionDetails)
+ {
+ fulfill({functionObject: functionObject, functionDetails: functionDetails});
+ }
+ }
+}
+
+/**
+ * @param {!WebInspector.RemoteObject} frameworkEventListener
+ * @return {!Promise<!WebInspector.EventListener>}
+ */
+WebInspector.buildEventListener = function(frameworkEventListener)
pfeldman 2015/08/24 23:29:44 This should be a part of the event listeners view
+{
+ var promises = [frameworkEventListener.callFunctionJSONPromise(function(){ return this; }, undefined)];
pfeldman 2015/08/24 23:29:44 Also hard to parse what it does, it uses inline fu
+ promises.push(frameworkEventListener.callFunctionPromise(effectiveFunction, undefined).then(targetFunction).then(WebInspector.functionDetails));
+ return Promise.all(promises).then(frameworkEventListenerCallback);
+
+ /**
+ * @param {!{object: ?WebInspector.RemoteObject, wasThrown: (boolean|undefined)}} result
+ * @return {!Promise<!WebInspector.RemoteObject>}
+ */
+ function targetFunction(result)
+ {
+ return WebInspector.targetFunction(/** @type {!WebInspector.RemoteObject} */(result.object));
+ }
+
+ /**
+ * @suppressReceiverCheck
+ * @this {Object}
+ * @return {function()}
+ */
+ function effectiveFunction()
+ {
+ if (typeof this.handler === "function")
+ return this.handler;
+ return typeof this.handler === "object" ? (this.handler.handlerEvent || this.handler.constructor) : null;
+ }
+
+ /**
+ * @param {!Array<*>} data
+ * @return {!WebInspector.EventListener}
+ */
+ function frameworkEventListenerCallback(data)
+ {
+ var listenerJSON = data[0];
+ var targetFunction = data[1];
+ return new WebInspector.EventListener(frameworkEventListener.target(), listenerJSON.type, listenerJSON.useCapture, targetFunction.functionDetails.location, targetFunction.functionObject, targetFunction.functionDetails.sourceURL);
+ }
+}
+
+/**
+ * @param {!{object: ?WebInspector.RemoteObject, wasThrown: (boolean|undefined)}} frameworkListenersResult
+ * @return {!Promise<?Array<!WebInspector.EventListener>>}
+ */
+WebInspector.castEventListeners = function(frameworkListenersResult)
pfeldman 2015/08/24 23:29:43 move into widget, also impossible to tell what lay
+{
+ if (frameworkListenersResult.wasThrown)
+ return /** @type{!Promise<?Array<!WebInspector.EventListener>>} */(Promise.resolve(null));
+ var frameworkListeners = frameworkListenersResult.object;
+ var promises = [];
+ for (var i = 0; i < frameworkListeners.arrayLength(); ++i)
+ promises.push(frameworkListeners.callFunctionPromise(function(idx){ return this[idx]; }, [WebInspector.RemoteObject.toCallArgument(i)]).then(buildEventListener));
+ return /** @type{!Promise<?Array<!WebInspector.EventListener>>} */(Promise.all(promises));
+
+ /**
+ * @param {!{object: ?WebInspector.RemoteObject, wasThrown: (boolean|undefined)}} result
+ * @return {!Promise<!WebInspector.EventListener>}
+ */
+ function buildEventListener(result)
+ {
+ return WebInspector.buildEventListener(/** @type {!WebInspector.RemoteObject} */(result.object));
+ }
+}
+
+
+/**
+ * @param {!{object: ?WebInspector.RemoteObject, wasThrown: (boolean|undefined)}} frameworkHandlersResult
+ * @return {!Promise<?Array<function()>>}
+ */
+WebInspector.castEventHandlers = function(frameworkHandlersResult)
pfeldman 2015/08/24 23:29:44 ditto
+{
+ var frameworkHandlers = frameworkHandlersResult.object;
+ return new Promise(promiseConstructor);
+
+ /**
+ * @param {function(?)} fulfill
+ * @param {function(*)} reject
+ */
+ function promiseConstructor(fulfill, reject)
+ {
+ frameworkHandlers.callFunctionPromise(function(){ return new Set(); }, undefined).then(setCreated);
+
+ /**
+ * @param {!{object: ?WebInspector.RemoteObject, wasThrown: (boolean|undefined)}} setResult
+ */
+ function setCreated(setResult)
+ {
+ if (setResult.wasThrown) {
+ fulfill(null);
+ return;
+ }
+ var setObject = setResult.object;
+ var promises = [];
+ for (var i = 0; i < frameworkHandlers.arrayLength(); ++i)
+ promises.push(frameworkHandlers.callFunctionPromise(function(idx){ return this[idx]; }, [WebInspector.RemoteObject.toCallArgument(i)]).then(targetFunction).then(addToSet));
+ Promise.all(promises).then(returnSet);
+
+ /**
+ * @param {!{object: ?WebInspector.RemoteObject, wasThrown: (boolean|undefined)}} result
+ */
+ function targetFunction(result)
+ {
+ return WebInspector.targetFunction(/** @type {!WebInspector.RemoteObject}*/(result.object));
+ }
+
+ /**
+ * @param {!WebInspector.RemoteObject} targetFunctionObject
+ */
+ function addToSet(targetFunctionObject)
+ {
+ return setObject.callFunctionPromise(function(f){ this.add(f); }, [WebInspector.RemoteObject.toCallArgument(targetFunctionObject)]);
+ }
+
+ function returnSet()
+ {
+ fulfill(setObject);
+ }
+ }
+ }
+}
+
+
+/**
+ * @return {!Array<!{handler:function(), useCapture: boolean, type:string}>}
+ * @this {Object}
+ */
+function devtoolsFrameworkEventListeners()
pfeldman 2015/08/24 23:29:44 ditto
+{
+ var listeners = [];
+ var getters = [jQueryEventListeners];
+ try {
+ if (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}
+ */
+function devtoolsFrameworkInternalHandlers()
pfeldman 2015/08/24 23:29:44 ditto
+{
+ var handlers = [];
+ var getters = [jQueryInternalHandlers];
+ try {
+ if (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;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698