I remember a time while learning how to use JavaScript when I wanted to attach the function name and file name to my debug calls, before fully grasping the utility of error stacks.
The Circumstance
Imagine you’re working in a cloud function like AWS Lambda. Deploying your function takes some time, and your ability to inspect it via a debugger is severely limited. To solve this, I used the debug module.
Starting Out
In a file named blah.js:
const v = require('debug')('verbose');
v('test');
By setting DEBUG=verbose, the output is verbose test +0ms.
Building the Stack
JavaScript lacks a global stack, so the cheapest way to get stack history is to actually drop the function into an error status.
const buildStack = () => {
const depth = 3;
if (!this.stackIs) {
Object.defineProperty(this, 'stackIs', {
get: function() {
const orig = Error.prepareStackTrace;
Error.prepareStackTrace = function(_, stack) {
return stack;
};
const err = new Error();
Error.captureStackTrace(err, arguments.callee);
const stack = err.stack;
Error.prepareStackTrace = orig;
return stack;
},
});
}
if (!this.lineIs) {
Object.defineProperty(this, 'lineIs', {
get: function() {
return this.stackIs[depth].getLineNumber();
},
});
}
if (!this.functionIs) {
Object.defineProperty(this, 'functionIs', {
get: function() {
return this.stackIs[depth].getFunctionName();
},
});
}
return {
function: this.functionIs,
line: this.lineIs,
};
};
This gives you an object containing the location of the debug call, which makes for really awesome debugging.
The full snippet is available in this gist, and I originally found the idea on Stack Overflow.