Title: [188283] trunk
Revision
188283
Author
[email protected]
Date
2015-08-11 13:15:16 -0700 (Tue, 11 Aug 2015)

Log Message

Web Inspector: Agent commands do not actually return a promise when expected
https://bugs.webkit.org/show_bug.cgi?id=138665

Reviewed by Timothy Hatcher.

Source/WebInspectorUI:

This patch unifies the handling of different invocation and dispatch modes in the
InspectorBackend protocol system. Command responses are dispatched to a provided
callback function; if no function was provided, then the command returns a promise.

Rather than awkwardly converting between promises and callbacks at invocation and
response dispatch time, the backend now stores the callback or promise thunks and
knows how to invoke each when the response comes. This mirrors how response handling
works in ProtocolTestStub.js. InspectorBackend includes more machinery to support Agent
objects and various debug flags.

Performanace impact is expected to be negligible, because there are relatively
few commands issued by the inspector frontend and returned promises are short-lived.

Remove all uses of Command.prototype.promise, since it is no longer necessary.

* UserInterface/Base/Test.js:
(InspectorTest.reloadPage):
* UserInterface/Controllers/ReplayManager.js:
(WebInspector.ReplayManager.prototype.getSession.get var):
(WebInspector.ReplayManager.getSegment.get var):
* UserInterface/Models/ReplaySession.js:
(WebInspector.ReplaySession.prototype.segmentsChanged):
* UserInterface/Models/Resource.js:
(WebInspector.Resource.prototype.requestContentFromBackend):
* UserInterface/Models/Script.js:
(WebInspector.Script.prototype.requestContentFromBackend):
* UserInterface/Models/SourceMapResource.js:
(WebInspector.SourceMapResource.prototype.requestContentFromBackend):
* UserInterface/Protocol/InspectorBackend.js:
(InspectorBackendClass):
(InspectorBackendClass.prototype.dispatch):
(InspectorBackendClass.prototype.runAfterPendingDispatches):
(InspectorBackendClass.prototype._sendCommandToBackendWithCallback.set this):
(InspectorBackendClass.set this):
(InspectorBackendClass.prototype._sendCommandToBackendWithCallback):
(InspectorBackendClass.prototype._dispatchResponseToCallback):
(InspectorBackendClass.prototype._dispatchResponseToPromise):
(InspectorBackendClass.prototype._flushPendingScripts):
(InspectorBackend.Command.prototype.invoke):
(InspectorBackend.Command.prototype._invokeWithArguments):
(InspectorBackendClass.prototype._willSendMessageToBackend.set return): Deleted.
(InspectorBackendClass._dispatchCallback.get if): Deleted.
(InspectorBackendClass.prototype._willSendMessageToBackend): Deleted.
(InspectorBackendClass.prototype._invokeCommand): Deleted.
(.callable): Deleted.
(InspectorBackend.Command.create): Deleted.
(InspectorBackend.Command.prototype.promise): Deleted.

LayoutTests:

Add a new test that only checks for proper invocation return values.
Once the async test suite infrastructure is available for frontend tests,
more thorough tests of promises and callbacks will be added.

* inspector/protocol/inspector-backend-invocation-return-value-expected.txt: Added.
* inspector/protocol/inspector-backend-invocation-return-value.html: Added.
* inspector/protocol/protocol-promise-result-expected.txt: Removed.
* inspector/protocol/protocol-promise-result.html: Removed.
* platform/win/TestExpectations: Remove deleted test.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (188282 => 188283)


--- trunk/LayoutTests/ChangeLog	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/LayoutTests/ChangeLog	2015-08-11 20:15:16 UTC (rev 188283)
@@ -1,3 +1,20 @@
+2015-08-11  Brian Burg  <[email protected]>
+
+        Web Inspector: Agent commands do not actually return a promise when expected
+        https://bugs.webkit.org/show_bug.cgi?id=138665
+
+        Reviewed by Timothy Hatcher.
+
+        Add a new test that only checks for proper invocation return values.
+        Once the async test suite infrastructure is available for frontend tests,
+        more thorough tests of promises and callbacks will be added.
+
+        * inspector/protocol/inspector-backend-invocation-return-value-expected.txt: Added.
+        * inspector/protocol/inspector-backend-invocation-return-value.html: Added.
+        * inspector/protocol/protocol-promise-result-expected.txt: Removed.
+        * inspector/protocol/protocol-promise-result.html: Removed.
+        * platform/win/TestExpectations: Remove deleted test.
+
 2015-08-11  Said Abou-Hallawa  <[email protected]>
 
         feMorphology is not rendered correctly on Retina display

