Skip to content

Instantly share code, notes, and snippets.

@PatrickJS
Forked from sebmarkbage/API.js
Created August 26, 2017 03:32
Show Gist options
  • Select an option

  • Save PatrickJS/6b47bc98bcbb261664b220a54d050284 to your computer and use it in GitHub Desktop.

Select an option

Save PatrickJS/6b47bc98bcbb261664b220a54d050284 to your computer and use it in GitHub Desktop.
Custom Stack Frames
type FrameScope = {
[key:string]: mixed
};
type StackFrame = {
name?: string,
fileName?: string,
lineNumber?: number,
columnNumber?: number,
scope?: FrameScope
};
type StackFrames = Array<StackFrame>;
type ExtendedConsoleAPI = {
...ConsoleAPI,
stack(frames: StackFrames) : void,
endStack() : void
};

The current execution context has a "custom stack" context with two internal slots [[Custom Stack Start]] and [[Custom Stack Override]].

console.stack - Assert that the first argument is an array. Store the current stack frame context at the VM level (same as new Error().stack) in the current execution context's [[Custom Stack Start]] slot. Store the first argument array in the current execution context's [[Custom Stack Override]] slot.

console.endStack - Clear the [[Custom Stack Start]] and [[Custom Stack Override]] stacks.

console.trace, console.warn, console.error etc. - For any function that logs stacks associated with the call. If there is something in the [[Custom Stack Start]] slot. Find the current stack from the current execution context. Find the common ancestor between [[Custom Stack Start]] and the current stack. Remove all the common ancestors. Replace them with [[Custom Stack Override]] in the root of the stack.

If a break point happens, e.g. due to an error being thrown, debugger call or custom break points. If there is something in the [[Custom Stack Start]] slot, use the same mechanism as console.log to determine the current stack to visualize in a debugger instead of the native stack. The scope property contains an object. Every "own" property is considered to be a variable with that name in scope of that stack frame. Useful for debugging.

TODO: Consider what should happen to new Error().stack if the error is created within a custom scope.

function foo(x) {
if (!x) {
console.warn('You must provide the x argument.');
}
}
function bar(x) {
return {
stack: [
{
name: 'bar',
fileName: 'Bar.js',
lineNumber: 10,
columnNumber: 5,
}
],
callback: foo.bind(null, x)
};
}
function invokeCallback(continuation) {
console.stack(continuation.stack);
continuation.callback();
console.endStack();
}
var continuation = bar(false);
invokeCallback(continuation);
// Logs:
// You must provide the x argument.
// at foo (Example.js:3:4)
// at bar (Bar.js:10:5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment