blob: e11b4aedebd3ed175a969156c4bdd323c2cd4ec6 [file]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DevTools Error Rendering Demo</title>
</head>
<body>
<h1>Error Rendering Demo</h1>
<p>This page generates various types of errors to test DevTools console error rendering.</p>
<script>
/**
* DevTools Error Rendering Demo Snippet
*
* This snippet generates various types of errors to test the SymbolizedErrorWidget.
* Best run on a clean page like 'about:blank' to avoid CSP issues.
* Ensure "Automatically ignore third party scripts" is enabled in DevTools Settings
* (usually enabled by default for node_modules).
*/
(async function() {
console.clear();
console.log("%cStarting Error Rendering Demo...", "font-weight: bold; font-size: 1.2em; color: #4caf50;");
// Helper to run code in a script tag (creates "real" script frames instead of eval)
function runInScriptTag(filename, code) {
const script = document.createElement('script');
script.textContent = `${code}\n//# sourceURL=${filename}`;
document.body.appendChild(script);
script.remove();
}
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
// 1. Standard Error
console.log("Testing simple error with standard stack frames.");
try {
(function standardErrorDemo() {
function nested3() { throw new Error("Standard Error occurred"); }
function nested2() { nested3(); }
function nested1() { nested2(); }
nested1();
})();
} catch(e) {
console.error(e);
}
// 2. Ignore-listed Frames
console.log("Testing ignore-listing. The frames from 'my-lib' (in node_modules) should be hidden by default.");
runInScriptTag('http://example.com/node_modules/my-lib/index.js', `
window.triggerIgnoredError = function() {
function ignoredFunc() {
throw new Error("Error from ignore-listed library");
}
function middleFunc() {
ignoredFunc();
}
middleFunc();
}
`);
try {
window.triggerIgnoredError();
} catch(e) {
console.error(e);
}
delete window.triggerIgnoredError;
// 3. Nested Eval Errors
console.log("Testing 'eval at' rendering with multiple levels of nesting.");
try {
eval(`
function evalLevel1() {
eval(\`
function evalLevel2() {
throw new Error("Error from nested eval");
}
evalLevel2();
//# sourceURL=http://example.com/internal/eval_level2.js
\`);
}
evalLevel1();
//# sourceURL=http://example.com/internal/eval_level1.js
`);
} catch(e) {
console.error(e);
}
// 4. Error with Cause
console.log("Testing nested errors using Error.cause.");
try {
const causeOfCause = new Error("The absolute root cause");
const cause = new Error("The intermediate cause", { cause: causeOfCause });
throw new Error("The main error that the user saw", { cause: cause });
} catch(e) {
console.error(e);
}
// 5. SyntaxError
console.log("Testing SyntaxError rendering, which should point to the syntax error location.");
try {
// This will throw a SyntaxError because 'class' is a reserved word and cannot be a variable name
eval("function syntaxErrorDemo() { const class = 1; } \n//# sourceURL=http://example.com/buggy-script.js");
} catch(e) {
console.error(e);
}
// 6. Unparsable Error
console.log("Testing fallback for stack traces that do not follow standard formats.");
try {
const err = new Error("Unparsable Error Demo");
Object.defineProperty(err, 'stack', {
value: "StrangeError: Something weird happened\n" +
" [custom protocol] -> raw_action_3948\n" +
" at weird-location-without-parens http://example.com/weird:99:99\n" +
" !!! random debug dump !!!"
});
throw err;
} catch(e) {
console.error(e);
}
// 7. Wasm Error
console.log("Testing WebAssembly frame rendering.");
try {
// Pre-compiled Wasm module that imports a JS function and calls it to throw an error
const hex = "0061736d01000000010401600000020f0103656e76077468726f774a5300000302010007090105637261736800010a0601040010000b";
const bytes = new Uint8Array(hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
const importObject = {
env: {
throwJS: function() {
throw new Error("JS error called from Wasm");
}
}
};
const { instance } = await WebAssembly.instantiate(bytes, importObject);
instance.exports.crash();
} catch(e) {
console.error(e);
}
// 8. Mixed Constellation
console.log("Testing a complex mix: Main error has cause, cause is in eval, which is inside an ignore-listed file.");
runInScriptTag('http://example.com/node_modules/third-party/lib.js', `
window.triggerMixedError = function() {
try {
eval(\`
function evalInThirdParty() {
const cause = new Error("Root cause inside eval in third-party");
throw new Error("Intermediate error inside eval in third-party", { cause });
}
evalInThirdParty();
//# sourceURL=http://example.com/node_modules/third-party/eval.js
\`);
} catch(e) {
throw e;
}
}
`);
try {
window.triggerMixedError();
} catch(e) {
console.error(new Error("Top-level application error", { cause: e }));
}
delete window.triggerMixedError;
// 9. Class & Method Stack Trace
console.log("Testing stack trace containing methods, accessors, private methods, and static variants.");
try {
class StackTest {
static get #staticPrivateAccessor() {
throw new Error("Class and Method Error");
}
static get staticPublicAccessor() {
return StackTest.#staticPrivateAccessor;
}
static #staticPrivateMethod() {
return StackTest.staticPublicAccessor;
}
static staticPublicMethod() {
return StackTest.#staticPrivateMethod();
}
get #privateAccessor() {
return StackTest.staticPublicMethod();
}
get publicAccessor() {
return this.#privateAccessor;
}
#privateMethod() {
return this.publicAccessor;
}
publicMethod() {
this.#privateMethod();
}
}
const testInstance = new StackTest();
testInstance.publicMethod();
} catch (e) {
console.error(e);
}
// 10. Direct Stack Log (console.log(e.stack))
console.log("Testing stack trace logging using console.log(e.stack) directly instead of console.error(e).");
try {
(function directStackLogDemo() {
function step3() { throw new Error("Direct stack log error"); }
function step2() { step3(); }
function step1() { step2(); }
step1();
})();
} catch (e) {
console.log(e.stack);
}
// 11. Source Map Class & Method (eval)
console.log("Testing source maps for class/method error.");
try {
eval(`class StackTest{static get#t(){throw new Error("Source map Class and Method Error")}static get staticPublicAccessor(){return StackTest.#t}static#s(){return StackTest.staticPublicAccessor}static staticPublicMethod(){return StackTest.#s()}get#c(){return StackTest.staticPublicMethod()}get publicAccessor(){return this.#c}#e(){return this.publicAccessor}publicMethod(){this.#e()}}function startClassChain(){new StackTest().publicMethod()}startClassChain();\n//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiY2xhc3NfbWV0aG9kX3NvdXJjZV9tYXAuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNsYXNzIFN0YWNrVGVzdCB7XG4gIHN0YXRpYyBnZXQgI3N0YXRpY1ByaXZhdGVBY2Nlc3NvcigpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb3VyY2UgbWFwIENsYXNzIGFuZCBNZXRob2QgRXJyb3JcIik7XG4gIH1cbiAgc3RhdGljIGdldCBzdGF0aWNQdWJsaWNBY2Nlc3NvcigpIHtcbiAgICByZXR1cm4gU3RhY2tUZXN0LiNzdGF0aWNQcml2YXRlQWNjZXNzb3I7XG4gIH1cbiAgc3RhdGljICNzdGF0aWNQcml2YXRlTWV0aG9kKCkge1xuICAgIHJldHVybiBTdGFja1Rlc3Quc3RhdGljUHVibGljQWNjZXNzb3I7XG4gIH1cbiAgc3RhdGljIHN0YXRpY1B1YmxpY01ldGhvZCgpIHtcbiAgICByZXR1cm4gU3RhY2tUZXN0LiNzdGF0aWNQcml2YXRlTWV0aG9kKCk7XG4gIH1cblxuICBnZXQgI3ByaXZhdGVBY2Nlc3NvcigpIHtcbiAgICByZXR1cm4gU3RhY2tUZXN0LnN0YXRpY1B1YmxpY01ldGhvZCgpO1xuICB9XG4gIGdldCBwdWJsaWNBY2Nlc3NvcigpIHtcbiAgICByZXR1cm4gdGhpcy4jcHJpdmF0ZUFjY2Vzc29yO1xuICB9XG4gICNwcml2YXRlTWV0aG9kKCkge1xuICAgIHJldHVybiB0aGlzLnB1YmxpY0FjY2Vzc29yO1xuICB9XG4gIHB1YmxpY01ldGhvZCgpIHtcbiAgICB0aGlzLiNwcml2YXRlTWV0aG9kKCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gc3RhcnRDbGFzc0NoYWluKCkge1xuICBjb25zdCB0ZXN0SW5zdGFuY2UgPSBuZXcgU3RhY2tUZXN0KCk7XG4gIHRlc3RJbnN0YW5jZS5wdWJsaWNNZXRob2QoKTtcbn1cblxuc3RhcnRDbGFzc0NoYWluKCk7XG4iXSwKICAibWFwcGluZ3MiOiAiQUFBQSxNQUFNLFNBQVUsQ0FDZCxVQUFXQSxJQUF5QixDQUNsQyxNQUFNLElBQUksTUFBTSxtQ0FBbUMsQ0FDckQsQ0FDQSxXQUFXLHNCQUF1QixDQUNoQyxPQUFPLFVBQVVBLEVBQ25CLENBQ0EsTUFBT0MsSUFBdUIsQ0FDNUIsT0FBTyxVQUFVLG9CQUNuQixDQUNBLE9BQU8sb0JBQXFCLENBQzFCLE9BQU8sVUFBVUEsR0FBcUIsQ0FDeEMsQ0FFQSxHQUFJQyxJQUFtQixDQUNyQixPQUFPLFVBQVUsbUJBQW1CLENBQ3RDLENBQ0EsSUFBSSxnQkFBaUIsQ0FDbkIsT0FBTyxLQUFLQSxFQUNkLENBQ0FDLElBQWlCLENBQ2YsT0FBTyxLQUFLLGNBQ2QsQ0FDQSxjQUFlLENBQ2IsS0FBS0EsR0FBZSxDQUN0QixDQUNGLENBRUEsU0FBUyxpQkFBa0IsQ0FDSixJQUFJLFVBQVUsRUFDdEIsYUFBYSxDQUM1QixDQUVBLGdCQUFnQiIsCiAgIm5hbWVzIjogWyIjc3RhdGljUHJpdmF0ZUFjY2Vzc29yIiwgIiNzdGF0aWNQcml2YXRlTWV0aG9kIiwgIiNwcml2YXRlQWNjZXNzb3IiLCAiI3ByaXZhdGVNZXRob2QiXQp9Cg==\n//# sourceURL=http://example.com/class_method_source_map.min.js`);
} catch (e) {
console.error(e);
}
console.log("%cDemo finished. Please inspect the errors in the Console panel.", "font-weight: bold; color: #4caf50;");
})();
</script>
</body>
</html>