Added: trunk/LayoutTests/inspector/protocol/inspector-backend-invocation-return-value-expected.txt (0 => 188283)


--- trunk/LayoutTests/inspector/protocol/inspector-backend-invocation-return-value-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/protocol/inspector-backend-invocation-return-value-expected.txt	2015-08-11 20:15:16 UTC (rev 188283)
@@ -0,0 +1,5 @@
+Testing the inspector backend's return values when invoking a protocol command in various ways.
+
+PASS: RuntimeAgent.evaluate should not return a promise when invoked with a function as the last parameter.
+PASS: RuntimeAgent.evaluate should return a Promise when invoked without a callback.
+

Added: trunk/LayoutTests/inspector/protocol/inspector-backend-invocation-return-value.html (0 => 188283)


--- trunk/LayoutTests/inspector/protocol/inspector-backend-invocation-return-value.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/protocol/inspector-backend-invocation-return-value.html	2015-08-11 20:15:16 UTC (rev 188283)
@@ -0,0 +1,22 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<script>
+function test()
+{
+    let dummyCallback = function(){};
+    let invokeCallbackResult = RuntimeAgent.evaluate("41", dummyCallback);
+    InspectorTest.expectThat(!(invokeCallbackResult instanceof Promise), "RuntimeAgent.evaluate should not return a promise when invoked with a function as the last parameter.");
+
+    let invokePromiseResult = RuntimeAgent.evaluate("42");
+    InspectorTest.expectThat(invokePromiseResult instanceof Promise, "RuntimeAgent.evaluate should return a Promise when invoked without a callback.");
+
+    InspectorTest.completeTest();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+    <p>Testing the inspector backend's return values when invoking a protocol command in various ways.</p>
+</body>
+</html>

Deleted: trunk/LayoutTests/inspector/protocol/protocol-promise-result-expected.txt (188282 => 188283)


--- trunk/LayoutTests/inspector/protocol/protocol-promise-result-expected.txt	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/LayoutTests/inspector/protocol/protocol-promise-result-expected.txt	2015-08-11 20:15:16 UTC (rev 188283)
@@ -1,7 +0,0 @@
-Testing that the inspector backend can return command results using promises.
-
-Using a callback, got RuntimeAgent.evaluate() result: 41
-Setting up two promises for RuntimeAgent.evaluate.
-Using a promise, got RuntimeAgent.evaluate() result: 42
-Using a promise, got RuntimeAgent.evaluate() result: 43
-

Deleted: trunk/LayoutTests/inspector/protocol/protocol-promise-result.html (188282 => 188283)


--- trunk/LayoutTests/inspector/protocol/protocol-promise-result.html	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/LayoutTests/inspector/protocol/protocol-promise-result.html	2015-08-11 20:15:16 UTC (rev 188283)
@@ -1,38 +0,0 @@
-<!doctype html>
-<html>
-<head>
-<script src=""
-<script>
-function test()
-{
-    var c1 = RuntimeAgent.evaluate("41", function(err, result, wasThrown) {
-        InspectorTest.log("Using a callback, got RuntimeAgent.evaluate() result: " + result.value);
-
-        InspectorTest.log("Setting up two promises for RuntimeAgent.evaluate.");
-
-        var p1 = RuntimeAgent.evaluate.promise("42");
-        var p2 = RuntimeAgent.evaluate("43");
-
-        InspectorTest.assert(!(c1 instanceof Promise), "A promise was returned even though a callback was supplied to the command!");
-
-        p1.then(function(payload) {
-            InspectorTest.log("Using a promise, got RuntimeAgent.evaluate() result: " + payload.result.value);
-        });
-        p2.then(function(payload) {
-            InspectorTest.log("Using a promise, got RuntimeAgent.evaluate() result: " + payload.result.value);
-        });
-
-        Promise.all([p1, p2]).then(function() {
-            InspectorTest.completeTest();
-        }).catch(function(error) {
-            InspectorTest.log("ERROR: " + error);
-            InspectorTest.completeTest();
-        })
-    });
-}
-</script>
-</head>
-<body _onload_="runTest()">
-    <p>Testing that the inspector backend can return command results using promises.</p>
-</body>
-</html>

Modified: trunk/LayoutTests/platform/win/TestExpectations (188282 => 188283)


--- trunk/LayoutTests/platform/win/TestExpectations	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/LayoutTests/platform/win/TestExpectations	2015-08-11 20:15:16 UTC (rev 188283)
@@ -2369,7 +2369,6 @@
 webkit.org/b/137157 [ Release ] inspector/model/remote-object-get-properties.html [ Pass Timeout ]
 webkit.org/b/137157 [ Debug ] inspector/model/remote-object-get-properties.html [ Skip ] # Debug Assertion
 webkit.org/b/137157 inspector/page/main-frame-resource.html [ Skip ]
-webkit.org/b/137157 inspector/protocol-promise-result.html [ Skip ]
 http/tests/inspector/css/bad-mime-type.html [ Skip ]
 inspector/test-harness-trivially-works.html [ Skip ]
 inspector/dom/content-node-region-info.html [ Crash Pass Failure Timeout ]

Modified: trunk/Source/WebInspectorUI/ChangeLog (188282 => 188283)


--- trunk/Source/WebInspectorUI/ChangeLog	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/Source/WebInspectorUI/ChangeLog	2015-08-11 20:15:16 UTC (rev 188283)
@@ -1,3 +1,58 @@
+2015-08-11  Brian Burg  <[email protected]>
+
+        Web Inspector: Agent commands do not actually return a promise when expected
+        https://bugs.webkit.org/show_bug.cgi?id=138665
+
+        Reviewed by Timothy Hatcher.
+
+        This patch unifies the handling of different invocation and dispatch modes in the
+        InspectorBackend protocol system. Command responses are dispatched to a provided
+        callback function; if no function was provided, then the command returns a promise.
+
+        Rather than awkwardly converting between promises and callbacks at invocation and
+        response dispatch time, the backend now stores the callback or promise thunks and
+        knows how to invoke each when the response comes. This mirrors how response handling
+        works in ProtocolTestStub.js. InspectorBackend includes more machinery to support Agent
+        objects and various debug flags.
+
+        Performanace impact is expected to be negligible, because there are relatively
+        few commands issued by the inspector frontend and returned promises are short-lived.
+
+        Remove all uses of Command.prototype.promise, since it is no longer necessary.
+
+        * UserInterface/Base/Test.js:
+        (InspectorTest.reloadPage):
+        * UserInterface/Controllers/ReplayManager.js:
+        (WebInspector.ReplayManager.prototype.getSession.get var):
+        (WebInspector.ReplayManager.getSegment.get var):
+        * UserInterface/Models/ReplaySession.js:
+        (WebInspector.ReplaySession.prototype.segmentsChanged):
+        * UserInterface/Models/Resource.js:
+        (WebInspector.Resource.prototype.requestContentFromBackend):
+        * UserInterface/Models/Script.js:
+        (WebInspector.Script.prototype.requestContentFromBackend):
+        * UserInterface/Models/SourceMapResource.js:
+        (WebInspector.SourceMapResource.prototype.requestContentFromBackend):
+        * UserInterface/Protocol/InspectorBackend.js:
+        (InspectorBackendClass):
+        (InspectorBackendClass.prototype.dispatch):
+        (InspectorBackendClass.prototype.runAfterPendingDispatches):
+        (InspectorBackendClass.prototype._sendCommandToBackendWithCallback.set this):
+        (InspectorBackendClass.set this):
+        (InspectorBackendClass.prototype._sendCommandToBackendWithCallback):
+        (InspectorBackendClass.prototype._dispatchResponseToCallback):
+        (InspectorBackendClass.prototype._dispatchResponseToPromise):
+        (InspectorBackendClass.prototype._flushPendingScripts):
+        (InspectorBackend.Command.prototype.invoke):
+        (InspectorBackend.Command.prototype._invokeWithArguments):
+        (InspectorBackendClass.prototype._willSendMessageToBackend.set return): Deleted.
+        (InspectorBackendClass._dispatchCallback.get if): Deleted.
+        (InspectorBackendClass.prototype._willSendMessageToBackend): Deleted.
+        (InspectorBackendClass.prototype._invokeCommand): Deleted.
+        (.callable): Deleted.
+        (InspectorBackend.Command.create): Deleted.
+        (InspectorBackend.Command.prototype.promise): Deleted.
+
 2015-08-11  Devin Rousso  <[email protected]>
 
         Web Inspector: Hovering over an element in the Elements tab should highlight the whole line

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Test.js (188282 => 188283)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Test.js	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Test.js	2015-08-11 20:15:16 UTC (rev 188283)
@@ -220,7 +220,7 @@
 
     this._testPageIsReloading = true;
 
-    return PageAgent.reload.promise(!!shouldIgnoreCache)
+    return PageAgent.reload(!!shouldIgnoreCache)
         .then(function() {
             this._shouldResendResults = true;
             this._testPageReloadedOnce = true;

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/ReplayManager.js (188282 => 188283)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/ReplayManager.js	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/ReplayManager.js	2015-08-11 20:15:16 UTC (rev 188283)
@@ -133,7 +133,7 @@
         if (this._sessionPromises.has(sessionId))
             return this._sessionPromises.get(sessionId);
 
-        var newPromise = ReplayAgent.getSessionData.promise(sessionId)
+        var newPromise = ReplayAgent.getSessionData(sessionId)
             .then(function(payload) {
                 return Promise.resolve(WebInspector.ReplaySession.fromPayload(sessionId, payload));
             });
@@ -148,7 +148,7 @@
         if (this._segmentPromises.has(segmentId))
             return this._segmentPromises.get(segmentId);
 
-        var newPromise = ReplayAgent.getSegmentData.promise(segmentId)
+        var newPromise = ReplayAgent.getSegmentData(segmentId)
             .then(function(payload) {
                 return Promise.resolve(new WebInspector.ReplaySessionSegment(segmentId, payload));
             });

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ReplaySession.js (188282 => 188283)


--- trunk/Source/WebInspectorUI/UserInterface/Models/ReplaySession.js	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ReplaySession.js	2015-08-11 20:15:16 UTC (rev 188283)
@@ -55,7 +55,7 @@
     segmentsChanged()
     {
         // The replay manager won't update the session's list of segments nor create a new session.
-        ReplayAgent.getSessionData.promise(this.identifier)
+        ReplayAgent.getSessionData(this.identifier)
             .then(this._updateFromPayload.bind(this));
     }
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js (188282 => 188283)


--- trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js	2015-08-11 20:15:16 UTC (rev 188283)
@@ -484,11 +484,11 @@
         // If we have the requestIdentifier we can get the actual response for this specific resource.
         // Otherwise the content will be cached resource data, which might not exist anymore.
         if (this._requestIdentifier)
-            return NetworkAgent.getResponseBody.promise(this._requestIdentifier);
+            return NetworkAgent.getResponseBody(this._requestIdentifier);
 
         // There is no request identifier or frame to request content from.
         if (this._parentFrame)
-            return PageAgent.getResourceContent.promise(this._parentFrame.id, this._url);
+            return PageAgent.getResourceContent(this._parentFrame.id, this._url);
 
         return Promise.reject(new Error("Content request failed."));
     }

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/Script.js (188282 => 188283)


--- trunk/Source/WebInspectorUI/UserInterface/Models/Script.js	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Script.js	2015-08-11 20:15:16 UTC (rev 188283)
@@ -118,7 +118,7 @@
             return Promise.reject(new Error("There is no identifier to request content with."));
         }
 
-        return DebuggerAgent.getScriptSource.promise(this._id);
+        return DebuggerAgent.getScriptSource(this._id);
     }
 
     saveIdentityToCookie(cookie)

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/SourceMapResource.js (188282 => 188283)


