Changeset 202875 in webkit


Ignore:
Timestamp:
Jul 6, 2016 1:22:46 PM (8 years ago)
Author:
BJ Burg
Message:

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.

Location:
trunk/Source/WebInspectorUI
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r202840 r202875  
     12016-07-06  Brian Burg  <bburg@apple.com>
     2
     3        Web Inspector: Uncaught Exception reporter should include the currently dispatching protocol event or request/response if applicable
     4        https://bugs.webkit.org/show_bug.cgi?id=159320
     5        <rdar://problem/27117754>
     6
     7        Reviewed by Timothy Hatcher and Joseph Pecoraro.
     8
     9        Keep track of the currently dispatched protocol response or protocol event and make
     10        them available to the uncaught exception reporter. If an internal exception is reported
     11        while dispatching an event or response, dump the protocol message(s) into the pre-filled
     12        bug report.
     13
     14        * UserInterface/Debug/UncaughtExceptionReporter.js:
     15        (stringifyAndTruncateObject): Added.
     16        Rearrange the code that generates the pre-filled report so it's easier to add optional sections.
     17
     18        * UserInterface/Protocol/InspectorBackend.js:
     19        (InspectorBackendClass):
     20        (InspectorBackendClass.prototype.get currentDispatchState): Expose the dispatching state.
     21        (InspectorBackendClass.prototype._sendCommandToBackendWithCallback):
     22        (InspectorBackendClass.prototype._sendCommandToBackendExpectingPromise):
     23        Store the originating command request with the pendingResponse data so that we can examine
     24        the originating request if the response causes an error. This will cause request message objects
     25        to be garbage-collected after their responses are dispatched rather than when the request is sent.
     26        But, I don't forsee this being a performance problem since we should always get a command response
     27        and pending command responses do not typically accumulate except when the inspector first loads.
     28
     29        (InspectorBackendClass.prototype._dispatchResponse): Save the response being dispatched.
     30        (InspectorBackendClass.prototype._dispatchResponseToCallback): Simplify exception reporting.
     31        (InspectorBackendClass.prototype._dispatchEvent): Save the event being dispatched.
     32
    1332016-07-05  Timothy Hatcher  <timothy@apple.com>
    234
  • trunk/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.js

    r202657 r202875  
    182182    } catch (e) { }
    183183
     184    let topLevelItems = [
     185        `Inspected URL:        ${inspectedPageURL || "(unknown)"}`,
     186        `Loading completed:    ${!!loadCompleted}`,
     187        `Frontend User Agent:  ${window.navigator.userAgent}`,
     188    ];
     189
     190    function stringifyAndTruncateObject(object) {
     191        let string = JSON.stringify(object);
     192        return string.length > 500 ? string.substr(0, 500) + "…" : string;
     193    }
     194
     195    if (InspectorBackend && InspectorBackend.currentDispatchState) {
     196        let state = InspectorBackend.currentDispatchState;
     197        if (state.event) {
     198            topLevelItems.push("Dispatch Source:      Protocol Event");
     199            topLevelItems.push("");
     200            topLevelItems.push("Protocol Event:");
     201            topLevelItems.push(stringifyAndTruncateObject(state.event));
     202        }
     203        if (state.response) {
     204            topLevelItems.push("Dispatch Source:      Protocol Command Response");
     205            topLevelItems.push("");
     206            topLevelItems.push("Protocol Command Response:");
     207            topLevelItems.push(stringifyAndTruncateObject(state.response));
     208        }
     209        if (state.request) {
     210            topLevelItems.push("");
     211            topLevelItems.push("Protocol Command Request:");
     212            topLevelItems.push(stringifyAndTruncateObject(state.request));
     213        }
     214    }
     215
    184216    let formattedErrorDetails = window.__uncaughtExceptions.map((entry) => formattedEntry(entry));
    185217    let detailsForBugReport = formattedErrorDetails.map((line) => ` - ${line}`).join("\n");
     218    topLevelItems.push("");
     219    topLevelItems.push("Uncaught Exceptions:");
     220    topLevelItems.push(detailsForBugReport);
     221
    186222    let encodedBugDescription = encodeURIComponent(`-------
    187 Auto-generated details:
    188 
    189 Inspected URL:        ${inspectedPageURL || "(unknown)"}
    190 Loading completed:    ${!!loadCompleted}
    191 Frontend User Agent:  ${window.navigator.userAgent}
    192 Uncaught exceptions:
    193 ${detailsForBugReport}
     223${topLevelItems.join("\n")}
    194224-------
    195225
  • trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js

    r202657 r202875  
    4444        this._activeTracers = [this._defaultTracer];
    4545
     46        this._currentDispatchState = {
     47            event: null,
     48            request: null,
     49            response: null,
     50        };
     51
    4652        this._dumpInspectorTimeStats = false;
    4753
     
    206212            messageObject["params"] = parameters;
    207213
    208         let responseData = {command, callback};
     214        let responseData = {command, request: messageObject, callback};
    209215
    210216        if (this.activeTracer)
     
    227233            messageObject["params"] = parameters;
    228234
    229         let responseData = {command};
     235        let responseData = {command, request: messageObject};
    230236
    231237        if (this.activeTracer)
     
    263269
    264270        let responseData = this._pendingResponses.take(sequenceId) || {};
    265         let {command, callback, promise} = responseData;
     271        let {request, command, callback, promise} = responseData;
    266272
    267273        let processingStartTimestamp = timestamp();
     
    269275            tracer.logWillHandleResponse(messageObject);
    270276
     277        this._currentDispatchState.request = request;
     278        this._currentDispatchState.response = messageObject;
     279
    271280        if (typeof callback === "function")
    272             this._dispatchResponseToCallback(command, messageObject, callback);
     281            this._dispatchResponseToCallback(command, request, messageObject, callback);
    273282        else if (typeof promise === "object")
    274283            this._dispatchResponseToPromise(command, messageObject, promise);
     
    276285            console.error("Received a command response without a corresponding callback or promise.", messageObject, command);
    277286
     287        this._currentDispatchState.request = null;
     288        this._currentDispatchState.response = null;
     289
    278290        let processingTime = (timestamp() - processingStartTimestamp).toFixed(3);
    279291        let roundTripTime = (processingStartTimestamp - responseData.sendRequestTimestamp).toFixed(3);
     
    286298    }
    287299
    288     _dispatchResponseToCallback(command, messageObject, callback)
     300    _dispatchResponseToCallback(command, requestObject, responseObject, callback)
    289301    {
    290302        let callbackArguments = [];
    291         callbackArguments.push(messageObject["error"] ? messageObject["error"].message : null);
    292 
    293         if (messageObject["result"]) {
    294             for (var parameterName of command.replySignature)
    295                 callbackArguments.push(messageObject["result"][parameterName]);
     303        callbackArguments.push(responseObject["error"] ? responseObject["error"].message : null);
     304
     305        if (responseObject["result"]) {
     306            for (let parameterName of command.replySignature)
     307                callbackArguments.push(responseObject["result"][parameterName]);
    296308        }
    297309
     
    299311            callback.apply(null, callbackArguments);
    300312        } catch (e) {
    301             WebInspector.reportInternalError(e, {
    302                 "cause": `An uncaught exception was thrown while dispatching response callback for command ${command.qualifiedName}.`,
    303                 "protocol-message": JSON.stringify(messageObject),
    304             });
     313            WebInspector.reportInternalError(e, {"cause": `An uncaught exception was thrown while dispatching response callback for command ${command.qualifiedName}.`});
    305314        }
    306315    }
     
    344353            tracer.logWillHandleEvent(messageObject);
    345354
     355        this._currentDispatchState.event = messageObject;
     356
    346357        try {
    347358            agent.dispatchEvent(eventName, eventArguments);
     
    350361                tracer.logFrontendException(messageObject, e);
    351362
    352             WebInspector.reportInternalError(e, {
    353                 "cause": `An uncaught exception was thrown while handling event: ${qualifiedName}`,
    354                 "protocol-message": JSON.stringify(messageObject),
    355             });
    356         }
     363            WebInspector.reportInternalError(e, {"cause": `An uncaught exception was thrown while handling event: ${qualifiedName}`});
     364        }
     365
     366        this._currentDispatchState.event = null;
    357367
    358368        let processingDuration = (timestamp() - processingStartTimestamp).toFixed(3);
     
    400410        return this._active;
    401411    }
     412
     413    get currentDispatchState() { return this._currentDispatchState; }
    402414
    403415    set dispatcher(value)
Note: See TracChangeset for help on using the changeset viewer.