Synchronous retrieval of source-mapped stack-traces
Venryx opened this issue · 2 comments
It would be nice if the library could synchronously return the source-mapped stack-trace of a "raw" stack-trace.
The first time you request the source-mapped stack-trace, of course, it has to be asynchronous since the source files have not yet been retrieved using AJAX.
However, every time other than the first time, it should be possible to perform the process synchronously. To make this better, we could add some sort of "prepare" function, which would retrieve the source files ahead of time, letting the user then get all the source-mapped stack-traces synchronously from then on.
Why is this useful? One reason is for debugging. When you want to see "What call-stack led to this line of code being run?", currently there is no way to get the source-mapped version of that synchronously. This means you can't return it as a debug string, display it to the user in an execution-blocking alert, etc.
I've needed this behavior in multiple projects now -- enough now that I think I'm going to take an attempt at it myself. Will update here if I make any progress. (it shouldn't be that hard, since the only inherently asynchronous process seems to be the source-file text retrieval)
Yay! I got it working synchronously.
I've included the instructions below, for anyone interested.
Setup
- Add bluebird to your project (v3.5.0 atm): http://bluebirdjs.com/docs/getting-started.html
- Replace the built-in
window.Promisewith bluebird'sPromise:
window.Promise = require("bluebird");
- Modify the
bluebird.jsfile (for npm:node_modules/bluebird/js/release/bluebird.js), with the following change:
[...]
target._attachExtraTrace(value);
handler = didReject;
}
-async.invoke(settler, target, {
+settler.call(target, {
handler: domain === null ? handler
: (typeof handler === "function" &&
[...]Done with the setup!
Usage
var stack;
StackTrace.get().then(stackValue=> {
stack = stackValue;
});
console.log("Stack received synchronously! Stack stringified: " + stack.map(a=>a.toString()).join("\n"));
Of course, for it to work synchronously, it has to already have requested the relevant source files. To pre-request those source files (so that the first actual call is synchronous), just call StackTrace.get() ahead of time (eg. when your page loads).
Readme?
As I've seen this ability requested a number of times by other users, would it be worth creating a Wiki page for this or something, and linking to it from the Readme?
By the way, the switching above to bluebird Promises does lead to bluebird printing a warning message, because it thinks the promises that stacktrace-js creates in its handlers are "not being returned". (I'm not sure why, as the system is still fully functional)
Anyway, the messages are only printed once, the first time you request the source-maps for a file.
To ignore this warning, you can either remove the check from bluebird's code, or wrap the console.warn function like so:
var warn_orig = console.warn;
console.warn = function(arguments) {
if (arguments[0] && arguments[0].indexOf("a promise was created in a handler but was not returned from it, see http://goo.gl/rRqMUw") != -1) return;
warn_orig.apply(this, arguments);
};
Just thought I'd mention it in case the warnings annoy anyone else.