--- trunk/Source/WebInspectorUI/UserInterface/Models/SourceMapResource.js	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/SourceMapResource.js	2015-08-11 20:15:16 UTC (rev 188283)
@@ -137,7 +137,7 @@
         if (!frameIdentifier)
             frameIdentifier = WebInspector.frameResourceManager.mainFrame.id;
 
-        return NetworkAgent.loadResource.promise(frameIdentifier, this.url).then(sourceMapResourceLoaded.bind(this)).catch(sourceMapResourceLoadError.bind(this));
+        return NetworkAgent.loadResource(frameIdentifier, this.url).then(sourceMapResourceLoaded.bind(this)).catch(sourceMapResourceLoadError.bind(this));
     }
 
     createSourceCodeLocation(lineNumber, columnNumber)

Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js (188282 => 188283)


--- trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js	2015-08-11 20:08:56 UTC (rev 188282)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js	2015-08-11 20:15:16 UTC (rev 188283)
@@ -35,8 +35,7 @@
     constructor()
     {
         this._lastSequenceId = 1;
-        this._pendingResponsesCount = 0;
-        this._callbackData = new Map;
+        this._pendingResponses = new Map;
         this._agents = {};
         this._deferredScripts = [];
 
@@ -83,7 +82,7 @@
         var messageObject = (typeof message === "string") ? JSON.parse(message) : message;
 
         if ("id" in messageObject)
-            this._dispatchCallback(messageObject);
+            this._dispatchResponse(messageObject);
         else
             this._dispatchEvent(messageObject);
     }
