Framework-agnostic micro-library for generating, parsing, and enhancing JavaScript stack traces in all environments
npx @tessl/cli install tessl/npm-stacktrace-js@2.0.0StackTrace.js is a framework-agnostic micro-library for generating, parsing, and enhancing JavaScript stack traces in all environments. It provides cross-browser compatible stack trace generation with source map support, Promise-based asynchronous APIs, and function instrumentation capabilities for debugging and error reporting.
npm install stacktrace-jsbower install stacktrace-jshttps://cdnjs.com/libraries/stacktrace.jsimport StackTrace from "stacktrace-js";For CommonJS:
const StackTrace = require("stacktrace-js");Browser (global):
// Available as window.StackTrace after including the scriptUMD (AMD):
define(['stacktrace'], function(StackTrace) {
// Use StackTrace here
});import StackTrace from "stacktrace-js";
// Get current stack trace
StackTrace.get()
.then(stackframes => {
stackframes.forEach(frame => {
console.log(frame.toString());
});
})
.catch(err => console.error(err));
// Parse an error object
try {
throw new Error("Something went wrong!");
} catch (error) {
StackTrace.fromError(error)
.then(stackframes => {
console.log("Stack trace:", stackframes);
});
}StackTrace.js is built around several key components:
Core functionality for capturing stack traces from various sources with optional source map enhancement.
/**
* Get a backtrace from invocation point with source map enhancement
* @param options - Optional configuration object
* @returns Promise resolving to Array of StackFrame objects
*/
function get(options?: StackTraceOptions): Promise<StackFrame[]>;
/**
* Get a backtrace synchronously (no source maps or function name guessing)
* @param options - Optional configuration object
* @returns Array of StackFrame objects
*/
function getSync(options?: StackTraceOptions): StackFrame[];Usage Examples:
// Asynchronous with source map enhancement
StackTrace.get({
filter: frame => !frame.functionName?.includes('internal'),
offline: false
}).then(stackframes => {
console.log('Enhanced stack trace:', stackframes);
});
// Synchronous (faster, less detailed)
const frames = StackTrace.getSync({
filter: frame => frame.fileName?.includes('my-app')
});
console.log('Sync stack trace:', frames);Parse existing Error objects and enhance them with source maps and location information.
/**
* Parse Error object and enhance with source maps
* @param error - Error object to parse
* @param options - Optional configuration object
* @returns Promise resolving to Array of StackFrame objects
*/
function fromError(error: Error, options?: StackTraceOptions): Promise<StackFrame[]>;Usage Examples:
// Parse caught errors
window.onerror = function(msg, file, line, col, error) {
StackTrace.fromError(error, {
sourceCache: {
'http://example.com/script.js': cachedSource
}
}).then(stackframes => {
// Send to error reporting service
reportError(msg, stackframes);
});
};
// Parse custom errors
const customError = new Error("Custom error");
StackTrace.fromError(customError).then(frames => {
console.log("Parsed error stack:", frames);
});Generate stack traces by walking the call chain when Error.stack is not available.
/**
* Generate backtrace by walking arguments.callee.caller chain
* @param options - Optional configuration object
* @returns Promise resolving to Array of StackFrame objects
*/
function generateArtificially(options?: StackTraceOptions): Promise<StackFrame[]>;Usage Examples:
// Fallback for environments without Error.stack
StackTrace.generateArtificially({
filter: frame => frame.functionName !== 'anonymous'
}).then(stackframes => {
console.log("Artificial stack trace:", stackframes);
});Wrap functions to automatically capture stack traces on invocation for debugging and profiling.
/**
* Wrap function to trigger callback with stack trace on each invocation
* @param fn - Function to instrument
* @param callback - Function called with stack trace array
* @param errback - Optional error callback function
* @param thisArg - Optional context object
* @returns Instrumented function
* @throws Error if fn is not a function
*/
function instrument<TFunc extends Function>(
fn: TFunc,
callback: (stackFrames: StackFrame[]) => void,
errback?: (error: Error) => void,
thisArg?: any
): TFunc;
/**
* Revert instrumented function to original state
* @param fn - Instrumented function to revert
* @returns Original (non-instrumented) function
* @throws Error if fn is not a function
*/
function deinstrument<TFunc extends Function>(fn: TFunc): TFunc;Usage Examples:
// Instrument a function for debugging
function processData(data) {
return data.map(item => item * 2);
}
const instrumentedProcess = StackTrace.instrument(
processData,
stackframes => {
console.log("processData called from:", stackframes[0]);
},
error => console.error("Failed to get stack trace:", error)
);
// Use the instrumented function
const result = instrumentedProcess([1, 2, 3]);
// Restore original function
const originalProcess = StackTrace.deinstrument(instrumentedProcess);Submit stack trace data to remote endpoints for centralized error tracking.
/**
* Serialize stackframes and POST to given URL
* @param stackframes - Array of StackFrame objects
* @param url - Target URL for POST request
* @param errorMsg - Optional error message string
* @param requestOptions - Optional HTTP request options (headers supported)
* @returns Promise resolving to response text
*/
function report(
stackframes: StackFrame[],
url: string,
errorMsg?: string,
requestOptions?: object
): Promise<any>;Usage Examples:
// Report errors to monitoring service
StackTrace.get().then(stackframes => {
return StackTrace.report(
stackframes,
'https://api.errorservice.com/errors',
'Unhandled exception occurred',
{
headers: {
'Authorization': 'Bearer token123',
'Content-Type': 'application/json'
}
}
);
}).then(response => {
console.log("Error reported successfully:", response);
});interface StackTraceOptions {
/** Filter function for stack frames */
filter?: (stackFrame: StackFrame) => boolean;
/** Pre-populated source cache to avoid network requests */
sourceCache?: SourceCache;
/** Set to true to prevent all network requests */
offline?: boolean;
}
interface SourceCache {
[url: string]: string | Promise<string>;
}
interface StackFrame {
/** Whether frame is constructor call */
isConstructor?: boolean;
/** Whether frame is from eval */
isEval?: boolean;
/** Whether frame is native code */
isNative?: boolean;
/** Whether frame is top-level */
isTopLevel?: boolean;
/** Column number in source */
columnNumber?: number;
/** Line number in source */
lineNumber?: number;
/** Source file name/URL */
fileName?: string;
/** Function name */
functionName?: string;
/** Source code line */
source?: string;
/** Function arguments */
args?: any[];
/** Origin frame for eval */
evalOrigin?: StackFrame;
/** Get/set methods for all properties */
getIsConstructor(): boolean;
setIsConstructor(): void;
getIsEval(): boolean;
setIsEval(): void;
getIsNative(): boolean;
setIsNative(): void;
getIsTopLevel(): boolean;
setIsTopLevel(): void;
getColumnNumber(): number;
setColumnNumber(): void;
getLineNumber(): number;
setLineNumber(): void;
getFileName(): string;
setFileName(): void;
getFunctionName(): string;
setFunctionName(): void;
getSource(): string;
setSource(): void;
getArgs(): any[];
setArgs(): void;
getEvalOrigin(): StackFrame;
setEvalOrigin(): void;
/** String representation */
toString(): string;
}StackTrace.js includes built-in error handling patterns:
Common error scenarios:
// Automatic error handling with window.onerror
window.onerror = function(msg, file, line, col, error) {
StackTrace.fromError(error).then(stackframes => {
console.log('Error stack trace:', stackframes);
// Send to error reporting service
}).catch(err => {
console.log('Failed to parse error:', err.message);
});
};
// Handle parsing failures
StackTrace.fromError(malformedError)
.catch(err => {
console.log("Failed to parse error:", err.message);
// Fallback to artificial generation
return StackTrace.generateArtificially();
});
// Handle network failures in reporting
StackTrace.report(frames, 'https://unreachable.com/api')
.catch(err => {
console.log("Failed to report error:", err.message);
// Could fallback to local storage or console logging
});Note: For Node.js-only applications, consider using the dedicated stack-trace package which provides similar API with optimizations specifically for server environments.