/*
 * Application Insights JavaScript SDK - Common, 3.3.10
 * Copyright (c) Microsoft and contributors. All rights reserved.
 */


import { __assignFn as __assign } from "@microsoft/applicationinsights-shims";
import { arrForEach, arrMap, isArray, isError, isFunction, isNullOrUndefined, isObject, isString, strTrim } from "@microsoft/applicationinsights-core-js";
import { asString, getWindow, objFreeze, strIndexOf } from "@nevware21/ts-utils";
import { strNotSpecified } from "../Constants";
import { _DYN_AI_DATA_CONTRACT, _DYN_ASSEMBLY, _DYN_EXCEPTIONS, _DYN_FILE_NAME, _DYN_HAS_FULL_STACK, _DYN_LENGTH, _DYN_LINE, _DYN_MATCH, _DYN_MEASUREMENTS, _DYN_MESSAGE, _DYN_NAME, _DYN_PARSED_STACK, _DYN_PROBLEM_GROUP, _DYN_PROPERTIES, _DYN_SEVERITY_LEVEL, _DYN_SIZE_IN_BYTES, _DYN_SPLIT, _DYN_STRINGIFY, _DYN_TO_STRING, _DYN_TYPE_NAME } from "../__DynamicConstants";
import { dataSanitizeException, dataSanitizeMeasurements, dataSanitizeMessage, dataSanitizeProperties, dataSanitizeString } from "./Common/DataSanitizer";
// These Regex covers the following patterns
// 1. Chrome/Firefox/IE/Edge:
//    at functionName (filename:lineNumber:columnNumber)
//    at functionName (filename:lineNumber)
//    at filename:lineNumber:columnNumber
//    at filename:lineNumber
//    at functionName@filename:lineNumber:columnNumber
// 2. Safari / Opera:
//    functionName@filename:lineNumber:columnNumber
//    functionName@filename:lineNumber
//    filename:lineNumber:columnNumber
//    filename:lineNumber
//    Line ## of scriptname script filename:lineNumber:columnNumber
//    Line ## of scriptname script filename
// 3. IE/Edge (Additional formats)
//    at functionName@filename:lineNumber
var STACKFRAME_BASE_SIZE = 58; // '{"method":"","level":,"assembly":"","fileName":"","line":}'.length
/**
 * Check if the string conforms to what looks like a stack frame line and not just a general message
 * comment or other non-stack related info.
 *
 * This  should be used to filter out any leading "message" lines from a stack trace, before attempting to parse
 * the individual stack frames. Once you have estabilsted the start of the stack frames you can then use the
 * FULL_STACK_FRAME_1, FULL_STACK_FRAME_2, FULL_STACK_FRAME_3, and EXTRACT_FILENAME to parse the individual
 * stack frames to extract the method, filename, line number, and column number.
 * These may still provide invalid matches, so the sequence of execution is important to avoid providing
 * an invalid parsed stack.
 */
