diff --git a/js/sentry-browser/bundle.min.js.map b/js/sentry-browser/bundle.min.js.map new file mode 100644 index 0000000..9952194 --- /dev/null +++ b/js/sentry-browser/bundle.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bundle.min.js","sources":["../../types/src/index.ts","../../utils/src/is.ts","../../utils/src/misc.ts","../../utils/src/object.ts","../../hub/src/scope.ts","../../utils/src/logger.ts","../../hub/src/hub.ts","../../minimal/src/index.ts","../../core/src/error.ts","../../core/src/dsn.ts","../../core/src/api.ts","../../utils/src/string.ts","../../core/src/integration.ts","../../core/src/baseclient.ts","../../core/src/interfaces.ts","../../utils/src/async.ts","../../core/src/requestbuffer.ts","../../core/src/basebackend.ts","../../core/src/integrations/dedupe.ts","../../core/src/integrations/functiontostring.ts","../../core/src/integrations/sdkinformation.ts","../../core/src/integrations/inboundfilters.ts","../../utils/is.js","../../utils/misc.js","../../utils/logger.js","../../core/src/integrations/extraerrordata.ts","../../core/src/integrations/pluggable/debug.ts","../../utils/src/path.ts","../../core/src/integrations/pluggable/rewriteframes.ts","../../utils/src/supports.ts","../src/md5.ts","../src/tracekit.ts","../src/parsers.ts","../src/transports/base.ts","../src/integrations/helpers.ts","../src/transports/fetch.ts","../src/transports/xhr.ts","../src/transports/beacon.ts","../src/backend.ts","../src/version.ts","../src/client.ts","../src/integrations/globalhandlers.ts","../src/integrations/breadcrumbs.ts","../src/integrations/trycatch.ts","../src/integrations/linkederrors.ts","../src/integrations/pluggable/reportingobserver.ts","../src/integrations/useragent.ts","../src/integrations/pluggable/ember.ts","../src/integrations/pluggable/vue.ts","../src/sdk.ts","../src/index.ts","../../core/src/sdk.ts"],"sourcesContent":["/** Supported Sentry transport protocols in a Dsn. */\nexport type DsnProtocol = 'http' | 'https';\n\n/** Primitive components of a Dsn. */\nexport interface DsnComponents {\n /** Protocol used to connect to Sentry. */\n protocol: DsnProtocol;\n /** Public authorization key. */\n user: string;\n /** Private authorization key (deprecated, optional). */\n pass?: string;\n /** Hostname of the Sentry instance. */\n host: string;\n /** Port of the Sentry instance. */\n port?: string;\n /** Sub path/ */\n path?: string;\n /** Project ID */\n projectId: string;\n}\n\n/** Anything that can be parsed into a Dsn. */\nexport type DsnLike = string | DsnComponents;\n\n/** JSDoc */\nexport enum Severity {\n /** JSDoc */\n Fatal = 'fatal',\n /** JSDoc */\n Error = 'error',\n /** JSDoc */\n Warning = 'warning',\n /** JSDoc */\n Log = 'log',\n /** JSDoc */\n Info = 'info',\n /** JSDoc */\n Debug = 'debug',\n /** JSDoc */\n Critical = 'critical',\n}\n\n// tslint:disable:no-unnecessary-qualifier no-namespace\nexport namespace Severity {\n /**\n * Converts a string-based level into a {@link Severity}.\n *\n * @param level string representation of Severity\n * @returns Severity\n */\n export function fromString(level: string): Severity {\n switch (level) {\n case 'debug':\n return Severity.Debug;\n case 'info':\n return Severity.Info;\n case 'warn':\n case 'warning':\n return Severity.Warning;\n case 'error':\n return Severity.Error;\n case 'fatal':\n return Severity.Fatal;\n case 'critical':\n return Severity.Critical;\n case 'log':\n default:\n return Severity.Log;\n }\n }\n}\n\n/** JSDoc */\nexport interface Breadcrumb {\n type?: string;\n level?: Severity;\n event_id?: string;\n category?: string;\n message?: string;\n data?: any;\n timestamp?: number;\n}\n\n/** JSDoc */\nexport interface User {\n [key: string]: any;\n id?: string;\n ip_address?: string;\n email?: string;\n username?: string;\n}\n\n/** JSDoc */\nexport interface SdkInfo {\n name: string;\n version: string;\n integrations?: string[];\n packages?: Package[];\n}\n\n/** JSDoc */\nexport interface Package {\n name: string;\n version: string;\n}\n\n/** JSDoc */\nexport interface StackFrame {\n filename?: string;\n function?: string;\n module?: string;\n platform?: string;\n lineno?: number;\n colno?: number;\n abs_path?: string;\n context_line?: string;\n pre_context?: string[];\n post_context?: string[];\n in_app?: boolean;\n vars?: { [key: string]: any };\n}\n\n/** JSDoc */\nexport interface Stacktrace {\n frames?: StackFrame[];\n frames_omitted?: [number, number];\n}\n\n/** JSDoc */\nexport interface Thread {\n id?: number;\n name?: string;\n stacktrace?: Stacktrace;\n crashed?: boolean;\n current?: boolean;\n}\n\n/** JSDoc */\nexport interface SentryException {\n type?: string;\n value?: string;\n module?: string;\n thread_id?: number;\n stacktrace?: Stacktrace;\n}\n\n/** JSDoc */\nexport interface Request {\n url?: string;\n method?: string;\n data?: any;\n query_string?: string;\n cookies?: { [key: string]: string };\n env?: { [key: string]: string };\n headers?: { [key: string]: string };\n}\n\n/** JSDoc */\nexport interface SentryEvent {\n event_id?: string;\n message?: string;\n timestamp?: number;\n level?: Severity;\n platform?: string;\n logger?: string;\n server_name?: string;\n release?: string;\n dist?: string;\n environment?: string;\n sdk?: SdkInfo;\n request?: Request;\n transaction?: string;\n modules?: { [key: string]: string };\n fingerprint?: string[];\n exception?: {\n values?: SentryException[];\n mechanism?: Mechanism;\n };\n stacktrace?: Stacktrace;\n breadcrumbs?: Breadcrumb[];\n contexts?: { [key: string]: object };\n tags?: { [key: string]: string };\n extra?: { [key: string]: any };\n user?: User;\n}\n\n/** JSDoc */\nexport interface Mechanism {\n type: string;\n handled: boolean;\n data?: {\n [key: string]: string;\n };\n}\n\n/** Integration interface */\nexport interface Integration {\n /**\n * Returns {@link IntegrationClass.id}\n */\n name: string;\n // TODO: Remove with v5\n /** @deprecated */\n install?(options?: object): void;\n\n // This takes no options on purpose, options should be passed in the constructor\n setupOnce(): void; // TODO: make not optional\n}\n\n/** Integration Class Interface */\nexport interface IntegrationClass {\n new (): T;\n /**\n * Property that holds the integration name\n */\n id: string;\n}\n\n/** JSDoc */\nexport interface SentryResponse {\n status: Status;\n event?: SentryEvent;\n reason?: string;\n}\n\n/** JSDoc */\nexport interface TransportOptions {\n [key: string]: any;\n /** Sentry DSN */\n dsn: DsnLike;\n /** Define custom headers */\n headers?: object;\n /** Set a HTTP proxy that should be used for outbound requests. */\n httpProxy?: string;\n /** Set a HTTPS proxy that should be used for outbound requests. */\n httpsProxy?: string;\n /** HTTPS proxy certificates path */\n caCerts?: string;\n}\n\n/** JSDoc */\nexport interface Transport {\n captureEvent(event: SentryEvent): Promise;\n}\n\n/** JSDoc */\nexport interface TransportClass {\n new (options: TransportOptions): T;\n}\n\n/** The status of an event. */\nexport enum Status {\n /** The status could not be determined. */\n Unknown = 'unknown',\n /** The event was skipped due to configuration or callbacks. */\n Skipped = 'skipped',\n /** The event was sent to Sentry successfully. */\n Success = 'success',\n /** The client is currently rate limited and will try again later. */\n RateLimit = 'rate_limit',\n /** The event could not be processed. */\n Invalid = 'invalid',\n /** A server-side error ocurred during submission. */\n Failed = 'failed',\n}\n\n// tslint:disable:no-unnecessary-qualifier no-namespace\nexport namespace Status {\n /**\n * Converts a HTTP status code into a {@link Status}.\n *\n * @param code The HTTP response status code.\n * @returns The send status or {@link Status.Unknown}.\n */\n export function fromHttpCode(code: number): Status {\n if (code >= 200 && code < 300) {\n return Status.Success;\n }\n\n if (code === 429) {\n return Status.RateLimit;\n }\n\n if (code >= 400 && code < 500) {\n return Status.Invalid;\n }\n\n if (code >= 500) {\n return Status.Failed;\n }\n\n return Status.Unknown;\n }\n}\n\n/** JSDoc */\nexport interface SentryWrappedFunction extends Function {\n [key: string]: any;\n __sentry__?: boolean;\n __sentry_wrapped__?: SentryWrappedFunction;\n __sentry_original__?: SentryWrappedFunction;\n}\n\n/** JSDoc */\nexport interface SentryEventHint {\n event_id?: string;\n syntheticException?: Error | null;\n originalException?: Error | null;\n data?: any;\n}\n\n/** JSDoc */\nexport interface SentryBreadcrumbHint {\n [key: string]: any;\n}\n","/**\n * Checks whether given value's type is one of a few Error or Error-like\n * {@link isError}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nexport function isError(wat: any): boolean {\n switch (Object.prototype.toString.call(wat)) {\n case '[object Error]':\n return true;\n case '[object Exception]':\n return true;\n case '[object DOMException]':\n return true;\n default:\n return wat instanceof Error;\n }\n}\n\n/**\n * Checks whether given value's type is ErrorEvent\n * {@link isErrorEvent}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nexport function isErrorEvent(wat: any): boolean {\n return Object.prototype.toString.call(wat) === '[object ErrorEvent]';\n}\n\n/**\n * Checks whether given value's type is DOMError\n * {@link isDOMError}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nexport function isDOMError(wat: any): boolean {\n return Object.prototype.toString.call(wat) === '[object DOMError]';\n}\n\n/**\n * Checks whether given value's type is DOMException\n * {@link isDOMException}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nexport function isDOMException(wat: any): boolean {\n return Object.prototype.toString.call(wat) === '[object DOMException]';\n}\n\n/**\n * Checks whether given value's type is an undefined\n * {@link isUndefined}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nexport function isUndefined(wat: any): boolean {\n return wat === void 0;\n}\n\n/**\n * Checks whether given value's type is a function\n * {@link isFunction}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nexport function isFunction(wat: any): boolean {\n return typeof wat === 'function';\n}\n\n/**\n * Checks whether given value's type is a string\n * {@link isString}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nexport function isString(wat: any): boolean {\n return Object.prototype.toString.call(wat) === '[object String]';\n}\n\n/**\n * Checks whether given value's type is an array\n * {@link isArray}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nexport function isArray(wat: any): boolean {\n return Object.prototype.toString.call(wat) === '[object Array]';\n}\n\n/**\n * Checks whether given value's type is an object literal\n * {@link isPlainObject}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nexport function isPlainObject(wat: any): boolean {\n return Object.prototype.toString.call(wat) === '[object Object]';\n}\n\n/**\n * Checks whether given value's type is an regexp\n * {@link isRegExp}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nexport function isRegExp(wat: any): boolean {\n return Object.prototype.toString.call(wat) === '[object RegExp]';\n}\n\n/**\n * Checks whether given value's type is a NaN\n * {@link isNaN}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nexport function isNaN(wat: any): boolean {\n return wat !== wat;\n}\n","import { SentryEvent, SentryWrappedFunction } from '@sentry/types';\nimport { isString } from './is';\n\n/**\n * Requires a module which is protected against bundler minification.\n *\n * @param request The module path to resolve\n */\nexport function dynamicRequire(mod: NodeModule, request: string): any {\n return mod.require(request);\n}\n\n/**\n * Checks whether we're in the Node.js or Browser environment\n *\n * @returns Answer to given question\n */\nexport function isNodeEnv(): boolean {\n // tslint:disable:strict-type-predicates\n return Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]';\n}\n\n/**\n * Safely get global scope object\n *\n * @returns Global scope object\n */\n// tslint:disable:strict-type-predicates\nexport function getGlobalObject(): Window | NodeJS.Global | {} {\n return isNodeEnv() ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {};\n}\n// tslint:enable:strict-type-predicates\n\n/**\n * Extended Window interface that allows for Crypto API usage in IE browsers\n */\ninterface MsCryptoWindow extends Window {\n msCrypto?: Crypto;\n}\n\n/**\n * UUID4 generator\n *\n * @returns string Generated UUID4.\n */\nexport function uuid4(): string {\n const global = getGlobalObject() as MsCryptoWindow;\n const crypto = global.crypto || global.msCrypto;\n\n if (!(crypto === void 0) && crypto.getRandomValues) {\n // Use window.crypto API if available\n const arr = new Uint16Array(8);\n crypto.getRandomValues(arr);\n\n // set 4 in byte 7\n // tslint:disable-next-line:no-bitwise\n arr[3] = (arr[3] & 0xfff) | 0x4000;\n // set 2 most significant bits of byte 9 to '10'\n // tslint:disable-next-line:no-bitwise\n arr[4] = (arr[4] & 0x3fff) | 0x8000;\n\n const pad = (num: number): string => {\n let v = num.toString(16);\n while (v.length < 4) {\n v = `0${v}`;\n }\n return v;\n };\n\n return (\n pad(arr[0]) + pad(arr[1]) + pad(arr[2]) + pad(arr[3]) + pad(arr[4]) + pad(arr[5]) + pad(arr[6]) + pad(arr[7])\n );\n } else {\n // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523\n return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, c => {\n // tslint:disable-next-line:no-bitwise\n const r = (Math.random() * 16) | 0;\n // tslint:disable-next-line:no-bitwise\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n}\n\n/**\n * Given a child DOM element, returns a query-selector statement describing that\n * and its ancestors\n * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]\n * @returns generated DOM path\n */\nexport function htmlTreeAsString(elem: Node): string {\n let currentElem: Node | null = elem;\n const MAX_TRAVERSE_HEIGHT = 5;\n const MAX_OUTPUT_LEN = 80;\n const out = [];\n let height = 0;\n let len = 0;\n const separator = ' > ';\n const sepLength = separator.length;\n let nextStr;\n\n while (currentElem && height++ < MAX_TRAVERSE_HEIGHT) {\n nextStr = htmlElementAsString(currentElem as HTMLElement);\n // bail out if\n // - nextStr is the 'html' element\n // - the length of the string that would be created exceeds MAX_OUTPUT_LEN\n // (ignore this limit if we are on the first iteration)\n if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN)) {\n break;\n }\n\n out.push(nextStr);\n\n len += nextStr.length;\n currentElem = currentElem.parentNode;\n }\n\n return out.reverse().join(separator);\n}\n\n/**\n * Returns a simple, query-selector representation of a DOM element\n * e.g. [HTMLElement] => input#foo.btn[name=baz]\n * @returns generated DOM path\n */\nexport function htmlElementAsString(elem: HTMLElement): string {\n const out = [];\n let className;\n let classes;\n let key;\n let attr;\n let i;\n\n if (!elem || !elem.tagName) {\n return '';\n }\n\n out.push(elem.tagName.toLowerCase());\n if (elem.id) {\n out.push(`#${elem.id}`);\n }\n\n className = elem.className;\n if (className && isString(className)) {\n classes = className.split(/\\s+/);\n for (i = 0; i < classes.length; i++) {\n out.push(`.${classes[i]}`);\n }\n }\n const attrWhitelist = ['type', 'name', 'title', 'alt'];\n for (i = 0; i < attrWhitelist.length; i++) {\n key = attrWhitelist[i];\n attr = elem.getAttribute(key);\n if (attr) {\n out.push(`[${key}=\"${attr}\"]`);\n }\n }\n return out.join('');\n}\n\n/**\n * Parses string form of URL into an object\n * // borrowed from https://tools.ietf.org/html/rfc3986#appendix-B\n * // intentionally using regex and not href parsing trick because React Native and other\n * // environments where DOM might not be available\n * @returns parsed URL object\n */\nexport function parseUrl(\n url: string,\n): {\n host?: string;\n path?: string;\n protocol?: string;\n relative?: string;\n} {\n if (!url) {\n return {};\n }\n\n const match = url.match(/^(([^:\\/?#]+):)?(\\/\\/([^\\/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$/);\n\n if (!match) {\n return {};\n }\n\n // coerce to undefined values to empty string so we don't get 'undefined'\n const query = match[6] || '';\n const fragment = match[8] || '';\n return {\n host: match[4],\n path: match[5],\n protocol: match[2],\n relative: match[5] + query + fragment, // everything minus origin\n };\n}\n\n/**\n * Extracts either message or type+value from an event that can be used for user-facing logs\n * @returns event's description\n */\nexport function getEventDescription(event: SentryEvent): string {\n if (event.message) {\n return event.message;\n } else if (event.exception && event.exception.values && event.exception.values[0]) {\n const exception = event.exception.values[0];\n\n if (exception.type && exception.value) {\n return `${exception.type}: ${exception.value}`;\n } else {\n return exception.type || exception.value || event.event_id || '';\n }\n } else {\n return event.event_id || '';\n }\n}\n\n/** JSDoc */\ninterface ExtensibleConsole extends Console {\n [key: string]: any;\n}\n\n/** JSDoc */\nexport function consoleSandbox(callback: () => any): any {\n const global = getGlobalObject() as Window;\n const levels = ['debug', 'info', 'warn', 'error', 'log'];\n\n if (!('console' in global)) {\n return callback();\n }\n\n const originalConsole = global.console as ExtensibleConsole;\n const wrappedLevels: { [key: string]: any } = {};\n\n // Restore all wrapped console methods\n levels.forEach(level => {\n if (level in global.console && (originalConsole[level] as SentryWrappedFunction).__sentry__) {\n wrappedLevels[level] = (originalConsole[level] as SentryWrappedFunction).__sentry_wrapped__;\n originalConsole[level] = (originalConsole[level] as SentryWrappedFunction).__sentry_original__;\n }\n });\n\n // Perform callback manipulations\n const result = callback();\n\n // Revert restoration to wrapped state\n Object.keys(wrappedLevels).forEach(level => {\n originalConsole[level] = wrappedLevels[level];\n });\n\n return result;\n}\n","import { SentryWrappedFunction } from '@sentry/types';\nimport { isNaN, isPlainObject, isUndefined } from './is';\n\n/**\n * Just an Error object with arbitrary attributes attached to it.\n */\ninterface ExtendedError extends Error {\n [key: string]: any;\n}\n\n/**\n * Serializes the given object into a string.\n * Like JSON.stringify, but doesn't throw on circular references.\n * Based on a `json-stringify-safe` package and modified to handle Errors serialization.\n *\n * The object must be serializable, i.e.:\n * - Only primitive types are allowed (object, array, number, string, boolean)\n * - Its depth should be considerably low for performance reasons\n *\n * @param object A JSON-serializable object.\n * @returns A string containing the serialized object.\n */\nexport function serialize(object: T): string {\n return JSON.stringify(object);\n}\n\n/**\n * Deserializes an object from a string previously serialized with\n * {@link serialize}.\n *\n * @param str A serialized object.\n * @returns The deserialized object.\n */\nexport function deserialize(str: string): T {\n return JSON.parse(str) as T;\n}\n\n/**\n * Creates a deep copy of the given object.\n *\n * The object must be serializable, i.e.:\n * - It must not contain any cycles\n * - Only primitive types are allowed (object, array, number, string, boolean)\n * - Its depth should be considerably low for performance reasons\n *\n * @param object A JSON-serializable object.\n * @returns The object clone.\n */\nexport function clone(object: T): T {\n return deserialize(serialize(object));\n}\n\n/**\n * Wrap a given object method with a higher-order function\n *\n * @param source An object that contains a method to be wrapped.\n * @param name A name of method to be wrapped.\n * @param replacement A function that should be used to wrap a given method.\n * @returns void\n */\n\nexport function fill(source: { [key: string]: any }, name: string, replacement: (...args: any[]) => any): void {\n if (!(name in source) || (source[name] as SentryWrappedFunction).__sentry__) {\n return;\n }\n const original = source[name] as () => any;\n const wrapped = replacement(original) as SentryWrappedFunction;\n wrapped.__sentry__ = true;\n wrapped.__sentry_original__ = original;\n wrapped.__sentry_wrapped__ = wrapped;\n source[name] = wrapped;\n}\n\n/**\n * Encodes given object into url-friendly format\n *\n * @param object An object that contains serializable values\n * @returns string Encoded\n */\nexport function urlEncode(object: { [key: string]: any }): string {\n return Object.keys(object)\n .map(\n // tslint:disable-next-line:no-unsafe-any\n key => `${encodeURIComponent(key)}=${encodeURIComponent(object[key])}`,\n )\n .join('&');\n}\n\n// Default Node.js REPL depth\nconst MAX_SERIALIZE_EXCEPTION_DEPTH = 3;\n// 100kB, as 200kB is max payload size, so half sounds reasonable\nconst MAX_SERIALIZE_EXCEPTION_SIZE = 100 * 1024;\nconst MAX_SERIALIZE_KEYS_LENGTH = 40;\n\n/** JSDoc */\nfunction utf8Length(value: string): number {\n // tslint:disable-next-line:no-bitwise\n return ~-encodeURI(value).split(/%..|./).length;\n}\n\n/** JSDoc */\nfunction jsonSize(value: any): number {\n return utf8Length(JSON.stringify(value));\n}\n\n/** JSDoc */\nfunction serializeValue(value: T): T | string {\n const maxLength = 40;\n\n if (typeof value === 'string') {\n return value.length <= maxLength ? value : `${value.substr(0, maxLength - 1)}\\u2026`;\n } else if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'undefined') {\n return value;\n } else if (isNaN(value)) {\n // NaN and undefined are not JSON.parseable, but we want to preserve this information\n return '[NaN]';\n } else if (isUndefined(value)) {\n return '[undefined]';\n }\n\n const type = Object.prototype.toString.call(value);\n\n // Node.js REPL notation\n if (type === '[object Object]') {\n return '[Object]';\n }\n if (type === '[object Array]') {\n return '[Array]';\n }\n if (type === '[object Function]') {\n const name = ((value as any) as (() => void)).name;\n return name ? `[Function: ${name}]` : '[Function]';\n }\n\n return value;\n}\n\n/** JSDoc */\nexport function serializeObject(value: T, depth: number): T | string | {} {\n if (depth === 0) {\n return serializeValue(value);\n }\n\n if (isPlainObject(value)) {\n const serialized: { [key: string]: any } = {};\n const val = value as {\n [key: string]: any;\n };\n\n Object.keys(val).forEach((key: string) => {\n serialized[key] = serializeObject(val[key], depth - 1);\n });\n\n return serialized;\n } else if (Array.isArray(value)) {\n const val = (value as any) as T[];\n return val.map(v => serializeObject(v, depth - 1));\n }\n\n return serializeValue(value);\n}\n\n/** JSDoc */\nexport function limitObjectDepthToSize(\n object: { [key: string]: any },\n depth: number = MAX_SERIALIZE_EXCEPTION_DEPTH,\n maxSize: number = MAX_SERIALIZE_EXCEPTION_SIZE,\n): T {\n const serialized = serializeObject(object, depth);\n\n if (jsonSize(serialize(serialized)) > maxSize) {\n return limitObjectDepthToSize(object, depth - 1);\n }\n\n return serialized as T;\n}\n\n/** JSDoc */\nexport function serializeKeysToEventMessage(keys: string[], maxLength: number = MAX_SERIALIZE_KEYS_LENGTH): string {\n if (!keys.length) {\n return '[object has no keys]';\n }\n\n if (keys[0].length >= maxLength) {\n return keys[0];\n }\n\n for (let includedKeys = keys.length; includedKeys > 0; includedKeys--) {\n const serialized = keys.slice(0, includedKeys).join(', ');\n if (serialized.length > maxLength) {\n continue;\n }\n if (includedKeys === keys.length) {\n return serialized;\n }\n return `${serialized}\\u2026`;\n }\n\n return '';\n}\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill\n/** JSDoc */\nexport function assign(target: any, ...args: any[]): object {\n if (target === null || target === undefined) {\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n const to = Object(target) as {\n [key: string]: any;\n };\n\n // tslint:disable-next-line\n for (let i = 0; i < args.length; i++) {\n const source = args[i];\n if (source !== null) {\n for (const nextKey in source as {\n [key: string]: any;\n }) {\n if (Object.prototype.hasOwnProperty.call(source, nextKey)) {\n to[nextKey] = (source as {\n [key: string]: any;\n })[nextKey];\n }\n }\n }\n }\n\n return to;\n}\n\n/**\n * Transforms Error object into an object literal with all it's attributes\n * attached to it.\n *\n * Based on: https://github.com/ftlabs/js-abbreviate/blob/fa709e5f139e7770a71827b1893f22418097fbda/index.js#L95-L106\n *\n * @param error An Error containing all relevant information\n * @returns An object with all error properties\n */\nfunction objectifyError(error: ExtendedError): object {\n // These properties are implemented as magical getters and don't show up in `for-in` loop\n const err: {\n stack: string | undefined;\n message: string;\n name: string;\n [key: string]: any;\n } = {\n message: error.message,\n name: error.name,\n stack: error.stack,\n };\n\n for (const i in error) {\n if (Object.prototype.hasOwnProperty.call(error, i)) {\n err[i] = error[i];\n }\n }\n\n return err;\n}\n\n/**\n * standardizeValue()\n *\n * translates undefined/NaN values to \"[undefined]\"/\"[NaN]\" respectively,\n * serializes Error objects\n * filter global objects\n */\nfunction standardizeValue(value: any, key: any): any {\n if (key === 'domain' && typeof value === 'object' && (value as { _events: any })._events) {\n return '[Domain]';\n }\n\n if (key === 'domainEmitter') {\n return '[DomainEmitter]';\n }\n\n if (typeof (global as any) !== 'undefined' && value === global) {\n return '[Global]';\n }\n\n if (typeof (window as any) !== 'undefined' && value === window) {\n return '[Window]';\n }\n\n if (typeof (document as any) !== 'undefined' && value === document) {\n return '[Document]';\n }\n\n if (value instanceof Date) {\n return `[Date] ${value}`;\n }\n\n if (value instanceof Error) {\n return objectifyError(value);\n }\n\n if (isNaN(value)) {\n return '[NaN]';\n }\n\n if (isUndefined(value)) {\n return '[undefined]';\n }\n\n if (typeof value === 'function') {\n return `[Function] ${(value as () => void).name || ''}`;\n }\n\n return value;\n}\n\n/**\n * standardizer()\n *\n * Remove circular references,\n * translates undefined/NaN values to \"[undefined]\"/\"[NaN]\" respectively,\n * and takes care of Error objects serialization\n */\nfunction standardizer(): (key: string, value: any) => any {\n const stack: any[] = [];\n const keys: string[] = [];\n\n /** recursive */\n function cycleStandardizer(_key: string, value: any): any {\n if (stack[0] === value) {\n return '[Circular ~]';\n }\n return `[Circular ~.${keys.slice(0, stack.indexOf(value)).join('.')}]`;\n }\n\n return function(this: any, key: string, value: any): any {\n if (stack.length > 0) {\n const thisPos = stack.indexOf(this);\n\n if (thisPos === -1) {\n stack.push(this);\n keys.push(key);\n } else {\n stack.splice(thisPos + 1);\n keys.splice(thisPos, Infinity, key);\n }\n\n if (stack.indexOf(value) !== -1) {\n // tslint:disable-next-line:no-parameter-reassignment\n value = cycleStandardizer.call(this, key, value);\n }\n } else {\n stack.push(value);\n }\n\n return standardizeValue(value, key);\n };\n}\n\n/**\n * safeNormalize()\n *\n * Creates a copy of the input by applying standardizer function on it and parsing it back to unify the data\n */\nexport function safeNormalize(input: any): any {\n try {\n return JSON.parse(JSON.stringify(input, standardizer()));\n } catch (_oO) {\n return '**non-serializable**';\n }\n}\n","import { Breadcrumb, SentryEvent, SentryEventHint, Severity, User } from '@sentry/types';\nimport { getGlobalObject } from '@sentry/utils/misc';\nimport { assign, safeNormalize } from '@sentry/utils/object';\n\nexport type EventProcessor = (event: SentryEvent, hint?: SentryEventHint) => Promise;\n\n/**\n * Holds additional event information. {@link Scope.applyToEvent} will be\n * called by the client before an event will be sent.\n */\nexport class Scope {\n /** Flag if notifiying is happening. */\n protected notifyingListeners: boolean = false;\n\n /** Callback for client to receive scope changes. */\n protected scopeListeners: Array<(scope: Scope) => void> = [];\n\n /** Callback list that will be called after {@link applyToEvent}. */\n protected eventProcessors: EventProcessor[] = [];\n\n /** Array of breadcrumbs. */\n protected breadcrumbs: Breadcrumb[] = [];\n\n /** User */\n protected user: User = {};\n\n /** Tags */\n protected tags: { [key: string]: string } = {};\n\n /** Extra */\n protected extra: { [key: string]: any } = {};\n\n /** Fingerprint */\n protected fingerprint?: string[];\n\n /** Severity */\n protected level?: Severity;\n\n /** Add internal on change listener. */\n public addScopeListener(callback: (scope: Scope) => void): void {\n this.scopeListeners.push(callback);\n }\n\n /** Add new event processor that will be called after {@link applyToEvent}. */\n public addEventProcessor(callback: EventProcessor): Scope {\n this.eventProcessors.push(callback);\n return this;\n }\n\n /**\n * This will be called on every set call.\n */\n protected notifyScopeListeners(): void {\n if (!this.notifyingListeners) {\n this.notifyingListeners = true;\n setTimeout(() => {\n this.scopeListeners.forEach(callback => {\n callback(this);\n });\n this.notifyingListeners = false;\n }, 0);\n }\n }\n\n /**\n * This will be called after {@link applyToEvent} is finished.\n */\n protected async notifyEventProcessors(event: SentryEvent, hint?: SentryEventHint): Promise {\n let processedEvent: SentryEvent | null = event;\n for (const processor of [...getGlobalEventProcessors(), ...this.eventProcessors]) {\n try {\n processedEvent = await processor({ ...processedEvent }, hint);\n if (processedEvent === null) {\n return null;\n }\n } catch (e) {\n continue;\n }\n }\n return processedEvent;\n }\n\n /**\n * Updates user context information for future events.\n * @param user User context object to merge into current context.\n */\n public setUser(user: User): Scope {\n this.user = safeNormalize(user);\n this.notifyScopeListeners();\n return this;\n }\n\n /**\n * Updates tags context information for future events.\n * @param tags Tags context object to merge into current context.\n */\n public setTag(key: string, value: string): Scope {\n this.tags = { ...this.tags, [key]: safeNormalize(value) };\n this.notifyScopeListeners();\n return this;\n }\n\n /**\n * Updates extra context information for future events.\n * @param extra context object to merge into current context.\n */\n public setExtra(key: string, extra: any): Scope {\n this.extra = { ...this.extra, [key]: safeNormalize(extra) };\n this.notifyScopeListeners();\n return this;\n }\n\n /**\n * Sets the fingerprint on the scope to send with the events.\n * @param fingerprint string[] to group events in Sentry.\n */\n public setFingerprint(fingerprint: string[]): Scope {\n this.fingerprint = safeNormalize(fingerprint);\n this.notifyScopeListeners();\n return this;\n }\n\n /**\n * Sets the level on the scope for future events.\n * @param level string {@link Severity}\n */\n public setLevel(level: Severity): Scope {\n this.level = safeNormalize(level);\n this.notifyScopeListeners();\n return this;\n }\n\n /**\n * Inherit values from the parent scope.\n * @param scope to clone.\n */\n public static clone(scope?: Scope): Scope {\n const newScope = new Scope();\n assign(newScope, scope, {\n scopeListeners: [],\n });\n if (scope) {\n newScope.extra = assign(scope.extra);\n newScope.tags = assign(scope.tags) as any;\n newScope.breadcrumbs = [...scope.breadcrumbs];\n newScope.eventProcessors = [...scope.eventProcessors];\n }\n return newScope;\n }\n\n /** Clears the current scope and resets its properties. */\n public clear(): void {\n this.breadcrumbs = [];\n this.tags = {};\n this.extra = {};\n this.user = {};\n this.level = undefined;\n this.fingerprint = undefined;\n this.notifyScopeListeners();\n }\n\n /**\n * Sets the breadcrumbs in the scope\n * @param breadcrumbs Breadcrumb\n * @param maxBreadcrumbs number of max breadcrumbs to merged into event.\n */\n public addBreadcrumb(breadcrumb: Breadcrumb, maxBreadcrumbs?: number): void {\n this.breadcrumbs =\n maxBreadcrumbs !== undefined && maxBreadcrumbs >= 0\n ? [...this.breadcrumbs, safeNormalize(breadcrumb)].slice(-maxBreadcrumbs)\n : [...this.breadcrumbs, safeNormalize(breadcrumb)];\n this.notifyScopeListeners();\n }\n\n /**\n * Applies fingerprint from the scope to the event if there's one,\n * uses message if there's one instead or get rid of empty fingerprint\n */\n private applyFingerprint(event: SentryEvent): void {\n // Make sure it's an array first and we actually have something in place\n event.fingerprint = event.fingerprint\n ? Array.isArray(event.fingerprint)\n ? event.fingerprint\n : [event.fingerprint]\n : [];\n\n // If we have something on the scope, then merge it with event\n if (this.fingerprint) {\n event.fingerprint = event.fingerprint.concat(this.fingerprint);\n } else if (event.message) {\n // If not, but we have message, use it instead\n event.fingerprint = event.fingerprint.concat(event.message);\n }\n\n // If we have no data at all, remove empty array default\n if (event.fingerprint && !event.fingerprint.length) {\n delete event.fingerprint;\n }\n }\n\n /**\n * Applies the current context and fingerprint to the event.\n * Note that breadcrumbs will be added by the client.\n * Also if the event has already breadcrumbs on it, we do not merge them.\n * @param event SentryEvent\n * @param hint May contain additional informartion about the original exception.\n * @param maxBreadcrumbs number of max breadcrumbs to merged into event.\n */\n public async applyToEvent(\n event: SentryEvent,\n hint?: SentryEventHint,\n maxBreadcrumbs?: number,\n ): Promise {\n if (this.extra && Object.keys(this.extra).length) {\n event.extra = { ...this.extra, ...event.extra };\n }\n if (this.tags && Object.keys(this.tags).length) {\n event.tags = { ...this.tags, ...event.tags };\n }\n if (this.user && Object.keys(this.user).length) {\n event.user = { ...this.user, ...event.user };\n }\n if (this.level) {\n event.level = this.level;\n }\n\n this.applyFingerprint(event);\n\n const hasNoBreadcrumbs = !event.breadcrumbs || event.breadcrumbs.length === 0;\n if (hasNoBreadcrumbs && this.breadcrumbs.length > 0) {\n event.breadcrumbs =\n maxBreadcrumbs !== undefined && maxBreadcrumbs >= 0\n ? this.breadcrumbs.slice(-maxBreadcrumbs)\n : this.breadcrumbs;\n }\n\n return this.notifyEventProcessors(event, hint);\n }\n}\n\n/**\n * Retruns the global event processors.\n */\nfunction getGlobalEventProcessors(): EventProcessor[] {\n const global: any = getGlobalObject();\n global.__SENTRY__ = global.__SENTRY__ || {};\n global.__SENTRY__.globalEventProcessors = global.__SENTRY__.globalEventProcessors || [];\n return global.__SENTRY__.globalEventProcessors;\n}\n\n/**\n * Add a EventProcessor to be kept globally.\n * @param callback EventProcessor to add\n */\nexport function addGlobalEventProcessor(callback: EventProcessor): void {\n getGlobalEventProcessors().push(callback);\n}\n","import { consoleSandbox, getGlobalObject } from './misc';\n\n// TODO: Implement different loggers for different environments\nconst global = getGlobalObject() as Window;\n\n/** JSDoc */\nclass Logger {\n /** JSDoc */\n private enabled: boolean;\n\n /** JSDoc */\n public constructor() {\n this.enabled = false;\n }\n\n /** JSDoc */\n public disable(): void {\n this.enabled = false;\n }\n\n /** JSDoc */\n public enable(): void {\n this.enabled = true;\n }\n\n /** JSDoc */\n public log(...args: any[]): void {\n if (!this.enabled) {\n return;\n }\n consoleSandbox(() => {\n global.console.log(`Sentry Logger [Log]: ${args.join(' ')}`); // tslint:disable-line:no-console\n });\n }\n\n /** JSDoc */\n public warn(...args: any[]): void {\n if (!this.enabled) {\n return;\n }\n consoleSandbox(() => {\n global.console.warn(`Sentry Logger [Warn]: ${args.join(' ')}`); // tslint:disable-line:no-console\n });\n }\n\n /** JSDoc */\n public error(...args: any[]): void {\n if (!this.enabled) {\n return;\n }\n consoleSandbox(() => {\n global.console.error(`Sentry Logger [Error]: ${args.join(' ')}`); // tslint:disable-line:no-console\n });\n }\n}\n\nconst logger = new Logger();\n\nexport { logger };\n","import {\n Breadcrumb,\n Integration,\n IntegrationClass,\n SentryBreadcrumbHint,\n SentryEvent,\n SentryEventHint,\n Severity,\n} from '@sentry/types';\nimport { logger } from '@sentry/utils/logger';\nimport { dynamicRequire, getGlobalObject, uuid4 } from '@sentry/utils/misc';\nimport { Carrier, Layer } from './interfaces';\nimport { Scope } from './scope';\n\ndeclare module 'domain' {\n export let active: Domain;\n /**\n * Extension for domain interface\n */\n export interface Domain {\n __SENTRY__?: Carrier;\n }\n}\n\n/**\n * API compatibility version of this hub.\n *\n * WARNING: This number should only be incresed when the global interface\n * changes a and new methods are introduced.\n */\nexport const API_VERSION = 3;\n\n/**\n * Internal class used to make sure we always have the latest internal functions\n * working in case we have a version conflict.\n */\nexport class Hub {\n /** Is a {@link Layer}[] containing the client and scope */\n private readonly stack: Layer[] = [];\n\n /** Contains the last event id of a captured event. */\n private _lastEventId?: string;\n\n /**\n * Creates a new instance of the hub, will push one {@link Layer} into the\n * internal stack on creation.\n *\n * @param client bound to the hub.\n * @param scope bound to the hub.\n * @param version number, higher number means higher priority.\n */\n public constructor(client?: any, scope: Scope = new Scope(), private readonly version: number = API_VERSION) {\n this.stack.push({ client, scope });\n }\n\n /**\n * Internal helper function to call a method on the top client if it exists.\n *\n * @param method The method to call on the client/client.\n * @param args Arguments to pass to the client/frontend.\n */\n private invokeClient(method: string, ...args: any[]): void {\n const top = this.getStackTop();\n if (top && top.client && top.client[method]) {\n top.client[method](...args, top.scope);\n }\n }\n\n /**\n * Internal helper function to call an async method on the top client if it\n * exists.\n *\n * @param method The method to call on the client/client.\n * @param args Arguments to pass to the client/frontend.\n */\n private invokeClientAsync(method: string, ...args: any[]): void {\n const top = this.getStackTop();\n if (top && top.client && top.client[method]) {\n top.client[method](...args, top.scope).catch((err: any) => {\n logger.error(err);\n });\n }\n }\n\n /**\n * Checks if this hub's version is older than the given version.\n *\n * @param version A version number to compare to.\n * @return True if the given version is newer; otherwise false.\n */\n public isOlderThan(version: number): boolean {\n return this.version < version;\n }\n\n /**\n * This binds the given client to the current scope.\n * @param client An SDK client (client) instance.\n */\n public bindClient(client?: any): void {\n const top = this.getStackTop();\n top.client = client;\n if (top && top.scope && client) {\n top.scope.addScopeListener((s: Scope) => {\n if (client.getBackend) {\n try {\n client.getBackend().storeScope(s);\n } catch {\n // Do nothing\n }\n }\n });\n }\n }\n\n /**\n * Create a new scope to store context information.\n *\n * The scope will be layered on top of the current one. It is isolated, i.e. all\n * breadcrumbs and context information added to this scope will be removed once\n * the scope ends. Be sure to always remove this scope with {@link this.popScope}\n * when the operation finishes or throws.\n *\n * @returns Scope, the new cloned scope\n */\n public pushScope(): Scope {\n // We want to clone the content of prev scope\n const stack = this.getStack();\n const parentScope = stack.length > 0 ? stack[stack.length - 1].scope : undefined;\n const scope = Scope.clone(parentScope);\n this.getStack().push({\n client: this.getClient(),\n scope,\n });\n return scope;\n }\n\n /**\n * Removes a previously pushed scope from the stack.\n *\n * This restores the state before the scope was pushed. All breadcrumbs and\n * context information added since the last call to {@link this.pushScope} are\n * discarded.\n */\n public popScope(): boolean {\n return this.getStack().pop() !== undefined;\n }\n\n /**\n * Creates a new scope with and executes the given operation within.\n * The scope is automatically removed once the operation\n * finishes or throws.\n *\n * This is essentially a convenience function for:\n *\n * pushScope();\n * callback();\n * popScope();\n *\n * @param callback that will be enclosed into push/popScope.\n */\n public withScope(callback: ((scope: Scope) => void)): void {\n const scope = this.pushScope();\n try {\n callback(scope);\n } finally {\n this.popScope();\n }\n }\n\n /** Returns the client of the top stack. */\n public getClient(): any | undefined {\n return this.getStackTop().client;\n }\n\n /** Returns the scope of the top stack. */\n public getScope(): Scope | undefined {\n return this.getStackTop().scope;\n }\n\n /** Returns the scope stack for domains or the process. */\n public getStack(): Layer[] {\n return this.stack;\n }\n\n /** Returns the topmost scope layer in the order domain > local > process. */\n public getStackTop(): Layer {\n return this.stack[this.stack.length - 1];\n }\n\n /**\n * Captures an exception event and sends it to Sentry.\n *\n * @param exception An exception-like object.\n * @param hint May contain additional information about the original exception.\n * @returns The generated eventId.\n */\n public captureException(exception: any, hint?: SentryEventHint): string {\n const eventId = (this._lastEventId = uuid4());\n this.invokeClientAsync('captureException', exception, {\n ...hint,\n event_id: eventId,\n });\n return eventId;\n }\n\n /**\n * Captures a message event and sends it to Sentry.\n *\n * @param message The message to send to Sentry.\n * @param level Define the level of the message.\n * @param hint May contain additional information about the original exception.\n * @returns The generated eventId.\n */\n public captureMessage(message: string, level?: Severity, hint?: SentryEventHint): string {\n const eventId = (this._lastEventId = uuid4());\n this.invokeClientAsync('captureMessage', message, level, {\n ...hint,\n event_id: eventId,\n });\n return eventId;\n }\n\n /**\n * Captures a manually created event and sends it to Sentry.\n *\n * @param event The event to send to Sentry.\n * @param hint May contain additional information about the original exception.\n */\n public captureEvent(event: SentryEvent, hint?: SentryEventHint): string {\n const eventId = (this._lastEventId = uuid4());\n this.invokeClientAsync('captureEvent', event, {\n ...hint,\n event_id: eventId,\n });\n return eventId;\n }\n\n /**\n * This is the getter for lastEventId.\n *\n * @returns The last event id of a captured event.\n */\n public lastEventId(): string | undefined {\n return this._lastEventId;\n }\n\n /**\n * Records a new breadcrumb which will be attached to future events.\n *\n * Breadcrumbs will be added to subsequent events to provide more context on\n * user's actions prior to an error or crash.\n *\n * @param breadcrumb The breadcrumb to record.\n * @param hint May contain additional information about the original breadcrumb.\n */\n public addBreadcrumb(breadcrumb: Breadcrumb, hint?: SentryBreadcrumbHint): void {\n this.invokeClient('addBreadcrumb', breadcrumb, { ...hint });\n }\n\n /**\n * Callback to set context information onto the scope.\n *\n * @param callback Callback function that receives Scope.\n */\n public configureScope(callback: (scope: Scope) => void): void {\n const top = this.getStackTop();\n if (top.scope && top.client) {\n // TODO: freeze flag\n callback(top.scope);\n }\n }\n\n /**\n * For the duraction of the callback, this hub will be set as the global current Hub.\n * This function is useful if you want to run your own client and hook into an already initialized one\n * e.g.: Reporting issues to your own sentry when running in your component while still using the users configuration.\n */\n public run(callback: ((hub: Hub) => void)): void {\n const oldHub = makeMain(this);\n try {\n callback(this);\n } finally {\n makeMain(oldHub);\n }\n }\n\n /** Returns the integration if installed on the current client. */\n public getIntegration(integration: IntegrationClass): T | null {\n try {\n return this.getClient().getIntegration(integration);\n } catch (_oO) {\n logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`);\n return null;\n }\n }\n}\n\n/** Returns the global shim registry. */\nexport function getMainCarrier(): Carrier {\n const carrier: any = getGlobalObject();\n carrier.__SENTRY__ = carrier.__SENTRY__ || {\n hub: undefined,\n };\n return carrier;\n}\n\n/**\n * Replaces the current main hub with the passed one on the global object\n *\n * @returns The old replaced hub\n */\nexport function makeMain(hub: Hub): Hub {\n const registry = getMainCarrier();\n const oldHub = getHubFromCarrier(registry);\n setHubOnCarrier(registry, hub);\n return oldHub;\n}\n\n/**\n * Returns the default hub instance.\n *\n * If a hub is already registered in the global carrier but this module\n * contains a more recent version, it replaces the registered version.\n * Otherwise, the currently registered hub will be returned.\n */\nexport function getCurrentHub(): Hub {\n // Get main carrier (global for every environment)\n const registry = getMainCarrier();\n\n // If there's no hub, or its an old API, assign a new one\n if (!hasHubOnCarrier(registry) || getHubFromCarrier(registry).isOlderThan(API_VERSION)) {\n setHubOnCarrier(registry, new Hub());\n }\n\n // Prefer domains over global if they are there\n try {\n // We need to use `dynamicRequire` because `require` on it's own will be optimized by webpack.\n // We do not want this to happen, we need to try to `require` the domain node module and fail if we are in browser\n // for example so we do not have to shim it and use `getCurrentHub` universally.\n const domain = dynamicRequire(module, 'domain');\n const activeDomain = domain.active;\n\n // If there no active domain, just return global hub\n if (!activeDomain) {\n return getHubFromCarrier(registry);\n }\n\n // If there's no hub on current domain, or its an old API, assign a new one\n if (!hasHubOnCarrier(activeDomain) || getHubFromCarrier(activeDomain).isOlderThan(API_VERSION)) {\n const registryHubTopStack = getHubFromCarrier(registry).getStackTop();\n setHubOnCarrier(activeDomain, new Hub(registryHubTopStack.client, Scope.clone(registryHubTopStack.scope)));\n }\n\n // Return hub that lives on a domain\n return getHubFromCarrier(activeDomain);\n } catch (_Oo) {\n // Return hub that lives on a global object\n return getHubFromCarrier(registry);\n }\n}\n\n/**\n * This will tell whether a carrier has a hub on it or not\n * @param carrier object\n */\nexport function hasHubOnCarrier(carrier: any): boolean {\n if (carrier && carrier.__SENTRY__ && carrier.__SENTRY__.hub) {\n return true;\n } else {\n return false;\n }\n}\n\n/**\n * This will create a new {@link Hub} and add to the passed object on\n * __SENTRY__.hub.\n * @param carrier object\n */\nexport function getHubFromCarrier(carrier: any): Hub {\n if (carrier && carrier.__SENTRY__ && carrier.__SENTRY__.hub) {\n return carrier.__SENTRY__.hub;\n } else {\n carrier.__SENTRY__ = {};\n carrier.__SENTRY__.hub = new Hub();\n return carrier.__SENTRY__.hub;\n }\n}\n\n/**\n * This will set passed {@link Hub} on the passed object's __SENTRY__.hub attribute\n * @param carrier object\n * @param hub Hub\n */\nexport function setHubOnCarrier(carrier: any, hub: Hub): boolean {\n if (!carrier) {\n return false;\n }\n carrier.__SENTRY__ = carrier.__SENTRY__ || {};\n carrier.__SENTRY__.hub = hub;\n return true;\n}\n","import { getCurrentHub, Hub, Scope } from '@sentry/hub';\nimport { Breadcrumb, SentryEvent, Severity } from '@sentry/types';\n\n/**\n * This calls a function on the current hub.\n * @param method function to call on hub.\n * @param args to pass to function.\n */\nfunction callOnHub(method: string, ...args: any[]): T {\n const hub = getCurrentHub();\n if (hub && hub[method as keyof Hub]) {\n // tslint:disable-next-line:no-unsafe-any\n return (hub[method as keyof Hub] as any)(...args);\n }\n throw new Error(`No hub defined or ${method} was not found on the hub, please open a bug report.`);\n}\n\n/**\n * Captures an exception event and sends it to Sentry.\n *\n * @param exception An exception-like object.\n * @returns The generated eventId.\n */\nexport function captureException(exception: any): string {\n let syntheticException: Error;\n try {\n throw new Error('Sentry syntheticException');\n } catch (exception) {\n syntheticException = exception as Error;\n }\n return callOnHub('captureException', exception, {\n originalException: exception,\n syntheticException,\n });\n}\n\n/**\n * Captures a message event and sends it to Sentry.\n *\n * @param message The message to send to Sentry.\n * @param level Define the level of the message.\n * @returns The generated eventId.\n */\nexport function captureMessage(message: string, level?: Severity): string {\n let syntheticException: Error;\n try {\n throw new Error(message);\n } catch (exception) {\n syntheticException = exception as Error;\n }\n return callOnHub('captureMessage', message, level, {\n originalException: message,\n syntheticException,\n });\n}\n\n/**\n * Captures a manually created event and sends it to Sentry.\n *\n * @param event The event to send to Sentry.\n * @returns The generated eventId.\n */\nexport function captureEvent(event: SentryEvent): string {\n return callOnHub('captureEvent', event);\n}\n\n/**\n * Records a new breadcrumb which will be attached to future events.\n *\n * Breadcrumbs will be added to subsequent events to provide more context on\n * user's actions prior to an error or crash.\n *\n * @param breadcrumb The breadcrumb to record.\n */\nexport function addBreadcrumb(breadcrumb: Breadcrumb): void {\n callOnHub('addBreadcrumb', breadcrumb);\n}\n\n/**\n * Callback to set context information onto the scope.\n * @param callback Callback function that receives Scope.\n */\nexport function configureScope(callback: (scope: Scope) => void): void {\n callOnHub('configureScope', callback);\n}\n\n/**\n * Creates a new scope with and executes the given operation within.\n * The scope is automatically removed once the operation\n * finishes or throws.\n *\n * This is essentially a convenience function for:\n *\n * pushScope();\n * callback();\n * popScope();\n *\n * @param callback that will be enclosed into push/popScope.\n */\nexport function withScope(callback: ((scope: Scope) => void)): void {\n callOnHub('withScope', callback);\n}\n\n/**\n * Calls a function on the latest client. Use this with caution, it's meant as\n * in \"internal\" helper so we don't need to expose every possible function in\n * the shim. It is not guaranteed that the client actually implements the\n * function.\n *\n * @param method The method to call on the client/client.\n * @param args Arguments to pass to the client/fontend.\n */\nexport function _callOnClient(method: string, ...args: any[]): void {\n callOnHub('invokeClient', method, ...args);\n}\n","/** An error emitted by Sentry SDKs and related utilities. */\nexport class SentryError extends Error {\n /** Display name of this error instance. */\n public name: string;\n\n public constructor(public message: string) {\n super(message);\n\n // tslint:disable:no-unsafe-any\n this.name = new.target.prototype.constructor.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import { DsnComponents, DsnLike, DsnProtocol } from '@sentry/types';\nimport { isNaN } from '@sentry/utils/is';\nimport { assign } from '@sentry/utils/object';\nimport { SentryError } from './error';\n\n/** Regular expression used to parse a Dsn. */\nconst DSN_REGEX = /^(?:(\\w+):)\\/\\/(?:(\\w+)(?::(\\w+))?@)([\\w\\.-]+)(?::(\\d+))?\\/(.+)/;\n\n/** The Sentry Dsn, identifying a Sentry instance and project. */\nexport class Dsn implements DsnComponents {\n /** Protocol used to connect to Sentry. */\n public protocol!: DsnProtocol;\n /** Public authorization key. */\n public user!: string;\n /** Private authorization key (deprecated, optional). */\n public pass!: string;\n /** Hostname of the Sentry instance. */\n public host!: string;\n /** Port of the Sentry instance. */\n public port!: string;\n /** Path */\n public path!: string;\n /** Project ID */\n public projectId!: string;\n\n /** Creates a new Dsn component */\n public constructor(from: DsnLike) {\n if (typeof from === 'string') {\n this.fromString(from);\n } else {\n this.fromComponents(from);\n }\n\n this.validate();\n }\n\n /**\n * Renders the string representation of this Dsn.\n *\n * By default, this will render the public representation without the password\n * component. To get the deprecated private representation, set `withPassword`\n * to true.\n *\n * @param withPassword When set to true, the password will be included.\n */\n public toString(withPassword: boolean = false): string {\n // tslint:disable-next-line:no-this-assignment\n const { host, path, pass, port, projectId, protocol, user } = this;\n return (\n `${protocol}://${user}${withPassword && pass ? `:${pass}` : ''}` +\n `@${host}${port ? `:${port}` : ''}/${path ? `${path}/` : path}${projectId}`\n );\n }\n\n /** Parses a string into this Dsn. */\n private fromString(str: string): void {\n const match = DSN_REGEX.exec(str);\n if (!match) {\n throw new SentryError('Invalid Dsn');\n }\n\n const [protocol, user, pass = '', host, port = '', lastPath] = match.slice(1);\n let path = '';\n let projectId = lastPath;\n const split = projectId.split('/');\n if (split.length > 1) {\n path = split.slice(0, -1).join('/');\n projectId = split.pop() as string;\n }\n assign(this, { host, pass, path, projectId, port, protocol, user });\n }\n\n /** Maps Dsn components into this instance. */\n private fromComponents(components: DsnComponents): void {\n this.protocol = components.protocol;\n this.user = components.user;\n this.pass = components.pass || '';\n this.host = components.host;\n this.port = components.port || '';\n this.path = components.path || '';\n this.projectId = components.projectId;\n }\n\n /** Validates this Dsn and throws on error. */\n private validate(): void {\n for (const component of ['protocol', 'user', 'host', 'projectId']) {\n if (!this[component as keyof DsnComponents]) {\n throw new SentryError(`Invalid Dsn: Missing ${component}`);\n }\n }\n\n if (this.protocol !== 'http' && this.protocol !== 'https') {\n throw new SentryError(`Invalid Dsn: Unsupported protocol \"${this.protocol}\"`);\n }\n\n if (this.port && isNaN(parseInt(this.port, 10))) {\n throw new SentryError(`Invalid Dsn: Invalid port number \"${this.port}\"`);\n }\n }\n}\n","import { DsnLike } from '@sentry/types';\nimport { urlEncode } from '@sentry/utils/object';\nimport { Dsn } from './dsn';\n\nconst SENTRY_API_VERSION = '7';\n\n/** Helper class to provide urls to different Sentry endpoints. */\nexport class API {\n /** The internally used Dsn object. */\n private readonly dsnObject: Dsn;\n /** Create a new instance of API */\n public constructor(public dsn: DsnLike) {\n this.dsnObject = new Dsn(dsn);\n }\n\n /** Returns the Dsn object. */\n public getDsn(): Dsn {\n return this.dsnObject;\n }\n\n /** Returns a string with auth headers in the url to the store endpoint. */\n public getStoreEndpoint(): string {\n return `${this.getBaseUrl()}${this.getStoreEndpointPath()}`;\n }\n\n /** Returns the store endpoint with auth added in url encoded. */\n public getStoreEndpointWithUrlEncodedAuth(): string {\n const dsn = this.dsnObject;\n const auth = {\n sentry_key: dsn.user,\n sentry_version: SENTRY_API_VERSION,\n };\n // Auth is intentionally sent as part of query string (NOT as custom HTTP header)\n // to avoid preflight CORS requests\n return `${this.getStoreEndpoint()}?${urlEncode(auth)}`;\n }\n\n /** Returns the base path of the url including the port. */\n private getBaseUrl(): string {\n const dsn = this.dsnObject;\n const protocol = dsn.protocol ? `${dsn.protocol}:` : '';\n const port = dsn.port ? `:${dsn.port}` : '';\n return `${protocol}//${dsn.host}${port}`;\n }\n\n /** Returns only the path component for the store endpoint. */\n public getStoreEndpointPath(): string {\n const dsn = this.dsnObject;\n return `${dsn.path ? `/${dsn.path}` : ''}/api/${dsn.projectId}/store/`;\n }\n\n /** Returns an object that can be used in request headers. */\n public getRequestHeaders(clientName: string, clientVersion: string): { [key: string]: string } {\n const dsn = this.dsnObject;\n const header = [`Sentry sentry_version=${SENTRY_API_VERSION}`];\n header.push(`sentry_timestamp=${new Date().getTime()}`);\n header.push(`sentry_client=${clientName}/${clientVersion}`);\n header.push(`sentry_key=${dsn.user}`);\n if (dsn.pass) {\n header.push(`sentry_secret=${dsn.pass}`);\n }\n return {\n 'Content-Type': 'application/json',\n 'X-Sentry-Auth': header.join(', '),\n };\n }\n\n /** Returns the url to the report dialog endpoint. */\n public getReportDialogEndpoint(\n dialogOptions: {\n [key: string]: any;\n user?: { name?: string; email?: string };\n } = {},\n ): string {\n const dsn = this.dsnObject;\n const endpoint = `${this.getBaseUrl()}${dsn.path ? `/${dsn.path}` : ''}/api/embed/error-page/`;\n\n const encodedOptions = [];\n encodedOptions.push(`dsn=${dsn.toString()}`);\n for (const key in dialogOptions) {\n if (key === 'user') {\n if (!dialogOptions.user) {\n continue;\n }\n if (dialogOptions.user.name) {\n encodedOptions.push(`name=${encodeURIComponent(dialogOptions.user.name)}`);\n }\n if (dialogOptions.user.email) {\n encodedOptions.push(`email=${encodeURIComponent(dialogOptions.user.email)}`);\n }\n } else {\n encodedOptions.push(`${encodeURIComponent(key)}=${encodeURIComponent(dialogOptions[key] as string)}`);\n }\n }\n if (encodedOptions.length) {\n return `${endpoint}?${encodedOptions.join('&')}`;\n }\n\n return endpoint;\n }\n}\n","import { isString } from './is';\n\n/**\n * Encodes given object into url-friendly format\n *\n * @param str An object that contains serializable values\n * @param max Maximum number of characters in truncated string\n * @returns string Encoded\n */\n\nexport function truncate(str: string, max: number = 0): string {\n if (max === 0 || !isString(str)) {\n return str;\n }\n return str.length <= max ? str : `${str.substr(0, max)}\\u2026`;\n}\n\n/**\n * This is basically just `trim_line` from\n * https://github.com/getsentry/sentry/blob/master/src/sentry/lang/javascript/processor.py#L67\n *\n * @param str An object that contains serializable values\n * @param max Maximum number of characters in truncated string\n * @returns string Encoded\n */\n\nexport function snipLine(line: string, colno: number): string {\n let newLine = line;\n const ll = newLine.length;\n if (ll <= 150) {\n return newLine;\n }\n if (colno > ll) {\n colno = ll; // tslint:disable-line:no-parameter-reassignment\n }\n\n let start = Math.max(colno - 60, 0);\n if (start < 5) {\n start = 0;\n }\n\n let end = Math.min(start + 140, ll);\n if (end > ll - 5) {\n end = ll;\n }\n if (end === ll) {\n start = Math.max(end - 140, 0);\n }\n\n newLine = newLine.slice(start, end);\n if (start > 0) {\n newLine = `'{snip} ${newLine}`;\n }\n if (end < ll) {\n newLine += ' {snip}';\n }\n\n return newLine;\n}\n\n/**\n * Join values in array\n * @param input array of values to be joined together\n * @param delimiter string to be placed in-between values\n * @returns Joined values\n */\nexport function safeJoin(input: any[], delimiter?: string): string {\n if (!Array.isArray(input)) {\n return '';\n }\n\n const output = [];\n // tslint:disable-next-line\n for (let i = 0; i < input.length; i++) {\n const value = input[i];\n try {\n output.push(String(value));\n } catch (e) {\n output.push('[value cannot be serialized]');\n }\n }\n\n return output.join(delimiter);\n}\n\n/**\n * Checks if given value is included in the target\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes#Polyfill\n * @param target source string\n * @param search string to be looked for\n * @returns An answer\n */\nexport function includes(target: string, search: string): boolean {\n if (search.length > target.length) {\n return false;\n } else {\n return target.indexOf(search) !== -1;\n }\n}\n","import { Integration } from '@sentry/types';\nimport { logger } from '@sentry/utils/logger';\nimport { Options } from './interfaces';\n\nexport const installedIntegrations: string[] = [];\n\n/** Map of integrations assigned to a client */\nexport interface IntegrationIndex {\n [key: string]: Integration;\n}\n\n/** Gets integration to install */\nexport function getIntegrationsToSetup(options: Options): Integration[] {\n const defaultIntegrations = (options.defaultIntegrations && [...options.defaultIntegrations]) || [];\n const userIntegrations = options.integrations;\n let integrations: Integration[] = [];\n if (Array.isArray(userIntegrations)) {\n const userIntegrationsNames = userIntegrations.map(i => i.name);\n const pickedIntegrationsNames = [];\n\n // Leave only unique default integrations, that were not overridden with provided user integrations\n for (const defaultIntegration of defaultIntegrations) {\n if (\n userIntegrationsNames.indexOf(getIntegrationName(defaultIntegration)) === -1 &&\n pickedIntegrationsNames.indexOf(getIntegrationName(defaultIntegration)) === -1\n ) {\n integrations.push(defaultIntegration);\n pickedIntegrationsNames.push(getIntegrationName(defaultIntegration));\n }\n }\n\n // Don't add same user integration twice\n for (const userIntegration of userIntegrations) {\n if (pickedIntegrationsNames.indexOf(getIntegrationName(userIntegration)) === -1) {\n integrations.push(userIntegration);\n pickedIntegrationsNames.push(getIntegrationName(userIntegration));\n }\n }\n } else if (typeof userIntegrations === 'function') {\n integrations = userIntegrations(defaultIntegrations);\n integrations = Array.isArray(integrations) ? integrations : [integrations];\n } else {\n return [...defaultIntegrations];\n }\n\n return integrations;\n}\n\n/** Setup given integration */\nexport function setupIntegration(integration: Integration, options: Options): void {\n if (installedIntegrations.indexOf(getIntegrationName(integration)) !== -1) {\n return;\n }\n\n try {\n integration.setupOnce();\n } catch (_Oo) {\n /** @deprecated */\n // TODO: Remove in v5\n logger.warn(`Integration ${getIntegrationName(integration)}: The install method is deprecated. Use \"setupOnce\".`);\n\n // tslint:disable:deprecation\n if (integration.install) {\n integration.install(options);\n }\n // tslint:enable:deprecation\n }\n\n installedIntegrations.push(getIntegrationName(integration));\n logger.log(`Integration installed: ${getIntegrationName(integration)}`);\n}\n\n/**\n * Given a list of integration instances this installs them all. When `withDefaults` is set to `true` then all default\n * integrations are added unless they were already provided before.\n * @param integrations array of integration instances\n * @param withDefault should enable default integrations\n */\nexport function setupIntegrations(options: O): IntegrationIndex {\n const integrations: IntegrationIndex = {};\n getIntegrationsToSetup(options).forEach(integration => {\n integrations[getIntegrationName(integration)] = integration;\n setupIntegration(integration, options);\n });\n return integrations;\n}\n\n/**\n * Returns the integration static id.\n * @param integration Integration to retrieve id\n */\nfunction getIntegrationName(integration: Integration): string {\n /**\n * @depracted\n */\n // tslint:disable-next-line:no-unsafe-any\n return (integration as any).constructor.id || integration.name;\n}\n","import { Scope } from '@sentry/hub';\nimport {\n Breadcrumb,\n Integration,\n IntegrationClass,\n SentryBreadcrumbHint,\n SentryEvent,\n SentryEventHint,\n SentryResponse,\n Severity,\n Status,\n} from '@sentry/types';\nimport { forget } from '@sentry/utils/async';\nimport { logger } from '@sentry/utils/logger';\nimport { consoleSandbox, uuid4 } from '@sentry/utils/misc';\nimport { truncate } from '@sentry/utils/string';\nimport { BackendClass } from './basebackend';\nimport { Dsn } from './dsn';\nimport { IntegrationIndex, setupIntegrations } from './integration';\nimport { Backend, Client, Options } from './interfaces';\n\n/**\n * Default maximum number of breadcrumbs added to an event. Can be overwritten\n * with {@link Options.maxBreadcrumbs}.\n */\nconst DEFAULT_BREADCRUMBS = 30;\n\n/**\n * Absolute maximum number of breadcrumbs added to an event. The\n * `maxBreadcrumbs` option cannot be higher than this value.\n */\nconst MAX_BREADCRUMBS = 100;\n\n/**\n * By default, truncates URL values to 250 chars\n */\nconst MAX_URL_LENGTH = 250;\n\n/**\n * Base implementation for all JavaScript SDK clients.\n *\n * Call the constructor with the corresponding backend constructor and options\n * specific to the client subclass. To access these options later, use\n * {@link Client.getOptions}. Also, the Backend instance is available via\n * {@link Client.getBackend}.\n *\n * If a Dsn is specified in the options, it will be parsed and stored. Use\n * {@link Client.getDsn} to retrieve the Dsn at any moment. In case the Dsn is\n * invalid, the constructor will throw a {@link SentryException}. Note that\n * without a valid Dsn, the SDK will not send any events to Sentry.\n *\n * Before sending an event via the backend, it is passed through\n * {@link BaseClient.prepareEvent} to add SDK information and scope data\n * (breadcrumbs and context). To add more custom information, override this\n * method and extend the resulting prepared event.\n *\n * To issue automatically created events (e.g. via instrumentation), use\n * {@link Client.captureEvent}. It will prepare the event and pass it through\n * the callback lifecycle. To issue auto-breadcrumbs, use\n * {@link Client.addBreadcrumb}.\n *\n * @example\n * class NodeClient extends BaseClient {\n * public constructor(options: NodeOptions) {\n * super(NodeBackend, options);\n * }\n *\n * // ...\n * }\n */\nexport abstract class BaseClient implements Client {\n /**\n * The backend used to physically interact in the enviornment. Usually, this\n * will correspond to the client. When composing SDKs, however, the Backend\n * from the root SDK will be used.\n */\n private readonly backend: B;\n\n /** Options passed to the SDK. */\n private readonly options: O;\n\n /**\n * The client Dsn, if specified in options. Without this Dsn, the SDK will be\n * disabled.\n */\n private readonly dsn?: Dsn;\n\n /**\n * Stores whether installation has been performed and was successful. Before\n * installing, this is undefined. Then it contains the success state.\n */\n private installed?: boolean;\n\n /** Array of used integrations. */\n private readonly integrations: IntegrationIndex;\n\n /**\n * Initializes this client instance.\n *\n * @param backendClass A constructor function to create the backend.\n * @param options Options for the client.\n */\n protected constructor(backendClass: BackendClass, options: O) {\n this.backend = new backendClass(options);\n this.options = options;\n\n if (options.dsn) {\n this.dsn = new Dsn(options.dsn);\n }\n // We have to setup the integrations in the constructor since we do not want\n // that anyone needs to call client.install();\n this.integrations = setupIntegrations(this.options);\n }\n\n /**\n * @inheritDoc\n */\n public install(): boolean {\n if (!this.isEnabled()) {\n return (this.installed = false);\n }\n\n const backend = this.getBackend();\n if (!this.installed && backend.install) {\n backend.install();\n }\n\n return (this.installed = true);\n }\n\n /**\n * Internal helper function to buffer promises.\n *\n * @param promise Any promise, but in this case Promise.\n */\n protected async buffer(promise: Promise): Promise {\n return this.getBackend()\n .getBuffer()\n .add(promise);\n }\n\n /**\n * @inheritDoc\n */\n public async captureException(exception: any, hint?: SentryEventHint, scope?: Scope): Promise {\n return this.buffer(\n (async () => {\n const event = await this.getBackend().eventFromException(exception, hint);\n return this.captureEvent(event, hint, scope);\n })(),\n );\n }\n\n /**\n * @inheritDoc\n */\n public async captureMessage(\n message: string,\n level?: Severity,\n hint?: SentryEventHint,\n scope?: Scope,\n ): Promise {\n return this.buffer(\n (async () => {\n const event = await this.getBackend().eventFromMessage(message, level, hint);\n return this.captureEvent(event, hint, scope);\n })(),\n );\n }\n\n /**\n * @inheritDoc\n */\n public async captureEvent(event: SentryEvent, hint?: SentryEventHint, scope?: Scope): Promise {\n // Adding this here is technically not correct since if you call captureMessage/captureException it's already\n // buffered. But since we not really need the count and we only need to know if the buffer is full or not,\n // This is fine...\n return this.buffer(\n (async () =>\n this.processEvent(event, async finalEvent => this.getBackend().sendEvent(finalEvent), hint, scope))(),\n );\n }\n\n /**\n * @inheritDoc\n */\n public addBreadcrumb(breadcrumb: Breadcrumb, hint?: SentryBreadcrumbHint, scope?: Scope): void {\n const { beforeBreadcrumb, maxBreadcrumbs = DEFAULT_BREADCRUMBS } = this.getOptions();\n\n if (maxBreadcrumbs <= 0) {\n return;\n }\n\n const timestamp = new Date().getTime() / 1000;\n const mergedBreadcrumb = { timestamp, ...breadcrumb };\n const finalBreadcrumb = beforeBreadcrumb\n ? (consoleSandbox(() => beforeBreadcrumb(mergedBreadcrumb, hint)) as Breadcrumb | null)\n : mergedBreadcrumb;\n\n if (finalBreadcrumb === null) {\n return;\n }\n\n if (this.getBackend().storeBreadcrumb(finalBreadcrumb) && scope) {\n scope.addBreadcrumb(finalBreadcrumb, Math.min(maxBreadcrumbs, MAX_BREADCRUMBS));\n }\n }\n\n /**\n * @inheritDoc\n */\n public getDsn(): Dsn | undefined {\n return this.dsn;\n }\n\n /**\n * @inheritDoc\n */\n public getOptions(): O {\n return this.options;\n }\n\n /** Returns the current backend. */\n protected getBackend(): B {\n return this.backend;\n }\n\n /** Determines whether this SDK is enabled and a valid Dsn is present. */\n protected isEnabled(): boolean {\n return this.getOptions().enabled !== false && this.dsn !== undefined;\n }\n\n /**\n * Adds common information to events.\n *\n * The information includes release and environment from `options`,\n * breadcrumbs and context (extra, tags and user) from the scope.\n *\n * Information that is already present in the event is never overwritten. For\n * nested objects, such as the context, keys are merged.\n *\n * @param event The original event.\n * @param hint May contain additional informartion about the original exception.\n * @param scope A scope containing event metadata.\n * @returns A new event with more information.\n */\n protected async prepareEvent(event: SentryEvent, scope?: Scope, hint?: SentryEventHint): Promise {\n const { environment, maxBreadcrumbs = DEFAULT_BREADCRUMBS, release, dist } = this.getOptions();\n\n const prepared = { ...event };\n if (prepared.environment === undefined && environment !== undefined) {\n prepared.environment = environment;\n }\n if (prepared.release === undefined && release !== undefined) {\n prepared.release = release;\n }\n\n if (prepared.dist === undefined && dist !== undefined) {\n prepared.dist = dist;\n }\n\n if (prepared.message) {\n prepared.message = truncate(prepared.message, MAX_URL_LENGTH);\n }\n\n const exception = prepared.exception && prepared.exception.values && prepared.exception.values[0];\n if (exception && exception.value) {\n exception.value = truncate(exception.value, MAX_URL_LENGTH);\n }\n\n const request = prepared.request;\n if (request && request.url) {\n request.url = truncate(request.url, MAX_URL_LENGTH);\n }\n\n if (prepared.event_id === undefined) {\n prepared.event_id = uuid4();\n }\n\n // This should be the last thing called, since we want that\n // {@link Hub.addEventProcessor} gets the finished prepared event.\n if (scope) {\n return scope.applyToEvent(prepared, hint, Math.min(maxBreadcrumbs, MAX_BREADCRUMBS));\n }\n\n return prepared;\n }\n\n /**\n * Processes an event (either error or message) and sends it to Sentry.\n *\n * This also adds breadcrumbs and context information to the event. However,\n * platform specific meta data (such as the User's IP address) must be added\n * by the SDK implementor.\n *\n * The returned event status offers clues to whether the event was sent to\n * Sentry and accepted there. If the {@link Options.shouldSend} hook returns\n * `false`, the status will be {@link SendStatus.Skipped}. If the rate limit\n * was exceeded, the status will be {@link SendStatus.RateLimit}.\n *\n * @param event The event to send to Sentry.\n * @param send A function to actually send the event.\n * @param scope A scope containing event metadata.\n * @param hint May contain additional informartion about the original exception.\n * @returns A Promise that resolves with the event status.\n */\n protected async processEvent(\n event: SentryEvent,\n send: (finalEvent: SentryEvent) => Promise,\n hint?: SentryEventHint,\n scope?: Scope,\n ): Promise {\n if (!this.isEnabled()) {\n return {\n status: Status.Skipped,\n };\n }\n\n const { beforeSend, sampleRate } = this.getOptions();\n\n // 1.0 === 100% events are sent\n // 0.0 === 0% events are sent\n if (typeof sampleRate === 'number' && Math.random() > sampleRate) {\n return {\n status: Status.Skipped,\n };\n }\n\n const prepared = await this.prepareEvent(event, scope, hint);\n if (prepared === null) {\n return {\n status: Status.Skipped,\n };\n }\n\n let finalEvent: SentryEvent | null = prepared;\n\n try {\n const isInternalException = hint && hint.data && (hint.data as { [key: string]: any }).__sentry__ === true;\n if (!isInternalException && beforeSend) {\n finalEvent = await beforeSend(prepared, hint);\n if ((typeof finalEvent as any) === 'undefined') {\n logger.error('`beforeSend` method has to return `null` or a valid event');\n }\n }\n } catch (exception) {\n forget(\n this.captureException(exception, {\n data: {\n __sentry__: true,\n },\n originalException: exception as Error,\n }),\n );\n\n return {\n reason: 'Event processing in beforeSend method threw an exception',\n status: Status.Invalid,\n };\n }\n\n if (finalEvent === null) {\n return {\n reason: 'Event dropped due to being discarded by beforeSend method',\n status: Status.Skipped,\n };\n }\n\n const response = await send(finalEvent);\n response.event = finalEvent;\n\n if (response.status === Status.RateLimit) {\n // TODO: Handle rate limits and maintain a queue. For now, we require SDK\n // implementors to override this method and handle it themselves.\n }\n\n return response;\n }\n\n /**\n * @inheritDoc\n */\n public async close(timeout?: number): Promise {\n return this.getBackend()\n .getBuffer()\n .drain(timeout);\n }\n\n /**\n * @inheritDoc\n */\n public getIntegrations(): IntegrationIndex {\n return this.integrations || {};\n }\n\n /**\n * @inheritDoc\n */\n public getIntegration(integration: IntegrationClass): T | null {\n try {\n return (this.integrations[integration.id] as T) || null;\n } catch (_oO) {\n logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`);\n return null;\n }\n }\n}\n","import { Scope } from '@sentry/hub';\nimport {\n Breadcrumb,\n Integration,\n IntegrationClass,\n SentryBreadcrumbHint,\n SentryEvent,\n SentryEventHint,\n SentryResponse,\n Severity,\n Transport,\n TransportClass,\n TransportOptions,\n} from '@sentry/types';\nimport { Dsn } from './dsn';\nimport { RequestBuffer } from './requestbuffer';\n\n/** Console logging verbosity for the SDK. */\nexport enum LogLevel {\n /** No logs will be generated. */\n None = 0,\n /** Only SDK internal errors will be logged. */\n Error = 1,\n /** Information useful for debugging the SDK will be logged. */\n Debug = 2,\n /** All SDK actions will be logged. */\n Verbose = 3,\n}\n\n/** Base configuration options for every SDK. */\nexport interface Options {\n /**\n * Enable debug functionality in the SDK itself\n */\n debug?: boolean;\n\n /**\n * Specifies whether this SDK should activate and send events to Sentry.\n * Disabling the SDK reduces all overhead from instrumentation, collecting\n * breadcrumbs and capturing events. Defaults to true.\n */\n enabled?: boolean;\n\n /**\n * The Dsn used to connect to Sentry and identify the project. If omitted, the\n * SDK will not send any data to Sentry.\n */\n dsn?: string;\n\n /**\n * If this is set to false, default integrations will not be added, otherwise this will internally be set to the\n * recommended default integrations.\n */\n defaultIntegrations?: boolean | Integration[];\n\n /**\n * List of integrations that should be installed after SDK was initialized.\n * Accepts either a list of integrations or a function that receives\n * default integrations and returns a new, updated list.\n */\n integrations?: Integration[] | ((integrations: Integration[]) => Integration[]);\n\n /**\n * A pattern for error messages which should not be sent to Sentry.\n * By default, all errors will be sent.\n */\n ignoreErrors?: Array;\n\n /**\n * Transport object that should be used to send events to Sentry\n */\n transport?: TransportClass;\n\n /**\n * Options for the default transport that the SDK uses.\n */\n transportOptions?: TransportOptions;\n\n /**\n * The release identifier used when uploading respective source maps. Specify\n * this value to allow Sentry to resolve the correct source maps when\n * processing events.\n */\n release?: string;\n\n /** The current environment of your application (e.g. \"production\"). */\n environment?: string;\n\n /** Sets the distribution for all events */\n dist?: string;\n\n /** The maximum number of breadcrumbs sent with events. Defaults to 100. */\n maxBreadcrumbs?: number;\n\n /** Console logging verbosity for the SDK Client. */\n logLevel?: LogLevel;\n\n /** A global sample rate to apply to all events (0 - 1). */\n sampleRate?: number;\n\n /** Attaches stacktraces to pure capture message / log integrations */\n attachStacktrace?: boolean;\n\n /**\n * A callback invoked during event submission, allowing to optionally modify\n * the event before it is sent to Sentry.\n *\n * Note that you must return a valid event from this callback. If you do not\n * wish to modify the event, simply return it at the end.\n * Returning null will case the event to be dropped.\n *\n * @param event The error or message event generated by the SDK.\n * @param hint May contain additional information about the original exception.\n * @returns A new event that will be sent | null.\n */\n beforeSend?(event: SentryEvent, hint?: SentryEventHint): SentryEvent | null | Promise;\n\n /**\n * A callback invoked when adding a breadcrumb, allowing to optionally modify\n * it before adding it to future events.\n *\n * Note that you must return a valid breadcrumb from this callback. If you do\n * not wish to modify the breadcrumb, simply return it at the end.\n * Returning null will case the breadcrumb to be dropped.\n *\n * @param breadcrumb The breadcrumb as created by the SDK.\n * @returns The breadcrumb that will be added | null.\n */\n beforeBreadcrumb?(breadcrumb: Breadcrumb, hint?: SentryBreadcrumbHint): Breadcrumb | null;\n}\n\n/**\n * User-Facing Sentry SDK Client Client.\n *\n * This interface contains all methods to interface with the SDK once it has\n * been installed. It allows to send events to Sentry, record breadcrumbs and\n * set a context included in every event. Since the SDK mutates its environment,\n * there will only be one instance during runtime. To retrieve that instance,\n * use {@link Client.getInstance}.\n *\n * Note that the call to {@link Client.install} should occur as early as\n * possible so that even errors during startup can be recorded reliably:\n *\n * @example\n * import { captureMessage } from '@sentry/node';\n * captureMessage('Custom message');\n */\nexport interface Client {\n /**\n * Installs the SDK if it hasn't been installed already.\n *\n * Since this performs modifications in the environment, such as instrumenting\n * library functionality or adding signal handlers, this method will only\n * execute once and cache its result.\n *\n * @returns If the installation was the successful or not.\n */\n install(): boolean;\n\n /**\n * Captures an exception event and sends it to Sentry.\n *\n * @param exception An exception-like object.\n * @param hint May contain additional information about the original exception.\n * @param scope An optional scope containing event metadata.\n * @returns SentryResponse status and event\n */\n captureException(exception: any, hint?: SentryEventHint, scope?: Scope): Promise;\n\n /**\n * Captures a message event and sends it to Sentry.\n *\n * @param message The message to send to Sentry.\n * @param level Define the level of the message.\n * @param hint May contain additional information about the original exception.\n * @param scope An optional scope containing event metadata.\n * @returns SentryResponse status and event\n */\n captureMessage(message: string, level?: Severity, hint?: SentryEventHint, scope?: Scope): Promise;\n\n /**\n * Captures a manually created event and sends it to Sentry.\n *\n * @param event The event to send to Sentry.\n * @param hint May contain additional information about the original exception.\n * @param scope An optional scope containing event metadata.\n * @returns SentryResponse status and event\n */\n captureEvent(event: SentryEvent, hint?: SentryEventHint, scope?: Scope): Promise;\n\n /**\n * Records a new breadcrumb which will be attached to future events.\n *\n * Breadcrumbs will be added to subsequent events to provide more context on\n * user's actions prior to an error or crash. To configure the maximum number\n * of breadcrumbs, use {@link Options.maxBreadcrumbs}.\n *\n * @param breadcrumb The breadcrumb to record.\n * @param hint May contain additional information about the original breadcrumb.\n * @param scope An optional scope to store this breadcrumb in.\n */\n addBreadcrumb(breadcrumb: Breadcrumb, hint?: SentryBreadcrumbHint, scope?: Scope): void;\n\n /** Returns the current Dsn. */\n getDsn(): Dsn | undefined;\n\n /** Returns the current options. */\n getOptions(): O;\n\n /**\n * A promise that resolves whenever the request buffer is empty.\n * If you provide a timeout and the buffer takes longer to drain the promise returns false.\n *\n * @param timeout Maximum time in ms the client should wait.\n */\n close(timeout?: number): Promise;\n\n /** Returns an array of installed integrations on the client. */\n getIntegration(integartion: IntegrationClass): T | null;\n}\n\n/**\n * Internal platform-dependent Sentry SDK Backend.\n *\n * While {@link Client} contains business logic specific to an SDK, the\n * Backend offers platform specific implementations for low-level operations.\n * These are persisting and loading information, sending events, and hooking\n * into the environment.\n *\n * Backends receive a handle to the Client in their constructor. When a\n * Backend automatically generates events or breadcrumbs, it must pass them to\n * the Client for validation and processing first.\n *\n * Usually, the Client will be of corresponding type, e.g. NodeBackend\n * receives NodeClient. However, higher-level SDKs can choose to instanciate\n * multiple Backends and delegate tasks between them. In this case, an event\n * generated by one backend might very well be sent by another one.\n *\n * The client also provides access to options via {@link Client.getOptions}\n * and context via {@link Client.getContext}. Note that the user might update\n * these any time and they should not be cached.\n */\nexport interface Backend {\n /** Installs the SDK into the environment. */\n install?(): boolean;\n\n /** Creates a {@link SentryEvent} from an exception. */\n eventFromException(exception: any, hint?: SentryEventHint): Promise;\n\n /** Creates a {@link SentryEvent} from a plain message. */\n eventFromMessage(message: string, level?: Severity, hint?: SentryEventHint): Promise;\n\n /** Submits the event to Sentry */\n sendEvent(event: SentryEvent): Promise;\n\n /**\n * Receives a breadcrumb and stores it in a platform-dependent way.\n *\n * This function is invoked by the client before merging the breadcrumb into\n * the scope. Return `false` to prevent this breadcrumb from being merged.\n * This should be done for custom breadcrumb management in the backend.\n *\n * In most cases, this method does not have to perform any action and can\n * simply return `true`. It can either be synchronous or asynchronous.\n *\n * @param breadcrumb The breadcrumb to store.\n * @returns True if the breadcrumb should be merged by the client.\n */\n storeBreadcrumb(breadcrumb: Breadcrumb): boolean;\n\n /**\n * Receives the whole scope and stores it in a platform-dependent way.\n *\n * This function is invoked by the scope after the scope is configured.\n * This should be done for custom context management in the backend.\n *\n * @param scope The scope to store.\n */\n storeScope(scope: Scope): void;\n\n /**\n * Returns the internal instance of the request buffer.\n * Only used internally.\n */\n getBuffer(): RequestBuffer;\n}\n","/**\n * Consumes the promise and logs the error when it rejects.\n * @param promise A promise to forget.\n */\nexport function forget(promise: Promise): void {\n promise.catch(e => {\n // TODO: Use a better logging mechanism\n console.error(e);\n });\n}\n\n/**\n * Helper to filter an array with asynchronous callbacks.\n *\n * @param array An array containing items to filter.\n * @param predicate An async predicate evaluated on every item.\n * @param thisArg Optional value passed as \"this\" into the callback.\n * @returns An array containing only values where the callback returned true.\n */\nexport async function filterAsync(\n array: T[],\n predicate: (item: T) => Promise | boolean,\n thisArg?: any,\n): Promise {\n const verdicts = await Promise.all(array.map(predicate, thisArg));\n return array.filter((_, index) => verdicts[index]);\n}\n","/** A simple queue that holds promises. */\nexport class RequestBuffer {\n /** Internal set of queued Promises */\n private readonly buffer: Array> = [];\n\n /**\n * Add a promise to the queue.\n *\n * @param task Can be any Promise\n * @returns The original promise.\n */\n public async add(task: Promise): Promise {\n if (this.buffer.indexOf(task) === -1) {\n this.buffer.push(task);\n }\n task.then(async () => this.remove(task)).catch(async () => this.remove(task));\n return task;\n }\n\n /**\n * Remove a promise to the queue.\n *\n * @param task Can be any Promise\n * @returns Removed promise.\n */\n public async remove(task: Promise): Promise {\n const removedTask = this.buffer.splice(this.buffer.indexOf(task), 1)[0];\n return removedTask;\n }\n\n /**\n * This function returns the number of unresolved promises in the queue.\n */\n public length(): number {\n return this.buffer.length;\n }\n\n /**\n * This will drain the whole queue, returns true if queue is empty or drained.\n * If timeout is provided and the queue takes longer to drain, the promise still resolves but with false.\n *\n * @param timeout Number in ms to wait until it resolves with false.\n */\n public async drain(timeout?: number): Promise {\n return new Promise(resolve => {\n const capturedSetTimeout = setTimeout(() => {\n if (timeout && timeout > 0) {\n resolve(false);\n }\n }, timeout);\n Promise.all(this.buffer)\n .then(() => {\n clearTimeout(capturedSetTimeout);\n resolve(true);\n })\n .catch(() => {\n resolve(true);\n });\n });\n }\n}\n","import { Scope } from '@sentry/hub';\nimport { Breadcrumb, SentryEvent, SentryEventHint, SentryResponse, Severity, Transport } from '@sentry/types';\nimport { logger } from '@sentry/utils/logger';\nimport { SentryError } from './error';\nimport { Backend, Options } from './interfaces';\nimport { RequestBuffer } from './requestbuffer';\n\n/** A class object that can instanciate Backend objects. */\nexport interface BackendClass {\n new (options: O): B;\n}\n\n/**\n * This is the base implemention of a Backend.\n */\nexport abstract class BaseBackend implements Backend {\n /** Options passed to the SDK. */\n protected readonly options: O;\n\n /** Creates a new browser backend instance. */\n public constructor(options: O) {\n this.options = options;\n if (!this.options.dsn) {\n logger.warn('No DSN provided, backend will not do anything.');\n }\n }\n\n /** Cached transport used internally. */\n protected transport?: Transport;\n\n /** A simple buffer holding all requests. */\n protected readonly buffer: RequestBuffer = new RequestBuffer();\n\n /**\n * @inheritDoc\n */\n public async eventFromException(_exception: any, _hint?: SentryEventHint): Promise {\n throw new SentryError('Backend has to implement `eventFromException` method');\n }\n\n /**\n * @inheritDoc\n */\n public async eventFromMessage(_message: string, _level?: Severity, _hint?: SentryEventHint): Promise {\n throw new SentryError('Backend has to implement `eventFromMessage` method');\n }\n\n /**\n * @inheritDoc\n */\n public async sendEvent(_event: SentryEvent): Promise {\n throw new SentryError('Backend has to implement `sendEvent` method');\n }\n\n /**\n * @inheritDoc\n */\n public storeBreadcrumb(_: Breadcrumb): boolean {\n return true;\n }\n\n /**\n * @inheritDoc\n */\n public storeScope(_: Scope): void {\n // Noop\n }\n\n /**\n * @inheritDoc\n */\n public getBuffer(): RequestBuffer {\n return this.buffer;\n }\n}\n","import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub';\nimport { Integration, SentryEvent, SentryException, StackFrame } from '@sentry/types';\nimport { logger } from '@sentry/utils/logger';\nimport { getEventDescription } from '@sentry/utils/misc';\n\n/** Deduplication filter */\nexport class Dedupe implements Integration {\n /**\n * @inheritDoc\n */\n private previousEvent?: SentryEvent;\n\n /**\n * @inheritDoc\n */\n public name: string = Dedupe.id;\n\n /**\n * @inheritDoc\n */\n public static id: string = 'Dedupe';\n\n /**\n * @inheritDoc\n */\n public setupOnce(): void {\n addGlobalEventProcessor(async (currentEvent: SentryEvent) => {\n const self = getCurrentHub().getIntegration(Dedupe);\n if (self) {\n // Juuust in case something goes wrong\n try {\n if (self.shouldDropEvent(currentEvent, self.previousEvent)) {\n return null;\n }\n } catch (_oO) {\n return (self.previousEvent = currentEvent);\n }\n\n return (self.previousEvent = currentEvent);\n }\n return currentEvent;\n });\n }\n\n /** JSDoc */\n public shouldDropEvent(currentEvent: SentryEvent, previousEvent?: SentryEvent): boolean {\n if (!previousEvent) {\n return false;\n }\n\n if (this.isSameMessageEvent(currentEvent, previousEvent)) {\n logger.warn(\n `Event dropped due to being a duplicate of previous event (same message).\\nEvent: ${getEventDescription(\n currentEvent,\n )}`,\n );\n return true;\n }\n\n if (this.isSameExceptionEvent(currentEvent, previousEvent)) {\n logger.warn(\n `Event dropped due to being a duplicate of previous event (same exception).\\nEvent: ${getEventDescription(\n currentEvent,\n )}`,\n );\n return true;\n }\n\n return false;\n }\n\n /** JSDoc */\n private isSameMessageEvent(currentEvent: SentryEvent, previousEvent: SentryEvent): boolean {\n const currentMessage = currentEvent.message;\n const previousMessage = previousEvent.message;\n\n // If no event has a message, they were both exceptions, so bail out\n if (!currentMessage && !previousMessage) {\n return false;\n }\n\n // If only one event has a stacktrace, but not the other one, they are not the same\n if ((currentMessage && !previousMessage) || (!currentMessage && previousMessage)) {\n return false;\n }\n\n if (currentMessage !== previousMessage) {\n return false;\n }\n\n if (!this.isSameFingerprint(currentEvent, previousEvent)) {\n return false;\n }\n\n if (!this.isSameStacktrace(currentEvent, previousEvent)) {\n return false;\n }\n\n return true;\n }\n\n /** JSDoc */\n private getFramesFromEvent(event: SentryEvent): StackFrame[] | undefined {\n const exception = event.exception;\n\n if (exception) {\n try {\n // @ts-ignore\n return exception.values[0].stacktrace.frames;\n } catch (_oO) {\n return undefined;\n }\n } else if (event.stacktrace) {\n return event.stacktrace.frames;\n } else {\n return undefined;\n }\n }\n\n /** JSDoc */\n private isSameStacktrace(currentEvent: SentryEvent, previousEvent: SentryEvent): boolean {\n let currentFrames = this.getFramesFromEvent(currentEvent);\n let previousFrames = this.getFramesFromEvent(previousEvent);\n\n // If no event has a fingerprint, they are assumed to be the same\n if (!currentFrames && !previousFrames) {\n return true;\n }\n\n // If only one event has a stacktrace, but not the other one, they are not the same\n if ((currentFrames && !previousFrames) || (!currentFrames && previousFrames)) {\n return false;\n }\n\n currentFrames = currentFrames as StackFrame[];\n previousFrames = previousFrames as StackFrame[];\n\n // If number of frames differ, they are not the same\n if (previousFrames.length !== currentFrames.length) {\n return false;\n }\n\n // Otherwise, compare the two\n for (let i = 0; i < previousFrames.length; i++) {\n const frameA = previousFrames[i];\n const frameB = currentFrames[i];\n\n if (\n frameA.filename !== frameB.filename ||\n frameA.lineno !== frameB.lineno ||\n frameA.colno !== frameB.colno ||\n frameA.function !== frameB.function\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n /** JSDoc */\n private getExceptionFromEvent(event: SentryEvent): SentryException | undefined {\n return event.exception && event.exception.values && event.exception.values[0];\n }\n\n /** JSDoc */\n private isSameExceptionEvent(currentEvent: SentryEvent, previousEvent: SentryEvent): boolean {\n const previousException = this.getExceptionFromEvent(previousEvent);\n const currentException = this.getExceptionFromEvent(currentEvent);\n\n if (!previousException || !currentException) {\n return false;\n }\n\n if (previousException.type !== currentException.type || previousException.value !== currentException.value) {\n return false;\n }\n\n if (!this.isSameFingerprint(currentEvent, previousEvent)) {\n return false;\n }\n\n if (!this.isSameStacktrace(currentEvent, previousEvent)) {\n return false;\n }\n\n return true;\n }\n\n /** JSDoc */\n private isSameFingerprint(currentEvent: SentryEvent, previousEvent: SentryEvent): boolean {\n let currentFingerprint = currentEvent.fingerprint;\n let previousFingerprint = previousEvent.fingerprint;\n\n // If no event has a fingerprint, they are assumed to be the same\n if (!currentFingerprint && !previousFingerprint) {\n return true;\n }\n\n // If only one event has a fingerprint, but not the other one, they are not the same\n if ((currentFingerprint && !previousFingerprint) || (!currentFingerprint && previousFingerprint)) {\n return false;\n }\n\n currentFingerprint = currentFingerprint as string[];\n previousFingerprint = previousFingerprint as string[];\n\n // Otherwise, compare the two\n try {\n return !!(currentFingerprint.join('') === previousFingerprint.join(''));\n } catch (_oO) {\n return false;\n }\n }\n}\n","import { Integration, SentryWrappedFunction } from '@sentry/types';\n\nlet originalFunctionToString: () => void;\n\n/** Patch toString calls to return proper name for wrapped functions */\nexport class FunctionToString implements Integration {\n /**\n * @inheritDoc\n */\n public name: string = FunctionToString.id;\n\n /**\n * @inheritDoc\n */\n public static id: string = 'FunctionToString';\n\n /**\n * @inheritDoc\n */\n public setupOnce(): void {\n originalFunctionToString = Function.prototype.toString;\n\n Function.prototype.toString = function(this: SentryWrappedFunction, ...args: any[]): string {\n const context = this.__sentry__ ? this.__sentry_original__ : this;\n // tslint:disable-next-line:no-unsafe-any\n return originalFunctionToString.apply(context, args);\n };\n }\n}\n","import { Integration } from '@sentry/types';\nimport { logger } from '@sentry/utils/logger';\n\n/**\n * @deprecated\n * This file can be safely removed in the next major bump\n */\n\n/** Adds SDK info to an event. */\nexport class SDKInformation implements Integration {\n /**\n * @inheritDoc\n */\n public name: string = 'SDKInformation';\n\n /**\n * @inheritDoc\n */\n public setupOnce(): void {\n logger.warn(\n \"SDKInformation Integration is deprecated and can be safely removed. It's functionality has been merged into the SDK's core.\",\n );\n }\n}\n","import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub';\nimport { Integration, SentryEvent } from '@sentry/types';\nimport { isRegExp } from '@sentry/utils/is';\nimport { logger } from '@sentry/utils/logger';\nimport { getEventDescription } from '@sentry/utils/misc';\nimport { includes } from '@sentry/utils/string';\nimport { Client } from '../interfaces';\n\n// \"Script error.\" is hard coded into browsers for errors that it can't read.\n// this is the result of a script being pulled in from an external domain and CORS.\nconst DEFAULT_IGNORE_ERRORS = [/^Script error\\.?$/, /^Javascript error: Script error\\.? on line 0$/];\n\n/** JSDoc */\ninterface InboundFiltersOptions {\n blacklistUrls?: Array;\n ignoreErrors?: Array;\n ignoreInternal?: boolean;\n whitelistUrls?: Array;\n}\n\n/** Inbound filters configurable by the user */\nexport class InboundFilters implements Integration {\n /**\n * @inheritDoc\n */\n public name: string = InboundFilters.id;\n /**\n * @inheritDoc\n */\n public static id: string = 'InboundFilters';\n\n public constructor(private readonly options: InboundFiltersOptions = {}) {}\n\n /**\n * @inheritDoc\n */\n public setupOnce(): void {\n addGlobalEventProcessor(async (event: SentryEvent) => {\n const hub = getCurrentHub();\n if (!hub) {\n return event;\n }\n const self = hub.getIntegration(InboundFilters);\n if (self) {\n const client = hub.getClient() as Client;\n const clientOptions = client ? client.getOptions() : {};\n const options = self.mergeOptions(clientOptions);\n if (self.shouldDropEvent(event, options)) {\n return null;\n }\n }\n return event;\n });\n }\n\n /** JSDoc */\n public shouldDropEvent(event: SentryEvent, options: InboundFiltersOptions): boolean {\n if (this.isSentryError(event, options)) {\n logger.warn(`Event dropped due to being internal Sentry Error.\\nEvent: ${getEventDescription(event)}`);\n return true;\n }\n if (this.isIgnoredError(event, options)) {\n logger.warn(\n `Event dropped due to being matched by \\`ignoreErrors\\` option.\\nEvent: ${getEventDescription(event)}`,\n );\n return true;\n }\n if (this.isBlacklistedUrl(event, options)) {\n logger.warn(\n `Event dropped due to being matched by \\`blacklistUrls\\` option.\\nEvent: ${getEventDescription(\n event,\n )}.\\nUrl: ${this.getEventFilterUrl(event)}`,\n );\n return true;\n }\n if (!this.isWhitelistedUrl(event, options)) {\n logger.warn(\n `Event dropped due to not being matched by \\`whitelistUrls\\` option.\\nEvent: ${getEventDescription(\n event,\n )}.\\nUrl: ${this.getEventFilterUrl(event)}`,\n );\n return true;\n }\n return false;\n }\n\n /** JSDoc */\n public isSentryError(event: SentryEvent, options: InboundFiltersOptions = {}): boolean {\n if (!options.ignoreInternal) {\n return false;\n }\n\n try {\n // tslint:disable-next-line:no-unsafe-any\n return (event as any).exception.values[0].type === 'SentryError';\n } catch (_oO) {\n return false;\n }\n }\n\n /** JSDoc */\n public isIgnoredError(event: SentryEvent, options: InboundFiltersOptions = {}): boolean {\n if (!options.ignoreErrors || !options.ignoreErrors.length) {\n return false;\n }\n\n return this.getPossibleEventMessages(event).some(message =>\n // Not sure why TypeScript complains here...\n (options.ignoreErrors as Array).some(pattern => this.isMatchingPattern(message, pattern)),\n );\n }\n\n /** JSDoc */\n public isBlacklistedUrl(event: SentryEvent, options: InboundFiltersOptions = {}): boolean {\n // TODO: Use Glob instead?\n if (!options.blacklistUrls || !options.blacklistUrls.length) {\n return false;\n }\n const url = this.getEventFilterUrl(event);\n return !url ? false : options.blacklistUrls.some(pattern => this.isMatchingPattern(url, pattern));\n }\n\n /** JSDoc */\n public isWhitelistedUrl(event: SentryEvent, options: InboundFiltersOptions = {}): boolean {\n // TODO: Use Glob instead?\n if (!options.whitelistUrls || !options.whitelistUrls.length) {\n return true;\n }\n const url = this.getEventFilterUrl(event);\n return !url ? true : options.whitelistUrls.some(pattern => this.isMatchingPattern(url, pattern));\n }\n\n /** JSDoc */\n public mergeOptions(clientOptions: InboundFiltersOptions = {}): InboundFiltersOptions {\n return {\n blacklistUrls: [...(this.options.blacklistUrls || []), ...(clientOptions.blacklistUrls || [])],\n ignoreErrors: [\n ...(this.options.ignoreErrors || []),\n ...(clientOptions.ignoreErrors || []),\n ...DEFAULT_IGNORE_ERRORS,\n ],\n ignoreInternal: typeof this.options.ignoreInternal !== 'undefined' ? this.options.ignoreInternal : true,\n whitelistUrls: [...(this.options.whitelistUrls || []), ...(clientOptions.whitelistUrls || [])],\n };\n }\n\n /** JSDoc */\n private isMatchingPattern(value: string, pattern: RegExp | string): boolean {\n if (isRegExp(pattern)) {\n return (pattern as RegExp).test(value);\n } else if (typeof pattern === 'string') {\n return includes(value, pattern);\n } else {\n return false;\n }\n }\n\n /** JSDoc */\n private getPossibleEventMessages(event: SentryEvent): string[] {\n if (event.message) {\n return [event.message];\n } else if (event.exception) {\n try {\n // tslint:disable-next-line:no-unsafe-any\n const { type, value } = (event as any).exception.values[0];\n return [`${value}`, `${type}: ${value}`];\n } catch (oO) {\n logger.error(`Cannot extract message for event ${getEventDescription(event)}`);\n return [];\n }\n } else {\n return [];\n }\n }\n\n /** JSDoc */\n private getEventFilterUrl(event: SentryEvent): string | null {\n try {\n if (event.stacktrace) {\n // tslint:disable-next-line:no-unsafe-any\n return (event as any).stacktrace.frames[0].filename;\n } else if (event.exception) {\n // tslint:disable-next-line:no-unsafe-any\n return (event as any).exception.values[0].stacktrace.frames[0].filename;\n } else {\n return null;\n }\n } catch (oO) {\n logger.error(`Cannot extract url for event ${getEventDescription(event)}`);\n return null;\n }\n }\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n/**\n * Checks whether given value's type is one of a few Error or Error-like\n * {@link isError}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nfunction isError(wat) {\n switch (Object.prototype.toString.call(wat)) {\n case '[object Error]':\n return true;\n case '[object Exception]':\n return true;\n case '[object DOMException]':\n return true;\n default:\n return wat instanceof Error;\n }\n}\nexports.isError = isError;\n/**\n * Checks whether given value's type is ErrorEvent\n * {@link isErrorEvent}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nfunction isErrorEvent(wat) {\n return Object.prototype.toString.call(wat) === '[object ErrorEvent]';\n}\nexports.isErrorEvent = isErrorEvent;\n/**\n * Checks whether given value's type is DOMError\n * {@link isDOMError}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nfunction isDOMError(wat) {\n return Object.prototype.toString.call(wat) === '[object DOMError]';\n}\nexports.isDOMError = isDOMError;\n/**\n * Checks whether given value's type is DOMException\n * {@link isDOMException}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nfunction isDOMException(wat) {\n return Object.prototype.toString.call(wat) === '[object DOMException]';\n}\nexports.isDOMException = isDOMException;\n/**\n * Checks whether given value's type is an undefined\n * {@link isUndefined}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nfunction isUndefined(wat) {\n return wat === void 0;\n}\nexports.isUndefined = isUndefined;\n/**\n * Checks whether given value's type is a function\n * {@link isFunction}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nfunction isFunction(wat) {\n return typeof wat === 'function';\n}\nexports.isFunction = isFunction;\n/**\n * Checks whether given value's type is a string\n * {@link isString}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nfunction isString(wat) {\n return Object.prototype.toString.call(wat) === '[object String]';\n}\nexports.isString = isString;\n/**\n * Checks whether given value's type is an array\n * {@link isArray}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nfunction isArray(wat) {\n return Object.prototype.toString.call(wat) === '[object Array]';\n}\nexports.isArray = isArray;\n/**\n * Checks whether given value's type is an object literal\n * {@link isPlainObject}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nfunction isPlainObject(wat) {\n return Object.prototype.toString.call(wat) === '[object Object]';\n}\nexports.isPlainObject = isPlainObject;\n/**\n * Checks whether given value's type is an regexp\n * {@link isRegExp}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nfunction isRegExp(wat) {\n return Object.prototype.toString.call(wat) === '[object RegExp]';\n}\nexports.isRegExp = isRegExp;\n/**\n * Checks whether given value's type is a NaN\n * {@link isNaN}.\n *\n * @param wat A value to be checked.\n * @returns A boolean representing the result.\n */\nfunction isNaN(wat) {\n return wat !== wat;\n}\nexports.isNaN = isNaN;\n//# sourceMappingURL=is.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar is_1 = require(\"./is\");\n/**\n * Requires a module which is protected against bundler minification.\n *\n * @param request The module path to resolve\n */\nfunction dynamicRequire(mod, request) {\n return mod.require(request);\n}\nexports.dynamicRequire = dynamicRequire;\n/**\n * Checks whether we're in the Node.js or Browser environment\n *\n * @returns Answer to given question\n */\nfunction isNodeEnv() {\n // tslint:disable:strict-type-predicates\n return Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]';\n}\nexports.isNodeEnv = isNodeEnv;\n/**\n * Safely get global scope object\n *\n * @returns Global scope object\n */\n// tslint:disable:strict-type-predicates\nfunction getGlobalObject() {\n return isNodeEnv() ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {};\n}\nexports.getGlobalObject = getGlobalObject;\n/**\n * UUID4 generator\n *\n * @returns string Generated UUID4.\n */\nfunction uuid4() {\n var global = getGlobalObject();\n var crypto = global.crypto || global.msCrypto;\n if (!(crypto === void 0) && crypto.getRandomValues) {\n // Use window.crypto API if available\n var arr = new Uint16Array(8);\n crypto.getRandomValues(arr);\n // set 4 in byte 7\n // tslint:disable-next-line:no-bitwise\n arr[3] = (arr[3] & 0xfff) | 0x4000;\n // set 2 most significant bits of byte 9 to '10'\n // tslint:disable-next-line:no-bitwise\n arr[4] = (arr[4] & 0x3fff) | 0x8000;\n var pad = function (num) {\n var v = num.toString(16);\n while (v.length < 4) {\n v = \"0\" + v;\n }\n return v;\n };\n return (pad(arr[0]) + pad(arr[1]) + pad(arr[2]) + pad(arr[3]) + pad(arr[4]) + pad(arr[5]) + pad(arr[6]) + pad(arr[7]));\n }\n else {\n // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523\n return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n // tslint:disable-next-line:no-bitwise\n var r = (Math.random() * 16) | 0;\n // tslint:disable-next-line:no-bitwise\n var v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n}\nexports.uuid4 = uuid4;\n/**\n * Given a child DOM element, returns a query-selector statement describing that\n * and its ancestors\n * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]\n * @returns generated DOM path\n */\nfunction htmlTreeAsString(elem) {\n var currentElem = elem;\n var MAX_TRAVERSE_HEIGHT = 5;\n var MAX_OUTPUT_LEN = 80;\n var out = [];\n var height = 0;\n var len = 0;\n var separator = ' > ';\n var sepLength = separator.length;\n var nextStr;\n while (currentElem && height++ < MAX_TRAVERSE_HEIGHT) {\n nextStr = htmlElementAsString(currentElem);\n // bail out if\n // - nextStr is the 'html' element\n // - the length of the string that would be created exceeds MAX_OUTPUT_LEN\n // (ignore this limit if we are on the first iteration)\n if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN)) {\n break;\n }\n out.push(nextStr);\n len += nextStr.length;\n currentElem = currentElem.parentNode;\n }\n return out.reverse().join(separator);\n}\nexports.htmlTreeAsString = htmlTreeAsString;\n/**\n * Returns a simple, query-selector representation of a DOM element\n * e.g. [HTMLElement] => input#foo.btn[name=baz]\n * @returns generated DOM path\n */\nfunction htmlElementAsString(elem) {\n var out = [];\n var className;\n var classes;\n var key;\n var attr;\n var i;\n if (!elem || !elem.tagName) {\n return '';\n }\n out.push(elem.tagName.toLowerCase());\n if (elem.id) {\n out.push(\"#\" + elem.id);\n }\n className = elem.className;\n if (className && is_1.isString(className)) {\n classes = className.split(/\\s+/);\n for (i = 0; i < classes.length; i++) {\n out.push(\".\" + classes[i]);\n }\n }\n var attrWhitelist = ['type', 'name', 'title', 'alt'];\n for (i = 0; i < attrWhitelist.length; i++) {\n key = attrWhitelist[i];\n attr = elem.getAttribute(key);\n if (attr) {\n out.push(\"[\" + key + \"=\\\"\" + attr + \"\\\"]\");\n }\n }\n return out.join('');\n}\nexports.htmlElementAsString = htmlElementAsString;\n/**\n * Parses string form of URL into an object\n * // borrowed from https://tools.ietf.org/html/rfc3986#appendix-B\n * // intentionally using regex and not href parsing trick because React Native and other\n * // environments where DOM might not be available\n * @returns parsed URL object\n */\nfunction parseUrl(url) {\n if (!url) {\n return {};\n }\n var match = url.match(/^(([^:\\/?#]+):)?(\\/\\/([^\\/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$/);\n if (!match) {\n return {};\n }\n // coerce to undefined values to empty string so we don't get 'undefined'\n var query = match[6] || '';\n var fragment = match[8] || '';\n return {\n host: match[4],\n path: match[5],\n protocol: match[2],\n relative: match[5] + query + fragment,\n };\n}\nexports.parseUrl = parseUrl;\n/**\n * Extracts either message or type+value from an event that can be used for user-facing logs\n * @returns event's description\n */\nfunction getEventDescription(event) {\n if (event.message) {\n return event.message;\n }\n else if (event.exception && event.exception.values && event.exception.values[0]) {\n var exception = event.exception.values[0];\n if (exception.type && exception.value) {\n return exception.type + \": \" + exception.value;\n }\n else {\n return exception.type || exception.value || event.event_id || '';\n }\n }\n else {\n return event.event_id || '';\n }\n}\nexports.getEventDescription = getEventDescription;\n/** JSDoc */\nfunction consoleSandbox(callback) {\n var global = getGlobalObject();\n var levels = ['debug', 'info', 'warn', 'error', 'log'];\n if (!('console' in global)) {\n return callback();\n }\n var originalConsole = global.console;\n var wrappedLevels = {};\n // Restore all wrapped console methods\n levels.forEach(function (level) {\n if (level in global.console && originalConsole[level].__sentry__) {\n wrappedLevels[level] = originalConsole[level].__sentry_wrapped__;\n originalConsole[level] = originalConsole[level].__sentry_original__;\n }\n });\n // Perform callback manipulations\n var result = callback();\n // Revert restoration to wrapped state\n Object.keys(wrappedLevels).forEach(function (level) {\n originalConsole[level] = wrappedLevels[level];\n });\n return result;\n}\nexports.consoleSandbox = consoleSandbox;\n//# sourceMappingURL=misc.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar misc_1 = require(\"./misc\");\n// TODO: Implement different loggers for different environments\nvar global = misc_1.getGlobalObject();\n/** JSDoc */\nvar Logger = /** @class */ (function () {\n /** JSDoc */\n function Logger() {\n this.enabled = false;\n }\n /** JSDoc */\n Logger.prototype.disable = function () {\n this.enabled = false;\n };\n /** JSDoc */\n Logger.prototype.enable = function () {\n this.enabled = true;\n };\n /** JSDoc */\n Logger.prototype.log = function () {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n if (!this.enabled) {\n return;\n }\n misc_1.consoleSandbox(function () {\n global.console.log(\"Sentry Logger [Log]: \" + args.join(' ')); // tslint:disable-line:no-console\n });\n };\n /** JSDoc */\n Logger.prototype.warn = function () {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n if (!this.enabled) {\n return;\n }\n misc_1.consoleSandbox(function () {\n global.console.warn(\"Sentry Logger [Warn]: \" + args.join(' ')); // tslint:disable-line:no-console\n });\n };\n /** JSDoc */\n Logger.prototype.error = function () {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n if (!this.enabled) {\n return;\n }\n misc_1.consoleSandbox(function () {\n global.console.error(\"Sentry Logger [Error]: \" + args.join(' ')); // tslint:disable-line:no-console\n });\n };\n return Logger;\n}());\nvar logger = new Logger();\nexports.logger = logger;\n//# sourceMappingURL=logger.js.map","import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub';\nimport { Integration, SentryEvent, SentryEventHint } from '@sentry/types';\nimport { isError } from '@sentry/utils/is';\nimport { logger } from '../../../utils/logger';\n\n/**\n * Just an Error object with arbitrary attributes attached to it.\n */\ninterface ExtendedError extends Error {\n [key: string]: unknown;\n}\n\n/** Patch toString calls to return proper name for wrapped functions */\nexport class ExtraErrorData implements Integration {\n /**\n * @inheritDoc\n */\n public name: string = ExtraErrorData.id;\n\n /**\n * @inheritDoc\n */\n public static id: string = 'ExtraErrorData';\n\n /**\n * @inheritDoc\n */\n public setupOnce(): void {\n addGlobalEventProcessor(async (event: SentryEvent, hint?: SentryEventHint) => {\n const self = getCurrentHub().getIntegration(ExtraErrorData);\n\n if (!self || !hint || !hint.originalException) {\n return event;\n }\n\n return this.enhanceEventWithErrorData(event, hint.originalException);\n });\n }\n\n /**\n * Attaches extracted information from the Error object to extra field in the SentryEvent\n */\n public enhanceEventWithErrorData(event: SentryEvent, error: Error): SentryEvent {\n const errorData = this.extractErrorData(error);\n\n if (errorData) {\n return {\n ...event,\n extra: {\n ...event.extra,\n ...errorData,\n },\n };\n }\n\n return event;\n }\n\n /**\n * Extract extra information from the Error object\n */\n private extractErrorData(error: ExtendedError): { [key: string]: unknown } | null {\n // We are trying to enhance already existing event, so no harm done if it won't succeed\n try {\n const nativeKeys = ['name', 'message', 'stack', 'line', 'column', 'fileName', 'lineNumber', 'columnNumber'];\n const name = error.name || error.constructor.name;\n const errorKeys = Object.keys(error).filter(key => nativeKeys.indexOf(key) === -1);\n\n if (errorKeys.length) {\n const extraErrorInfo: { [key: string]: unknown } = {};\n for (const key of errorKeys) {\n let value = error[key];\n if (isError(value)) {\n value = (value as Error).name || (value as Error).constructor.name;\n }\n extraErrorInfo[key] = value;\n }\n return {\n [name]: extraErrorInfo,\n };\n }\n\n return null;\n } catch (oO) {\n logger.error('Unable to extract extra data from the Error object:', oO);\n return null;\n }\n }\n}\n","import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub';\nimport { Integration, SentryEvent, SentryEventHint } from '@sentry/types';\n\n/** JSDoc */\ninterface DebugOptions {\n stringify?: boolean;\n debugger?: boolean;\n}\n\n/** JSDoc */\nexport class Debug implements Integration {\n /**\n * @inheritDoc\n */\n public name: string = Debug.id;\n\n /**\n * @inheritDoc\n */\n public static id: string = 'Debug';\n\n /** JSDoc */\n private readonly options: DebugOptions;\n\n /**\n * @inheritDoc\n */\n public constructor(options?: DebugOptions) {\n this.options = {\n debugger: false,\n stringify: false,\n ...options,\n };\n }\n\n /**\n * @inheritDoc\n */\n public setupOnce(): void {\n addGlobalEventProcessor(async (event: SentryEvent, hint?: SentryEventHint) => {\n const self = getCurrentHub().getIntegration(Debug);\n if (self) {\n // tslint:disable:no-console\n // tslint:disable:no-debugger\n if (self.options.debugger) {\n debugger;\n }\n\n if (self.options.stringify) {\n console.log(JSON.stringify(event, null, 2));\n if (hint) {\n console.log(JSON.stringify(hint, null, 2));\n }\n } else {\n console.log(event);\n if (hint) {\n console.log(hint);\n }\n }\n }\n return event;\n });\n }\n}\n","// Slightly modified (no IE8 support, ES6) and transcribed to TypeScript\n// https://raw.githubusercontent.com/calvinmetcalf/rollup-plugin-node-builtins/master/src/es6/path.js\n\n/** JSDoc */\nfunction normalizeArray(parts: string[], allowAboveRoot?: boolean): string[] {\n // if the path tries to go above the root, `up` ends up > 0\n let up = 0;\n for (let i = parts.length - 1; i >= 0; i--) {\n const last = parts[i];\n if (last === '.') {\n parts.splice(i, 1);\n } else if (last === '..') {\n parts.splice(i, 1);\n up++;\n } else if (up) {\n parts.splice(i, 1);\n up--;\n }\n }\n\n // if the path is allowed to go above the root, restore leading ..s\n if (allowAboveRoot) {\n for (; up--; up) {\n parts.unshift('..');\n }\n }\n\n return parts;\n}\n\n// Split a filename into [root, dir, basename, ext], unix version\n// 'root' is just a slash, or nothing.\nconst splitPathRe = /^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;\n/** JSDoc */\nfunction splitPath(filename: string): string[] {\n const parts = splitPathRe.exec(filename);\n return parts ? parts.slice(1) : [];\n}\n\n// path.resolve([from ...], to)\n// posix version\n/** JSDoc */\nexport function resolve(...args: string[]): string {\n let resolvedPath = '';\n let resolvedAbsolute = false;\n\n for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n const path = i >= 0 ? args[i] : '/';\n\n // Skip empty entries\n if (!path) {\n continue;\n }\n\n resolvedPath = `${path}/${resolvedPath}`;\n resolvedAbsolute = path.charAt(0) === '/';\n }\n\n // At this point the path should be resolved to a full absolute path, but\n // handle relative paths to be safe (might happen when process.cwd() fails)\n\n // Normalize the path\n resolvedPath = normalizeArray(resolvedPath.split('/').filter(p => !!p), !resolvedAbsolute).join('/');\n\n return (resolvedAbsolute ? '/' : '') + resolvedPath || '.';\n}\n\n/** JSDoc */\nfunction trim(arr: string[]): string[] {\n let start = 0;\n for (; start < arr.length; start++) {\n if (arr[start] !== '') {\n break;\n }\n }\n\n let end = arr.length - 1;\n for (; end >= 0; end--) {\n if (arr[end] !== '') {\n break;\n }\n }\n\n if (start > end) {\n return [];\n }\n return arr.slice(start, end - start + 1);\n}\n\n// path.relative(from, to)\n// posix version\n/** JSDoc */\nexport function relative(from: string, to: string): string {\n // tslint:disable:no-parameter-reassignment\n from = resolve(from).substr(1);\n to = resolve(to).substr(1);\n\n const fromParts = trim(from.split('/'));\n const toParts = trim(to.split('/'));\n\n const length = Math.min(fromParts.length, toParts.length);\n let samePartsLength = length;\n for (let i = 0; i < length; i++) {\n if (fromParts[i] !== toParts[i]) {\n samePartsLength = i;\n break;\n }\n }\n\n let outputParts = [];\n for (let i = samePartsLength; i < fromParts.length; i++) {\n outputParts.push('..');\n }\n\n outputParts = outputParts.concat(toParts.slice(samePartsLength));\n\n return outputParts.join('/');\n}\n\n// path.normalize(path)\n// posix version\n/** JSDoc */\nexport function normalize(path: string): string {\n const isPathAbsolute = isAbsolute(path);\n const trailingSlash = path.substr(-1) === '/';\n\n // Normalize the path\n let normalizedPath = normalizeArray(path.split('/').filter(p => !!p), !isPathAbsolute).join('/');\n\n if (!normalizedPath && !isPathAbsolute) {\n normalizedPath = '.';\n }\n if (normalizedPath && trailingSlash) {\n normalizedPath += '/';\n }\n\n return (isPathAbsolute ? '/' : '') + normalizedPath;\n}\n\n// posix version\n/** JSDoc */\nexport function isAbsolute(path: string): boolean {\n return path.charAt(0) === '/';\n}\n\n// posix version\n/** JSDoc */\nexport function join(...args: string[]): string {\n return normalize(args.join('/'));\n}\n\n/** JSDoc */\nexport function dirname(path: string): string {\n const result = splitPath(path);\n const root = result[0];\n let dir = result[1];\n\n if (!root && !dir) {\n // No dirname whatsoever\n return '.';\n }\n\n if (dir) {\n // It has a dirname, strip trailing slash\n dir = dir.substr(0, dir.length - 1);\n }\n\n return root + dir;\n}\n\n/** JSDoc */\nexport function basename(path: string, ext?: string): string {\n let f = splitPath(path)[2];\n if (ext && f.substr(ext.length * -1) === ext) {\n f = f.substr(0, f.length - ext.length);\n }\n return f;\n}\n","import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub';\nimport { Integration, SentryEvent, StackFrame } from '@sentry/types';\nimport { basename, relative } from '@sentry/utils/path';\n\ntype StackFrameIteratee = (frame: StackFrame) => Promise;\n\n/** Rewrite event frames paths */\nexport class RewriteFrames implements Integration {\n /**\n * @inheritDoc\n */\n public name: string = RewriteFrames.id;\n\n /**\n * @inheritDoc\n */\n public static id: string = 'RewriteFrames';\n\n /**\n * @inheritDoc\n */\n private readonly root?: string;\n\n /**\n * @inheritDoc\n */\n private readonly iteratee: StackFrameIteratee = async (frame: StackFrame) => {\n if (frame.filename && frame.filename.startsWith('/')) {\n const base = this.root ? relative(this.root, frame.filename) : basename(frame.filename);\n frame.filename = `app:///${base}`;\n }\n return frame;\n };\n\n /**\n * @inheritDoc\n */\n public constructor(options: { root?: string; iteratee?: StackFrameIteratee } = {}) {\n if (options.root) {\n this.root = options.root;\n }\n if (options.iteratee) {\n this.iteratee = options.iteratee;\n }\n }\n\n /**\n * @inheritDoc\n */\n public setupOnce(): void {\n addGlobalEventProcessor(async event => {\n const self = getCurrentHub().getIntegration(RewriteFrames);\n if (self) {\n return self.process(event);\n }\n return event;\n });\n }\n\n /** JSDoc */\n public async process(event: SentryEvent): Promise {\n const frames = this.getFramesFromEvent(event);\n if (frames) {\n for (const i in frames) {\n // tslint:disable-next-line\n frames[i] = await this.iteratee(frames[i]);\n }\n }\n return event;\n }\n\n /** JSDoc */\n private getFramesFromEvent(event: SentryEvent): StackFrame[] | undefined {\n const exception = event.exception;\n\n if (exception) {\n try {\n // tslint:disable-next-line:no-unsafe-any\n return (exception as any).values[0].stacktrace.frames;\n } catch (_oO) {\n return undefined;\n }\n } else if (event.stacktrace) {\n return event.stacktrace.frames;\n } else {\n return undefined;\n }\n }\n}\n","import { getGlobalObject } from './misc';\n\n/**\n * Tells whether current environment supports ErrorEvent objects\n * {@link supportsErrorEvent}.\n *\n * @returns Answer to the given question.\n */\nexport function supportsErrorEvent(): boolean {\n try {\n // tslint:disable:no-unused-expression\n new ErrorEvent('');\n return true;\n } catch (e) {\n return false;\n }\n}\n\n/**\n * Tells whether current environment supports DOMError objects\n * {@link supportsDOMError}.\n *\n * @returns Answer to the given question.\n */\nexport function supportsDOMError(): boolean {\n try {\n // It really needs 1 argument, not 0.\n // Chrome: VM89:1 Uncaught TypeError: Failed to construct 'DOMError':\n // 1 argument required, but only 0 present.\n // @ts-ignore\n // tslint:disable:no-unused-expression\n new DOMError('');\n return true;\n } catch (e) {\n return false;\n }\n}\n\n/**\n * Tells whether current environment supports DOMException objects\n * {@link supportsDOMException}.\n *\n * @returns Answer to the given question.\n */\nexport function supportsDOMException(): boolean {\n try {\n // tslint:disable:no-unused-expression\n new DOMException('');\n return true;\n } catch (e) {\n return false;\n }\n}\n\n/**\n * Tells whether current environment supports Fetch API\n * {@link supportsFetch}.\n *\n * @returns Answer to the given question.\n */\nexport function supportsFetch(): boolean {\n if (!('fetch' in getGlobalObject())) {\n return false;\n }\n\n try {\n // tslint:disable-next-line:no-unused-expression\n new Headers();\n // tslint:disable-next-line:no-unused-expression\n new Request('');\n // tslint:disable-next-line:no-unused-expression\n new Response();\n return true;\n } catch (e) {\n return false;\n }\n}\n\n/**\n * Tells whether current environment supports Fetch API natively\n * {@link supportsNativeFetch}.\n *\n * @returns Answer to the given question.\n */\nexport function supportsNativeFetch(): boolean {\n if (!supportsFetch()) {\n return false;\n }\n const global = getGlobalObject();\n const fetch = (global as any).fetch;\n // tslint:disable-next-line:no-unsafe-any\n return fetch.toString().indexOf('native') !== -1;\n}\n\n/**\n * Tells whether current environment supports sendBeacon API\n * {@link supportsBeacon}.\n *\n * @returns Answer to the given question.\n */\nexport function supportsBeacon(): boolean {\n const global = getGlobalObject();\n return 'navigator' in global && 'sendBeacon' in global.navigator;\n}\n\n/**\n * Tells whether current environment supports ReportingObserver API\n * {@link supportsReportingObserver}.\n *\n * @returns Answer to the given question.\n */\nexport function supportsReportingObserver(): boolean {\n return 'ReportingObserver' in getGlobalObject();\n}\n\n/**\n * Tells whether current environment supports Referrer Policy API\n * {@link supportsReferrerPolicy}.\n *\n * @returns Answer to the given question.\n */\nexport function supportsReferrerPolicy(): boolean {\n // Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default\n // https://caniuse.com/#feat=referrer-policy\n // It doesn't. And it throw exception instead of ignoring this parameter...\n // REF: https://github.com/getsentry/raven-js/issues/1233\n\n if (!supportsFetch()) {\n return false;\n }\n\n try {\n // tslint:disable:no-unused-expression\n new Request('pickleRick', {\n referrerPolicy: 'origin' as ReferrerPolicy,\n });\n return true;\n } catch (e) {\n return false;\n }\n}\n\n/**\n * Tells whether current environment supports History API\n * {@link supportsHistory}.\n *\n * @returns Answer to the given question.\n */\nexport function supportsHistory(): boolean {\n // NOTE: in Chrome App environment, touching history.pushState, *even inside\n // a try/catch block*, will cause Chrome to output an error to console.error\n // borrowed from: https://github.com/angular/angular.js/pull/13945/files\n const global = getGlobalObject();\n const chrome = (global as any).chrome;\n // tslint:disable-next-line:no-unsafe-any\n const isChromePackagedApp = chrome && chrome.app && chrome.app.runtime;\n const hasHistoryApi = 'history' in global && !!global.history.pushState && !!global.history.replaceState;\n\n return !isChromePackagedApp && hasHistoryApi;\n}\n","// tslint:disable\n\n/*\n * JavaScript MD5\n * https://github.com/blueimp/JavaScript-MD5\n *\n * Copyright 2011, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * https://opensource.org/licenses/MIT\n *\n * Based on\n * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message\n * Digest Algorithm, as defined in RFC 1321.\n * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009\n * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n * Distributed under the BSD License\n * See http://pajhome.org.uk/crypt/md5 for more info.\n */\n\n/**\n * Add integers, wrapping at 2^32. This uses 16-bit operations internally\n * to work around bugs in some JS interpreters.\n */\nfunction safeAdd(x: number, y: number) {\n const lsw = (x & 0xffff) + (y & 0xffff);\n const msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n return (msw << 16) | (lsw & 0xffff);\n}\n\n/**\n * Bitwise rotate a 32-bit number to the left.\n */\nfunction bitRotateLeft(num: number, cnt: number) {\n return (num << cnt) | (num >>> (32 - cnt));\n}\n\n/**\n * These functions implement the four basic operations the algorithm uses.\n */\nfunction md5cmn(q: number, a: number, b: number, x: number, s: number, t: number) {\n return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);\n}\nfunction md5ff(a: number, b: number, c: number, d: number, x: number, s: number, t: number) {\n return md5cmn((b & c) | (~b & d), a, b, x, s, t);\n}\nfunction md5gg(a: number, b: number, c: number, d: number, x: number, s: number, t: number) {\n return md5cmn((b & d) | (c & ~d), a, b, x, s, t);\n}\nfunction md5hh(a: number, b: number, c: number, d: number, x: number, s: number, t: number) {\n return md5cmn(b ^ c ^ d, a, b, x, s, t);\n}\nfunction md5ii(a: number, b: number, c: number, d: number, x: number, s: number, t: number) {\n return md5cmn(c ^ (b | ~d), a, b, x, s, t);\n}\n\n/**\n * Calculate the MD5 of an array of little-endian words, and a bit length.\n */\nfunction binlMD5(x: any[], len: number) {\n /** append padding */\n x[len >> 5] |= 0x80 << len % 32;\n x[(((len + 64) >>> 9) << 4) + 14] = len;\n\n let i;\n let olda;\n let oldb;\n let oldc;\n let oldd;\n let a = 1732584193;\n let b = -271733879;\n let c = -1732584194;\n let d = 271733878;\n\n for (i = 0; i < x.length; i += 16) {\n olda = a;\n oldb = b;\n oldc = c;\n oldd = d;\n\n a = md5ff(a, b, c, d, x[i], 7, -680876936);\n d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);\n c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);\n b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);\n a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);\n d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);\n c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);\n b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);\n a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);\n d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);\n c = md5ff(c, d, a, b, x[i + 10], 17, -42063);\n b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);\n a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);\n d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);\n c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);\n b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);\n\n a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);\n d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);\n c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);\n b = md5gg(b, c, d, a, x[i], 20, -373897302);\n a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);\n d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);\n c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);\n b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);\n a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);\n d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);\n c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);\n b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);\n a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);\n d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);\n c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);\n b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);\n\n a = md5hh(a, b, c, d, x[i + 5], 4, -378558);\n d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);\n c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);\n b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);\n a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);\n d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);\n c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);\n b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);\n a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);\n d = md5hh(d, a, b, c, x[i], 11, -358537222);\n c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);\n b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);\n a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);\n d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);\n c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);\n b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);\n\n a = md5ii(a, b, c, d, x[i], 6, -198630844);\n d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);\n c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);\n b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);\n a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);\n d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);\n c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);\n b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);\n a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);\n d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);\n c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);\n b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);\n a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);\n d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);\n c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);\n b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);\n\n a = safeAdd(a, olda);\n b = safeAdd(b, oldb);\n c = safeAdd(c, oldc);\n d = safeAdd(d, oldd);\n }\n return [a, b, c, d];\n}\n\n/**\n * Convert an array of little-endian words to a string\n */\nfunction binl2rstr(input: any[]) {\n let i;\n let output = '';\n const length32 = input.length * 32;\n for (i = 0; i < length32; i += 8) {\n output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff);\n }\n return output;\n}\n\n/**\n * Convert a raw string to an array of little-endian words\n * Characters >255 have their high-byte silently ignored.\n */\nfunction rstr2binl(input: string) {\n let i;\n const output: any[] = [];\n output[(input.length >> 2) - 1] = undefined;\n for (i = 0; i < output.length; i += 1) {\n output[i] = 0;\n }\n const length8 = input.length * 8;\n for (i = 0; i < length8; i += 8) {\n output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32;\n }\n return output;\n}\n\n/**\n * Calculate the MD5 of a raw string\n */\nfunction rstrMD5(s: string) {\n return binl2rstr(binlMD5(rstr2binl(s), s.length * 8));\n}\n\n/**\n * Calculate the HMAC-MD5, of a key and some data (raw strings)\n */\nfunction rstrHMACMD5(key: string, data: string) {\n let i;\n let bkey = rstr2binl(key);\n const ipad = [];\n const opad = [];\n let hash;\n ipad[15] = opad[15] = undefined;\n if (bkey.length > 16) {\n bkey = binlMD5(bkey, key.length * 8);\n }\n for (i = 0; i < 16; i += 1) {\n ipad[i] = bkey[i] ^ 0x36363636;\n opad[i] = bkey[i] ^ 0x5c5c5c5c;\n }\n hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);\n return binl2rstr(binlMD5(opad.concat(hash), 512 + 128));\n}\n\n/**\n * Convert a raw string to a hex string\n */\nfunction rstr2hex(input: string) {\n const hexTab = '0123456789abcdef';\n let output = '';\n let x;\n let i;\n for (i = 0; i < input.length; i += 1) {\n x = input.charCodeAt(i);\n output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f);\n }\n return output;\n}\n\n/**\n * Encode a string as utf-8\n */\nfunction str2rstrUTF8(input: string) {\n return unescape(encodeURIComponent(input));\n}\n\n/*\n * Take string arguments and return either raw or hex encoded strings\n */\nfunction rawMD5(s: string) {\n return rstrMD5(str2rstrUTF8(s));\n}\nfunction hexMD5(s: string) {\n return rstr2hex(rawMD5(s));\n}\nfunction rawHMACMD5(k: string, d: string) {\n return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d));\n}\nfunction hexHMACMD5(k: string, d: string) {\n return rstr2hex(rawHMACMD5(k, d));\n}\n\nfunction md5(string: string, key?: string, raw?: boolean) {\n if (!key) {\n if (!raw) {\n return hexMD5(string);\n }\n return rawMD5(string);\n }\n if (!raw) {\n return hexHMACMD5(key, string);\n }\n return rawHMACMD5(key, string);\n}\n\nexport { md5 };\n","// tslint:disable\n\nimport { isUndefined, isError, isErrorEvent } from '@sentry/utils/is';\nimport { getGlobalObject } from '@sentry/utils/misc';\n\nexport interface StackFrame {\n url: string;\n func: string;\n args: string[];\n line: number;\n column: number;\n context: string[];\n}\n\nexport interface StackTrace {\n /**\n * Known modes: callers, failed, multiline, onerror, stack, stacktrace\n */\n mode: string;\n mechanism: string;\n name: string;\n message: string;\n url: string;\n stack: StackFrame[];\n useragent: string;\n}\n\ninterface ComputeStackTrace {\n /**\n * Computes a stack trace for an exception.\n * @param {Error} ex\n * @param {(string|number)=} depth\n */\n (ex: Error, depth?: string | number): StackTrace;\n\n /**\n * Adds information about the first frame to incomplete stack traces.\n * Safari and IE require this to get complete data on the first frame.\n * @param {Object.} stackInfo Stack trace information from\n * one of the compute* methods.\n * @param {string} url The URL of the script that caused an error.\n * @param {(number|string)} lineNo The line number of the script that\n * caused an error.\n * @param {string=} message The error generated by the browser, which\n * hopefully contains the name of the object that caused the error.\n * @return {boolean} Whether or not the stack information was\n * augmented.\n */\n augmentStackTraceWithInitialElement: (\n stackInfo: string,\n url: string,\n lineNo: string | number,\n message?: string,\n ) => boolean;\n\n /**\n * Tries to use an externally loaded copy of source code to determine\n * the name of a function by looking at the name of the variable it was\n * assigned to, if any.\n * @param {string} url URL of source code.\n * @param {(string|number)} lineNo Line number in source code.\n * @return {string} The function name, if discoverable.\n */\n guessFunctionName: (url: string, lineNo: string | number) => string;\n\n /**\n * Retrieves the surrounding lines from where an exception occurred.\n * @param {string} url URL of source code.\n * @param {(string|number)} line Line number in source code to centre\n * around for context.\n * @return {?Array.} Lines of source code.\n */\n gatherContext: (url: string, line: string | number) => string[];\n\n /**\n * Logs a stacktrace starting from the previous call and working down.\n * @param {(number|string)=} depth How many frames deep to trace.\n * @return {Object.} Stack trace information.\n */\n ofCaller: (depth?: string | number) => StackTrace;\n\n /**\n * Retrieves source code from the source code cache.\n * @param {string} url URL of source code.\n * @return {Array.} Source contents.\n */\n getSource: (url: string) => string[];\n}\n\ninterface ReportSubscriber {\n (stackTrace: StackTrace, isWindowError: boolean, error: any): void;\n}\n\ninterface Report {\n /**\n * Reports an unhandled Error to TraceKit.\n * @param {Error} ex\n */\n (ex: Error): void;\n\n /**\n * Add a crash handler.\n * @param {Function} handler\n */\n subscribe(handler: ReportSubscriber): void;\n\n /**\n * Remove a crash handler.\n * @param {Function} handler\n */\n unsubscribe(handler: ReportSubscriber): void;\n}\n\n/**\n * TraceKit - Cross brower stack traces\n *\n * This was originally forked from github.com/occ/TraceKit, but has since been\n * largely modified and is now maintained as part of Sentry JS SDK.\n *\n * NOTE: Last merge with upstream repository\n * Jul 11,2018 - #f03357c\n *\n * https://github.com/csnover/TraceKit\n * @license MIT\n * @namespace TraceKit\n */\n\nvar window = getGlobalObject() as Window;\n\ninterface TraceKit {\n wrap(func: () => void): () => void;\n report: any;\n collectWindowErrors: any;\n computeStackTrace: any;\n remoteFetching: any;\n linesOfContext: any;\n extendToAsynchronousCallbacks: any;\n}\n\nvar TraceKit: TraceKit = {\n wrap: () => () => {},\n report: false,\n collectWindowErrors: false,\n computeStackTrace: false,\n remoteFetching: false,\n linesOfContext: false,\n extendToAsynchronousCallbacks: false,\n};\n\n// var TraceKit: TraceKitInterface = {};\n// var TraceKit = {};\n\n// global reference to slice\nvar _slice = [].slice;\nvar UNKNOWN_FUNCTION = '?';\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types\nvar ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/;\n\n/**\n * A better form of hasOwnProperty
\n * Example: `_has(MainHostObject, property) === true/false`\n *\n * @param {Object} object to check property\n * @param {string} key to check\n * @return {Boolean} true if the object has the key and it is not inherited\n */\nfunction _has(object: any, key: any) {\n return Object.prototype.hasOwnProperty.call(object, key);\n}\n\n/**\n * A safe form of location.href
\n *\n * @return {string} location.href\n */\nfunction getLocationHref() {\n if (typeof document === 'undefined' || document.location == null) return '';\n return document.location.href;\n}\n\n/**\n * A safe form of location.origin
\n *\n * @return {string} location.origin\n */\nfunction getLocationOrigin() {\n if (typeof document === 'undefined' || document.location == null) return '';\n\n // Oh dear IE10...\n if (!document.location.origin) {\n return (\n document.location.protocol +\n '//' +\n document.location.hostname +\n (document.location.port ? ':' + document.location.port : '')\n );\n }\n\n return document.location.origin;\n}\n\n/**\n * Wrap any function in a TraceKit reporter
\n * Example: `func = TraceKit.wrap(func);`\n *\n * @param {Function} func Function to be wrapped\n * @return {Function} The wrapped func\n * @memberof TraceKit\n */\nTraceKit.wrap = function traceKitWrapper(func: any) {\n function wrapped() {\n try {\n // @ts-ignore\n return func.apply(this, arguments);\n } catch (e) {\n TraceKit.report(e);\n throw e;\n }\n }\n return wrapped;\n};\n\n/**\n * Cross-browser processing of unhandled exceptions\n *\n * Syntax:\n * ```js\n * TraceKit.report.subscribe(function(stackInfo) { ... })\n * TraceKit.report.unsubscribe(function(stackInfo) { ... })\n * TraceKit.report(exception)\n * try { ...code... } catch(ex) { TraceKit.report(ex); }\n * ```\n *\n * Supports:\n * - Firefox: full stack trace with line numbers, plus column number\n * on top frame; column number is not guaranteed\n * - Opera: full stack trace with line and column numbers\n * - Chrome: full stack trace with line and column numbers\n * - Safari: line and column number for the top frame only; some frames\n * may be missing, and column number is not guaranteed\n * - IE: line and column number for the top frame only; some frames\n * may be missing, and column number is not guaranteed\n *\n * In theory, TraceKit should work on all of the following versions:\n * - IE5.5+ (only 8.0 tested)\n * - Firefox 0.9+ (only 3.5+ tested)\n * - Opera 7+ (only 10.50 tested; versions 9 and earlier may require\n * Exceptions Have Stacktrace to be enabled in opera:config)\n * - Safari 3+ (only 4+ tested)\n * - Chrome 1+ (only 5+ tested)\n * - Konqueror 3.5+ (untested)\n *\n * Requires TraceKit.computeStackTrace.\n *\n * Tries to catch all unhandled exceptions and report them to the\n * subscribed handlers. Please note that TraceKit.report will rethrow the\n * exception. This is REQUIRED in order to get a useful stack trace in IE.\n * If the exception does not reach the top of the browser, you will only\n * get a stack trace from the point where TraceKit.report was called.\n *\n * Handlers receive a TraceKit.StackTrace object as described in the\n * TraceKit.computeStackTrace docs.\n *\n * @memberof TraceKit\n * @namespace\n */\nTraceKit.report = (function reportModuleWrapper() {\n var handlers: any = [],\n lastException: any = null,\n lastExceptionStack: any = null;\n\n /**\n * Add a crash handler.\n * @param {Function} handler\n * @memberof TraceKit.report\n */\n function subscribe(handler: any) {\n // NOTE: We call both handlers manually in browser/integrations/globalhandler.ts\n // So user can choose which one he wants to attach\n\n // installGlobalHandler();\n // installGlobalUnhandledRejectionHandler();\n handlers.push(handler);\n }\n\n /**\n * Remove a crash handler.\n * @param {Function} handler\n * @memberof TraceKit.report\n */\n function unsubscribe(handler: any) {\n for (var i = handlers.length - 1; i >= 0; --i) {\n if (handlers[i] === handler) {\n handlers.splice(i, 1);\n }\n }\n\n if (handlers.length === 0) {\n uninstallGlobalHandler();\n uninstallGlobalUnhandledRejectionHandler();\n }\n }\n\n /**\n * Dispatch stack information to all handlers.\n * @param {TraceKit.StackTrace} stack\n * @param {boolean} isWindowError Is this a top-level window error?\n * @param {Error=} error The error that's being handled (if available, null otherwise)\n * @memberof TraceKit.report\n * @throws An exception if an error occurs while calling an handler.\n */\n function notifyHandlers(stack: any, isWindowError: any, error: any) {\n var exception = null;\n if (isWindowError && !TraceKit.collectWindowErrors) {\n return;\n }\n for (var i in handlers) {\n if (_has(handlers, i)) {\n try {\n handlers[i](stack, isWindowError, error);\n } catch (inner) {\n exception = inner;\n }\n }\n }\n\n if (exception) {\n throw exception;\n }\n }\n\n var _oldOnerrorHandler: any, _onErrorHandlerInstalled: any;\n var _oldOnunhandledrejectionHandler: any, _onUnhandledRejectionHandlerInstalled: any;\n\n /**\n * Ensures all global unhandled exceptions are recorded.\n * Supported by Gecko and IE.\n * @param {string} message Error message.\n * @param {string} url URL of script that generated the exception.\n * @param {(number|string)} lineNo The line number at which the error occurred.\n * @param {(number|string)=} columnNo The column number at which the error occurred.\n * @param {Error=} errorObj The actual Error object.\n * @memberof TraceKit.report\n */\n function traceKitWindowOnError(message: any, url: any, lineNo: any, columnNo: any, errorObj: any) {\n var stack = null;\n // If 'errorObj' is ErrorEvent, get real Error from inside\n errorObj = isErrorEvent(errorObj) ? errorObj.error : errorObj;\n // If 'message' is ErrorEvent, get real message from inside\n message = isErrorEvent(message) ? message.message : message;\n\n if (lastExceptionStack) {\n TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(lastExceptionStack, url, lineNo, message);\n processLastException();\n } else if (errorObj && isError(errorObj)) {\n stack = TraceKit.computeStackTrace(errorObj);\n stack.mechanism = 'onerror';\n notifyHandlers(stack, true, errorObj);\n } else {\n var location: any = {\n url: url,\n line: lineNo,\n column: columnNo,\n };\n\n var name;\n var msg = message; // must be new var or will modify original `arguments`\n if ({}.toString.call(message) === '[object String]') {\n var groups = message.match(ERROR_TYPES_RE);\n if (groups) {\n name = groups[1];\n msg = groups[2];\n }\n }\n\n location.func = TraceKit.computeStackTrace.guessFunctionName(location.url, location.line);\n location.context = TraceKit.computeStackTrace.gatherContext(location.url, location.line);\n stack = {\n name: name,\n message: msg,\n mode: 'onerror',\n mechanism: 'onerror',\n stack: [\n {\n ...location,\n // Firefox sometimes doesn't return url correctly and this is an old behavior\n // that I prefer to port here as well.\n // It can be altered only here, as previously it's using `location.url` for other things — Kamil\n url: location.url || getLocationHref(),\n },\n ],\n };\n\n notifyHandlers(stack, true, null);\n }\n\n if (_oldOnerrorHandler) {\n // @ts-ignore\n return _oldOnerrorHandler.apply(this, arguments);\n }\n\n return false;\n }\n\n /**\n * Ensures all unhandled rejections are recorded.\n * @param {PromiseRejectionEvent} e event.\n * @memberof TraceKit.report\n * @see https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onunhandledrejection\n * @see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent\n */\n function traceKitWindowOnUnhandledRejection(e: any) {\n var err = (e && (e.detail ? e.detail.reason : e.reason)) || e;\n var stack = TraceKit.computeStackTrace(err);\n stack.mechanism = 'onunhandledrejection';\n notifyHandlers(stack, true, err);\n }\n\n /**\n * Install a global onerror handler\n * @memberof TraceKit.report\n */\n function installGlobalHandler() {\n if (_onErrorHandlerInstalled === true) {\n return;\n }\n\n _oldOnerrorHandler = window.onerror;\n window.onerror = traceKitWindowOnError;\n _onErrorHandlerInstalled = true;\n }\n\n /**\n * Uninstall the global onerror handler\n * @memberof TraceKit.report\n */\n function uninstallGlobalHandler() {\n if (_onErrorHandlerInstalled) {\n window.onerror = _oldOnerrorHandler;\n _onErrorHandlerInstalled = false;\n }\n }\n\n /**\n * Install a global onunhandledrejection handler\n * @memberof TraceKit.report\n */\n function installGlobalUnhandledRejectionHandler() {\n if (_onUnhandledRejectionHandlerInstalled === true) {\n return;\n }\n\n _oldOnunhandledrejectionHandler = (window as any).onunhandledrejection;\n (window as any).onunhandledrejection = traceKitWindowOnUnhandledRejection;\n _onUnhandledRejectionHandlerInstalled = true;\n }\n\n /**\n * Uninstall the global onunhandledrejection handler\n * @memberof TraceKit.report\n */\n function uninstallGlobalUnhandledRejectionHandler() {\n if (_onUnhandledRejectionHandlerInstalled) {\n window.onerror = _oldOnunhandledrejectionHandler;\n _onUnhandledRejectionHandlerInstalled = false;\n }\n }\n\n /**\n * Process the most recent exception\n * @memberof TraceKit.report\n */\n function processLastException() {\n var _lastExceptionStack = lastExceptionStack,\n _lastException = lastException;\n lastExceptionStack = null;\n lastException = null;\n notifyHandlers(_lastExceptionStack, false, _lastException);\n }\n\n /**\n * Reports an unhandled Error to TraceKit.\n * @param {Error} ex\n * @memberof TraceKit.report\n * @throws An exception if an incomplete stack trace is detected (old IE browsers).\n */\n function report(ex: any) {\n if (lastExceptionStack) {\n if (lastException === ex) {\n return; // already caught by an inner catch block, ignore\n } else {\n processLastException();\n }\n }\n\n var stack = TraceKit.computeStackTrace(ex);\n lastExceptionStack = stack;\n lastException = ex;\n\n // If the stack trace is incomplete, wait for 2 seconds for\n // slow slow IE to see if onerror occurs or not before reporting\n // this exception; otherwise, we will end up with an incomplete\n // stack trace\n setTimeout(\n function() {\n if (lastException === ex) {\n processLastException();\n }\n },\n stack.incomplete ? 2000 : 0,\n );\n\n throw ex; // re-throw to propagate to the top level (and cause window.onerror)\n }\n\n (report as any).subscribe = subscribe;\n (report as any).unsubscribe = unsubscribe;\n (report as any).installGlobalHandler = installGlobalHandler;\n (report as any).installGlobalUnhandledRejectionHandler = installGlobalUnhandledRejectionHandler;\n\n return report;\n})();\n\n/**\n * An object representing a single stack frame.\n * @typedef {Object} StackFrame\n * @property {string} url The JavaScript or HTML file URL.\n * @property {string} func The function name, or empty for anonymous functions (if guessing did not work).\n * @property {string[]?} args The arguments passed to the function, if known.\n * @property {number=} line The line number, if known.\n * @property {number=} column The column number, if known.\n * @property {string[]} context An array of source code lines; the middle element corresponds to the correct line#.\n * @memberof TraceKit\n */\n\n/**\n * An object representing a JavaScript stack trace.\n * @typedef {Object} StackTrace\n * @property {string} name The name of the thrown exception.\n * @property {string} message The exception error message.\n * @property {TraceKit.StackFrame[]} stack An array of stack frames.\n * @property {string} mode 'stack', 'stacktrace', 'multiline', 'callers', 'onerror', or 'failed' -- method used to collect the stack trace.\n * @memberof TraceKit\n */\n\n/**\n * TraceKit.computeStackTrace: cross-browser stack traces in JavaScript\n *\n * Syntax:\n * ```js\n * s = TraceKit.computeStackTrace.ofCaller([depth])\n * s = TraceKit.computeStackTrace(exception) // consider using TraceKit.report instead (see below)\n * ```\n *\n * Supports:\n * - Firefox: full stack trace with line numbers and unreliable column\n * number on top frame\n * - Opera 10: full stack trace with line and column numbers\n * - Opera 9-: full stack trace with line numbers\n * - Chrome: full stack trace with line and column numbers\n * - Safari: line and column number for the topmost stacktrace element\n * only\n * - IE: no line numbers whatsoever\n *\n * Tries to guess names of anonymous functions by looking for assignments\n * in the source code. In IE and Safari, we have to guess source file names\n * by searching for function bodies inside all page scripts. This will not\n * work for scripts that are loaded cross-domain.\n * Here be dragons: some function names may be guessed incorrectly, and\n * duplicate functions may be mismatched.\n *\n * TraceKit.computeStackTrace should only be used for tracing purposes.\n * Logging of unhandled exceptions should be done with TraceKit.report,\n * which builds on top of TraceKit.computeStackTrace and provides better\n * IE support by utilizing the window.onerror event to retrieve information\n * about the top of the stack.\n *\n * Note: In IE and Safari, no stack trace is recorded on the Error object,\n * so computeStackTrace instead walks its *own* chain of callers.\n * This means that:\n * * in Safari, some methods may be missing from the stack trace;\n * * in IE, the topmost function in the stack trace will always be the\n * caller of computeStackTrace.\n *\n * This is okay for tracing (because you are likely to be calling\n * computeStackTrace from the function you want to be the topmost element\n * of the stack trace anyway), but not okay for logging unhandled\n * exceptions (because your catch block will likely be far away from the\n * inner function that actually caused the exception).\n *\n * Tracing example:\n * ```js\n * function trace(message) {\n * var stackInfo = TraceKit.computeStackTrace.ofCaller();\n * var data = message + \"\\n\";\n * for(var i in stackInfo.stack) {\n * var item = stackInfo.stack[i];\n * data += (item.func || '[anonymous]') + \"() in \" + item.url + \":\" + (item.line || '0') + \"\\n\";\n * }\n * if (window.console)\n * console.info(data);\n * else\n * alert(data);\n * }\n * ```\n * @memberof TraceKit\n * @namespace\n */\nTraceKit.computeStackTrace = (function computeStackTraceWrapper() {\n var debug = false,\n sourceCache = {};\n\n /**\n * Attempts to retrieve source code via XMLHttpRequest, which is used\n * to look up anonymous function names.\n * @param {string} url URL of source code.\n * @return {string} Source contents.\n * @memberof TraceKit.computeStackTrace\n */\n function loadSource(url: any) {\n if (!TraceKit.remoteFetching) {\n //Only attempt request if remoteFetching is on.\n return '';\n }\n try {\n var getXHR = function() {\n try {\n return new (window as any).XMLHttpRequest();\n } catch (e) {\n // explicitly bubble up the exception if not found\n return new (window as any).ActiveXObject('Microsoft.XMLHTTP');\n }\n };\n\n var request = getXHR();\n request.open('GET', url, false);\n request.send('');\n return request.responseText;\n } catch (e) {\n return '';\n }\n }\n\n /**\n * Retrieves source code from the source code cache.\n * @param {string} url URL of source code.\n * @return {Array.} Source contents.\n * @memberof TraceKit.computeStackTrace\n */\n function getSource(url: any) {\n if (typeof url !== 'string') {\n return [];\n }\n\n if (!_has(sourceCache, url)) {\n // URL needs to be able to fetched within the acceptable domain. Otherwise,\n // cross-domain errors will be triggered.\n /*\n Regex matches:\n 0 - Full Url\n 1 - Protocol\n 2 - Domain\n 3 - Port (Useful for internal applications)\n 4 - Path\n */\n var source = '';\n var domain = '';\n try {\n domain = window.document.domain;\n } catch (e) {}\n var match = /(.*)\\:\\/\\/([^:\\/]+)([:\\d]*)\\/{0,1}([\\s\\S]*)/.exec(url);\n if (match && match[2] === domain) {\n source = loadSource(url);\n }\n (sourceCache as any)[url] = source ? source.split('\\n') : [];\n }\n\n return (sourceCache as any)[url];\n }\n\n /**\n * Tries to use an externally loaded copy of source code to determine\n * the name of a function by looking at the name of the variable it was\n * assigned to, if any.\n * @param {string} url URL of source code.\n * @param {(string|number)} lineNo Line number in source code.\n * @return {string} The function name, if discoverable.\n * @memberof TraceKit.computeStackTrace\n */\n function guessFunctionName(url: any, lineNo: any) {\n var reFunctionArgNames = /function ([^(]*)\\(([^)]*)\\)/,\n reGuessFunction = /['\"]?([0-9A-Za-z$_]+)['\"]?\\s*[:=]\\s*(function|eval|new Function)/,\n line = '',\n maxLines = 10,\n source = getSource(url),\n m;\n\n if (!source.length) {\n return UNKNOWN_FUNCTION;\n }\n\n // Walk backwards from the first line in the function until we find the line which\n // matches the pattern above, which is the function definition\n for (var i = 0; i < maxLines; ++i) {\n line = source[lineNo - i] + line;\n\n if (!isUndefined(line)) {\n if ((m = reGuessFunction.exec(line))) {\n return m[1];\n } else if ((m = reFunctionArgNames.exec(line))) {\n return m[1];\n }\n }\n }\n\n return UNKNOWN_FUNCTION;\n }\n\n /**\n * Retrieves the surrounding lines from where an exception occurred.\n * @param {string} url URL of source code.\n * @param {(string|number)} line Line number in source code to center around for context.\n * @return {?Array.} Lines of source code.\n * @memberof TraceKit.computeStackTrace\n */\n function gatherContext(url: any, line: any) {\n var source = getSource(url);\n\n if (!source.length) {\n return null;\n }\n\n var context = [],\n // linesBefore & linesAfter are inclusive with the offending line.\n // if linesOfContext is even, there will be one extra line\n // *before* the offending line.\n linesBefore = Math.floor(TraceKit.linesOfContext / 2),\n // Add one extra line if linesOfContext is odd\n linesAfter = linesBefore + (TraceKit.linesOfContext % 2),\n start = Math.max(0, line - linesBefore - 1),\n end = Math.min(source.length, line + linesAfter - 1);\n\n line -= 1; // convert to 0-based index\n\n for (var i = start; i < end; ++i) {\n if (!isUndefined(source[i])) {\n context.push(source[i]);\n }\n }\n\n return context.length > 0 ? context : null;\n }\n\n /**\n * Escapes special characters, except for whitespace, in a string to be\n * used inside a regular expression as a string literal.\n * @param {string} text The string.\n * @return {string} The escaped string literal.\n * @memberof TraceKit.computeStackTrace\n */\n function escapeRegExp(text: any) {\n return text.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#]/g, '\\\\$&');\n }\n\n /**\n * Escapes special characters in a string to be used inside a regular\n * expression as a string literal. Also ensures that HTML entities will\n * be matched the same as their literal friends.\n * @param {string} body The string.\n * @return {string} The escaped string.\n * @memberof TraceKit.computeStackTrace\n */\n function escapeCodeAsRegExpForMatchingInsideHTML(body: any) {\n return escapeRegExp(body)\n .replace('<', '(?:<|<)')\n .replace('>', '(?:>|>)')\n .replace('&', '(?:&|&)')\n .replace('\"', '(?:\"|")')\n .replace(/\\s+/g, '\\\\s+');\n }\n\n /**\n * Determines where a code fragment occurs in the source code.\n * @param {RegExp} re The function definition.\n * @param {Array.} urls A list of URLs to search.\n * @return {?Object.} An object containing\n * the url, line, and column number of the defined function.\n * @memberof TraceKit.computeStackTrace\n */\n function findSourceInUrls(re: any, urls: any) {\n var source, m;\n for (var i = 0, j = urls.length; i < j; ++i) {\n if ((source = getSource(urls[i])).length) {\n source = source.join('\\n');\n if ((m = re.exec(source))) {\n return {\n url: urls[i],\n line: source.substring(0, m.index).split('\\n').length,\n column: m.index - source.lastIndexOf('\\n', m.index) - 1,\n };\n }\n }\n }\n\n return null;\n }\n\n /**\n * Determines at which column a code fragment occurs on a line of the\n * source code.\n * @param {string} fragment The code fragment.\n * @param {string} url The URL to search.\n * @param {(string|number)} line The line number to examine.\n * @return {?number} The column number.\n * @memberof TraceKit.computeStackTrace\n */\n function findSourceInLine(fragment: any, url: any, line: any) {\n var source = getSource(url),\n re = new RegExp('\\\\b' + escapeRegExp(fragment) + '\\\\b'),\n m;\n\n line -= 1;\n\n if (source && source.length > line && (m = re.exec(source[line]))) {\n return m.index;\n }\n\n return null;\n }\n\n /**\n * Determines where a function was defined within the source code.\n * @param {(Function|string)} func A function reference or serialized\n * function definition.\n * @return {?Object.} An object containing\n * the url, line, and column number of the defined function.\n * @memberof TraceKit.computeStackTrace\n */\n function findSourceByFunctionBody(func: any) {\n if (isUndefined(window && window.document)) {\n return;\n }\n\n var urls = [getLocationHref()],\n scripts = window.document.getElementsByTagName('script'),\n body,\n code = '' + func,\n codeRE = /^function(?:\\s+([\\w$]+))?\\s*\\(([\\w\\s,]*)\\)\\s*\\{\\s*(\\S[\\s\\S]*\\S)\\s*\\}\\s*$/,\n eventRE = /^function on([\\w$]+)\\s*\\(event\\)\\s*\\{\\s*(\\S[\\s\\S]*\\S)\\s*\\}\\s*$/,\n re,\n parts,\n result;\n\n for (var i = 0; i < scripts.length; ++i) {\n var script = scripts[i];\n if (script.src) {\n urls.push(script.src);\n }\n }\n\n if (!(parts = codeRE.exec(code))) {\n re = new RegExp(escapeRegExp(code).replace(/\\s+/g, '\\\\s+'));\n }\n\n // not sure if this is really necessary, but I don’t have a test\n // corpus large enough to confirm that and it was in the original.\n else {\n var name = parts[1] ? '\\\\s+' + parts[1] : '',\n args = parts[2].split(',').join('\\\\s*,\\\\s*');\n\n body = escapeRegExp(parts[3]).replace(/;$/, ';?'); // semicolon is inserted if the function ends with a comment.replace(/\\s+/g, '\\\\s+');\n re = new RegExp('function' + name + '\\\\s*\\\\(\\\\s*' + args + '\\\\s*\\\\)\\\\s*{\\\\s*' + body + '\\\\s*}');\n }\n\n // look for a normal function definition\n if ((result = findSourceInUrls(re, urls))) {\n return result;\n }\n\n // look for an old-school event handler function\n if ((parts = eventRE.exec(code))) {\n var event = parts[1];\n body = escapeCodeAsRegExpForMatchingInsideHTML(parts[2]);\n\n // look for a function defined in HTML as an onXXX handler\n re = new RegExp('on' + event + '=[\\\\\\'\"]\\\\s*' + body + '\\\\s*[\\\\\\'\"]', 'i');\n\n if ((result = findSourceInUrls(re, urls[0]))) {\n return result;\n }\n\n // look for ???\n re = new RegExp(body);\n\n if ((result = findSourceInUrls(re, urls))) {\n return result;\n }\n }\n\n return null;\n }\n\n // Contents of Exception in various browsers.\n //\n // SAFARI:\n // ex.message = Can't find variable: qq\n // ex.line = 59\n // ex.sourceId = 580238192\n // ex.sourceURL = http://...\n // ex.expressionBeginOffset = 96\n // ex.expressionCaretOffset = 98\n // ex.expressionEndOffset = 98\n // ex.name = ReferenceError\n //\n // FIREFOX:\n // ex.message = qq is not defined\n // ex.fileName = http://...\n // ex.lineNumber = 59\n // ex.columnNumber = 69\n // ex.stack = ...stack trace... (see the example below)\n // ex.name = ReferenceError\n //\n // CHROME:\n // ex.message = qq is not defined\n // ex.name = ReferenceError\n // ex.type = not_defined\n // ex.arguments = ['aa']\n // ex.stack = ...stack trace...\n //\n // INTERNET EXPLORER:\n // ex.message = ...\n // ex.name = ReferenceError\n //\n // OPERA:\n // ex.message = ...message... (see the example below)\n // ex.name = ReferenceError\n // ex.opera#sourceloc = 11 (pretty much useless, duplicates the info in ex.message)\n // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace'\n\n /**\n * Computes stack trace information from the stack property.\n * Chrome and Gecko use this property.\n * @param {Error} ex\n * @return {?TraceKit.StackTrace} Stack trace information.\n * @memberof TraceKit.computeStackTrace\n */\n function computeStackTraceFromStackProp(ex: any) {\n if (!ex.stack) {\n return null;\n }\n\n var chrome = /^\\s*at (?:(.*?) ?\\()?((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\\/).*?)(?::(\\d+))?(?::(\\d+))?\\)?\\s*$/i,\n gecko = /^\\s*(.*?)(?:\\((.*?)\\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|moz-extension).*?:\\/.*?|\\[native code\\]|[^@]*bundle)(?::(\\d+))?(?::(\\d+))?\\s*$/i,\n winjs = /^\\s*at (?:((?:\\[object object\\])?.+) )?\\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\\d+)(?::(\\d+))?\\)?\\s*$/i,\n // Used to additionally parse URL/line/column from eval frames\n isEval,\n geckoEval = /(\\S+) line (\\d+)(?: > eval line \\d+)* > eval/i,\n chromeEval = /\\((\\S*)(?::(\\d+))(?::(\\d+))\\)/,\n lines = ex.stack.split('\\n'),\n stack = [],\n submatch,\n parts,\n element,\n reference = /^(.*) is undefined$/.exec(ex.message);\n\n for (var i = 0, j = lines.length; i < j; ++i) {\n if ((parts = chrome.exec(lines[i]))) {\n var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line\n isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line\n if (isEval && (submatch = chromeEval.exec(parts[2]))) {\n // throw out eval line/column and use top-most line/column number\n parts[2] = submatch[1]; // url\n // NOTE: It's messing out our integration tests in Karma, let's see if we can live with it – Kamil\n // parts[3] = submatch[2]; // line\n // parts[4] = submatch[3]; // column\n }\n element = {\n url: !isNative ? parts[2] : null,\n func: parts[1] || UNKNOWN_FUNCTION,\n args: isNative ? [parts[2]] : [],\n line: parts[3] ? +parts[3] : null,\n column: parts[4] ? +parts[4] : null,\n };\n } else if ((parts = winjs.exec(lines[i]))) {\n element = {\n url: parts[2],\n func: parts[1] || UNKNOWN_FUNCTION,\n args: [],\n line: +parts[3],\n column: parts[4] ? +parts[4] : null,\n };\n } else if ((parts = gecko.exec(lines[i]))) {\n isEval = parts[3] && parts[3].indexOf(' > eval') > -1;\n if (isEval && (submatch = geckoEval.exec(parts[3]))) {\n // throw out eval line/column and use top-most line number\n parts[3] = submatch[1];\n // NOTE: It's messing out our integration tests in Karma, let's see if we can live with it – Kamil\n // parts[4] = submatch[2];\n // parts[5] = null; // no column when eval\n } else if (i === 0 && !parts[5] && !isUndefined(ex.columnNumber)) {\n // FireFox uses this awesome columnNumber property for its top frame\n // Also note, Firefox's column number is 0-based and everything else expects 1-based,\n // so adding 1\n // NOTE: this hack doesn't work if top-most frame is eval\n stack[0].column = ex.columnNumber + 1;\n }\n element = {\n url: parts[3],\n func: parts[1] || UNKNOWN_FUNCTION,\n args: parts[2] ? parts[2].split(',') : [],\n line: parts[4] ? +parts[4] : null,\n column: parts[5] ? +parts[5] : null,\n };\n } else {\n continue;\n }\n\n if (!element.func && element.line) {\n element.func = guessFunctionName(element.url, element.line);\n }\n\n if (TraceKit.remoteFetching && element.url && element.url.substr(0, 5) === 'blob:') {\n // Special case for handling JavaScript loaded into a blob.\n // We use a synchronous AJAX request here as a blob is already in\n // memory - it's not making a network request. This will generate a warning\n // in the browser console, but there has already been an error so that's not\n // that much of an issue.\n var xhr = new XMLHttpRequest();\n xhr.open('GET', element.url, false);\n xhr.send('');\n\n // If we failed to download the source, skip this patch\n if (xhr.status === 200) {\n var source = xhr.responseText || '';\n\n // We trim the source down to the last 300 characters as sourceMappingURL is always at the end of the file.\n // Why 300? To be in line with: https://github.com/getsentry/sentry/blob/4af29e8f2350e20c28a6933354e4f42437b4ba42/src/sentry/lang/javascript/processor.py#L164-L175\n source = source.slice(-300);\n\n // Now we dig out the source map URL\n var sourceMaps = source.match(/\\/\\/# sourceMappingURL=(.*)$/);\n\n // If we don't find a source map comment or we find more than one, continue on to the next element.\n if (sourceMaps) {\n var sourceMapAddress = sourceMaps[1];\n\n // Now we check to see if it's a relative URL.\n // If it is, convert it to an absolute one.\n if (sourceMapAddress.charAt(0) === '~') {\n sourceMapAddress = getLocationOrigin() + sourceMapAddress.slice(1);\n }\n\n // Now we strip the '.map' off of the end of the URL and update the\n // element so that Sentry can match the map to the blob.\n element.url = sourceMapAddress.slice(0, -4);\n }\n }\n }\n\n (element as any).context = element.line ? gatherContext(element.url, element.line) : null;\n\n stack.push(element);\n }\n\n if (!stack.length) {\n return null;\n }\n\n if (stack[0] && stack[0].line && !stack[0].column && reference) {\n stack[0].column = findSourceInLine(reference[1], stack[0].url, stack[0].line);\n }\n\n return {\n mode: 'stack',\n name: ex.name,\n message: ex.message,\n stack: stack,\n };\n }\n\n /**\n * Computes stack trace information from the stacktrace property.\n * Opera 10+ uses this property.\n * @param {Error} ex\n * @return {?TraceKit.StackTrace} Stack trace information.\n * @memberof TraceKit.computeStackTrace\n */\n function computeStackTraceFromStacktraceProp(ex: any) {\n // Access and store the stacktrace property before doing ANYTHING\n // else to it because Opera is not very good at providing it\n // reliably in other circumstances.\n var stacktrace = ex.stacktrace;\n if (!stacktrace) {\n return;\n }\n\n var opera10Regex = / line (\\d+).*script (?:in )?(\\S+)(?:: in function (\\S+))?$/i,\n opera11Regex = / line (\\d+), column (\\d+)\\s*(?:in (?:]+)>|([^\\)]+))\\((.*)\\))? in (.*):\\s*$/i,\n lines = stacktrace.split('\\n'),\n stack = [],\n parts;\n\n for (var line = 0; line < lines.length; line += 2) {\n var element = null;\n if ((parts = opera10Regex.exec(lines[line]))) {\n element = {\n url: parts[2],\n line: +parts[1],\n column: null,\n func: parts[3],\n args: [],\n };\n } else if ((parts = opera11Regex.exec(lines[line]))) {\n element = {\n url: parts[6],\n line: +parts[1],\n column: +parts[2],\n func: parts[3] || parts[4],\n args: parts[5] ? parts[5].split(',') : [],\n };\n }\n\n if (element) {\n if (!element.func && element.line) {\n element.func = guessFunctionName(element.url, element.line);\n }\n if (element.line) {\n try {\n (element as any).context = gatherContext(element.url, element.line);\n } catch (exc) {}\n }\n\n if (!(element as any).context) {\n (element as any).context = [lines[line + 1]];\n }\n\n stack.push(element);\n }\n }\n\n if (!stack.length) {\n return null;\n }\n\n return {\n mode: 'stacktrace',\n name: ex.name,\n message: ex.message,\n stack: stack,\n };\n }\n\n /**\n * NOT TESTED.\n * Computes stack trace information from an error message that includes\n * the stack trace.\n * Opera 9 and earlier use this method if the option to show stack\n * traces is turned on in opera:config.\n * @param {Error} ex\n * @return {?TraceKit.StackTrace} Stack information.\n * @memberof TraceKit.computeStackTrace\n */\n function computeStackTraceFromOperaMultiLineMessage(ex: any) {\n // TODO: Clean this function up\n // Opera includes a stack trace into the exception message. An example is:\n //\n // Statement on line 3: Undefined variable: undefinedFunc\n // Backtrace:\n // Line 3 of linked script file://localhost/Users/andreyvit/Projects/TraceKit/javascript-client/sample.js: In function zzz\n // undefinedFunc(a);\n // Line 7 of inline#1 script in file://localhost/Users/andreyvit/Projects/TraceKit/javascript-client/sample.html: In function yyy\n // zzz(x, y, z);\n // Line 3 of inline#1 script in file://localhost/Users/andreyvit/Projects/TraceKit/javascript-client/sample.html: In function xxx\n // yyy(a, a, a);\n // Line 1 of function script\n // try { xxx('hi'); return false; } catch(ex) { TraceKit.report(ex); }\n // ...\n\n var lines = ex.message.split('\\n');\n if (lines.length < 4) {\n return null;\n }\n\n var lineRE1 = /^\\s*Line (\\d+) of linked script ((?:file|https?|blob)\\S+)(?:: in function (\\S+))?\\s*$/i,\n lineRE2 = /^\\s*Line (\\d+) of inline#(\\d+) script in ((?:file|https?|blob)\\S+)(?:: in function (\\S+))?\\s*$/i,\n lineRE3 = /^\\s*Line (\\d+) of function script\\s*$/i,\n stack = [],\n scripts = window && window.document && window.document.getElementsByTagName('script'),\n inlineScriptBlocks = [],\n parts;\n\n for (var s in scripts) {\n if (_has(scripts, s) && !scripts[s].src) {\n inlineScriptBlocks.push(scripts[s]);\n }\n }\n\n for (var line = 2; line < lines.length; line += 2) {\n var item = null;\n if ((parts = lineRE1.exec(lines[line]))) {\n item = {\n url: parts[2],\n func: parts[3],\n args: [],\n line: +parts[1],\n column: null,\n };\n } else if ((parts = lineRE2.exec(lines[line]))) {\n item = {\n url: parts[3],\n func: parts[4],\n args: [],\n line: +parts[1],\n column: null, // TODO: Check to see if inline#1 (+parts[2]) points to the script number or column number.\n };\n var relativeLine = +parts[1]; // relative to the start of the