Each JavaScript engine uses its own format for stack traces, but they are fairly consistent in their high-level structure. Every implementation uses a separate line in the stack to represent each function call. The call that directly caused the error is placed at the top, and the call that started the whole call chain is placed at the bottom. Below are some examples of stack traces:
function foo() {
bar();
}
function bar() {
baz();
}
function baz() {
console.log(new Error().stack);
}
foo();
#### JavaScriptCore
baz@filename.js:10:24
bar@filename.js:6:6
foo@filename.js:2:6
global code@filename.js:13:4
#### SpiderMonkey
baz@filename.js:10:15
bar@filename.js:6:3
foo@filename.js:2:3
@filename.js:13:1
#### V8
Error
at baz (filename.js:10:15)
at bar (filename.js:6:3)
at foo (filename.js:2:3)
at filename.js:13:1
V8 provides the non-standard stack trace API for customizing the stack trace, including Error.captureStackTrace(), Error.stackTraceLimit, and Error.prepareStackTrace(). Other engines support this API to varying extents.
Different engines set this value at different times. Most modern engines set it when the Error object is created. This means you can get the full call stack information within a function using the following:
function foo() {
console.log(new Error().stack);
}
Without having to throw an error and then catch it.
Stack frames can be things other than explicit function calls, too. For example, event listeners, timeout jobs, and promise handlers all begin their own call chain. Source code within eval() and Function constructor calls also appear in the stack:
console.log(new Function("return new Error('Function failed')")().stack);
console.log("====");
console.log(eval("new Error('eval failed')").stack);
#### JavaScriptCore
anonymous@
global code@filename.js:1:65
====
eval code@
eval@[native code]
global code@filename.js:3:17
#### SpiderMonkey
anonymous@filename.js line 1 > Function:1:8
@filename.js:1:65
====
@filename.js line 3 > eval:1:1
@filename.js:3:13
#### V8
Error: Function failed
at eval (eval at <anonymous> (filename.js:1:13), <anonymous>:1:8)
at filename.js:1:65
====
Error: eval failed
at eval (eval at <anonymous> (filename.js:3:13), <anonymous>:1:1)
at filename.js:3:13
In Firefox, you can use the //# sourceURL directive to name an eval source. See the Firefox Debug eval sources docs and the Naming eval Scripts with the //# sourceURL Directive blog post for more details.