var IS_FRAME = /^\s{0,50}(from\s|at\s|Line\s{1,5}\d{1,10}\s{1,5}of|\w{1,50}@\w{1,80}|[^\(\s\n]+:[0-9\?]+(?::[0-9\?]+)?)/;
/**
 * Parse a well formed stack frame with both the line and column numbers
 * ----------------------------------
 * **Primary focus of the matching**
 * - at functionName (filename:lineNumber:columnNumber)
 * - at filename:lineNumber:columnNumber
 * - at functionName@filename:lineNumber:columnNumber
 * - functionName (filename:lineNumber:columnNumber)
 * - filename:lineNumber:columnNumber
 * - functionName@filename:lineNumber:columnNumber
 */
var FULL_STACK_FRAME_1 = /^(?:\s{0,50}at)?\s{0,50}([^\@\()\s]+)?\s{0,50}(?:\s|\@|\()\s{0,5}([^\(\s\n\]]+):([0-9\?]+):([0-9\?]+)\)?$/;
/**
 * Parse a well formed stack frame with only a line number.
 * ----------------------------------
 * > Note: this WILL also match with line and column number, but the line number is included with the filename
 * > you should attempt to match with FULL_STACK_FRAME_1 first.
 *
 * **Primary focus of the matching (run FULL_STACK_FRAME_1 first)**
 * - at functionName (filename:lineNumber)
 * - at filename:lineNumber
 * - at functionName@filename:lineNumber
 * - functionName (filename:lineNumber)
 * - filename:lineNumber
 * - functionName@filename:lineNumber
 *
 * **Secondary matches**
 * - at functionName (filename:lineNumber:columnNumber)
 * - at filename:lineNumber:columnNumber
 * - at functionName@filename:lineNumber:columnNumber
 * - functionName (filename:lineNumber:columnNumber)
 * - filename:lineNumber:columnNumber
 * - functionName@filename:lineNumber:columnNumber
 */
var FULL_STACK_FRAME_2 = /^(?:\s{0,50}at)?\s{0,50}([^\@\()\s]+)?\s{0,50}(?:\s|\@|\()\s{0,5}([^\(\s\n\]]+):([0-9\?]+)\)?$/;
/**
 * Attempt to Parse a frame that doesn't include a line or column number.
 * ----------------------------------
 * > Note: this WILL also match lines with a line or line and column number, you should attempt to match with
 * both FULL_STACK_FRAME_1 and FULL_STACK_FRAME_2 first to avoid false positives.
 *
 * **Unexpected Invalid Matches** (Matches that should be avoided -- by using the FULL_STACK_FRAME_1 and FULL_STACK_FRAME_2 first)
 * - at https://localhost:44365/static/node_bundles/@microsoft/blah/js/bundle.js:144112:27
 * - at https://localhost:44365/static/node_bundles/@microsoft/blah/js/bundle.js:144112:27
 *
 * **Primary focus of the matching (run FULL_STACK_FRAME_1 first)**
 * - at functionName@filename
 * - at functionName (filename)
 * - at functionName filename
 * - at filename  <- Will actuall match this as the "method" and not the filename (care should be taken to avoid this)
 * - functionName@filename
 * - functionName (filename)
 * - functionName filename
 * - functionName
 *
 * **Secondary matches** (The line and column numbers will be included with the matched filename)
 * - at functionName (filename:lineNumber:columnNumber)
 * - at functionName (filename:lineNumber)
 * - at filename:lineNumber:columnNumber
 * - at filename:lineNumber
 * - at functionName@filename:lineNumber:columnNumber
 * - at functionName@filename:lineNumber
 * - functionName (filename:lineNumber:columnNumber)
 * - functionName (filename:lineNumber)
 * - filename:lineNumber:columnNumber
 * - filename:lineNumber
 * - functionName@filename:lineNumber:columnNumber
 * - functionName@filename:lineNumber
  */
var FULL_STACK_FRAME_3 = /^(?:\s{0,50}at)?\s{0,50}([^\@\()\s]+)?\s{0,50}(?:\s|\@|\()\s{0,5}([^\(\s\n\)\]]+)\)?$/;
/**
 * Attempt to extract the filename (with or without line and column numbers) from a string.
 * ----------------------------------
 * > Note: this will only match the filename (with any line or column numbers) and will
 * > return what looks like the filename, however, it will also match random strings that
 * > look like a filename, so care should be taken to ensure that the filename is actually
 * > a filename before using it.
 * >
 * > It is recommended to use this in conjunction with the FULL_STACK_FRAME_1, FULL_STACK_FRAME_2, and FULL_STACK_FRAME_3
 * > to ensure first to reduce false matches, if all of these fail then you can use this to extract the filename from a random
 * > strings to identify any potential filename from a known stack frame line.
 *
 * **Known Invalid matching**
 *
 * This regex will basically match any "final" string of a line or one that is trailed by a comma, so this should not
 * be used as the "only" matching regex, but rather as a final fallback to extract the filename from a string.
 * If you are certain that the string line is a stack frame and not part of the exception message (lines before the stack)
 * or trailing comments, then you can use this to extract the filename and then further parse with PARSE_FILENAME_LINE_COL
 * and PARSE_FILENAME_LINE_ONLY to extract any potential the line and column numbers.
 *
 * **Primary focus of the matching**
 * - at (anonymous) @ VM60:1
 * - Line 21 of linked script file://localhost/C:/Temp/stacktrace.js
 * - Line 11 of inline#1 script in http://localhost:3000/static/js/main.206f4846.js:2:296748
 * - Line 68 of inline#2 script in file://localhost/teststack.html
 * - at Global code (http://example.com/stacktrace.js:11:1)
 */
var EXTRACT_FILENAME = /(?:^|\(|\s{0,10}[\w\)]+\@)?([^\(\n\s\]\)]+)(?:\:([0-9]+)(?:\:([0-9]+))?)?\)?(?:,|$)/;
/**
 * Attempt to extract the filename, line number, and column number from a string.
 */
