Modified: trunk/Source/WebInspectorUI/ChangeLog (202874 => 202875)
--- trunk/Source/WebInspectorUI/ChangeLog 2016-07-06 20:14:38 UTC (rev 202874)
+++ trunk/Source/WebInspectorUI/ChangeLog 2016-07-06 20:22:46 UTC (rev 202875)
@@ -1,3 +1,35 @@
+2016-07-06 Brian Burg <[email protected]>
+
+ Web Inspector: Uncaught Exception reporter should include the currently dispatching protocol event or request/response if applicable
+ https://bugs.webkit.org/show_bug.cgi?id=159320
+ <rdar://problem/27117754>
+
+ Reviewed by Timothy Hatcher and Joseph Pecoraro.
+
+ Keep track of the currently dispatched protocol response or protocol event and make
+ them available to the uncaught exception reporter. If an internal exception is reported
+ while dispatching an event or response, dump the protocol message(s) into the pre-filled
+ bug report.
+
+ * UserInterface/Debug/UncaughtExceptionReporter.js:
+ (stringifyAndTruncateObject): Added.
+ Rearrange the code that generates the pre-filled report so it's easier to add optional sections.
+
+ * UserInterface/Protocol/InspectorBackend.js:
+ (InspectorBackendClass):
+ (InspectorBackendClass.prototype.get currentDispatchState): Expose the dispatching state.
+ (InspectorBackendClass.prototype._sendCommandToBackendWithCallback):
+ (InspectorBackendClass.prototype._sendCommandToBackendExpectingPromise):
+ Store the originating command request with the pendingResponse data so that we can examine
+ the originating request if the response causes an error. This will cause request message objects
+ to be garbage-collected after their responses are dispatched rather than when the request is sent.
+ But, I don't forsee this being a performance problem since we should always get a command response
+ and pending command responses do not typically accumulate except when the inspector first loads.
+
+ (InspectorBackendClass.prototype._dispatchResponse): Save the response being dispatched.
+ (InspectorBackendClass.prototype._dispatchResponseToCallback): Simplify exception reporting.
+ (InspectorBackendClass.prototype._dispatchEvent): Save the event being dispatched.
+
2016-07-05 Timothy Hatcher <[email protected]>
Web Inspector: Switch last uses of -webkit-linear-gradient() to linear-gradient()
Modified: trunk/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.js (202874 => 202875)
--- trunk/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.js 2016-07-06 20:14:38 UTC (rev 202874)
+++ trunk/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.js 2016-07-06 20:22:46 UTC (rev 202875)
@@ -181,16 +181,46 @@
inspectedPageURL = WebInspector.frameResourceManager.mainFrame.url;
} catch (e) { }
+ let topLevelItems = [
+ `Inspected URL: ${inspectedPageURL || "(unknown)"}`,
+ `Loading completed: ${!!loadCompleted}`,
+ `Frontend User Agent: ${window.navigator.userAgent}`,
+ ];
+
+ function stringifyAndTruncateObject(object) {
+ let string = JSON.stringify(object);
+ return string.length > 500 ? string.substr(0, 500) + "…" : string;
+ }
+
+ if (InspectorBackend && InspectorBackend.currentDispatchState) {
+ let state = InspectorBackend.currentDispatchState;
+ if (state.event) {
+ topLevelItems.push("Dispatch Source: Protocol Event");
+ topLevelItems.push("");
+ topLevelItems.push("Protocol Event:");
+ topLevelItems.push(stringifyAndTruncateObject(state.event));
+ }
+ if (state.response) {
+ topLevelItems.push("Dispatch Source: Protocol Command Response");
+ topLevelItems.push("");
+ topLevelItems.push("Protocol Command Response:");
+ topLevelItems.push(stringifyAndTruncateObject(state.response));
+ }
+ if (state.request) {
+ topLevelItems.push("");
+ topLevelItems.push("Protocol Command Request:");
+ topLevelItems.push(stringifyAndTruncateObject(state.request));
+ }
+ }
+
let formattedErrorDetails = window.__uncaughtExceptions.map((entry) => formattedEntry(entry));
let detailsForBugReport = formattedErrorDetails.map((line) => ` - ${line}`).join("\n");
+ topLevelItems.push("");
+ topLevelItems.push("Uncaught Exceptions:");
+ topLevelItems.push(detailsForBugReport);
+
let encodedBugDescription = encodeURIComponent(`-------
-Auto-generated details:
-
-Inspected URL: ${inspectedPageURL || "(unknown)"}
-Loading completed: ${!!loadCompleted}
-Frontend User Agent: ${window.navigator.userAgent}
-Uncaught exceptions:
-${detailsForBugReport}
+${topLevelItems.join("\n")}
-------
* STEPS TO REPRODUCE
Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js (202874 => 202875)
--- trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js 2016-07-06 20:14:38 UTC (rev 202874)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js 2016-07-06 20:22:46 UTC (rev 202875)
@@ -43,6 +43,12 @@
this._defaultTracer = new WebInspector.LoggingProtocolTracer;
this._activeTracers = [this._defaultTracer];
+ this._currentDispatchState = {
+ event: null,
+ request: null,
+ response: null,
+ };
+
this._dumpInspectorTimeStats = false;
let setting = WebInspector.autoLogProtocolMessagesSetting = new WebInspector.Setting("auto-collect-protocol-messages", false);
@@ -205,7 +211,7 @@
if (!isEmptyObject(parameters))
messageObject["params"] = parameters;
- let responseData = {command, callback};
+ let responseData = {command, request: messageObject, callback};
if (this.activeTracer)
responseData.sendRequestTimestamp = timestamp();
@@ -226,7 +232,7 @@
if (!isEmptyObject(parameters))
messageObject["params"] = parameters;
- let responseData = {command};
+ let responseData = {command, request: messageObject};
if (this.activeTracer)
responseData.sendRequestTimestamp = timestamp();
@@ -262,19 +268,25 @@
console.assert(this._pendingResponses.has(sequenceId), sequenceId, this._pendingResponses);
let responseData = this._pendingResponses.take(sequenceId) || {};
- let {command, callback, promise} = responseData;
+ let {request, command, callback, promise} = responseData;
let processingStartTimestamp = timestamp();
for (let tracer of this.activeTracers)
tracer.logWillHandleResponse(messageObject);
+ this._currentDispatchState.request = request;
+ this._currentDispatchState.response = messageObject;
+
if (typeof callback === "function")
- this._dispatchResponseToCallback(command, messageObject, callback);
+ this._dispatchResponseToCallback(command, request, 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);
+ this._currentDispatchState.request = null;
+ this._currentDispatchState.response = null;
+
let processingTime = (timestamp() - processingStartTimestamp).toFixed(3);
let roundTripTime = (processingStartTimestamp - responseData.sendRequestTimestamp).toFixed(3);
@@ -285,23 +297,20 @@
this._flushPendingScripts();
}
- _dispatchResponseToCallback(command, messageObject, callback)
+ _dispatchResponseToCallback(command, requestObject, responseObject, callback)
{
let callbackArguments = [];
- callbackArguments.push(messageObject["error"] ? messageObject["error"].message : null);
+ callbackArguments.push(responseObject["error"] ? responseObject["error"].message : null);
- if (messageObject["result"]) {
- for (var parameterName of command.replySignature)
- callbackArguments.push(messageObject["result"][parameterName]);
+ if (responseObject["result"]) {
+ for (let parameterName of command.replySignature)
+ callbackArguments.push(responseObject["result"][parameterName]);
}
try {
callback.apply(null, callbackArguments);
} catch (e) {
- WebInspector.reportInternalError(e, {
- "cause": `An uncaught exception was thrown while dispatching response callback for command ${command.qualifiedName}.`,
- "protocol-message": JSON.stringify(messageObject),
- });
+ WebInspector.reportInternalError(e, {"cause": `An uncaught exception was thrown while dispatching response callback for command ${command.qualifiedName}.`});
}
}
@@ -343,6 +352,8 @@
for (let tracer of this.activeTracers)
tracer.logWillHandleEvent(messageObject);
+ this._currentDispatchState.event = messageObject;
+
try {
agent.dispatchEvent(eventName, eventArguments);
} catch (e) {
@@ -349,12 +360,11 @@
for (let tracer of this.activeTracers)
tracer.logFrontendException(messageObject, e);
- WebInspector.reportInternalError(e, {
- "cause": `An uncaught exception was thrown while handling event: ${qualifiedName}`,
- "protocol-message": JSON.stringify(messageObject),
- });
+ WebInspector.reportInternalError(e, {"cause": `An uncaught exception was thrown while handling event: ${qualifiedName}`});
}
+ this._currentDispatchState.event = null;
+
let processingDuration = (timestamp() - processingStartTimestamp).toFixed(3);
for (let tracer of this.activeTracers)
tracer.logDidHandleEvent(messageObject, {dispatch: processingDuration});
@@ -400,6 +410,8 @@
return this._active;
}
+ get currentDispatchState() { return this._currentDispatchState; }
+
set dispatcher(value)
{
this._dispatcher = value;