(on node version '4.2.1', v8 '4.5.103.35')
var TE = class tError extends Error {
constructor(message) {
super(message);
this.name = tError.name;
Error.captureStackTrace(this, tError);
}
static prepareStackTrace() {
console.log('run is prepareStackTrace');
return 'MyPrepareStack'
}
get stack() {
console('getter stack');
return 'MyStack';
}
};
TE.stackTraceLimit = 1;
console.log('ErrorPrepare:', TE.prepareStackTrace);
var e = new TE('MyError');
console.log('ErrorName: ', e.name);
console.log('ErrorStack: ', e.stack);
OUTPUT:
D:\>node ./Error
ErrorPrepare: prepareStackTrace() {
console.log('run is prepareStackTrace');
return 'MyPrepareStack'
}
ErrorName: tError
ErrorStack: tError: MyError
at Object.<anonymous> (D:\Error.js:23:9)
at Module._pile (module.js:435:26)
at Object.Module._extensions..js (module.js:442:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Function.Module.runMain (module.js:467:10)
at startup (node.js:134:18)
at node.js:961:3
Using the native API's getters is not working for me.
How do you format the stackTrace using the native stackTrace API, Error.prepareStackTrace
?
(on node version '4.2.1', v8 '4.5.103.35')
var TE = class tError extends Error {
constructor(message) {
super(message);
this.name = tError.name;
Error.captureStackTrace(this, tError);
}
static prepareStackTrace() {
console.log('run is prepareStackTrace');
return 'MyPrepareStack'
}
get stack() {
console('getter stack');
return 'MyStack';
}
};
TE.stackTraceLimit = 1;
console.log('ErrorPrepare:', TE.prepareStackTrace);
var e = new TE('MyError');
console.log('ErrorName: ', e.name);
console.log('ErrorStack: ', e.stack);
OUTPUT:
D:\>node ./Error
ErrorPrepare: prepareStackTrace() {
console.log('run is prepareStackTrace');
return 'MyPrepareStack'
}
ErrorName: tError
ErrorStack: tError: MyError
at Object.<anonymous> (D:\Error.js:23:9)
at Module._pile (module.js:435:26)
at Object.Module._extensions..js (module.js:442:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Function.Module.runMain (module.js:467:10)
at startup (node.js:134:18)
at node.js:961:3
Using the native API's getters is not working for me.
How do you format the stackTrace using the native stackTrace API, Error.prepareStackTrace
?
-
captureStackTrace
vsprepareStackTrace
? – Daniel A. White Commented Oct 26, 2015 at 12:33 - 1 I still don't understand the question. Those static methods are not being called because the code does not call them, all right. – E_net4 Commented Oct 26, 2015 at 12:40
-
@E_net4 The static method appears to be irrelevant to the question. (But maybe I'm wrong; OP, please clarify?) The interesting question here (for me) is why the class's
stack
getter is not being called whene.stack
is accessed. That is,Error
's getter forstack
is running instead oftError
's getter, even thoughe
is atError
instance. – apsillers Commented Oct 26, 2015 at 12:44 -
1
My guess is that
Error.captureStackTrace()
creates an instancestack
property, which shadows the getter on the prototype. – Bergi Commented Oct 26, 2015 at 12:49 - The problem is that "get stack()" is never called, even if to describe the class as: class tError extends Error { get stack() { return 'MyStack'; } }; – Игорь Новожилов Commented Oct 26, 2015 at 14:40
1 Answer
Reset to default 8Your not inheriting from anything when using Error.prepareStackTrace
.
About Error.prepareStackTrace
Error.prepareStackTrace
is quite different from your typical JS API because it runs your code internally (or it might be better to say Natively). Really your writing the code in JavaScript, but its not a JavaScript API, and it's not a Node API, but rather, its a V8 JavaScript Engine API. Its not something that you can find in other engines.
Parts of the StackTrace
I remember when I first learned about Error.prepareStackTrace
, I was really confused because the WebStorm hover widget showed it being a Callback Function. It didn't list all the available API methods I have listed below. Another thing that confused me, was when I read the V8 Documentation on StackTraces (which I suggest you do too if you want to really understand this topic), the docs mentioned CallSites
, which threw me off, because I never heard of CallSites. But its important to know, that not only does prepareStackTrace
grant access to an array of CallSites, the lines in the standard formatted JavaScript StackTrace that look like...
'at' /foo/foo.js:11:32
'at' /foo/bar.js:59:22
...are the CallSites returned by prepareStackTrace
.
In the lines above, you can see 3-parts, all obtainable by the V8 CallSite API's getters.
- FilePath
- Line Number
- Column Number
Using Error.prepareStackTrace
export class Err extends Error {
_stack?:string;
constructor(message: string) {
super(message);
const _prepareStackTrace = Error.prepareStackTrace;
Error.prepareStackTrace = (_, callsites) => {
callsites.forEach(callsite => {
callsite.getLineNumber();
callsite.getColumnNumber();
});
};
this._stack = this.stack;
Error.prepareStackTrace = _prepareStackTrace;
}
}
This is in TypeScript as that's how I have my editor setup rn, and I wanted to offer a working example. Often times people will do something like I have authored below. This allows the user to get their current position in there code using...
const pos = new Err('')._stack;
This assigns the current row | col in the code to pos
.
A couple things to note when using Error.prepareStackTrace
are:
Error.prepareStackTrace
looks like you would want to use a callback function with it, but really you want to use the Assignment Operator (=
) to assign a function to Error.prepareStackTrace. The function you assign will work as if it were a callback.The function assigned to
Error.prepareStackTrace
should have two parameters. The first parameter is the Error Object & the second parameter is an array of CallSites. Typically developers callforEach((item, index)=>{ /* do stuff to item */})
on theCallSites
parameter to access all available callsites, and do what ever is desired to them.There is another function associated with this subject, and that is the
Error.captureStackTrace
method. This is used by the V8 engine when a stackTrace needs to be fetched, but access to the method is not exclusive, as V8 JS developers have access to it.Error.prepareStackTrace
&Error.captureStackTrace
are both native V8 JavaScript functions, and are both available for use within the Node.js RTE (written during v16.2.0). Browsers do not support either function.As stated above,
Error.prepareStackTrace
is called by the V8 engine automatically. When that happens, the parameters of the function that is assigned toError.prepareStackTrace
are automatically passed the their arguments. The arguments include an Error Object, and that Error Object's Stack-Trace (This is also stated above, if your confused its because you jumped around, and did not read the list in order.).The stack returned by the snippet above can be manipulated by the following method calls, so long as the data is available. Just because the method is available does not mean that data is available for the method.
getThis: returns the value of this
getTypeName: returns the type of this as a string. This is the name of the function stored in the constructor field of this, if available, otherwise the object’s [[Class]] internal property.
getFunction: returns the current function
getFunctionName: returns the name of the current function, typically its name property. If a name property is not available an attempt is made to infer a name from the function’s context.
getMethodName: returns the name of the property of this or one of its prototypes that holds the current function
getFileName: if this function was defined in a script returns the name of the script
getLineNumber: if this function was defined in a script returns the current line number
getColumnNumber: if this function was defined in a script returns the current column number
getEvalOrigin: if this function was created using a call to eval returns a string representing the location where eval was called
isToplevel: is this a top-level invocation, that is, is this the global object?
isEval: does this call take place in code defined by a call to eval?
isNative: is this call in native V8 code?
isConstructor: is this a constructor call?
isAsync: is this an async call (i.e. await or Promise.all())?
isPromiseAll: is this an async call to Promise.all()?
getPromiseIndex: returns the index of the promise element that was followed in Promise.all() for async stack traces, or null if the CallSite is not a Promise.all() call.
LINKS:
V8 Official Documentation - A must read for understanding this topic.
Codota Code Examples - This is good for seeing how others use it.
NPM Module that implements Error.prepareStackTrace for you.