var PARSE_FILENAME_LINE_COL = /([^\(\s\n]+):([0-9]+):([0-9]+)$/;
/**
 * Attempt to extract the filename and line number from a string.
 */
var PARSE_FILENAME_LINE_ONLY = /([^\(\s\n]+):([0-9]+)$/;
var NoMethod = "<no_method>";
var strError = "error";
var strStack = "stack";
var strStackDetails = "stackDetails";
var strErrorSrc = "errorSrc";
var strMessage = "message";
var strDescription = "description";
var _parseSequence = [
    { re: FULL_STACK_FRAME_1, len: 5, m: 1, fn: 2, ln: 3, col: 4 },
    { chk: _ignoreNative, pre: _scrubAnonymous, re: FULL_STACK_FRAME_2, len: 4, m: 1, fn: 2, ln: 3 },
    { re: FULL_STACK_FRAME_3, len: 3, m: 1, fn: 2, hdl: _handleFilename },
    { re: EXTRACT_FILENAME, len: 2, fn: 1, hdl: _handleFilename }
];
function _scrubAnonymous(frame) {
    return frame.replace(/(\(anonymous\))/, "<anonymous>");
}
function _ignoreNative(frame) {
    return strIndexOf(frame, "[native") < 0;
}
function _stringify(value, convertToString) {
    var result = value;
    if (result && !isString(result)) {
        if (JSON && JSON[_DYN_STRINGIFY /* @min:%2estringify */]) {
            result = JSON[_DYN_STRINGIFY /* @min:%2estringify */](value);
            if (convertToString && (!result || result === "{}")) {
                if (isFunction(value[_DYN_TO_STRING /* @min:%2etoString */])) {
                    result = value[_DYN_TO_STRING /* @min:%2etoString */]();
                }
                else {
                    result = "" + value;
                }
            }
        }
        else {
            result = "" + value + " - (Missing JSON.stringify)";
        }
    }
    return result || "";
}
function _formatMessage(theEvent, errorType) {
    var evtMessage = theEvent;
    if (theEvent) {
        if (evtMessage && !isString(evtMessage)) {
            evtMessage = theEvent[strMessage] || theEvent[strDescription] || evtMessage;
        }
        // Make sure the message is a string
        if (evtMessage && !isString(evtMessage)) {
            // tslint:disable-next-line: prefer-conditional-expression
            evtMessage = _stringify(evtMessage, true);
        }
        if (theEvent["filename"]) {
            // Looks like an event object with filename
            evtMessage = evtMessage + " @" + (theEvent["filename"] || "") + ":" + (theEvent["lineno"] || "?") + ":" + (theEvent["colno"] || "?");
        }
    }
    // Automatically add the error type to the message if it does already appear to be present
    if (errorType && errorType !== "String" && errorType !== "Object" && errorType !== "Error" && strIndexOf(evtMessage || "", errorType) === -1) {
        evtMessage = errorType + ": " + evtMessage;
    }
    return evtMessage || "";
}
function _isExceptionDetailsInternal(value) {
    try {
        if (isObject(value)) {
            return "hasFullStack" in value && "typeName" in value;
        }
    }
    catch (e) {
        // This can happen with some native browser objects, but should not happen for the type we are checking for
    }
    return false;
}
function _isExceptionInternal(value) {
    try {
        if (isObject(value)) {
            return ("ver" in value && "exceptions" in value && "properties" in value);
        }
    }
    catch (e) {
        // This can happen with some native browser objects, but should not happen for the type we are checking for
    }
    return false;
}
function _isStackDetails(details) {
    return details && details.src && isString(details.src) && details.obj && isArray(details.obj);
}
function _convertStackObj(errorStack) {
    var src = errorStack || "";
    if (!isString(src)) {
        if (isString(src[strStack])) {
            src = src[strStack];
        }
        else {
            src = "" + src;
        }
    }
    var items = src[_DYN_SPLIT /* @min:%2esplit */]("\n");
    return {
        src: src,
        obj: items
    };
}
function _getOperaStack(errorMessage) {
    var stack = [];
    var lines = errorMessage[_DYN_SPLIT /* @min:%2esplit */]("\n");
    for (var lp = 0; lp < lines[_DYN_LENGTH /* @min:%2elength */]; lp++) {
        var entry = lines[lp];
        if (lines[lp + 1]) {
            entry += "@" + lines[lp + 1];
            lp++;
        }
        stack.push(entry);
    }
    return {
        src: errorMessage,
        obj: stack
    };
}
function _getStackFromErrorObj(errorObj) {
    var details = null;
    if (errorObj) {
        try {
            /* Using bracket notation is support older browsers (IE 7/8 -- dont remember the version) that throw when using dot
            notation for undefined objects and we don't want to loose the error from being reported */
            if (errorObj[strStack]) {
                // Chrome/Firefox
                details = _convertStackObj(errorObj[strStack]);
            }
            else if (errorObj[strError] && errorObj[strError][strStack]) {
                // Edge error event provides the stack and error object
                details = _convertStackObj(errorObj[strError][strStack]);
            }
            else if (errorObj["exception"] && errorObj.exception[strStack]) {
                details = _convertStackObj(errorObj.exception[strStack]);
            }
            else if (_isStackDetails(errorObj)) {
                details = errorObj;
            }
            else if (_isStackDetails(errorObj[strStackDetails])) {
                details = errorObj[strStackDetails];
            }
            else if (getWindow() && getWindow()["opera"] && errorObj[strMessage]) {
                // Opera
                details = _getOperaStack(errorObj[_DYN_MESSAGE /* @min:%2emessage */]);
            }
            else if (errorObj["reason"] && errorObj.reason[strStack]) {
                // UnhandledPromiseRejection
                details = _convertStackObj(errorObj.reason[strStack]);
            }
            else if (isString(errorObj)) {
                details = _convertStackObj(errorObj);
            }
            else {
                var evtMessage = errorObj[strMessage] || errorObj[strDescription] || "";
                if (isString(errorObj[strErrorSrc])) {
                    if (evtMessage) {
                        evtMessage += "\n";
                    }
                    evtMessage += " from " + errorObj[strErrorSrc];
                }
                if (evtMessage) {
                    details = _convertStackObj(evtMessage);
                }
            }
        }
        catch (e) {
            // something unexpected happened so to avoid failing to report any error lets swallow the exception
            // and fallback to the callee/caller method
            details = _convertStackObj(e);
        }
    }
    return details || {
        src: "",
        obj: null
    };
}
function _formatStackTrace(stackDetails) {
    var stack = "";
    if (stackDetails) {
        if (stackDetails.obj) {
            stack = stackDetails.obj.join("\n");
        }
        else {
            stack = stackDetails.src || "";
        }
    }
    return stack;
}
function _parseStack(stack) {
    var parsedStack;
    var frames = stack.obj;
    if (frames && frames[_DYN_LENGTH /* @min:%2elength */] > 0) {
        parsedStack = [];
        var level_1 = 0;
        var foundStackStart_1 = false;
        var totalSizeInBytes_1 = 0;
        arrForEach(frames, function (frame) {
            if (foundStackStart_1 || _isStackFrame(frame)) {
                var theFrame = asString(frame);
                // Once we have found the first stack frame we treat the rest of the lines as part of the stack
                foundStackStart_1 = true;
                var parsedFrame = _extractStackFrame(theFrame, level_1);
                if (parsedFrame) {
                    totalSizeInBytes_1 += parsedFrame[_DYN_SIZE_IN_BYTES /* @min:%2esizeInBytes */];
                    parsedStack.push(parsedFrame);
                    level_1++;
                }
            }
        });
        // DP Constraint - exception parsed stack must be < 32KB
        // remove frames from the middle to meet the threshold
        var exceptionParsedStackThreshold = 32 * 1024;
        if (totalSizeInBytes_1 > exceptionParsedStackThreshold) {
            var left = 0;
            var right = parsedStack[_DYN_LENGTH /* @min:%2elength */] - 1;
            var size = 0;
            var acceptedLeft = left;
            var acceptedRight = right;
            while (left < right) {
                // check size
                var lSize = parsedStack[left][_DYN_SIZE_IN_BYTES /* @min:%2esizeInBytes */];
                var rSize = parsedStack[right][_DYN_SIZE_IN_BYTES /* @min:%2esizeInBytes */];
                size += lSize + rSize;
                if (size > exceptionParsedStackThreshold) {
                    // remove extra frames from the middle
                    var howMany = acceptedRight - acceptedLeft + 1;
                    parsedStack.splice(acceptedLeft, howMany);
                    break;
                }
                // update pointers
                acceptedLeft = left;
                acceptedRight = right;
                left++;
                right--;
            }
        }
    }
    return parsedStack;
}
function _getErrorType(errorType) {
    // Gets the Error Type by passing the constructor (used to get the true type of native error object).
    var typeName = "";
    if (errorType) {
        typeName = errorType.typeName || errorType[_DYN_NAME /* @min:%2ename */] || "";
        if (!typeName) {
            try {
                var funcNameRegex = /function (.{1,200})\(/;
                var results = (funcNameRegex).exec((errorType).constructor[_DYN_TO_STRING /* @min:%2etoString */]());
                typeName = (results && results[_DYN_LENGTH /* @min:%2elength */] > 1) ? results[1] : "";
            }
            catch (e) {
                // eslint-disable-next-line no-empty -- Ignoring any failures as nothing we can do
            }
        }
    }
    return typeName;
}
/**
 * Formats the provided errorObj for display and reporting, it may be a String, Object, integer or undefined depending on the browser.
 * @param errorObj - The supplied errorObj
 */
export function _formatErrorCode(errorObj) {
    if (errorObj) {
        try {
            if (!isString(errorObj)) {
                var errorType = _getErrorType(errorObj);
                var result = _stringify(errorObj, false);
                if (!result || result === "{}") {
                    if (errorObj[strError]) {
                        // Looks like an MS Error Event
                        errorObj = errorObj[strError];
                        errorType = _getErrorType(errorObj);
                    }
                    result = _stringify(errorObj, true);
                }
                if (strIndexOf(result, errorType) !== 0 && errorType !== "String") {
                    return errorType + ":" + result;
                }
                return result;
            }
        }
        catch (e) {
            // eslint-disable-next-line no-empty -- Ignoring any failures as nothing we can do
        }
    }
    // Fallback to just letting the object format itself into a string
    return "" + (errorObj || "");
}
var Exception = /** @class */ (function () {
    /**
     * Constructs a new instance of the ExceptionTelemetry object
     */
    function Exception(logger, exception, properties, measurements, severityLevel, id) {
        this.aiDataContract = {
            ver: 1 /* FieldType.Required */,
            exceptions: 1 /* FieldType.Required */,
            severityLevel: 0 /* FieldType.Default */,
            properties: 0 /* FieldType.Default */,
            measurements: 0 /* FieldType.Default */
        };
        var _self = this;
        _self.ver = 2; // TODO: handle the CS"4.0" ==> breeze 2 conversion in a better way
        if (!_isExceptionInternal(exception)) {
            if (!properties) {
                properties = {};
            }
            if (id) {
                properties.id = id;
            }
            _self[_DYN_EXCEPTIONS /* @min:%2eexceptions */] = [_createExceptionDetails(logger, exception, properties)];
            _self[_DYN_PROPERTIES /* @min:%2eproperties */] = dataSanitizeProperties(logger, properties);
            _self[_DYN_MEASUREMENTS /* @min:%2emeasurements */] = dataSanitizeMeasurements(logger, measurements);
            if (severityLevel) {
                _self[_DYN_SEVERITY_LEVEL /* @min:%2eseverityLevel */] = severityLevel;
            }
            if (id) {
                _self.id = id;
            }
        }
        else {
            _self[_DYN_EXCEPTIONS /* @min:%2eexceptions */] = exception[_DYN_EXCEPTIONS /* @min:%2eexceptions */] || [];
            _self[_DYN_PROPERTIES /* @min:%2eproperties */] = exception[_DYN_PROPERTIES /* @min:%2eproperties */];
            _self[_DYN_MEASUREMENTS /* @min:%2emeasurements */] = exception[_DYN_MEASUREMENTS /* @min:%2emeasurements */];
            if (exception[_DYN_SEVERITY_LEVEL /* @min:%2eseverityLevel */]) {
                _self[_DYN_SEVERITY_LEVEL /* @min:%2eseverityLevel */] = exception[_DYN_SEVERITY_LEVEL /* @min:%2eseverityLevel */];
            }
            if (exception.id) {
                _self.id = exception.id;
                exception[_DYN_PROPERTIES /* @min:%2eproperties */].id = exception.id;
            }
            if (exception[_DYN_PROBLEM_GROUP /* @min:%2eproblemGroup */]) {
                _self[_DYN_PROBLEM_GROUP /* @min:%2eproblemGroup */] = exception[_DYN_PROBLEM_GROUP /* @min:%2eproblemGroup */];
            }
            // bool/int types, use isNullOrUndefined
            if (!isNullOrUndefined(exception.isManual)) {
                _self.isManual = exception.isManual;
            }
        }
    }
    Exception.CreateAutoException = function (message, url, lineNumber, columnNumber, error, evt, stack, errorSrc) {
        var errorType = _getErrorType(error || evt || message);
        return {
            message: _formatMessage(message, errorType),
            url: url,
            lineNumber: lineNumber,
            columnNumber: columnNumber,
            error: _formatErrorCode(error || evt || message),
            evt: _formatErrorCode(evt || message),
            typeName: errorType,
            stackDetails: _getStackFromErrorObj(stack || error || evt),
            errorSrc: errorSrc
        };
    };
    Exception.CreateFromInterface = function (logger, exception, properties, measurements) {
        var exceptions = exception[_DYN_EXCEPTIONS /* @min:%2eexceptions */]
            && arrMap(exception[_DYN_EXCEPTIONS /* @min:%2eexceptions */], function (ex) { return _createExDetailsFromInterface(logger, ex); });
        var exceptionData = new Exception(logger, __assign(__assign({}, exception), { exceptions: exceptions }), properties, measurements);
        return exceptionData;
    };
    Exception.prototype.toInterface = function () {
        var _a = this, exceptions = _a.exceptions, properties = _a.properties, measurements = _a.measurements, severityLevel = _a.severityLevel, problemGroup = _a.problemGroup, id = _a.id, isManual = _a.isManual;
        var exceptionDetailsInterface = exceptions instanceof Array
            && arrMap(exceptions, function (exception) { return exception.toInterface(); })
            || undefined;
        return {
            ver: "4.0",
            exceptions: exceptionDetailsInterface,
            severityLevel: severityLevel,
            properties: properties,
            measurements: measurements,
            problemGroup: problemGroup,
            id: id,
            isManual: isManual
        };
    };
    /**
     * Creates a simple exception with 1 stack frame. Useful for manual constracting of exception.
     */
    Exception.CreateSimpleException = function (message, typeName, assembly, fileName, details, line) {
        var _a;
        return {
            exceptions: [
                (_a = {},
                    _a[_DYN_HAS_FULL_STACK /* @min:hasFullStack */] = true,
                    _a.message = message,
                    _a.stack = details,
                    _a.typeName = typeName,
                    _a)
            ]
        };
    };
    Exception.envelopeType = "Microsoft.ApplicationInsights.{0}.Exception";
    Exception.dataType = "ExceptionData";
    Exception.formatError = _formatErrorCode;
    return Exception;
}());
export { Exception };
var exDetailsAiDataContract = objFreeze({
    id: 0 /* FieldType.Default */,
    outerId: 0 /* FieldType.Default */,
    typeName: 1 /* FieldType.Required */,
    message: 1 /* FieldType.Required */,
    hasFullStack: 0 /* FieldType.Default */,
    stack: 0 /* FieldType.Default */,
    parsedStack: 2 /* FieldType.Array */
});
function _toInterface() {
    var _self = this;
    var parsedStack = isArray(_self[_DYN_PARSED_STACK /* @min:%2eparsedStack */])
        && arrMap(_self[_DYN_PARSED_STACK /* @min:%2eparsedStack */], function (frame) { return _parsedFrameToInterface(frame); });
    var exceptionDetailsInterface = {
        id: _self.id,
        outerId: _self.outerId,
        typeName: _self[_DYN_TYPE_NAME /* @min:%2etypeName */],
        message: _self[_DYN_MESSAGE /* @min:%2emessage */],
        hasFullStack: _self[_DYN_HAS_FULL_STACK /* @min:%2ehasFullStack */],
        stack: _self[strStack],
        parsedStack: parsedStack || undefined
    };
    return exceptionDetailsInterface;
}
export function _createExceptionDetails(logger, exception, properties) {
    var _a;
    var id;
    var outerId;
    var typeName;
    var message;
    var hasFullStack;
    var theStack;
    var parsedStack;
    if (!_isExceptionDetailsInternal(exception)) {
        var error = exception;
        var evt = error && error.evt;
        if (!isError(error)) {
            error = error[strError] || evt || error;
        }
        typeName = dataSanitizeString(logger, _getErrorType(error)) || strNotSpecified;
        message = dataSanitizeMessage(logger, _formatMessage(exception || error, typeName)) || strNotSpecified;
        var stack = exception[strStackDetails] || _getStackFromErrorObj(exception);
        parsedStack = _parseStack(stack);
        // after parsedStack is inited, iterate over each frame object, sanitize its assembly field
        if (isArray(parsedStack)) {
            arrMap(parsedStack, function (frame) {
                frame[_DYN_ASSEMBLY /* @min:%2eassembly */] = dataSanitizeString(logger, frame[_DYN_ASSEMBLY /* @min:%2eassembly */]);
                frame[_DYN_FILE_NAME /* @min:%2efileName */] = dataSanitizeString(logger, frame[_DYN_FILE_NAME /* @min:%2efileName */]);
            });
        }
        theStack = dataSanitizeException(logger, _formatStackTrace(stack));
        hasFullStack = isArray(parsedStack) && parsedStack[_DYN_LENGTH /* @min:%2elength */] > 0;
        if (properties) {
            properties[_DYN_TYPE_NAME /* @min:%2etypeName */] = properties[_DYN_TYPE_NAME /* @min:%2etypeName */] || typeName;
        }
    }
    else {
        typeName = exception[_DYN_TYPE_NAME /* @min:%2etypeName */];
        message = exception[_DYN_MESSAGE /* @min:%2emessage */];
        theStack = exception[strStack];
        parsedStack = exception[_DYN_PARSED_STACK /* @min:%2eparsedStack */] || [];
        hasFullStack = exception[_DYN_HAS_FULL_STACK /* @min:%2ehasFullStack */];
    }
    return _a = {},
        _a[_DYN_AI_DATA_CONTRACT /* @min:aiDataContract */] = exDetailsAiDataContract,
        _a.id = id,
        _a.outerId = outerId,
        _a.typeName = typeName,
        _a.message = message,
        _a[_DYN_HAS_FULL_STACK /* @min:hasFullStack */] = hasFullStack,
        _a.stack = theStack,
        _a.parsedStack = parsedStack,
        _a.toInterface = _toInterface,
        _a;
}
export function _createExDetailsFromInterface(logger, exception) {
    var parsedStack = (isArray(exception[_DYN_PARSED_STACK /* @min:%2eparsedStack */])
        && arrMap(exception[_DYN_PARSED_STACK /* @min:%2eparsedStack */], function (frame) { return _stackFrameFromInterface(frame); }))
        || exception[_DYN_PARSED_STACK /* @min:%2eparsedStack */];
    var exceptionDetails = _createExceptionDetails(logger, __assign(__assign({}, exception), { parsedStack: parsedStack }));
    return exceptionDetails;
}
function _parseFilename(theFrame, fileName) {
    var lineCol = fileName[_DYN_MATCH /* @min:%2ematch */](PARSE_FILENAME_LINE_COL);
    if (lineCol && lineCol[_DYN_LENGTH /* @min:%2elength */] >= 4) {
        theFrame[_DYN_FILE_NAME /* @min:%2efileName */] = lineCol[1];
        theFrame[_DYN_LINE /* @min:%2eline */] = parseInt(lineCol[2]);
    }
    else {
        var lineNo = fileName[_DYN_MATCH /* @min:%2ematch */](PARSE_FILENAME_LINE_ONLY);
        if (lineNo && lineNo[_DYN_LENGTH /* @min:%2elength */] >= 3) {
            theFrame[_DYN_FILE_NAME /* @min:%2efileName */] = lineNo[1];
            theFrame[_DYN_LINE /* @min:%2eline */] = parseInt(lineNo[2]);
        }
        else {
            theFrame[_DYN_FILE_NAME /* @min:%2efileName */] = fileName;
        }
    }
}
function _handleFilename(theFrame, sequence, matches) {
    var filename = theFrame[_DYN_FILE_NAME /* @min:%2efileName */];
    if (sequence.fn && matches && matches[_DYN_LENGTH /* @min:%2elength */] > sequence.fn) {
        if (sequence.ln && matches[_DYN_LENGTH /* @min:%2elength */] > sequence.ln) {
            filename = strTrim(matches[sequence.fn] || "");
            theFrame[_DYN_LINE /* @min:%2eline */] = parseInt(strTrim(matches[sequence.ln] || "")) || 0;
        }
        else {
            filename = strTrim(matches[sequence.fn] || "");
        }
    }
    if (filename) {
        _parseFilename(theFrame, filename);
    }
}
function _isStackFrame(frame) {
    var result = false;
    if (frame && isString(frame)) {
        var trimmedFrame = strTrim(frame);
        if (trimmedFrame) {
            result = IS_FRAME.test(trimmedFrame);
        }
    }
    return result;
}
var stackFrameAiDataContract = objFreeze({
    level: 1 /* FieldType.Required */,
    method: 1 /* FieldType.Required */,
    assembly: 0 /* FieldType.Default */,
    fileName: 0 /* FieldType.Default */,
    line: 0 /* FieldType.Default */
});
export function _extractStackFrame(frame, level) {
    var _a;
    var theFrame;
    if (frame && isString(frame) && strTrim(frame)) {
        theFrame = (_a = {},
            _a[_DYN_AI_DATA_CONTRACT /* @min:aiDataContract */] = stackFrameAiDataContract,
            _a.level = level,
            _a.assembly = strTrim(frame),
            _a.method = NoMethod,
            _a.fileName = "",
            _a.line = 0,
            _a.sizeInBytes = 0,
            _a);
        var idx = 0;
        while (idx < _parseSequence[_DYN_LENGTH /* @min:%2elength */]) {
            var sequence = _parseSequence[idx];
            if (sequence.chk && !sequence.chk(frame)) {
                break;
            }
            if (sequence.pre) {
                frame = sequence.pre(frame);
            }
            // Attempt to "parse" the stack frame
            var matches = frame[_DYN_MATCH /* @min:%2ematch */](sequence.re);
            if (matches && matches[_DYN_LENGTH /* @min:%2elength */] >= sequence.len) {
                if (sequence.m) {
                    theFrame.method = strTrim(matches[sequence.m] || NoMethod);
                }
                if (sequence.hdl) {
                    // Run any custom handler
                    sequence.hdl(theFrame, sequence, matches);
                }
                else if (sequence.fn) {
                    if (sequence.ln) {
                        theFrame[_DYN_FILE_NAME /* @min:%2efileName */] = strTrim(matches[sequence.fn] || "");
                        theFrame[_DYN_LINE /* @min:%2eline */] = parseInt(strTrim(matches[sequence.ln] || "")) || 0;
                    }
                    else {
                        _parseFilename(theFrame, matches[sequence.fn] || "");
                    }
                }
                // We found a match so stop looking
                break;
            }
            idx++;
        }
    }
    return _populateFrameSizeInBytes(theFrame);
}
function _stackFrameFromInterface(frame) {
    var _a;
    var parsedFrame = (_a = {},
        _a[_DYN_AI_DATA_CONTRACT /* @min:aiDataContract */] = stackFrameAiDataContract,
        _a.level = frame.level,
        _a.method = frame.method,
        _a.assembly = frame[_DYN_ASSEMBLY /* @min:%2eassembly */],
        _a.fileName = frame[_DYN_FILE_NAME /* @min:%2efileName */],
        _a.line = frame[_DYN_LINE /* @min:%2eline */],
        _a.sizeInBytes = 0,
        _a);
    return _populateFrameSizeInBytes(parsedFrame);
}
function _populateFrameSizeInBytes(frame) {
    var sizeInBytes = STACKFRAME_BASE_SIZE;
    if (frame) {
        sizeInBytes += frame.method[_DYN_LENGTH /* @min:%2elength */];
        sizeInBytes += frame.assembly[_DYN_LENGTH /* @min:%2elength */];
        sizeInBytes += frame.fileName[_DYN_LENGTH /* @min:%2elength */];
        sizeInBytes += frame.level.toString()[_DYN_LENGTH /* @min:%2elength */];
        sizeInBytes += frame.line.toString()[_DYN_LENGTH /* @min:%2elength */];
        frame[_DYN_SIZE_IN_BYTES /* @min:%2esizeInBytes */] = sizeInBytes;
    }
    return frame;
}
export function _parsedFrameToInterface(frame) {
    return {
        level: frame.level,
        method: frame.method,
        assembly: frame[_DYN_ASSEMBLY /* @min:%2eassembly */],
        fileName: frame[_DYN_FILE_NAME /* @min:%2efileName */],
        line: frame[_DYN_LINE /* @min:%2eline */]
    };
}
//# sourceMappingURL=Exception.js.map