summaryrefslogtreecommitdiff
path: root/Source/WebInspectorUI/UserInterface/Debug
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebInspectorUI/UserInterface/Debug
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Debug')
-rw-r--r--Source/WebInspectorUI/UserInterface/Debug/Bootstrap.js61
-rw-r--r--Source/WebInspectorUI/UserInterface/Debug/CapturingProtocolTracer.js89
-rw-r--r--Source/WebInspectorUI/UserInterface/Debug/ProtocolTrace.js56
-rw-r--r--Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.css114
-rw-r--r--Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.js275
5 files changed, 595 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Debug/Bootstrap.js b/Source/WebInspectorUI/UserInterface/Debug/Bootstrap.js
new file mode 100644
index 000000000..f54d93ae7
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/Debug/Bootstrap.js
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 University of Washington.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This function is invoked after the inspector has loaded.
+WebInspector.runBootstrapOperations = function() {
+ WebInspector.showDebugUISetting = new WebInspector.Setting("show-debug-ui", false);
+
+ // Toggle Debug UI setting.
+ new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.Option | WebInspector.KeyboardShortcut.Modifier.Shift | WebInspector.KeyboardShortcut.Modifier.CommandOrControl, "D", () => {
+ WebInspector.showDebugUISetting.value = !WebInspector.showDebugUISetting.value;
+ });
+
+ // Reload the Web Inspector.
+ new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.Option | WebInspector.KeyboardShortcut.Modifier.Shift | WebInspector.KeyboardShortcut.Modifier.CommandOrControl, "R", () => {
+ window.location.reload();
+ });
+
+ let toolTip = "Enable dump inspector messages to console";
+ let activatedToolTip = "Disable dump inspector messages to console";
+ let debugInspectorToolbarButton = new WebInspector.ActivateButtonToolbarItem("debug-inspector", toolTip, activatedToolTip, null, "Images/Console.svg");
+ debugInspectorToolbarButton.activated = InspectorBackend.dumpInspectorProtocolMessages;
+ WebInspector.toolbar.addToolbarItem(debugInspectorToolbarButton, WebInspector.Toolbar.Section.CenterRight);
+ debugInspectorToolbarButton.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, () => {
+ InspectorBackend.dumpInspectorProtocolMessages = !InspectorBackend.dumpInspectorProtocolMessages;
+ debugInspectorToolbarButton.activated = InspectorBackend.dumpInspectorProtocolMessages;
+ });
+
+ function updateDebugUI()
+ {
+ debugInspectorToolbarButton.hidden = !WebInspector.showDebugUISetting.value;
+ }
+
+ WebInspector.showDebugUISetting.addEventListener(WebInspector.Setting.Event.Changed, () => {
+ updateDebugUI();
+ WebInspector.notifications.dispatchEventToListeners(WebInspector.Notification.DebugUIEnabledDidChange);
+ });
+
+ updateDebugUI();
+};
diff --git a/Source/WebInspectorUI/UserInterface/Debug/CapturingProtocolTracer.js b/Source/WebInspectorUI/UserInterface/Debug/CapturingProtocolTracer.js
new file mode 100644
index 000000000..f44754a8e
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/Debug/CapturingProtocolTracer.js
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.CapturingProtocolTracer = class CapturingProtocolTracer extends WebInspector.ProtocolTracer
+{
+ constructor()
+ {
+ super();
+
+ this._trace = new WebInspector.ProtocolTrace;
+ }
+
+ // Public
+
+ get trace()
+ {
+ return this._trace;
+ }
+
+ logFrontendException(message, exception)
+ {
+ this._processEntry({type: "exception", message: this._stringifyMessage(message), exception});
+ }
+
+ logProtocolError(message, error)
+ {
+ this._processEntry({type: "error", message: this._stringifyMessage(message), error});
+ }
+
+ logFrontendRequest(message)
+ {
+ this._processEntry({type: "request", message: this._stringifyMessage(message)});
+ }
+
+ logDidHandleResponse(message, timings = null)
+ {
+ let entry = {type: "response", message: this._stringifyMessage(message)};
+ if (timings)
+ entry.timings = Object.shallowCopy(timings);
+
+ this._processEntry(entry);
+ }
+
+ logDidHandleEvent(message, timings = null)
+ {
+ let entry = {type: "event", message: this._stringifyMessage(message)};
+ if (timings)
+ entry.timings = Object.shallowCopy(timings);
+
+ this._processEntry(entry);
+ }
+
+ _stringifyMessage(message)
+ {
+ try {
+ return JSON.stringify(message);
+ } catch (e) {
+ console.error("couldn't stringify object:", message, e);
+ return {};
+ }
+ }
+
+ _processEntry(entry)
+ {
+ this._trace.addEntry(entry);
+ }
+};
diff --git a/Source/WebInspectorUI/UserInterface/Debug/ProtocolTrace.js b/Source/WebInspectorUI/UserInterface/Debug/ProtocolTrace.js
new file mode 100644
index 000000000..a26a965d8
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/Debug/ProtocolTrace.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ProtocolTrace = class ProtocolTrace extends WebInspector.Object
+{
+ constructor()
+ {
+ super();
+
+ this._entries = [];
+ }
+
+ // Public
+
+ addEntry(entry) {
+ this._entries.push(entry);
+ }
+
+ get saveData() {
+ let now = new Date();
+ let YYYY = now.getFullYear();
+ let MM = now.getMonth() + 1;
+ let DD = now.getDate();
+ let hh = now.getHours();
+ let mm = now.getMinutes();
+ let ss = now.getSeconds();
+
+ // This follows the file name of screen shots on OS X (en-US):
+ // "Protocol Trace 2015-12-31 at 12.43.04.json".
+ // When the Intl API is implemented, we can do a better job.
+ let filename = WebInspector.unlocalizedString(`Protocol Trace at ${YYYY}-${MM}-${DD} ${hh}.${mm}.${ss}.json`);
+ return {url: "web-inspector:///" + encodeURIComponent(filename), content: JSON.stringify(this._entries)};
+ }
+};
diff --git a/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.css b/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.css
new file mode 100644
index 000000000..8b7e01dd0
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.css
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.sheet-container {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ z-index: var(--z-index-uncaught-exception-sheet);
+ background-color: hsl(0, 0%, 96%);
+ overflow: scroll;
+}
+
+.uncaught-exception-sheet {
+ padding: 50px 55px 50px 65px;
+ font-family: '-webkit-system-font';
+ font-size: 11pt;
+ min-width: 400px;
+ color: hsl(0, 0%, 40%);
+}
+
+.uncaught-exception-sheet a {
+ text-decoration: underline;
+ color: hsl(240, 55%, 30%);
+ cursor: pointer;
+ font-weight: 500;
+ font-size: 97%;
+}
+.uncaught-exception-sheet a:hover,
+.uncaught-exception-sheet a:active {
+ color: hsl(240, 55%, 25%);
+}
+
+.uncaught-exception-sheet h1,
+.uncaught-exception-sheet h2 {
+ font-size: 24px;
+ line-height: 28px;
+ margin-bottom: 0px;
+ margin-top: 10px;
+ font-weight: normal;
+}
+
+.uncaught-exception-sheet h2 {
+ margin-top: 40px;
+}
+
+.uncaught-exception-sheet h1 > img {
+ height: 35px;
+ position: relative;
+ margin-left: -50px;
+ margin-top: -5px;
+ float: left;
+}
+
+.uncaught-exception-sheet h2 > img {
+ height: 25px;
+ position: relative;
+ margin-left: -45px;
+ margin-top: 0px;
+ float: left;
+}
+
+.uncaught-exception-sheet dl {
+ max-width: 600px;
+}
+
+.uncaught-exception-sheet dt {
+ font-style: italic;
+ font-size: 17px;
+}
+
+.uncaught-exception-sheet dd {
+ margin: 10px 0 20px 10px;
+ font-size: 13px;
+ line-height: 18px;
+}
+
+.uncaught-exception-sheet ul {
+ font-family: Menlo, monospace;
+ font-size: 12px;
+ line-height: 18px;
+ margin: 0 0 0 2px;
+ padding: 0;
+}
+
+.uncaught-exception-sheet li {
+ margin-bottom: 20px;
+ word-break: break-word;
+ -webkit-user-select: text;
+ white-space: pre;
+}
diff --git a/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.js b/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.js
new file mode 100644
index 000000000..43ce09db6
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.js
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+(function() {
+
+const windowEvents = ["beforecopy", "copy", "click", "dragover", "focus"];
+const documentEvents = ["focus", "blur", "resize", "keydown", "keyup", "mousemove", "pagehide", "contextmenu"];
+
+function stopEventPropagation(event) {
+ if (event.target.classList && event.target.classList.contains("bypass-event-blocking"))
+ return;
+
+ event.stopPropagation();
+}
+
+function blockEventHandlers() {
+ // FIXME (151959): text selection on the sheet doesn't work for some reason.
+ for (let name of windowEvents)
+ window.addEventListener(name, stopEventPropagation, true);
+ for (let name of documentEvents)
+ document.addEventListener(name, stopEventPropagation, true);
+}
+
+function unblockEventHandlers() {
+ for (let name of windowEvents)
+ window.removeEventListener(name, stopEventPropagation, true);
+ for (let name of documentEvents)
+ document.removeEventListener(name, stopEventPropagation, true);
+}
+
+function handleError(error) {
+ handleUncaughtExceptionRecord({
+ message: error.message,
+ url: parseURL(error.sourceURL).lastPathComponent,
+ lineNumber: error.line,
+ columnNumber: error.column,
+ stack: error.stack,
+ details: error.details,
+ });
+}
+
+function handleUncaughtException(event) {
+ handleUncaughtExceptionRecord({
+ message: event.message,
+ url: parseURL(event.filename).lastPathComponent,
+ lineNumber: event.lineno,
+ columnNumber: event.colno,
+ stack: typeof event.error === "object" && event.error !== null ? event.error.stack : null,
+ });
+}
+
+function handleUncaughtExceptionRecord(exceptionRecord) {
+ if (!window.__uncaughtExceptions)
+ window.__uncaughtExceptions = [];
+
+ const loadCompleted = window.__frontendCompletedLoad;
+ const isFirstException = !window.__uncaughtExceptions.length;
+
+ // If an uncaught exception happens after loading is done, only show
+ // the first such exception. Many others may follow if internal
+ // state has been corrupted, but these are unhelpful to report.
+ if (!loadCompleted || isFirstException)
+ window.__uncaughtExceptions.push(exceptionRecord);
+
+ // If WebInspector.contentLoaded throws an uncaught exception, then these
+ // listeners will not work correctly because the UI is not fully loaded.
+ // Prevent any event handlers from running in an inconsistent state.
+ if (isFirstException)
+ blockEventHandlers();
+
+ if (isFirstException && !loadCompleted) {
+ // Signal that loading is done even though we can't guarantee that
+ // evaluating code on the inspector page will do anything useful.
+ // Without this, the frontend host may never show the window.
+ if (InspectorFrontendHost)
+ InspectorFrontendHost.loaded();
+
+ // Don't tell InspectorFrontendAPI that loading is done, since it can
+ // clear some of the error boilerplate page by accident.
+ }
+
+ createErrorSheet();
+}
+
+function dismissErrorSheet() {
+ unblockEventHandlers();
+
+ window.__sheetElement.remove();
+ window.__sheetElement = null;
+ window.__uncaughtExceptions = [];
+
+ // Do this last in case WebInspector's internal state is corrupted.
+ WebInspector.updateWindowTitle();
+
+ // FIXME (151959): tell the frontend host to hide a draggable title bar.
+}
+
+function createErrorSheet() {
+ // Early errors like parse errors may happen in the <head>, so attach
+ // a body if none exists yet. Code below expects document.body to exist.
+ if (!document.body)
+ document.write("<body></body></html>");
+
+ // FIXME (151959): tell the frontend host to show a draggable title bar.
+ if (InspectorFrontendHost)
+ InspectorFrontendHost.inspectedURLChanged("Internal Error");
+
+ // Only allow one sheet element at a time.
+ if (window.__sheetElement) {
+ window.__sheetElement.remove();
+ window.__sheetElement = null;
+ }
+
+ const loadCompleted = window.__frontendCompletedLoad;
+ let firstException = window.__uncaughtExceptions[0];
+
+ // Inlined from Utilities.js, because that file may not have loaded.
+ function insertWordBreakCharacters(text) {
+ return text.replace(/([\/;:\)\]\}&?])/g, "$1\u200b");
+ }
+
+ // This trampoline is necessary since none of our functions will be
+ // in scope of an href="javascript:"-style evaluation.
+ function handleLinkClick(event) {
+ if (event.target.tagName !== "A")
+ return;
+ if (event.target.id === "dismiss-error-sheet")
+ dismissErrorSheet();
+ }
+
+ function formattedEntry(entry) {
+ const indent = " ";
+ let lines = [`${entry.message} (at ${entry.url}:${entry.lineNumber}:${entry.columnNumber})`];
+ if (entry.stack) {
+ let stackLines = entry.stack.split(/\n/g);
+ for (let stackLine of stackLines) {
+ let atIndex = stackLine.indexOf("@");
+ let slashIndex = Math.max(stackLine.lastIndexOf("/"), atIndex);
+ let functionName = stackLine.substring(0, atIndex) || "?";
+ let location = stackLine.substring(slashIndex + 1, stackLine.length);
+ lines.push(`${indent}${functionName} @ ${location}`);
+ }
+ }
+
+ if (entry.details) {
+ lines.push("");
+ lines.push("Additional Details:");
+ for (let key in entry.details) {
+ let value = entry.details[key];
+ lines.push(`${indent}${key} --> ${value}`);
+ }
+ }
+
+ return lines.join("\n");
+ }
+
+ let inspectedPageURL = null;
+ try {
+ 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(`-------
+${topLevelItems.join("\n")}
+-------
+
+* STEPS TO REPRODUCE
+1. What were you doing? Include setup or other preparations to reproduce the exception.
+2. Include explicit, accurate, and minimal steps taken. Do not include extraneous or irrelevant steps.
+
+* NOTES
+Document any additional information that might be useful in resolving the problem, such as screen shots or other included attachments.
+`);
+ let encodedBugTitle = encodeURIComponent(`Uncaught Exception: ${firstException.message}`);
+ let encodedInspectedURL = encodeURIComponent(inspectedPageURL || "http://");
+ let prefilledBugReportLink = `https://bugs.webkit.org/enter_bug.cgi?alias=&assigned_to=webkit-unassigned%40lists.webkit.org&attach_text=&blocked=&bug_file_loc=${encodedInspectedURL}&bug_severity=Normal&bug_status=NEW&comment=${encodedBugDescription}&component=Web%20Inspector&contenttypeentry=&contenttypemethod=autodetect&contenttypeselection=text%2Fplain&data=&dependson=&description=&flag_type-1=X&flag_type-3=X&form_name=enter_bug&keywords=&op_sys=All&priority=P2&product=WebKit&rep_platform=All&short_desc=${encodedBugTitle}&version=WebKit%20Nightly%20Build`;
+ let detailsForHTML = formattedErrorDetails.map((line) => `<li>${insertWordBreakCharacters(line)}</li>`).join("\n");
+
+ let dismissOptionHTML = !loadCompleted ? "" : `<dt>A frivolous exception will not stop me!</dt>
+ <dd><a class="bypass-event-blocking" id="dismiss-error-sheet">Click to close this view</a> and return
+ to the Web Inspector without reloading. However, some things might not work without reloading if the error corrupted the Inspector's internal state.</dd>`;
+
+ let sheetElement = window.__sheetElement = document.createElement("div");
+ sheetElement.classList.add("sheet-container");
+ sheetElement.innerHTML = `<div class="uncaught-exception-sheet">
+ <h1>
+ <img src="Images/Errors.svg">
+ Web Inspector encountered an internal error.
+ </h1>
+ <dl>
+ <dd>Usually, this is caused by a syntax error while modifying the Web Inspector
+ UI, or running an updated frontend with out-of-date WebKit build.</dt>
+ <dt>I didn't do anything...?</dt>
+ <dd>If you don't think you caused this error to happen,
+ <a href="${prefilledBugReportLink}">click to file a pre-populated
+ bug with this information</a>. It is possible that someone else broke it by accident.</dd>
+ <dt>Oops, can I try again?</dt>
+ <dd><a href="javascript:window.location.reload()">Click to reload the Inspector</a>
+ again after making local changes.</dd>
+ ${dismissOptionHTML}
+ </dl>
+ <h2>
+ <img src="Images/Console.svg">
+ These uncaught exceptions caused the problem:
+ </h2>
+ <p><ul>${detailsForHTML}</ul></p>
+ </div>`;
+
+ sheetElement.addEventListener("click", handleLinkClick, true);
+ document.body.appendChild(sheetElement);
+}
+
+window.addEventListener("error", handleUncaughtException);
+window.handlePromiseException = window.handleInternalException = handleError;
+
+})();