All files / Scripts stacks.ts

81.25% Statements 26/32
62.5% Branches 5/8
83.33% Functions 5/6
88.88% Lines 24/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56  9x   9x 9x 9x   9x 9x       161x 161x 147x         133x 133x 133x         9x 7x   2x     9x         9x   9x 9x 3x     9x 9x 133x   9x              
import { StackFrame, StackTraceOptions } from "stacktrace-js";
import * as stackTrace from "stacktrace-js";
 
import { diagnostics } from "./Diag";
import { Errors } from "./Errors";
import { Strings } from "./Strings";
 
export class Stack {
    public static options: StackTraceOptions = {offline: false, filter: Stack.filterStack};
 
    // While trying to get our error tracking under control, let's not filter our stacks
    private static filterStack(item: StackFrame):boolean {
        Iif (!item.fileName) return true;
        if (item.fileName.indexOf("stacktrace") !== -1) return false; // remove stacktrace.js frames
        if (item.fileName.indexOf("stacks.ts") !== -1) return false; // remove stacks.ts frames
        //if (item.functionName === "ShowError") return false;
        //if (item.functionName === "showError") return false;
        //if (item.functionName === "Errors.log") return false; // Logs with Errors.log in them usually have location where it was called from - keep those
        //if (item.functionName === "GetStack") return false;
        Iif (item.functionName === "Errors.isError") return false; // Not called from anywhere interesting
        Iif (item.functionName?.indexOf("Promise._immediateFn") !== -1) return false; // only shows in IE stacks
        return true;
    }
 
    private static async getExceptionStack(exception: unknown): Promise<StackFrame[]> {
        let stack;
        if (!Errors.isError(exception)) {
            stack = await stackTrace.get(Stack.options);
        } else {
            stack = await stackTrace.fromError(exception as Error, Stack.options);
        }
 
        return stack;
    }
 
    public static parse(exception: unknown, message: string | null, handler: (eventName: string, stack: string[]) => void): void {
        let stack;
        const exceptionMessage = Errors.getErrorMessage(exception);
 
        let eventName = Strings.joinArray([message, exceptionMessage], " : ");
        if (!eventName) {
            eventName = "Unknown exception";
        }
 
        this.getExceptionStack(exception).then((stackframes) => {
            stack = stackframes.map(function (sf) {
                return sf.toString();
            });
            handler(eventName, stack);
        }).catch((err) => {
            diagnostics.trackEvent({ name: "Errors.parse errback" });
            stack = [JSON.stringify(exception, null, 2), "Parsing error:", JSON.stringify(err, null, 2)];
            handler(eventName, stack);
        });
    }
}