summaryrefslogtreecommitdiffstats
path: root/devtools/client/webconsole/test/browser/browser_webconsole_uncaught_exception.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/webconsole/test/browser/browser_webconsole_uncaught_exception.js')
-rw-r--r--devtools/client/webconsole/test/browser/browser_webconsole_uncaught_exception.js130
1 files changed, 130 insertions, 0 deletions
diff --git a/devtools/client/webconsole/test/browser/browser_webconsole_uncaught_exception.js b/devtools/client/webconsole/test/browser/browser_webconsole_uncaught_exception.js
new file mode 100644
index 0000000000..48970dd2f6
--- /dev/null
+++ b/devtools/client/webconsole/test/browser/browser_webconsole_uncaught_exception.js
@@ -0,0 +1,130 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that stack traces are shown when primitive values are thrown instead of
+// error objects.
+
+"use strict";
+
+const TEST_URI = `data:text/html,<!DOCTYPE html><meta charset=utf8>Test uncaught exception`;
+
+add_task(async function () {
+ const hud = await openNewTabAndConsole(TEST_URI);
+
+ await checkThrowingWithStack(hud, `"tomato"`, "Uncaught tomato");
+ await checkThrowingWithStack(hud, `""`, "Uncaught <empty string>");
+ await checkThrowingWithStack(hud, `42`, "Uncaught 42");
+ await checkThrowingWithStack(hud, `0`, "Uncaught 0");
+ await checkThrowingWithStack(hud, `null`, "Uncaught null");
+ await checkThrowingWithStack(hud, `undefined`, "Uncaught undefined");
+ await checkThrowingWithStack(hud, `false`, "Uncaught false");
+
+ await checkThrowingWithStack(
+ hud,
+ `new Error("watermelon")`,
+ "Uncaught Error: watermelon"
+ );
+
+ await checkThrowingWithStack(
+ hud,
+ `(err = new Error("lettuce"), err.name = "VegetableError", err)`,
+ "Uncaught VegetableError: lettuce"
+ );
+
+ await checkThrowingWithStack(
+ hud,
+ `{ fav: "eggplant" }`,
+ `Uncaught Object { fav: "eggplant" }`
+ );
+
+ info("Check custom error with name and message getters");
+ // register the class
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], function () {
+ const script = content.document.createElement("script");
+ script.append(
+ content.document.createTextNode(
+ `
+ class CustomError extends Error {
+ get name() {
+ return "CustomErrorName";
+ }
+
+ get message() {
+ return "custom-error-message";
+ }
+ }`.trim()
+ )
+ );
+ content.document.body.append(script);
+ });
+
+ await checkThrowingWithStack(
+ hud,
+ `new CustomError()`,
+ "Uncaught CustomErrorName: custom-error-message",
+ // Additional frames: the stacktrace contains the CustomError call
+ [1]
+ );
+ info("Check that object in errors can be expanded");
+ const rejectedObjectMessage = findErrorMessage(hud, "eggplant");
+ const oi = rejectedObjectMessage.querySelector(".tree");
+ ok(true, "The object was rendered in an ObjectInspector");
+
+ info("Expanding the object");
+ const onOiExpanded = waitFor(() => {
+ return oi.querySelectorAll(".node").length === 3;
+ });
+ oi.querySelector(".arrow").click();
+ await onOiExpanded;
+
+ ok(
+ oi.querySelector(".arrow").classList.contains("expanded"),
+ "Object expanded"
+ );
+
+ // The object inspector now looks like:
+ // Object { fav: "eggplant" }
+ // | fav: "eggplant"
+ // | <prototype>: Object { ... }
+
+ const oiNodes = oi.querySelectorAll(".node");
+ is(oiNodes.length, 3, "There is the expected number of nodes in the tree");
+
+ ok(oiNodes[0].textContent.includes(`Object { fav: "eggplant" }`));
+ ok(oiNodes[1].textContent.includes(`fav: "eggplant"`));
+ ok(oiNodes[2].textContent.includes(`<prototype>: Object { \u2026 }`));
+});
+
+async function checkThrowingWithStack(
+ hud,
+ expression,
+ expectedMessage,
+ additionalFrameLines = []
+) {
+ await SpecialPowers.spawn(
+ gBrowser.selectedBrowser,
+ [expression],
+ function (expr) {
+ const script = content.document.createElement("script");
+ script.append(
+ content.document.createTextNode(`
+ a = () => {throw ${expr}};
+ b = () => a();
+ c = () => b();
+ d = () => c();
+ d();
+ `)
+ );
+ content.document.body.append(script);
+ script.remove();
+ }
+ );
+ return checkMessageStack(hud, expectedMessage, [
+ ...additionalFrameLines,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ ]);
+}