Changeset 202657 in webkit


Ignore:
Timestamp:
Jun 29, 2016 4:05:55 PM (8 years ago)
Author:
BJ Burg
Message:

Web Inspector: Uncaught Exception page never shows if exception is thrown while processing a protocol event
https://bugs.webkit.org/show_bug.cgi?id=159182

Reviewed by Joseph Pecoraro.

Since we catch exceptions raised during the handling of protocol responses and events, there
is no way for these exceptions to trigger the global exception handler that shows the Uncaught
Exception Reporter sheet. We should show these in the sheet because it makes them get fixed faster.

Add a new entry point, WebInspector.reportInternalError, that takes an error or string and
a free-form map of strings to strings for storing additional information such as message data.
Pass the error and any other relevant details to this entry point, which decides whether to
show the uncaught exception reporter or quietly log the error to Inspector2 console.

In future patches, I would like to do the following once the common errors are fixed:

  • enable reporting via Uncaught Exception Reporter for all engineering builds
  • move internal console.error call sites to use WebInspector.reportInternalError
  • UserInterface/Base/Main.js: Add reportInternalError, which redirects to the uncaught

exception reporter sheet or does console.error. It also adds a console.assert that could
cause the debugger to pause if desired.

  • UserInterface/Debug/UncaughtExceptionReporter.css:

(.sheet-container): Make the report scrollable now that we could potentially show a lot of text.

  • UserInterface/Debug/UncaughtExceptionReporter.js:

(handleError): Also pass along the 'details' poperty.
(formattedEntry): Refactor the code so it additionally prints out the keys and values of
the 'details' property. It does not do any coercions, so callers must convert values to strings.

  • UserInterface/Protocol/InspectorBackend.js:

(InspectorBackendClass.prototype._dispatchResponse): Inlined a function.
(InspectorBackendClass.prototype._dispatchResponseToCallback):
(InspectorBackendClass.prototype._dispatchEvent):
Report uncaught exceptions via WebInspector.reportInternalError.

(InspectorBackendClass.prototype._reportProtocolError): Deleted, inlined into the single use site.

