"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.lazyJoinStacks = exports.joinStacks = exports.isWritableStack = exports.isLazyStack = void 0;
const newline = /\r?\n/;
const onoCall = /\bono[ @]/;
/**
 * Is the property lazily computed?
 */
function isLazyStack(stackProp) {
    return Boolean(stackProp &&
        stackProp.configurable &&
        typeof stackProp.get === "function");
}
exports.isLazyStack = isLazyStack;
/**
 * Is the stack property writable?
 */
function isWritableStack(stackProp) {
    return Boolean(
    // If there is no stack property, then it's writable, since assigning it will create it
    !stackProp ||
        stackProp.writable ||
        typeof stackProp.set === "function");
}
exports.isWritableStack = isWritableStack;
/**
 * Appends the original `Error.stack` property to the new Error's stack.
 */
function joinStacks(newError, originalError) {
    let newStack = popStack(newError.stack);
    let originalStack = originalError ? originalError.stack : undefined;
    if (newStack && originalStack) {
        return newStack + "\n\n" + originalStack;
    }
    else {
        return newStack || originalStack;
    }
}
exports.joinStacks = joinStacks;
/**
 * Calls `joinStacks` lazily, when the `Error.stack` property is accessed.
 */
function lazyJoinStacks(lazyStack, newError, originalError) {
    if (originalError) {
        Object.defineProperty(newError, "stack", {
            get: () => {
                let newStack = lazyStack.get.apply(newError);
                return joinStacks({ stack: newStack }, originalError);
            },
            enumerable: false,
            configurable: true
        });
    }
    else {
        lazyPopStack(newError, lazyStack);
    }
}
exports.lazyJoinStacks = lazyJoinStacks;
/**
 * Removes Ono from the stack, so that the stack starts at the original error location
 */
function popStack(stack) {
    if (stack) {
        let lines = stack.split(newline);
        // Find the Ono call(s) in the stack, and remove them
        let onoStart;
        for (let i = 0; i < lines.length; i++) {
            let line = lines[i];
            if (onoCall.test(line)) {
                if (onoStart === undefined) {
                    // We found the first Ono call in the stack trace.
                    // There may be other subsequent Ono calls as well.
                    onoStart = i;
                }
            }
            else if (onoStart !== undefined) {
                // We found the first non-Ono call after one or more Ono calls.
                // So remove the Ono call lines from the stack trace
                lines.splice(onoStart, i - onoStart);
                break;
            }
        }
        if (lines.length > 0) {
            return lines.join("\n");
        }
    }
    // If we get here, then the stack doesn't contain a call to `ono`.
    // This may be due to minification or some optimization of the JS engine.
    // So just return the stack as-is.
    return stack;
}
/**
 * Calls `popStack` lazily, when the `Error.stack` property is accessed.
 */
function lazyPopStack(error, lazyStack) {
    Object.defineProperty(error, "stack", {
        get: () => popStack(lazyStack.get.apply(error)),
        enumerable: false,
        configurable: true
    });
}
//# sourceMappingURL=stack.js.map