@@ -93,7 +92,7 @@
         console.assert(script);
         console.assert(typeof script === "function");
 
-        if (!this._pendingResponsesCount)
+        if (!this._pendingResponses.size)
             script.call(this);
         else
             this._deferredScripts.push(script);
@@ -122,81 +121,128 @@
         return agent;
     }
 
-    _willSendMessageToBackend(command, callback)
+    _sendCommandToBackendWithCallback(command, parameters, callback)
     {
-        ++this._pendingResponsesCount;
-        var sequenceId = this._lastSequenceId++;
+        let sequenceId = this._lastSequenceId++;
 
-        if (callback && typeof callback === "function") {
-            var callbackData =  {
-                "callback": callback,
-                "command": command,
-            };
+        let messageObject = {
+            "id": sequenceId,
+            "method": command.qualifiedName,
+        };
 
-            if (this.dumpInspectorTimeStats)
-                callbackData.sendRequestTime = Date.now();
+        if (Object.keys(parameters).length)
+            messageObject["params"] = parameters;
 
-            this._callbackData.set(sequenceId, callbackData);
-        }
+        let responseData = {command, callback};
 
-        return sequenceId;
+        // FIXME: <https://webkit.org/b/135467> use performance.now() where available.
+        if (this.dumpInspectorTimeStats)
+            responseData.sendRequestTime = Date.now();
+
+        this._pendingResponses.set(sequenceId, responseData);
+        this._sendMessageToBackend(messageObject);
     }
 