Location:
trunk/Source/WebInspectorUI
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r202634 r202657  
     12016-06-29  Brian Burg  <bburg@apple.com>
     2
     3        Web Inspector: Uncaught Exception page never shows if exception is thrown while processing a protocol event
     4        https://bugs.webkit.org/show_bug.cgi?id=159182
     5
     6        Reviewed by Joseph Pecoraro.
     7
     8        Since we catch exceptions raised during the handling of protocol responses and events, there
     9        is no way for these exceptions to trigger the global exception handler that shows the Uncaught
     10        Exception Reporter sheet. We should show these in the sheet because it makes them get fixed faster.
     11
     12        Add a new entry point, WebInspector.reportInternalError, that takes an error or string and
     13        a free-form map of strings to strings for storing additional information such as message data.
     14        Pass the error and any other relevant details to this entry point, which decides whether to
     15        show the uncaught exception reporter or quietly log the error to Inspector^2 console.
     16
     17        In future patches, I would like to do the following once the common errors are fixed:
     18         - enable reporting via Uncaught Exception Reporter for all engineering builds
     19         - move internal console.error call sites to use WebInspector.reportInternalError
     20
     21        * UserInterface/Base/Main.js: Add reportInternalError, which redirects to the uncaught
     22        exception reporter sheet or does console.error. It also adds a console.assert that could
     23        cause the debugger to pause if desired.
     24
     25        * UserInterface/Debug/UncaughtExceptionReporter.css:
     26        (.sheet-container): Make the report scrollable now that we could potentially show a lot of text.
     27
     28        * UserInterface/Debug/UncaughtExceptionReporter.js:
     29        (handleError): Also pass along the 'details' poperty.
     30        (formattedEntry): Refactor the code so it additionally prints out the keys and values of
     31        the 'details' property. It does not do any coercions, so callers must convert values to strings.
     32
     33        * UserInterface/Protocol/InspectorBackend.js:
     34        (InspectorBackendClass.prototype._dispatchResponse): Inlined a function.
     35        (InspectorBackendClass.prototype._dispatchResponseToCallback):
     36        (InspectorBackendClass.prototype._dispatchEvent):
     37        Report uncaught exceptions via WebInspector.reportInternalError.
     38
     39        (InspectorBackendClass.prototype._reportProtocolError): Deleted, inlined into the single use site.
     40
    1412016-06-29  Joseph Pecoraro  <pecoraro@apple.com>
    242
  • trunk/Source/WebInspectorUI/UserInterface/Base/Main.js

    r201891 r202657  
    24372437};
    24382438
     2439WebInspector.reportInternalError = function(errorOrString, details={})
     2440{
     2441    // The 'details' object includes additional information from the caller as free-form string keys and values.
     2442    // Each key and value will be shown in the uncaught exception reporter, console error message, or in
     2443    // a pre-filled bug report generated for this internal error.
     2444
     2445    let error = (errorOrString instanceof Error) ? errorOrString : new Error(errorOrString);
     2446    error.details = details;
     2447
     2448    // The error will be displayed in the Uncaught Exception Reporter sheet if DebugUI is enabled.
     2449    if (WebInspector.isDebugUIEnabled()) {
     2450        // This assert allows us to stop the debugger at an internal exception. It doesn't re-throw
     2451        // exceptions because the original exception would be lost through window.onerror.
     2452        // This workaround can be removed once <https://webkit.org/b/158192> is fixed.
     2453        console.assert(false, "An internal exception was thrown.", error);
     2454        handleInternalException(error);
     2455    } else
     2456        console.error(error);
     2457};
     2458
    24392459// OpenResourceDialog delegate
    24402460
  • trunk/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.css

    r202025 r202657  
    3232    z-index: var(--z-index-uncaught-exception-sheet);
    3333    background-color: hsl(0, 0%, 96%);
     34    overflow: scroll;
    3435}
    3536
     
    3839    font-family: '-webkit-system-font';
    3940    font-size: 11pt;
    40     overflow-y: auto;
    4141    min-width: 400px;
    4242    color: hsl(0, 0%, 40%);
  • trunk/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.js

    r202266 r202657  
    5858        columnNumber: error.column,
    5959        stack: error.stack,
     60        details: error.details,
    6061    });
    6162}
     
    151152
    152153    function formattedEntry(entry) {
    153         let message = `${entry.message} (at ${entry.url}:${entry.lineNumber}:${entry.columnNumber})`;
    154         if (!entry.stack)
    155             return message;
    156 
    157154        const indent = "    ";
    158         let results = [];
    159         let lines = entry.stack.split(/\n/g);
    160         for (let line of lines) {
    161             let atIndex = line.indexOf("@");
    162             let slashIndex = Math.max(line.lastIndexOf("/"), atIndex);
    163             let functionName = line.substring(0, atIndex) || "?";
    164             let location = line.substring(slashIndex + 1, line.length);
    165             results.push(`${indent}${functionName} @ ${location}`);
     155        let lines = [`${entry.message} (at ${entry.url}:${entry.lineNumber}:${entry.columnNumber})`];
     156        if (entry.stack) {
     157            let stackLines = entry.stack.split(/\n/g);
     158            for (let stackLine of stackLines) {
     159                let atIndex = stackLine.indexOf("@");
     160                let slashIndex = Math.max(stackLine.lastIndexOf("/"), atIndex);
     161                let functionName = stackLine.substring(0, atIndex) || "?";
     162                let location = stackLine.substring(slashIndex + 1, stackLine.length);
     163                lines.push(`${indent}${functionName} @ ${location}`);
     164            }
    166165        }
    167166
    168         return message + "\n" + results.join("\n");
     167        if (entry.details) {
     168            lines.push("");
     169            lines.push("Additional Details:")
     170            for (let key in entry.details) {
     171                let value = entry.details[key];
     172                lines.push(`${indent}${key} --> ${value}`);
     173            }
     174        }
     175
     176        return lines.join("\n");
    169177    }
    170178
     
    233241
    234242window.addEventListener("error", handleUncaughtException);
    235 window.handlePromiseException = handleError;
     243window.handlePromiseException = window.handleInternalException = handleError;
    236244
    237245})();
  • trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js

    r201669 r202657  
    256256        if (messageObject["error"]) {
    257257            if (messageObject["error"].code !== -32000)
    258                 this._reportProtocolError(messageObject);
     258                console.error("Request with id = " + messageObject["id"] + " failed. " + JSON.stringify(messageObject["error"]));
    259259        }
    260260
     
    299299            callback.apply(null, callbackArguments);
    300300        } catch (e) {
    301             console.error("Uncaught exception in inspector page while dispatching callback for command " + command.qualifiedName, 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            });
    302305        }
    303306    }
     
    344347            agent.dispatchEvent(eventName, eventArguments);
    345348        } catch (e) {
    346             console.error("Uncaught exception in inspector page while handling event " + qualifiedName, e);
    347349            for (let tracer of this.activeTracers)
    348350                tracer.logFrontendException(messageObject, e);
     351
     352            WebInspector.reportInternalError(e, {
     353                "cause": `An uncaught exception was thrown while handling event: ${qualifiedName}`,
     354                "protocol-message": JSON.stringify(messageObject),
     355            });
    349356        }
    350357
     
    352359        for (let tracer of this.activeTracers)
    353360            tracer.logDidHandleEvent(messageObject, {dispatch: processingDuration});
    354     }
    355 
    356     _reportProtocolError(messageObject)
    357     {
    358         console.error("Request with id = " + messageObject["id"] + " failed. " + JSON.stringify(messageObject["error"]));
    359361    }
    360362
Note: See TracChangeset for help on using the changeset viewer.