-    _dispatchCallback(messageObject)
+    _sendCommandToBackendExpectingPromise(command, parameters)
     {
-        --this._pendingResponsesCount;
-        console.assert(this._pendingResponsesCount >= 0);
+        let sequenceId = this._lastSequenceId++;
 
+        let messageObject = {
+            "id": sequenceId,
+            "method": command.qualifiedName,
+        };
+
+        if (Object.keys(parameters).length)
+            messageObject["params"] = parameters;
+
+        let responseData = {command};
+
+        // FIXME: <https://webkit.org/b/135467> use performance.now() where available.
+        if (this.dumpInspectorTimeStats)
+            responseData.sendRequestTime = Date.now();
+
+        let responsePromise = new Promise(function(resolve, reject) {
+            responseData.promise = {resolve, reject};
+        });
+
+        this._pendingResponses.set(sequenceId, responseData);
+        this._sendMessageToBackend(messageObject);
+
+        return responsePromise;
+    }
+
+    _sendMessageToBackend(messageObject)
+    {
+        let stringifiedMessage = JSON.stringify(messageObject);
+        if (this.dumpInspectorProtocolMessages)
+            console.log("frontend: " + stringifiedMessage);
+
+        InspectorFrontendHost.sendMessageToBackend(stringifiedMessage);
+    }
+
+    _dispatchResponse(messageObject)
+    {
+        console.assert(this._pendingResponses.size >= 0);
+
         if (messageObject["error"]) {
             if (messageObject["error"].code !== -32000)
                 this._reportProtocolError(messageObject);
         }
 
-        var callbackData = this._callbackData.get(messageObject["id"]);
-        if (callbackData && typeof callbackData.callback === "function") {
-            var command = callbackData.command;
-            var callback = callbackData.callback;
-            var callbackArguments = [];
+        let sequenceId = messageObject["id"];
+        console.assert(this._pendingResponses.has(sequenceId), sequenceId, this._pendingResponses);
 
-            callbackArguments.push(messageObject["error"] ? messageObject["error"].message : null);
+        let responseData = this._pendingResponses.take(sequenceId);
+        let {command, callback, promise} = responseData;
 
-            if (messageObject["result"]) {
-                // FIXME: this should be indicated by invoking the command differently, rather
-                // than by setting a magical property on the callback. <webkit.org/b/132386>
-                if (callback.expectsResultObject) {
-                    // The callback expects results as an object with properties, this is useful
-                    // for backwards compatibility with renamed or different parameters.
-                    callbackArguments.push(messageObject["result"]);
-                } else {
-                    for (var parameterName of command.replySignature)
-                        callbackArguments.push(messageObject["result"][parameterName]);
-                }
-            }
+        var processingStartTime;
+        if (this.dumpInspectorTimeStats)
+            processingStartTime = Date.now();
 
-            var processingStartTime;
-            if (this.dumpInspectorTimeStats)
-                processingStartTime = Date.now();
+        if (typeof callback === "function")
+            this._dispatchResponseToCallback(command, messageObject, callback);
+        else if (typeof promise === "object")
+            this._dispatchResponseToPromise(command, messageObject, promise);
+        else
+            console.error("Received a command response without a corresponding callback or promise.", messageObject, command);
 
-            try {
-                callback.apply(null, callbackArguments);
-            } catch (e) {
-                console.error("Uncaught exception in inspector page while dispatching callback for command " + command.qualifiedName + ": ", e, e.stack);
-            }
+        var processingDuration = Date.now() - processingStartTime;
+        if (this.warnForLongMessageHandling && processingDuration > this.longMessageHandlingThreshold)
+            console.warn("InspectorBackend: took " + processingDuration + "ms to handle response for command: " + command.qualifiedName);
 
-            var processingDuration = Date.now() - processingStartTime;
-            if (this.warnForLongMessageHandling && processingDuration > this.longMessageHandlingThreshold)
-                console.warn("InspectorBackend: took " + processingDuration + "ms to handle response for command: " + command.qualifiedName);
+        if (this.dumpInspectorTimeStats)
+            console.log("time-stats: Handling: " + processingDuration + "ms; RTT: " + (processingStartTime - responseData.sendRequestTime) + "ms; (command " + command.qualifiedName + ")");
 
-            if (this.dumpInspectorTimeStats)
-                console.log("time-stats: Handling: " + processingDuration + "ms; RTT: " + (processingStartTime - callbackData.sendRequestTime) + "ms; (command " + command.qualifiedName + ")");
+        if (this._deferredScripts.length && !this._pendingResponses.size)
+            this._flushPendingScripts();
+    }
 
-            this._callbackData.delete(messageObject["id"]);
+    _dispatchResponseToCallback(command, messageObject, callback)
+    {
+        let callbackArguments = [];
+        callbackArguments.push(messageObject["error"] ? messageObject["error"].message : null);
+
+        if (messageObject["result"]) {
+            for (var parameterName of command.replySignature)
+                callbackArguments.push(messageObject["result"][parameterName]);
         }
 
-        if (this._deferredScripts.length && !this._pendingResponsesCount)
-            this._flushPendingScripts();
+        try {
+            callback.apply(null, callbackArguments);
+        } catch (e) {
+            console.error("Uncaught exception in inspector page while dispatching callback for command " + command.qualifiedName + ": ", e, e.stack);
+        }
     }
 
+    _dispatchResponseToPromise(command, messageObject, promise)
+    {
+        let {resolve, reject} = promise;
+        if (messageObject["error"])
+            reject(new Error(messageObject["error"].message));
+        else
+            resolve(messageObject["result"]);
+    }
+
     _dispatchEvent(messageObject)
     {
         var qualifiedName = messageObject["method"];
@@ -243,25 +289,6 @@
             console.log("time-stats: Handling: " + processingDuration + "ms (event " + messageObject["method"] + ")");
     }
 
-    _invokeCommand(command, parameters, callback)
-    {
-        var messageObject = {};
-        messageObject["method"] = command.qualifiedName;
-
-        if (parameters)
-            messageObject["params"] = parameters;
-
-        // We always assign an id as a sequence identifier.
-        // Callback data is saved only if a callback is actually passed.
-        messageObject["id"] = this._willSendMessageToBackend(command, callback);
-
-        var stringifiedMessage = JSON.stringify(messageObject);
-        if (this.dumpInspectorProtocolMessages)
-            console.log("frontend: " + stringifiedMessage);
-
-        InspectorFrontendHost.sendMessageToBackend(stringifiedMessage);
-    }
-
     _reportProtocolError(messageObject)
     {
         console.error("Request with id = " + messageObject["id"] + " failed. " + JSON.stringify(messageObject["error"]));
@@ -269,7 +296,7 @@
 
     _flushPendingScripts()
     {
-        console.assert(!this._pendingResponsesCount);
+        console.assert(this._pendingResponses.size === 0);
 
         var scriptsToRun = this._deferredScripts;
         this._deferredScripts = [];
@@ -378,9 +405,6 @@
     var instance = new InspectorBackend.Command(backend, commandName, callSignature, replySignature);
 
     function callable() {
-        // If the last argument to the command is not a function, return a result promise.
-        if (!arguments.length || typeof arguments[arguments.length - 1] !== "function")
-            return instance.promise.apply(instance, arguments);
         return instance._invokeWithArguments.apply(instance, arguments);
     }
 
@@ -421,28 +445,12 @@
     {
         'use strict';
 
-        var instance = this._instance;
-        instance._backend._invokeCommand(instance, commandArguments, callback);
-    },
+        let instance = this._instance;
 
-    promise: function()
-    {
-        'use strict';
-
-        var instance = this._instance;
-        var promiseArguments = Array.from(arguments);
-        return new Promise(function(resolve, reject) {
-            function convertToPromiseCallback(error, payload) {
-                return error ? reject(new Error(error)) : resolve(payload);
-            }
-
-            // FIXME: this should be indicated by invoking the command differently, rather
-            // than by setting a magical property on the callback. <webkit.org/b/132386>
-            convertToPromiseCallback.expectsResultObject = true;
-
-            promiseArguments.push(convertToPromiseCallback);
-            instance._invokeWithArguments.apply(instance, promiseArguments);
-        });
+        if (typeof callback === "function")
+            instance._backend._sendCommandToBackendWithCallback(instance, commandArguments, callback);
+        else
+            return instance._backend._sendCommandToBackendExpectingPromise(instance, commandArguments);
     },
 
     supports: function(parameterName)
@@ -461,23 +469,22 @@
     {
         'use strict';
 
-        var instance = this._instance;
-        var commandArguments = Array.from(arguments);
-        var callback = typeof commandArguments.lastValue === "function" ? commandArguments.pop() : null;
+        let instance = this._instance;
+        let commandArguments = Array.from(arguments);
+        let callback = typeof commandArguments.lastValue === "function" ? commandArguments.pop() : null;
 
-        var parameters = {};
-        for (var i = 0; i < instance.callSignature.length; ++i) {
-            var parameter = instance.callSignature[i];
-            var parameterName = parameter["name"];
-            var typeName = parameter["type"];
-            var optionalFlag = parameter["optional"];
+        let parameters = {};
+        for (let parameter of instance.callSignature) {
+            let parameterName = parameter["name"];
+            let typeName = parameter["type"];
+            let optionalFlag = parameter["optional"];
 
             if (!commandArguments.length && !optionalFlag) {
                 console.error("Protocol Error: Invalid number of arguments for method '" + instance.qualifiedName + "' call. It must have the following arguments '" + JSON.stringify(instance.callSignature) + "'.");
                 return;
             }
 
-            var value = commandArguments.shift();
+            let value = commandArguments.shift();
             if (optionalFlag && value === undefined)
                 continue;
 
@@ -496,7 +503,10 @@
             }
         }
 
-        instance._backend._invokeCommand(instance, Object.keys(parameters).length ? parameters : null, callback);
+        if (callback)
+            instance._backend._sendCommandToBackendWithCallback(instance, parameters, callback);
+        else
+            return instance._backend._sendCommandToBackendExpectingPromise(instance, parameters);
     }
 };
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to