mirror of
https://github.com/rxliuli/apps.apple.com.git
synced 2025-11-10 00:30:32 +00:00
init commit
This commit is contained in:
145
shared/logger/node_modules/@sentry/utils/esm/baggage.js
generated
vendored
Normal file
145
shared/logger/node_modules/@sentry/utils/esm/baggage.js
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
import { isString } from './is.js';
|
||||
import { logger } from './logger.js';
|
||||
|
||||
const BAGGAGE_HEADER_NAME = 'baggage';
|
||||
|
||||
const SENTRY_BAGGAGE_KEY_PREFIX = 'sentry-';
|
||||
|
||||
const SENTRY_BAGGAGE_KEY_PREFIX_REGEX = /^sentry-/;
|
||||
|
||||
/**
|
||||
* Max length of a serialized baggage string
|
||||
*
|
||||
* https://www.w3.org/TR/baggage/#limits
|
||||
*/
|
||||
const MAX_BAGGAGE_STRING_LENGTH = 8192;
|
||||
|
||||
/**
|
||||
* Takes a baggage header and turns it into Dynamic Sampling Context, by extracting all the "sentry-" prefixed values
|
||||
* from it.
|
||||
*
|
||||
* @param baggageHeader A very bread definition of a baggage header as it might appear in various frameworks.
|
||||
* @returns The Dynamic Sampling Context that was found on `baggageHeader`, if there was any, `undefined` otherwise.
|
||||
*/
|
||||
function baggageHeaderToDynamicSamplingContext(
|
||||
// Very liberal definition of what any incoming header might look like
|
||||
baggageHeader,
|
||||
) {
|
||||
if (!isString(baggageHeader) && !Array.isArray(baggageHeader)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Intermediary object to store baggage key value pairs of incoming baggage headers on.
|
||||
// It is later used to read Sentry-DSC-values from.
|
||||
let baggageObject = {};
|
||||
|
||||
if (Array.isArray(baggageHeader)) {
|
||||
// Combine all baggage headers into one object containing the baggage values so we can later read the Sentry-DSC-values from it
|
||||
baggageObject = baggageHeader.reduce((acc, curr) => {
|
||||
const currBaggageObject = baggageHeaderToObject(curr);
|
||||
return {
|
||||
...acc,
|
||||
...currBaggageObject,
|
||||
};
|
||||
}, {});
|
||||
} else {
|
||||
// Return undefined if baggage header is an empty string (technically an empty baggage header is not spec conform but
|
||||
// this is how we choose to handle it)
|
||||
if (!baggageHeader) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
baggageObject = baggageHeaderToObject(baggageHeader);
|
||||
}
|
||||
|
||||
// Read all "sentry-" prefixed values out of the baggage object and put it onto a dynamic sampling context object.
|
||||
const dynamicSamplingContext = Object.entries(baggageObject).reduce((acc, [key, value]) => {
|
||||
if (key.match(SENTRY_BAGGAGE_KEY_PREFIX_REGEX)) {
|
||||
const nonPrefixedKey = key.slice(SENTRY_BAGGAGE_KEY_PREFIX.length);
|
||||
acc[nonPrefixedKey] = value;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// Only return a dynamic sampling context object if there are keys in it.
|
||||
// A keyless object means there were no sentry values on the header, which means that there is no DSC.
|
||||
if (Object.keys(dynamicSamplingContext).length > 0) {
|
||||
return dynamicSamplingContext ;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a Dynamic Sampling Object into a baggage header by prefixing all the keys on the object with "sentry-".
|
||||
*
|
||||
* @param dynamicSamplingContext The Dynamic Sampling Context to turn into a header. For convenience and compatibility
|
||||
* with the `getDynamicSamplingContext` method on the Transaction class ,this argument can also be `undefined`. If it is
|
||||
* `undefined` the function will return `undefined`.
|
||||
* @returns a baggage header, created from `dynamicSamplingContext`, or `undefined` either if `dynamicSamplingContext`
|
||||
* was `undefined`, or if `dynamicSamplingContext` didn't contain any values.
|
||||
*/
|
||||
function dynamicSamplingContextToSentryBaggageHeader(
|
||||
// this also takes undefined for convenience and bundle size in other places
|
||||
dynamicSamplingContext,
|
||||
) {
|
||||
// Prefix all DSC keys with "sentry-" and put them into a new object
|
||||
const sentryPrefixedDSC = Object.entries(dynamicSamplingContext).reduce(
|
||||
(acc, [dscKey, dscValue]) => {
|
||||
if (dscValue) {
|
||||
acc[`${SENTRY_BAGGAGE_KEY_PREFIX}${dscKey}`] = dscValue;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
return objectToBaggageHeader(sentryPrefixedDSC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will parse a baggage header, which is a simple key-value map, into a flat object.
|
||||
*
|
||||
* @param baggageHeader The baggage header to parse.
|
||||
* @returns a flat object containing all the key-value pairs from `baggageHeader`.
|
||||
*/
|
||||
function baggageHeaderToObject(baggageHeader) {
|
||||
return baggageHeader
|
||||
.split(',')
|
||||
.map(baggageEntry => baggageEntry.split('=').map(keyOrValue => decodeURIComponent(keyOrValue.trim())))
|
||||
.reduce((acc, [key, value]) => {
|
||||
acc[key] = value;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a flat object (key-value pairs) into a baggage header, which is also just key-value pairs.
|
||||
*
|
||||
* @param object The object to turn into a baggage header.
|
||||
* @returns a baggage header string, or `undefined` if the object didn't have any values, since an empty baggage header
|
||||
* is not spec compliant.
|
||||
*/
|
||||
function objectToBaggageHeader(object) {
|
||||
if (Object.keys(object).length === 0) {
|
||||
// An empty baggage header is not spec compliant: We return undefined.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return Object.entries(object).reduce((baggageHeader, [objectKey, objectValue], currentIndex) => {
|
||||
const baggageEntry = `${encodeURIComponent(objectKey)}=${encodeURIComponent(objectValue)}`;
|
||||
const newBaggageHeader = currentIndex === 0 ? baggageEntry : `${baggageHeader},${baggageEntry}`;
|
||||
if (newBaggageHeader.length > MAX_BAGGAGE_STRING_LENGTH) {
|
||||
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
|
||||
logger.warn(
|
||||
`Not adding key: ${objectKey} with val: ${objectValue} to baggage header due to exceeding baggage size limits.`,
|
||||
);
|
||||
return baggageHeader;
|
||||
} else {
|
||||
return newBaggageHeader;
|
||||
}
|
||||
}, '');
|
||||
}
|
||||
|
||||
export { BAGGAGE_HEADER_NAME, MAX_BAGGAGE_STRING_LENGTH, SENTRY_BAGGAGE_KEY_PREFIX, SENTRY_BAGGAGE_KEY_PREFIX_REGEX, baggageHeaderToDynamicSamplingContext, dynamicSamplingContextToSentryBaggageHeader };
|
||||
//# sourceMappingURL=baggage.js.map
|
||||
152
shared/logger/node_modules/@sentry/utils/esm/browser.js
generated
vendored
Normal file
152
shared/logger/node_modules/@sentry/utils/esm/browser.js
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
import { isString } from './is.js';
|
||||
import { getGlobalObject } from './worldwide.js';
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const WINDOW = getGlobalObject();
|
||||
|
||||
const DEFAULT_MAX_STRING_LENGTH = 80;
|
||||
|
||||
/**
|
||||
* Given a child DOM element, returns a query-selector statement describing that
|
||||
* and its ancestors
|
||||
* e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]
|
||||
* @returns generated DOM path
|
||||
*/
|
||||
function htmlTreeAsString(
|
||||
elem,
|
||||
options = {},
|
||||
) {
|
||||
|
||||
// try/catch both:
|
||||
// - accessing event.target (see getsentry/raven-js#838, #768)
|
||||
// - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly
|
||||
// - can throw an exception in some circumstances.
|
||||
try {
|
||||
let currentElem = elem ;
|
||||
const MAX_TRAVERSE_HEIGHT = 5;
|
||||
const out = [];
|
||||
let height = 0;
|
||||
let len = 0;
|
||||
const separator = ' > ';
|
||||
const sepLength = separator.length;
|
||||
let nextStr;
|
||||
const keyAttrs = Array.isArray(options) ? options : options.keyAttrs;
|
||||
const maxStringLength = (!Array.isArray(options) && options.maxStringLength) || DEFAULT_MAX_STRING_LENGTH;
|
||||
|
||||
while (currentElem && height++ < MAX_TRAVERSE_HEIGHT) {
|
||||
nextStr = _htmlElementAsString(currentElem, keyAttrs);
|
||||
// bail out if
|
||||
// - nextStr is the 'html' element
|
||||
// - the length of the string that would be created exceeds maxStringLength
|
||||
// (ignore this limit if we are on the first iteration)
|
||||
if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= maxStringLength)) {
|
||||
break;
|
||||
}
|
||||
|
||||
out.push(nextStr);
|
||||
|
||||
len += nextStr.length;
|
||||
currentElem = currentElem.parentNode;
|
||||
}
|
||||
|
||||
return out.reverse().join(separator);
|
||||
} catch (_oO) {
|
||||
return '<unknown>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a simple, query-selector representation of a DOM element
|
||||
* e.g. [HTMLElement] => input#foo.btn[name=baz]
|
||||
* @returns generated DOM path
|
||||
*/
|
||||
function _htmlElementAsString(el, keyAttrs) {
|
||||
const elem = el
|
||||
|
||||
;
|
||||
|
||||
const out = [];
|
||||
let className;
|
||||
let classes;
|
||||
let key;
|
||||
let attr;
|
||||
let i;
|
||||
|
||||
if (!elem || !elem.tagName) {
|
||||
return '';
|
||||
}
|
||||
|
||||
out.push(elem.tagName.toLowerCase());
|
||||
|
||||
// Pairs of attribute keys defined in `serializeAttribute` and their values on element.
|
||||
const keyAttrPairs =
|
||||
keyAttrs && keyAttrs.length
|
||||
? keyAttrs.filter(keyAttr => elem.getAttribute(keyAttr)).map(keyAttr => [keyAttr, elem.getAttribute(keyAttr)])
|
||||
: null;
|
||||
|
||||
if (keyAttrPairs && keyAttrPairs.length) {
|
||||
keyAttrPairs.forEach(keyAttrPair => {
|
||||
out.push(`[${keyAttrPair[0]}="${keyAttrPair[1]}"]`);
|
||||
});
|
||||
} else {
|
||||
if (elem.id) {
|
||||
out.push(`#${elem.id}`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line prefer-const
|
||||
className = elem.className;
|
||||
if (className && isString(className)) {
|
||||
classes = className.split(/\s+/);
|
||||
for (i = 0; i < classes.length; i++) {
|
||||
out.push(`.${classes[i]}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
const allowedAttrs = ['aria-label', 'type', 'name', 'title', 'alt'];
|
||||
for (i = 0; i < allowedAttrs.length; i++) {
|
||||
key = allowedAttrs[i];
|
||||
attr = elem.getAttribute(key);
|
||||
if (attr) {
|
||||
out.push(`[${key}="${attr}"]`);
|
||||
}
|
||||
}
|
||||
return out.join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* A safe form of location.href
|
||||
*/
|
||||
function getLocationHref() {
|
||||
try {
|
||||
return WINDOW.document.location.href;
|
||||
} catch (oO) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a DOM element by using document.querySelector.
|
||||
*
|
||||
* This wrapper will first check for the existance of the function before
|
||||
* actually calling it so that we don't have to take care of this check,
|
||||
* every time we want to access the DOM.
|
||||
*
|
||||
* Reason: DOM/querySelector is not available in all environments.
|
||||
*
|
||||
* We have to cast to any because utils can be consumed by a variety of environments,
|
||||
* and we don't want to break TS users. If you know what element will be selected by
|
||||
* `document.querySelector`, specify it as part of the generic call. For example,
|
||||
* `const element = getDomElement<Element>('selector');`
|
||||
*
|
||||
* @param selector the selector string passed on to document.querySelector
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function getDomElement(selector) {
|
||||
if (WINDOW.document && WINDOW.document.querySelector) {
|
||||
return WINDOW.document.querySelector(selector) ;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export { getDomElement, getLocationHref, htmlTreeAsString };
|
||||
//# sourceMappingURL=browser.js.map
|
||||
59
shared/logger/node_modules/@sentry/utils/esm/buildPolyfills/_optionalChain.js
generated
vendored
Normal file
59
shared/logger/node_modules/@sentry/utils/esm/buildPolyfills/_optionalChain.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Polyfill for the optional chain operator, `?.`, given previous conversion of the expression into an array of values,
|
||||
* descriptors, and functions.
|
||||
*
|
||||
* Adapted from Sucrase (https://github.com/alangpierce/sucrase)
|
||||
* See https://github.com/alangpierce/sucrase/blob/265887868966917f3b924ce38dfad01fbab1329f/src/transformers/OptionalChainingNullishTransformer.ts#L15
|
||||
*
|
||||
* @param ops Array result of expression conversion
|
||||
* @returns The value of the expression
|
||||
*/
|
||||
function _optionalChain(ops) {
|
||||
let lastAccessLHS = undefined;
|
||||
let value = ops[0];
|
||||
let i = 1;
|
||||
while (i < ops.length) {
|
||||
const op = ops[i] ;
|
||||
const fn = ops[i + 1] ;
|
||||
i += 2;
|
||||
// by checking for loose equality to `null`, we catch both `null` and `undefined`
|
||||
if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) {
|
||||
// really we're meaning to return `undefined` as an actual value here, but it saves bytes not to write it
|
||||
return;
|
||||
}
|
||||
if (op === 'access' || op === 'optionalAccess') {
|
||||
lastAccessLHS = value;
|
||||
value = fn(value);
|
||||
} else if (op === 'call' || op === 'optionalCall') {
|
||||
value = fn((...args) => (value ).call(lastAccessLHS, ...args));
|
||||
lastAccessLHS = undefined;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// Sucrase version
|
||||
// function _optionalChain(ops) {
|
||||
// let lastAccessLHS = undefined;
|
||||
// let value = ops[0];
|
||||
// let i = 1;
|
||||
// while (i < ops.length) {
|
||||
// const op = ops[i];
|
||||
// const fn = ops[i + 1];
|
||||
// i += 2;
|
||||
// if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) {
|
||||
// return undefined;
|
||||
// }
|
||||
// if (op === 'access' || op === 'optionalAccess') {
|
||||
// lastAccessLHS = value;
|
||||
// value = fn(value);
|
||||
// } else if (op === 'call' || op === 'optionalCall') {
|
||||
// value = fn((...args) => value.call(lastAccessLHS, ...args));
|
||||
// lastAccessLHS = undefined;
|
||||
// }
|
||||
// }
|
||||
// return value;
|
||||
// }
|
||||
|
||||
export { _optionalChain };
|
||||
//# sourceMappingURL=_optionalChain.js.map
|
||||
25
shared/logger/node_modules/@sentry/utils/esm/clientreport.js
generated
vendored
Normal file
25
shared/logger/node_modules/@sentry/utils/esm/clientreport.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
import { createEnvelope } from './envelope.js';
|
||||
import { dateTimestampInSeconds } from './time.js';
|
||||
|
||||
/**
|
||||
* Creates client report envelope
|
||||
* @param discarded_events An array of discard events
|
||||
* @param dsn A DSN that can be set on the header. Optional.
|
||||
*/
|
||||
function createClientReportEnvelope(
|
||||
discarded_events,
|
||||
dsn,
|
||||
timestamp,
|
||||
) {
|
||||
const clientReportItem = [
|
||||
{ type: 'client_report' },
|
||||
{
|
||||
timestamp: timestamp || dateTimestampInSeconds(),
|
||||
discarded_events,
|
||||
},
|
||||
];
|
||||
return createEnvelope(dsn ? { dsn } : {}, [clientReportItem]);
|
||||
}
|
||||
|
||||
export { createClientReportEnvelope };
|
||||
//# sourceMappingURL=clientreport.js.map
|
||||
126
shared/logger/node_modules/@sentry/utils/esm/dsn.js
generated
vendored
Normal file
126
shared/logger/node_modules/@sentry/utils/esm/dsn.js
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
import { logger } from './logger.js';
|
||||
|
||||
/** Regular expression used to parse a Dsn. */
|
||||
const DSN_REGEX = /^(?:(\w+):)\/\/(?:(\w+)(?::(\w+)?)?@)([\w.-]+)(?::(\d+))?\/(.+)/;
|
||||
|
||||
function isValidProtocol(protocol) {
|
||||
return protocol === 'http' || protocol === 'https';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the string representation of this Dsn.
|
||||
*
|
||||
* By default, this will render the public representation without the password
|
||||
* component. To get the deprecated private representation, set `withPassword`
|
||||
* to true.
|
||||
*
|
||||
* @param withPassword When set to true, the password will be included.
|
||||
*/
|
||||
function dsnToString(dsn, withPassword = false) {
|
||||
const { host, path, pass, port, projectId, protocol, publicKey } = dsn;
|
||||
return (
|
||||
`${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ''}` +
|
||||
`@${host}${port ? `:${port}` : ''}/${path ? `${path}/` : path}${projectId}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a Dsn from a given string.
|
||||
*
|
||||
* @param str A Dsn as string
|
||||
* @returns Dsn as DsnComponents or undefined if @param str is not a valid DSN string
|
||||
*/
|
||||
function dsnFromString(str) {
|
||||
const match = DSN_REGEX.exec(str);
|
||||
|
||||
if (!match) {
|
||||
// This should be logged to the console
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Invalid Sentry Dsn: ${str}`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const [protocol, publicKey, pass = '', host, port = '', lastPath] = match.slice(1);
|
||||
let path = '';
|
||||
let projectId = lastPath;
|
||||
|
||||
const split = projectId.split('/');
|
||||
if (split.length > 1) {
|
||||
path = split.slice(0, -1).join('/');
|
||||
projectId = split.pop() ;
|
||||
}
|
||||
|
||||
if (projectId) {
|
||||
const projectMatch = projectId.match(/^\d+/);
|
||||
if (projectMatch) {
|
||||
projectId = projectMatch[0];
|
||||
}
|
||||
}
|
||||
|
||||
return dsnFromComponents({ host, pass, path, projectId, port, protocol: protocol , publicKey });
|
||||
}
|
||||
|
||||
function dsnFromComponents(components) {
|
||||
return {
|
||||
protocol: components.protocol,
|
||||
publicKey: components.publicKey || '',
|
||||
pass: components.pass || '',
|
||||
host: components.host,
|
||||
port: components.port || '',
|
||||
path: components.path || '',
|
||||
projectId: components.projectId,
|
||||
};
|
||||
}
|
||||
|
||||
function validateDsn(dsn) {
|
||||
if (!(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const { port, projectId, protocol } = dsn;
|
||||
|
||||
const requiredComponents = ['protocol', 'publicKey', 'host', 'projectId'];
|
||||
const hasMissingRequiredComponent = requiredComponents.find(component => {
|
||||
if (!dsn[component]) {
|
||||
logger.error(`Invalid Sentry Dsn: ${component} missing`);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (hasMissingRequiredComponent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!projectId.match(/^\d+$/)) {
|
||||
logger.error(`Invalid Sentry Dsn: Invalid projectId ${projectId}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isValidProtocol(protocol)) {
|
||||
logger.error(`Invalid Sentry Dsn: Invalid protocol ${protocol}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (port && isNaN(parseInt(port, 10))) {
|
||||
logger.error(`Invalid Sentry Dsn: Invalid port ${port}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a valid Sentry Dsn object, identifying a Sentry instance and project.
|
||||
* @returns a valid DsnComponents object or `undefined` if @param from is an invalid DSN source
|
||||
*/
|
||||
function makeDsn(from) {
|
||||
const components = typeof from === 'string' ? dsnFromString(from) : dsnFromComponents(from);
|
||||
if (!components || !validateDsn(components)) {
|
||||
return undefined;
|
||||
}
|
||||
return components;
|
||||
}
|
||||
|
||||
export { dsnFromString, dsnToString, makeDsn };
|
||||
//# sourceMappingURL=dsn.js.map
|
||||
34
shared/logger/node_modules/@sentry/utils/esm/env.js
generated
vendored
Normal file
34
shared/logger/node_modules/@sentry/utils/esm/env.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This module exists for optimizations in the build process through rollup and terser. We define some global
|
||||
* constants, which can be overridden during build. By guarding certain pieces of code with functions that return these
|
||||
* constants, we can control whether or not they appear in the final bundle. (Any code guarded by a false condition will
|
||||
* never run, and will hence be dropped during treeshaking.) The two primary uses for this are stripping out calls to
|
||||
* `logger` and preventing node-related code from appearing in browser bundles.
|
||||
*
|
||||
* Attention:
|
||||
* This file should not be used to define constants/flags that are intended to be used for tree-shaking conducted by
|
||||
* users. These flags should live in their respective packages, as we identified user tooling (specifically webpack)
|
||||
* having issues tree-shaking these constants across package boundaries.
|
||||
* An example for this is the __SENTRY_DEBUG__ constant. It is declared in each package individually because we want
|
||||
* users to be able to shake away expressions that it guards.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Figures out if we're building a browser bundle.
|
||||
*
|
||||
* @returns true if this is a browser bundle build.
|
||||
*/
|
||||
function isBrowserBundle() {
|
||||
return typeof __SENTRY_BROWSER_BUNDLE__ !== 'undefined' && !!__SENTRY_BROWSER_BUNDLE__;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get source of SDK.
|
||||
*/
|
||||
function getSDKSource() {
|
||||
// @ts-ignore "npm" is injected by rollup during build process
|
||||
return "npm";
|
||||
}
|
||||
|
||||
export { getSDKSource, isBrowserBundle };
|
||||
//# sourceMappingURL=env.js.map
|
||||
232
shared/logger/node_modules/@sentry/utils/esm/envelope.js
generated
vendored
Normal file
232
shared/logger/node_modules/@sentry/utils/esm/envelope.js
generated
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
import { dsnToString } from './dsn.js';
|
||||
import { normalize } from './normalize.js';
|
||||
import { dropUndefinedKeys } from './object.js';
|
||||
|
||||
/**
|
||||
* Creates an envelope.
|
||||
* Make sure to always explicitly provide the generic to this function
|
||||
* so that the envelope types resolve correctly.
|
||||
*/
|
||||
function createEnvelope(headers, items = []) {
|
||||
return [headers, items] ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to an envelope.
|
||||
* Make sure to always explicitly provide the generic to this function
|
||||
* so that the envelope types resolve correctly.
|
||||
*/
|
||||
function addItemToEnvelope(envelope, newItem) {
|
||||
const [headers, items] = envelope;
|
||||
return [headers, [...items, newItem]] ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to loop through the items and item types of an envelope.
|
||||
* (This function was mostly created because working with envelope types is painful at the moment)
|
||||
*
|
||||
* If the callback returns true, the rest of the items will be skipped.
|
||||
*/
|
||||
function forEachEnvelopeItem(
|
||||
envelope,
|
||||
callback,
|
||||
) {
|
||||
const envelopeItems = envelope[1];
|
||||
|
||||
for (const envelopeItem of envelopeItems) {
|
||||
const envelopeItemType = envelopeItem[0].type;
|
||||
const result = callback(envelopeItem, envelopeItemType);
|
||||
|
||||
if (result) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the envelope contains any of the given envelope item types
|
||||
*/
|
||||
function envelopeContainsItemType(envelope, types) {
|
||||
return forEachEnvelopeItem(envelope, (_, type) => types.includes(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a string to UTF8.
|
||||
*/
|
||||
function encodeUTF8(input, textEncoder) {
|
||||
const utf8 = textEncoder || new TextEncoder();
|
||||
return utf8.encode(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes an envelope.
|
||||
*/
|
||||
function serializeEnvelope(envelope, textEncoder) {
|
||||
const [envHeaders, items] = envelope;
|
||||
|
||||
// Initially we construct our envelope as a string and only convert to binary chunks if we encounter binary data
|
||||
let parts = JSON.stringify(envHeaders);
|
||||
|
||||
function append(next) {
|
||||
if (typeof parts === 'string') {
|
||||
parts = typeof next === 'string' ? parts + next : [encodeUTF8(parts, textEncoder), next];
|
||||
} else {
|
||||
parts.push(typeof next === 'string' ? encodeUTF8(next, textEncoder) : next);
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of items) {
|
||||
const [itemHeaders, payload] = item;
|
||||
|
||||
append(`\n${JSON.stringify(itemHeaders)}\n`);
|
||||
|
||||
if (typeof payload === 'string' || payload instanceof Uint8Array) {
|
||||
append(payload);
|
||||
} else {
|
||||
let stringifiedPayload;
|
||||
try {
|
||||
stringifiedPayload = JSON.stringify(payload);
|
||||
} catch (e) {
|
||||
// In case, despite all our efforts to keep `payload` circular-dependency-free, `JSON.strinify()` still
|
||||
// fails, we try again after normalizing it again with infinite normalization depth. This of course has a
|
||||
// performance impact but in this case a performance hit is better than throwing.
|
||||
stringifiedPayload = JSON.stringify(normalize(payload));
|
||||
}
|
||||
append(stringifiedPayload);
|
||||
}
|
||||
}
|
||||
|
||||
return typeof parts === 'string' ? parts : concatBuffers(parts);
|
||||
}
|
||||
|
||||
function concatBuffers(buffers) {
|
||||
const totalLength = buffers.reduce((acc, buf) => acc + buf.length, 0);
|
||||
|
||||
const merged = new Uint8Array(totalLength);
|
||||
let offset = 0;
|
||||
for (const buffer of buffers) {
|
||||
merged.set(buffer, offset);
|
||||
offset += buffer.length;
|
||||
}
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an envelope
|
||||
*/
|
||||
function parseEnvelope(
|
||||
env,
|
||||
textEncoder,
|
||||
textDecoder,
|
||||
) {
|
||||
let buffer = typeof env === 'string' ? textEncoder.encode(env) : env;
|
||||
|
||||
function readBinary(length) {
|
||||
const bin = buffer.subarray(0, length);
|
||||
// Replace the buffer with the remaining data excluding trailing newline
|
||||
buffer = buffer.subarray(length + 1);
|
||||
return bin;
|
||||
}
|
||||
|
||||
function readJson() {
|
||||
let i = buffer.indexOf(0xa);
|
||||
// If we couldn't find a newline, we must have found the end of the buffer
|
||||
if (i < 0) {
|
||||
i = buffer.length;
|
||||
}
|
||||
|
||||
return JSON.parse(textDecoder.decode(readBinary(i))) ;
|
||||
}
|
||||
|
||||
const envelopeHeader = readJson();
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const items = [];
|
||||
|
||||
while (buffer.length) {
|
||||
const itemHeader = readJson();
|
||||
const binaryLength = typeof itemHeader.length === 'number' ? itemHeader.length : undefined;
|
||||
|
||||
items.push([itemHeader, binaryLength ? readBinary(binaryLength) : readJson()]);
|
||||
}
|
||||
|
||||
return [envelopeHeader, items];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates attachment envelope items
|
||||
*/
|
||||
function createAttachmentEnvelopeItem(
|
||||
attachment,
|
||||
textEncoder,
|
||||
) {
|
||||
const buffer = typeof attachment.data === 'string' ? encodeUTF8(attachment.data, textEncoder) : attachment.data;
|
||||
|
||||
return [
|
||||
dropUndefinedKeys({
|
||||
type: 'attachment',
|
||||
length: buffer.length,
|
||||
filename: attachment.filename,
|
||||
content_type: attachment.contentType,
|
||||
attachment_type: attachment.attachmentType,
|
||||
}),
|
||||
buffer,
|
||||
];
|
||||
}
|
||||
|
||||
const ITEM_TYPE_TO_DATA_CATEGORY_MAP = {
|
||||
session: 'session',
|
||||
sessions: 'session',
|
||||
attachment: 'attachment',
|
||||
transaction: 'transaction',
|
||||
event: 'error',
|
||||
client_report: 'internal',
|
||||
user_report: 'default',
|
||||
profile: 'profile',
|
||||
replay_event: 'replay',
|
||||
replay_recording: 'replay',
|
||||
check_in: 'monitor',
|
||||
};
|
||||
|
||||
/**
|
||||
* Maps the type of an envelope item to a data category.
|
||||
*/
|
||||
function envelopeItemTypeToDataCategory(type) {
|
||||
return ITEM_TYPE_TO_DATA_CATEGORY_MAP[type];
|
||||
}
|
||||
|
||||
/** Extracts the minimal SDK info from from the metadata or an events */
|
||||
function getSdkMetadataForEnvelopeHeader(metadataOrEvent) {
|
||||
if (!metadataOrEvent || !metadataOrEvent.sdk) {
|
||||
return;
|
||||
}
|
||||
const { name, version } = metadataOrEvent.sdk;
|
||||
return { name, version };
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates event envelope headers, based on event, sdk info and tunnel
|
||||
* Note: This function was extracted from the core package to make it available in Replay
|
||||
*/
|
||||
function createEventEnvelopeHeaders(
|
||||
event,
|
||||
sdkInfo,
|
||||
tunnel,
|
||||
dsn,
|
||||
) {
|
||||
const dynamicSamplingContext = event.sdkProcessingMetadata && event.sdkProcessingMetadata.dynamicSamplingContext;
|
||||
return {
|
||||
event_id: event.event_id ,
|
||||
sent_at: new Date().toISOString(),
|
||||
...(sdkInfo && { sdk: sdkInfo }),
|
||||
...(!!tunnel && { dsn: dsnToString(dsn) }),
|
||||
...(dynamicSamplingContext && {
|
||||
trace: dropUndefinedKeys({ ...dynamicSamplingContext }),
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
export { addItemToEnvelope, createAttachmentEnvelopeItem, createEnvelope, createEventEnvelopeHeaders, envelopeContainsItemType, envelopeItemTypeToDataCategory, forEachEnvelopeItem, getSdkMetadataForEnvelopeHeader, parseEnvelope, serializeEnvelope };
|
||||
//# sourceMappingURL=envelope.js.map
|
||||
17
shared/logger/node_modules/@sentry/utils/esm/error.js
generated
vendored
Normal file
17
shared/logger/node_modules/@sentry/utils/esm/error.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/** An error emitted by Sentry SDKs and related utilities. */
|
||||
class SentryError extends Error {
|
||||
/** Display name of this error instance. */
|
||||
|
||||
constructor( message, logLevel = 'warn') {
|
||||
super(message);this.message = message;
|
||||
this.name = new.target.prototype.constructor.name;
|
||||
// This sets the prototype to be `Error`, not `SentryError`. It's unclear why we do this, but commenting this line
|
||||
// out causes various (seemingly totally unrelated) playwright tests consistently time out. FYI, this makes
|
||||
// instances of `SentryError` fail `obj instanceof SentryError` checks.
|
||||
Object.setPrototypeOf(this, new.target.prototype);
|
||||
this.logLevel = logLevel;
|
||||
}
|
||||
}
|
||||
|
||||
export { SentryError };
|
||||
//# sourceMappingURL=error.js.map
|
||||
631
shared/logger/node_modules/@sentry/utils/esm/instrument.js
generated
vendored
Normal file
631
shared/logger/node_modules/@sentry/utils/esm/instrument.js
generated
vendored
Normal file
@@ -0,0 +1,631 @@
|
||||
import { isString } from './is.js';
|
||||
import { logger, CONSOLE_LEVELS } from './logger.js';
|
||||
import { fill } from './object.js';
|
||||
import { getFunctionName } from './stacktrace.js';
|
||||
import { supportsNativeFetch } from './supports.js';
|
||||
import { getGlobalObject } from './worldwide.js';
|
||||
import { supportsHistory } from './vendor/supportsHistory.js';
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const WINDOW = getGlobalObject();
|
||||
|
||||
const SENTRY_XHR_DATA_KEY = '__sentry_xhr_v2__';
|
||||
|
||||
/**
|
||||
* Instrument native APIs to call handlers that can be used to create breadcrumbs, APM spans etc.
|
||||
* - Console API
|
||||
* - Fetch API
|
||||
* - XHR API
|
||||
* - History API
|
||||
* - DOM API (click/typing)
|
||||
* - Error API
|
||||
* - UnhandledRejection API
|
||||
*/
|
||||
|
||||
const handlers = {};
|
||||
const instrumented = {};
|
||||
|
||||
/** Instruments given API */
|
||||
function instrument(type) {
|
||||
if (instrumented[type]) {
|
||||
return;
|
||||
}
|
||||
|
||||
instrumented[type] = true;
|
||||
|
||||
switch (type) {
|
||||
case 'console':
|
||||
instrumentConsole();
|
||||
break;
|
||||
case 'dom':
|
||||
instrumentDOM();
|
||||
break;
|
||||
case 'xhr':
|
||||
instrumentXHR();
|
||||
break;
|
||||
case 'fetch':
|
||||
instrumentFetch();
|
||||
break;
|
||||
case 'history':
|
||||
instrumentHistory();
|
||||
break;
|
||||
case 'error':
|
||||
instrumentError();
|
||||
break;
|
||||
case 'unhandledrejection':
|
||||
instrumentUnhandledRejection();
|
||||
break;
|
||||
default:
|
||||
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('unknown instrumentation type:', type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add handler that will be called when given type of instrumentation triggers.
|
||||
* Use at your own risk, this might break without changelog notice, only used internally.
|
||||
* @hidden
|
||||
*/
|
||||
function addInstrumentationHandler(type, callback) {
|
||||
handlers[type] = handlers[type] || [];
|
||||
(handlers[type] ).push(callback);
|
||||
instrument(type);
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
function triggerHandlers(type, data) {
|
||||
if (!type || !handlers[type]) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const handler of handlers[type] || []) {
|
||||
try {
|
||||
handler(data);
|
||||
} catch (e) {
|
||||
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
|
||||
logger.error(
|
||||
`Error while triggering instrumentation handler.\nType: ${type}\nName: ${getFunctionName(handler)}\nError:`,
|
||||
e,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
function instrumentConsole() {
|
||||
if (!('console' in WINDOW)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CONSOLE_LEVELS.forEach(function (level) {
|
||||
if (!(level in WINDOW.console)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fill(WINDOW.console, level, function (originalConsoleMethod) {
|
||||
return function (...args) {
|
||||
triggerHandlers('console', { args, level });
|
||||
|
||||
// this fails for some browsers. :(
|
||||
if (originalConsoleMethod) {
|
||||
originalConsoleMethod.apply(WINDOW.console, args);
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
function instrumentFetch() {
|
||||
if (!supportsNativeFetch()) {
|
||||
return;
|
||||
}
|
||||
|
||||
fill(WINDOW, 'fetch', function (originalFetch) {
|
||||
return function (...args) {
|
||||
const { method, url } = parseFetchArgs(args);
|
||||
|
||||
const handlerData = {
|
||||
args,
|
||||
fetchData: {
|
||||
method,
|
||||
url,
|
||||
},
|
||||
startTimestamp: Date.now(),
|
||||
};
|
||||
|
||||
triggerHandlers('fetch', {
|
||||
...handlerData,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
return originalFetch.apply(WINDOW, args).then(
|
||||
(response) => {
|
||||
triggerHandlers('fetch', {
|
||||
...handlerData,
|
||||
endTimestamp: Date.now(),
|
||||
response,
|
||||
});
|
||||
return response;
|
||||
},
|
||||
(error) => {
|
||||
triggerHandlers('fetch', {
|
||||
...handlerData,
|
||||
endTimestamp: Date.now(),
|
||||
error,
|
||||
});
|
||||
// NOTE: If you are a Sentry user, and you are seeing this stack frame,
|
||||
// it means the sentry.javascript SDK caught an error invoking your application code.
|
||||
// This is expected behavior and NOT indicative of a bug with sentry.javascript.
|
||||
throw error;
|
||||
},
|
||||
);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function hasProp(obj, prop) {
|
||||
return !!obj && typeof obj === 'object' && !!(obj )[prop];
|
||||
}
|
||||
|
||||
function getUrlFromResource(resource) {
|
||||
if (typeof resource === 'string') {
|
||||
return resource;
|
||||
}
|
||||
|
||||
if (!resource) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (hasProp(resource, 'url')) {
|
||||
return resource.url;
|
||||
}
|
||||
|
||||
if (resource.toString) {
|
||||
return resource.toString();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the fetch arguments to find the used Http method and the url of the request
|
||||
*/
|
||||
function parseFetchArgs(fetchArgs) {
|
||||
if (fetchArgs.length === 0) {
|
||||
return { method: 'GET', url: '' };
|
||||
}
|
||||
|
||||
if (fetchArgs.length === 2) {
|
||||
const [url, options] = fetchArgs ;
|
||||
|
||||
return {
|
||||
url: getUrlFromResource(url),
|
||||
method: hasProp(options, 'method') ? String(options.method).toUpperCase() : 'GET',
|
||||
};
|
||||
}
|
||||
|
||||
const arg = fetchArgs[0];
|
||||
return {
|
||||
url: getUrlFromResource(arg ),
|
||||
method: hasProp(arg, 'method') ? String(arg.method).toUpperCase() : 'GET',
|
||||
};
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
function instrumentXHR() {
|
||||
if (!('XMLHttpRequest' in WINDOW)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const xhrproto = XMLHttpRequest.prototype;
|
||||
|
||||
fill(xhrproto, 'open', function (originalOpen) {
|
||||
return function ( ...args) {
|
||||
const url = args[1];
|
||||
const xhrInfo = (this[SENTRY_XHR_DATA_KEY] = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
method: isString(args[0]) ? args[0].toUpperCase() : args[0],
|
||||
url: args[1],
|
||||
request_headers: {},
|
||||
});
|
||||
|
||||
// if Sentry key appears in URL, don't capture it as a request
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
if (isString(url) && xhrInfo.method === 'POST' && url.match(/sentry_key/)) {
|
||||
this.__sentry_own_request__ = true;
|
||||
}
|
||||
|
||||
const onreadystatechangeHandler = () => {
|
||||
// For whatever reason, this is not the same instance here as from the outer method
|
||||
const xhrInfo = this[SENTRY_XHR_DATA_KEY];
|
||||
|
||||
if (!xhrInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.readyState === 4) {
|
||||
try {
|
||||
// touching statusCode in some platforms throws
|
||||
// an exception
|
||||
xhrInfo.status_code = this.status;
|
||||
} catch (e) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
triggerHandlers('xhr', {
|
||||
args: args ,
|
||||
endTimestamp: Date.now(),
|
||||
startTimestamp: Date.now(),
|
||||
xhr: this,
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
if ('onreadystatechange' in this && typeof this.onreadystatechange === 'function') {
|
||||
fill(this, 'onreadystatechange', function (original) {
|
||||
return function ( ...readyStateArgs) {
|
||||
onreadystatechangeHandler();
|
||||
return original.apply(this, readyStateArgs);
|
||||
};
|
||||
});
|
||||
} else {
|
||||
this.addEventListener('readystatechange', onreadystatechangeHandler);
|
||||
}
|
||||
|
||||
// Intercepting `setRequestHeader` to access the request headers of XHR instance.
|
||||
// This will only work for user/library defined headers, not for the default/browser-assigned headers.
|
||||
// Request cookies are also unavailable for XHR, as `Cookie` header can't be defined by `setRequestHeader`.
|
||||
fill(this, 'setRequestHeader', function (original) {
|
||||
return function ( ...setRequestHeaderArgs) {
|
||||
const [header, value] = setRequestHeaderArgs ;
|
||||
|
||||
const xhrInfo = this[SENTRY_XHR_DATA_KEY];
|
||||
|
||||
if (xhrInfo) {
|
||||
xhrInfo.request_headers[header.toLowerCase()] = value;
|
||||
}
|
||||
|
||||
return original.apply(this, setRequestHeaderArgs);
|
||||
};
|
||||
});
|
||||
|
||||
return originalOpen.apply(this, args);
|
||||
};
|
||||
});
|
||||
|
||||
fill(xhrproto, 'send', function (originalSend) {
|
||||
return function ( ...args) {
|
||||
const sentryXhrData = this[SENTRY_XHR_DATA_KEY];
|
||||
if (sentryXhrData && args[0] !== undefined) {
|
||||
sentryXhrData.body = args[0];
|
||||
}
|
||||
|
||||
triggerHandlers('xhr', {
|
||||
args,
|
||||
startTimestamp: Date.now(),
|
||||
xhr: this,
|
||||
});
|
||||
|
||||
return originalSend.apply(this, args);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
let lastHref;
|
||||
|
||||
/** JSDoc */
|
||||
function instrumentHistory() {
|
||||
if (!supportsHistory()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldOnPopState = WINDOW.onpopstate;
|
||||
WINDOW.onpopstate = function ( ...args) {
|
||||
const to = WINDOW.location.href;
|
||||
// keep track of the current URL state, as we always receive only the updated state
|
||||
const from = lastHref;
|
||||
lastHref = to;
|
||||
triggerHandlers('history', {
|
||||
from,
|
||||
to,
|
||||
});
|
||||
if (oldOnPopState) {
|
||||
// Apparently this can throw in Firefox when incorrectly implemented plugin is installed.
|
||||
// https://github.com/getsentry/sentry-javascript/issues/3344
|
||||
// https://github.com/bugsnag/bugsnag-js/issues/469
|
||||
try {
|
||||
return oldOnPopState.apply(this, args);
|
||||
} catch (_oO) {
|
||||
// no-empty
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** @hidden */
|
||||
function historyReplacementFunction(originalHistoryFunction) {
|
||||
return function ( ...args) {
|
||||
const url = args.length > 2 ? args[2] : undefined;
|
||||
if (url) {
|
||||
// coerce to string (this is what pushState does)
|
||||
const from = lastHref;
|
||||
const to = String(url);
|
||||
// keep track of the current URL state, as we always receive only the updated state
|
||||
lastHref = to;
|
||||
triggerHandlers('history', {
|
||||
from,
|
||||
to,
|
||||
});
|
||||
}
|
||||
return originalHistoryFunction.apply(this, args);
|
||||
};
|
||||
}
|
||||
|
||||
fill(WINDOW.history, 'pushState', historyReplacementFunction);
|
||||
fill(WINDOW.history, 'replaceState', historyReplacementFunction);
|
||||
}
|
||||
|
||||
const debounceDuration = 1000;
|
||||
let debounceTimerID;
|
||||
let lastCapturedEvent;
|
||||
|
||||
/**
|
||||
* Decide whether the current event should finish the debounce of previously captured one.
|
||||
* @param previous previously captured event
|
||||
* @param current event to be captured
|
||||
*/
|
||||
function shouldShortcircuitPreviousDebounce(previous, current) {
|
||||
// If there was no previous event, it should always be swapped for the new one.
|
||||
if (!previous) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If both events have different type, then user definitely performed two separate actions. e.g. click + keypress.
|
||||
if (previous.type !== current.type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
// If both events have the same type, it's still possible that actions were performed on different targets.
|
||||
// e.g. 2 clicks on different buttons.
|
||||
if (previous.target !== current.target) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
// just accessing `target` property can throw an exception in some rare circumstances
|
||||
// see: https://github.com/getsentry/sentry-javascript/issues/838
|
||||
}
|
||||
|
||||
// If both events have the same type _and_ same `target` (an element which triggered an event, _not necessarily_
|
||||
// to which an event listener was attached), we treat them as the same action, as we want to capture
|
||||
// only one breadcrumb. e.g. multiple clicks on the same button, or typing inside a user input box.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide whether an event should be captured.
|
||||
* @param event event to be captured
|
||||
*/
|
||||
function shouldSkipDOMEvent(event) {
|
||||
// We are only interested in filtering `keypress` events for now.
|
||||
if (event.type !== 'keypress') {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const target = event.target ;
|
||||
|
||||
if (!target || !target.tagName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only consider keypress events on actual input elements. This will disregard keypresses targeting body
|
||||
// e.g.tabbing through elements, hotkeys, etc.
|
||||
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
// just accessing `target` property can throw an exception in some rare circumstances
|
||||
// see: https://github.com/getsentry/sentry-javascript/issues/838
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps addEventListener to capture UI breadcrumbs
|
||||
* @param handler function that will be triggered
|
||||
* @param globalListener indicates whether event was captured by the global event listener
|
||||
* @returns wrapped breadcrumb events handler
|
||||
* @hidden
|
||||
*/
|
||||
function makeDOMEventHandler(handler, globalListener = false) {
|
||||
return (event) => {
|
||||
// It's possible this handler might trigger multiple times for the same
|
||||
// event (e.g. event propagation through node ancestors).
|
||||
// Ignore if we've already captured that event.
|
||||
if (!event || lastCapturedEvent === event) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We always want to skip _some_ events.
|
||||
if (shouldSkipDOMEvent(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const name = event.type === 'keypress' ? 'input' : event.type;
|
||||
|
||||
// If there is no debounce timer, it means that we can safely capture the new event and store it for future comparisons.
|
||||
if (debounceTimerID === undefined) {
|
||||
handler({
|
||||
event: event,
|
||||
name,
|
||||
global: globalListener,
|
||||
});
|
||||
lastCapturedEvent = event;
|
||||
}
|
||||
// If there is a debounce awaiting, see if the new event is different enough to treat it as a unique one.
|
||||
// If that's the case, emit the previous event and store locally the newly-captured DOM event.
|
||||
else if (shouldShortcircuitPreviousDebounce(lastCapturedEvent, event)) {
|
||||
handler({
|
||||
event: event,
|
||||
name,
|
||||
global: globalListener,
|
||||
});
|
||||
lastCapturedEvent = event;
|
||||
}
|
||||
|
||||
// Start a new debounce timer that will prevent us from capturing multiple events that should be grouped together.
|
||||
clearTimeout(debounceTimerID);
|
||||
debounceTimerID = WINDOW.setTimeout(() => {
|
||||
debounceTimerID = undefined;
|
||||
}, debounceDuration);
|
||||
};
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
function instrumentDOM() {
|
||||
if (!('document' in WINDOW)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make it so that any click or keypress that is unhandled / bubbled up all the way to the document triggers our dom
|
||||
// handlers. (Normally we have only one, which captures a breadcrumb for each click or keypress.) Do this before
|
||||
// we instrument `addEventListener` so that we don't end up attaching this handler twice.
|
||||
const triggerDOMHandler = triggerHandlers.bind(null, 'dom');
|
||||
const globalDOMEventHandler = makeDOMEventHandler(triggerDOMHandler, true);
|
||||
WINDOW.document.addEventListener('click', globalDOMEventHandler, false);
|
||||
WINDOW.document.addEventListener('keypress', globalDOMEventHandler, false);
|
||||
|
||||
// After hooking into click and keypress events bubbled up to `document`, we also hook into user-handled
|
||||
// clicks & keypresses, by adding an event listener of our own to any element to which they add a listener. That
|
||||
// way, whenever one of their handlers is triggered, ours will be, too. (This is needed because their handler
|
||||
// could potentially prevent the event from bubbling up to our global listeners. This way, our handler are still
|
||||
// guaranteed to fire at least once.)
|
||||
['EventTarget', 'Node'].forEach((target) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
const proto = (WINDOW )[target] && (WINDOW )[target].prototype;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, no-prototype-builtins
|
||||
if (!proto || !proto.hasOwnProperty || !proto.hasOwnProperty('addEventListener')) {
|
||||
return;
|
||||
}
|
||||
|
||||
fill(proto, 'addEventListener', function (originalAddEventListener) {
|
||||
return function (
|
||||
|
||||
type,
|
||||
listener,
|
||||
options,
|
||||
) {
|
||||
if (type === 'click' || type == 'keypress') {
|
||||
try {
|
||||
const el = this ;
|
||||
const handlers = (el.__sentry_instrumentation_handlers__ = el.__sentry_instrumentation_handlers__ || {});
|
||||
const handlerForType = (handlers[type] = handlers[type] || { refCount: 0 });
|
||||
|
||||
if (!handlerForType.handler) {
|
||||
const handler = makeDOMEventHandler(triggerDOMHandler);
|
||||
handlerForType.handler = handler;
|
||||
originalAddEventListener.call(this, type, handler, options);
|
||||
}
|
||||
|
||||
handlerForType.refCount++;
|
||||
} catch (e) {
|
||||
// Accessing dom properties is always fragile.
|
||||
// Also allows us to skip `addEventListenrs` calls with no proper `this` context.
|
||||
}
|
||||
}
|
||||
|
||||
return originalAddEventListener.call(this, type, listener, options);
|
||||
};
|
||||
});
|
||||
|
||||
fill(
|
||||
proto,
|
||||
'removeEventListener',
|
||||
function (originalRemoveEventListener) {
|
||||
return function (
|
||||
|
||||
type,
|
||||
listener,
|
||||
options,
|
||||
) {
|
||||
if (type === 'click' || type == 'keypress') {
|
||||
try {
|
||||
const el = this ;
|
||||
const handlers = el.__sentry_instrumentation_handlers__ || {};
|
||||
const handlerForType = handlers[type];
|
||||
|
||||
if (handlerForType) {
|
||||
handlerForType.refCount--;
|
||||
// If there are no longer any custom handlers of the current type on this element, we can remove ours, too.
|
||||
if (handlerForType.refCount <= 0) {
|
||||
originalRemoveEventListener.call(this, type, handlerForType.handler, options);
|
||||
handlerForType.handler = undefined;
|
||||
delete handlers[type]; // eslint-disable-line @typescript-eslint/no-dynamic-delete
|
||||
}
|
||||
|
||||
// If there are no longer any custom handlers of any type on this element, cleanup everything.
|
||||
if (Object.keys(handlers).length === 0) {
|
||||
delete el.__sentry_instrumentation_handlers__;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Accessing dom properties is always fragile.
|
||||
// Also allows us to skip `addEventListenrs` calls with no proper `this` context.
|
||||
}
|
||||
}
|
||||
|
||||
return originalRemoveEventListener.call(this, type, listener, options);
|
||||
};
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
let _oldOnErrorHandler = null;
|
||||
/** JSDoc */
|
||||
function instrumentError() {
|
||||
_oldOnErrorHandler = WINDOW.onerror;
|
||||
|
||||
WINDOW.onerror = function (msg, url, line, column, error) {
|
||||
triggerHandlers('error', {
|
||||
column,
|
||||
error,
|
||||
line,
|
||||
msg,
|
||||
url,
|
||||
});
|
||||
|
||||
if (_oldOnErrorHandler && !_oldOnErrorHandler.__SENTRY_LOADER__) {
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
return _oldOnErrorHandler.apply(this, arguments);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
WINDOW.onerror.__SENTRY_INSTRUMENTED__ = true;
|
||||
}
|
||||
|
||||
let _oldOnUnhandledRejectionHandler = null;
|
||||
/** JSDoc */
|
||||
function instrumentUnhandledRejection() {
|
||||
_oldOnUnhandledRejectionHandler = WINDOW.onunhandledrejection;
|
||||
|
||||
WINDOW.onunhandledrejection = function (e) {
|
||||
triggerHandlers('unhandledrejection', e);
|
||||
|
||||
if (_oldOnUnhandledRejectionHandler && !_oldOnUnhandledRejectionHandler.__SENTRY_LOADER__) {
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
return _oldOnUnhandledRejectionHandler.apply(this, arguments);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
WINDOW.onunhandledrejection.__SENTRY_INSTRUMENTED__ = true;
|
||||
}
|
||||
|
||||
export { SENTRY_XHR_DATA_KEY, addInstrumentationHandler, parseFetchArgs };
|
||||
//# sourceMappingURL=instrument.js.map
|
||||
179
shared/logger/node_modules/@sentry/utils/esm/is.js
generated
vendored
Normal file
179
shared/logger/node_modules/@sentry/utils/esm/is.js
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
const objectToString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
* Checks whether given value's type is one of a few Error or Error-like
|
||||
* {@link isError}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isError(wat) {
|
||||
switch (objectToString.call(wat)) {
|
||||
case '[object Error]':
|
||||
case '[object Exception]':
|
||||
case '[object DOMException]':
|
||||
return true;
|
||||
default:
|
||||
return isInstanceOf(wat, Error);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Checks whether given value is an instance of the given built-in class.
|
||||
*
|
||||
* @param wat The value to be checked
|
||||
* @param className
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isBuiltin(wat, className) {
|
||||
return objectToString.call(wat) === `[object ${className}]`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value's type is ErrorEvent
|
||||
* {@link isErrorEvent}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isErrorEvent(wat) {
|
||||
return isBuiltin(wat, 'ErrorEvent');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value's type is DOMError
|
||||
* {@link isDOMError}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isDOMError(wat) {
|
||||
return isBuiltin(wat, 'DOMError');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value's type is DOMException
|
||||
* {@link isDOMException}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isDOMException(wat) {
|
||||
return isBuiltin(wat, 'DOMException');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value's type is a string
|
||||
* {@link isString}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isString(wat) {
|
||||
return isBuiltin(wat, 'String');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value is a primitive (undefined, null, number, boolean, string, bigint, symbol)
|
||||
* {@link isPrimitive}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isPrimitive(wat) {
|
||||
return wat === null || (typeof wat !== 'object' && typeof wat !== 'function');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value's type is an object literal
|
||||
* {@link isPlainObject}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isPlainObject(wat) {
|
||||
return isBuiltin(wat, 'Object');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value's type is an Event instance
|
||||
* {@link isEvent}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isEvent(wat) {
|
||||
return typeof Event !== 'undefined' && isInstanceOf(wat, Event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value's type is an Element instance
|
||||
* {@link isElement}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isElement(wat) {
|
||||
return typeof Element !== 'undefined' && isInstanceOf(wat, Element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value's type is an regexp
|
||||
* {@link isRegExp}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isRegExp(wat) {
|
||||
return isBuiltin(wat, 'RegExp');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value has a then function.
|
||||
* @param wat A value to be checked.
|
||||
*/
|
||||
function isThenable(wat) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
return Boolean(wat && wat.then && typeof wat.then === 'function');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value's type is a SyntheticEvent
|
||||
* {@link isSyntheticEvent}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isSyntheticEvent(wat) {
|
||||
return isPlainObject(wat) && 'nativeEvent' in wat && 'preventDefault' in wat && 'stopPropagation' in wat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value is NaN
|
||||
* {@link isNaN}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isNaN(wat) {
|
||||
return typeof wat === 'number' && wat !== wat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given value's type is an instance of provided constructor.
|
||||
* {@link isInstanceOf}.
|
||||
*
|
||||
* @param wat A value to be checked.
|
||||
* @param base A constructor to be used in a check.
|
||||
* @returns A boolean representing the result.
|
||||
*/
|
||||
function isInstanceOf(wat, base) {
|
||||
try {
|
||||
return wat instanceof base;
|
||||
} catch (_e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export { isDOMError, isDOMException, isElement, isError, isErrorEvent, isEvent, isInstanceOf, isNaN, isPlainObject, isPrimitive, isRegExp, isString, isSyntheticEvent, isThenable };
|
||||
//# sourceMappingURL=is.js.map
|
||||
83
shared/logger/node_modules/@sentry/utils/esm/logger.js
generated
vendored
Normal file
83
shared/logger/node_modules/@sentry/utils/esm/logger.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
import { getGlobalSingleton, GLOBAL_OBJ } from './worldwide.js';
|
||||
|
||||
/** Prefix for logging strings */
|
||||
const PREFIX = 'Sentry Logger ';
|
||||
|
||||
const CONSOLE_LEVELS = ['debug', 'info', 'warn', 'error', 'log', 'assert', 'trace'] ;
|
||||
|
||||
/**
|
||||
* Temporarily disable sentry console instrumentations.
|
||||
*
|
||||
* @param callback The function to run against the original `console` messages
|
||||
* @returns The results of the callback
|
||||
*/
|
||||
function consoleSandbox(callback) {
|
||||
if (!('console' in GLOBAL_OBJ)) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
const originalConsole = GLOBAL_OBJ.console ;
|
||||
const wrappedLevels = {};
|
||||
|
||||
// Restore all wrapped console methods
|
||||
CONSOLE_LEVELS.forEach(level => {
|
||||
// TODO(v7): Remove this check as it's only needed for Node 6
|
||||
const originalWrappedFunc =
|
||||
originalConsole[level] && (originalConsole[level] ).__sentry_original__;
|
||||
if (level in originalConsole && originalWrappedFunc) {
|
||||
wrappedLevels[level] = originalConsole[level] ;
|
||||
originalConsole[level] = originalWrappedFunc ;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
return callback();
|
||||
} finally {
|
||||
// Revert restoration to wrapped state
|
||||
Object.keys(wrappedLevels).forEach(level => {
|
||||
originalConsole[level] = wrappedLevels[level ];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function makeLogger() {
|
||||
let enabled = false;
|
||||
const logger = {
|
||||
enable: () => {
|
||||
enabled = true;
|
||||
},
|
||||
disable: () => {
|
||||
enabled = false;
|
||||
},
|
||||
};
|
||||
|
||||
if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
|
||||
CONSOLE_LEVELS.forEach(name => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
logger[name] = (...args) => {
|
||||
if (enabled) {
|
||||
consoleSandbox(() => {
|
||||
GLOBAL_OBJ.console[name](`${PREFIX}[${name}]:`, ...args);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
} else {
|
||||
CONSOLE_LEVELS.forEach(name => {
|
||||
logger[name] = () => undefined;
|
||||
});
|
||||
}
|
||||
|
||||
return logger ;
|
||||
}
|
||||
|
||||
// Ensure we only have a single logger instance, even if multiple versions of @sentry/utils are being used
|
||||
let logger;
|
||||
if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
|
||||
logger = getGlobalSingleton('logger', makeLogger);
|
||||
} else {
|
||||
logger = makeLogger();
|
||||
}
|
||||
|
||||
export { CONSOLE_LEVELS, consoleSandbox, logger };
|
||||
//# sourceMappingURL=logger.js.map
|
||||
45
shared/logger/node_modules/@sentry/utils/esm/memo.js
generated
vendored
Normal file
45
shared/logger/node_modules/@sentry/utils/esm/memo.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
/**
|
||||
* Helper to decycle json objects
|
||||
*/
|
||||
function memoBuilder() {
|
||||
const hasWeakSet = typeof WeakSet === 'function';
|
||||
const inner = hasWeakSet ? new WeakSet() : [];
|
||||
function memoize(obj) {
|
||||
if (hasWeakSet) {
|
||||
if (inner.has(obj)) {
|
||||
return true;
|
||||
}
|
||||
inner.add(obj);
|
||||
return false;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
||||
for (let i = 0; i < inner.length; i++) {
|
||||
const value = inner[i];
|
||||
if (value === obj) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
inner.push(obj);
|
||||
return false;
|
||||
}
|
||||
|
||||
function unmemoize(obj) {
|
||||
if (hasWeakSet) {
|
||||
inner.delete(obj);
|
||||
} else {
|
||||
for (let i = 0; i < inner.length; i++) {
|
||||
if (inner[i] === obj) {
|
||||
inner.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return [memoize, unmemoize];
|
||||
}
|
||||
|
||||
export { memoBuilder };
|
||||
//# sourceMappingURL=memo.js.map
|
||||
197
shared/logger/node_modules/@sentry/utils/esm/misc.js
generated
vendored
Normal file
197
shared/logger/node_modules/@sentry/utils/esm/misc.js
generated
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
import { addNonEnumerableProperty } from './object.js';
|
||||
import { snipLine } from './string.js';
|
||||
import { GLOBAL_OBJ } from './worldwide.js';
|
||||
|
||||
/**
|
||||
* UUID4 generator
|
||||
*
|
||||
* @returns string Generated UUID4.
|
||||
*/
|
||||
function uuid4() {
|
||||
const gbl = GLOBAL_OBJ ;
|
||||
const crypto = gbl.crypto || gbl.msCrypto;
|
||||
|
||||
if (crypto && crypto.randomUUID) {
|
||||
return crypto.randomUUID().replace(/-/g, '');
|
||||
}
|
||||
|
||||
const getRandomByte =
|
||||
crypto && crypto.getRandomValues ? () => crypto.getRandomValues(new Uint8Array(1))[0] : () => Math.random() * 16;
|
||||
|
||||
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
|
||||
// Concatenating the following numbers as strings results in '10000000100040008000100000000000'
|
||||
return (([1e7] ) + 1e3 + 4e3 + 8e3 + 1e11).replace(/[018]/g, c =>
|
||||
// eslint-disable-next-line no-bitwise
|
||||
((c ) ^ ((getRandomByte() & 15) >> ((c ) / 4))).toString(16),
|
||||
);
|
||||
}
|
||||
|
||||
function getFirstException(event) {
|
||||
return event.exception && event.exception.values ? event.exception.values[0] : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts either message or type+value from an event that can be used for user-facing logs
|
||||
* @returns event's description
|
||||
*/
|
||||
function getEventDescription(event) {
|
||||
const { message, event_id: eventId } = event;
|
||||
if (message) {
|
||||
return message;
|
||||
}
|
||||
|
||||
const firstException = getFirstException(event);
|
||||
if (firstException) {
|
||||
if (firstException.type && firstException.value) {
|
||||
return `${firstException.type}: ${firstException.value}`;
|
||||
}
|
||||
return firstException.type || firstException.value || eventId || '<unknown>';
|
||||
}
|
||||
return eventId || '<unknown>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds exception values, type and value to an synthetic Exception.
|
||||
* @param event The event to modify.
|
||||
* @param value Value of the exception.
|
||||
* @param type Type of the exception.
|
||||
* @hidden
|
||||
*/
|
||||
function addExceptionTypeValue(event, value, type) {
|
||||
const exception = (event.exception = event.exception || {});
|
||||
const values = (exception.values = exception.values || []);
|
||||
const firstException = (values[0] = values[0] || {});
|
||||
if (!firstException.value) {
|
||||
firstException.value = value || '';
|
||||
}
|
||||
if (!firstException.type) {
|
||||
firstException.type = type || 'Error';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds exception mechanism data to a given event. Uses defaults if the second parameter is not passed.
|
||||
*
|
||||
* @param event The event to modify.
|
||||
* @param newMechanism Mechanism data to add to the event.
|
||||
* @hidden
|
||||
*/
|
||||
function addExceptionMechanism(event, newMechanism) {
|
||||
const firstException = getFirstException(event);
|
||||
if (!firstException) {
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultMechanism = { type: 'generic', handled: true };
|
||||
const currentMechanism = firstException.mechanism;
|
||||
firstException.mechanism = { ...defaultMechanism, ...currentMechanism, ...newMechanism };
|
||||
|
||||
if (newMechanism && 'data' in newMechanism) {
|
||||
const mergedData = { ...(currentMechanism && currentMechanism.data), ...newMechanism.data };
|
||||
firstException.mechanism.data = mergedData;
|
||||
}
|
||||
}
|
||||
|
||||
// https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
||||
const SEMVER_REGEXP =
|
||||
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
||||
|
||||
/**
|
||||
* Represents Semantic Versioning object
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parses input into a SemVer interface
|
||||
* @param input string representation of a semver version
|
||||
*/
|
||||
function parseSemver(input) {
|
||||
const match = input.match(SEMVER_REGEXP) || [];
|
||||
const major = parseInt(match[1], 10);
|
||||
const minor = parseInt(match[2], 10);
|
||||
const patch = parseInt(match[3], 10);
|
||||
return {
|
||||
buildmetadata: match[5],
|
||||
major: isNaN(major) ? undefined : major,
|
||||
minor: isNaN(minor) ? undefined : minor,
|
||||
patch: isNaN(patch) ? undefined : patch,
|
||||
prerelease: match[4],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This function adds context (pre/post/line) lines to the provided frame
|
||||
*
|
||||
* @param lines string[] containing all lines
|
||||
* @param frame StackFrame that will be mutated
|
||||
* @param linesOfContext number of context lines we want to add pre/post
|
||||
*/
|
||||
function addContextToFrame(lines, frame, linesOfContext = 5) {
|
||||
// When there is no line number in the frame, attaching context is nonsensical and will even break grouping
|
||||
if (frame.lineno === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const maxLines = lines.length;
|
||||
const sourceLine = Math.max(Math.min(maxLines, frame.lineno - 1), 0);
|
||||
|
||||
frame.pre_context = lines
|
||||
.slice(Math.max(0, sourceLine - linesOfContext), sourceLine)
|
||||
.map((line) => snipLine(line, 0));
|
||||
|
||||
frame.context_line = snipLine(lines[Math.min(maxLines - 1, sourceLine)], frame.colno || 0);
|
||||
|
||||
frame.post_context = lines
|
||||
.slice(Math.min(sourceLine + 1, maxLines), sourceLine + 1 + linesOfContext)
|
||||
.map((line) => snipLine(line, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not we've already captured the given exception (note: not an identical exception - the very object
|
||||
* in question), and marks it captured if not.
|
||||
*
|
||||
* This is useful because it's possible for an error to get captured by more than one mechanism. After we intercept and
|
||||
* record an error, we rethrow it (assuming we've intercepted it before it's reached the top-level global handlers), so
|
||||
* that we don't interfere with whatever effects the error might have had were the SDK not there. At that point, because
|
||||
* the error has been rethrown, it's possible for it to bubble up to some other code we've instrumented. If it's not
|
||||
* caught after that, it will bubble all the way up to the global handlers (which of course we also instrument). This
|
||||
* function helps us ensure that even if we encounter the same error more than once, we only record it the first time we
|
||||
* see it.
|
||||
*
|
||||
* Note: It will ignore primitives (always return `false` and not mark them as seen), as properties can't be set on
|
||||
* them. {@link: Object.objectify} can be used on exceptions to convert any that are primitives into their equivalent
|
||||
* object wrapper forms so that this check will always work. However, because we need to flag the exact object which
|
||||
* will get rethrown, and because that rethrowing happens outside of the event processing pipeline, the objectification
|
||||
* must be done before the exception captured.
|
||||
*
|
||||
* @param A thrown exception to check or flag as having been seen
|
||||
* @returns `true` if the exception has already been captured, `false` if not (with the side effect of marking it seen)
|
||||
*/
|
||||
function checkOrSetAlreadyCaught(exception) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
if (exception && (exception ).__sentry_captured__) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
// set it this way rather than by assignment so that it's not ennumerable and therefore isn't recorded by the
|
||||
// `ExtraErrorData` integration
|
||||
addNonEnumerableProperty(exception , '__sentry_captured__', true);
|
||||
} catch (err) {
|
||||
// `exception` is a primitive, so we can't mark it seen
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given input is already an array, and if it isn't, wraps it in one.
|
||||
*
|
||||
* @param maybeArray Input to turn into an array, if necessary
|
||||
* @returns The input, if already an array, or an array with the input as the only element, if not
|
||||
*/
|
||||
function arrayify(maybeArray) {
|
||||
return Array.isArray(maybeArray) ? maybeArray : [maybeArray];
|
||||
}
|
||||
|
||||
export { addContextToFrame, addExceptionMechanism, addExceptionTypeValue, arrayify, checkOrSetAlreadyCaught, getEventDescription, parseSemver, uuid4 };
|
||||
//# sourceMappingURL=misc.js.map
|
||||
66
shared/logger/node_modules/@sentry/utils/esm/node.js
generated
vendored
Normal file
66
shared/logger/node_modules/@sentry/utils/esm/node.js
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
import { isBrowserBundle } from './env.js';
|
||||
|
||||
/**
|
||||
* NOTE: In order to avoid circular dependencies, if you add a function to this module and it needs to print something,
|
||||
* you must either a) use `console.log` rather than the logger, or b) put your function elsewhere.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks whether we're in the Node.js or Browser environment
|
||||
*
|
||||
* @returns Answer to given question
|
||||
*/
|
||||
function isNodeEnv() {
|
||||
// explicitly check for browser bundles as those can be optimized statically
|
||||
// by terser/rollup.
|
||||
return (
|
||||
!isBrowserBundle() &&
|
||||
Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requires a module which is protected against bundler minification.
|
||||
*
|
||||
* @param request The module path to resolve
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
|
||||
function dynamicRequire(mod, request) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
return mod.require(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for dynamically loading module that should work with linked dependencies.
|
||||
* The problem is that we _should_ be using `require(require.resolve(moduleName, { paths: [cwd()] }))`
|
||||
* However it's _not possible_ to do that with Webpack, as it has to know all the dependencies during
|
||||
* build time. `require.resolve` is also not available in any other way, so we cannot create,
|
||||
* a fake helper like we do with `dynamicRequire`.
|
||||
*
|
||||
* We always prefer to use local package, thus the value is not returned early from each `try/catch` block.
|
||||
* That is to mimic the behavior of `require.resolve` exactly.
|
||||
*
|
||||
* @param moduleName module name to require
|
||||
* @returns possibly required module
|
||||
*/
|
||||
function loadModule(moduleName) {
|
||||
let mod;
|
||||
|
||||
try {
|
||||
mod = dynamicRequire(module, moduleName);
|
||||
} catch (e) {
|
||||
// no-empty
|
||||
}
|
||||
|
||||
try {
|
||||
const { cwd } = dynamicRequire(module, 'process');
|
||||
mod = dynamicRequire(module, `${cwd()}/node_modules/${moduleName}`) ;
|
||||
} catch (e) {
|
||||
// no-empty
|
||||
}
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
export { dynamicRequire, isNodeEnv, loadModule };
|
||||
//# sourceMappingURL=node.js.map
|
||||
263
shared/logger/node_modules/@sentry/utils/esm/normalize.js
generated
vendored
Normal file
263
shared/logger/node_modules/@sentry/utils/esm/normalize.js
generated
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
import { isNaN, isSyntheticEvent } from './is.js';
|
||||
import { memoBuilder } from './memo.js';
|
||||
import { convertToPlainObject } from './object.js';
|
||||
import { getFunctionName } from './stacktrace.js';
|
||||
|
||||
/**
|
||||
* Recursively normalizes the given object.
|
||||
*
|
||||
* - Creates a copy to prevent original input mutation
|
||||
* - Skips non-enumerable properties
|
||||
* - When stringifying, calls `toJSON` if implemented
|
||||
* - Removes circular references
|
||||
* - Translates non-serializable values (`undefined`/`NaN`/functions) to serializable format
|
||||
* - Translates known global objects/classes to a string representations
|
||||
* - Takes care of `Error` object serialization
|
||||
* - Optionally limits depth of final output
|
||||
* - Optionally limits number of properties/elements included in any single object/array
|
||||
*
|
||||
* @param input The object to be normalized.
|
||||
* @param depth The max depth to which to normalize the object. (Anything deeper stringified whole.)
|
||||
* @param maxProperties The max number of elements or properties to be included in any single array or
|
||||
* object in the normallized output.
|
||||
* @returns A normalized version of the object, or `"**non-serializable**"` if any errors are thrown during normalization.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function normalize(input, depth = 100, maxProperties = +Infinity) {
|
||||
try {
|
||||
// since we're at the outermost level, we don't provide a key
|
||||
return visit('', input, depth, maxProperties);
|
||||
} catch (err) {
|
||||
return { ERROR: `**non-serializable** (${err})` };
|
||||
}
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
function normalizeToSize(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
object,
|
||||
// Default Node.js REPL depth
|
||||
depth = 3,
|
||||
// 100kB, as 200kB is max payload size, so half sounds reasonable
|
||||
maxSize = 100 * 1024,
|
||||
) {
|
||||
const normalized = normalize(object, depth);
|
||||
|
||||
if (jsonSize(normalized) > maxSize) {
|
||||
return normalizeToSize(object, depth - 1, maxSize);
|
||||
}
|
||||
|
||||
return normalized ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a node to perform normalization on it
|
||||
*
|
||||
* @param key The key corresponding to the given node
|
||||
* @param value The node to be visited
|
||||
* @param depth Optional number indicating the maximum recursion depth
|
||||
* @param maxProperties Optional maximum number of properties/elements included in any single object/array
|
||||
* @param memo Optional Memo class handling decycling
|
||||
*/
|
||||
function visit(
|
||||
key,
|
||||
value,
|
||||
depth = +Infinity,
|
||||
maxProperties = +Infinity,
|
||||
memo = memoBuilder(),
|
||||
) {
|
||||
const [memoize, unmemoize] = memo;
|
||||
|
||||
// Get the simple cases out of the way first
|
||||
if (
|
||||
value == null || // this matches null and undefined -> eqeq not eqeqeq
|
||||
(['number', 'boolean', 'string'].includes(typeof value) && !isNaN(value))
|
||||
) {
|
||||
return value ;
|
||||
}
|
||||
|
||||
const stringified = stringifyValue(key, value);
|
||||
|
||||
// Anything we could potentially dig into more (objects or arrays) will have come back as `"[object XXXX]"`.
|
||||
// Everything else will have already been serialized, so if we don't see that pattern, we're done.
|
||||
if (!stringified.startsWith('[object ')) {
|
||||
return stringified;
|
||||
}
|
||||
|
||||
// From here on, we can assert that `value` is either an object or an array.
|
||||
|
||||
// Do not normalize objects that we know have already been normalized. As a general rule, the
|
||||
// "__sentry_skip_normalization__" property should only be used sparingly and only should only be set on objects that
|
||||
// have already been normalized.
|
||||
if ((value )['__sentry_skip_normalization__']) {
|
||||
return value ;
|
||||
}
|
||||
|
||||
// We can set `__sentry_override_normalization_depth__` on an object to ensure that from there
|
||||
// We keep a certain amount of depth.
|
||||
// This should be used sparingly, e.g. we use it for the redux integration to ensure we get a certain amount of state.
|
||||
const remainingDepth =
|
||||
typeof (value )['__sentry_override_normalization_depth__'] === 'number'
|
||||
? ((value )['__sentry_override_normalization_depth__'] )
|
||||
: depth;
|
||||
|
||||
// We're also done if we've reached the max depth
|
||||
if (remainingDepth === 0) {
|
||||
// At this point we know `serialized` is a string of the form `"[object XXXX]"`. Clean it up so it's just `"[XXXX]"`.
|
||||
return stringified.replace('object ', '');
|
||||
}
|
||||
|
||||
// If we've already visited this branch, bail out, as it's circular reference. If not, note that we're seeing it now.
|
||||
if (memoize(value)) {
|
||||
return '[Circular ~]';
|
||||
}
|
||||
|
||||
// If the value has a `toJSON` method, we call it to extract more information
|
||||
const valueWithToJSON = value ;
|
||||
if (valueWithToJSON && typeof valueWithToJSON.toJSON === 'function') {
|
||||
try {
|
||||
const jsonValue = valueWithToJSON.toJSON();
|
||||
// We need to normalize the return value of `.toJSON()` in case it has circular references
|
||||
return visit('', jsonValue, remainingDepth - 1, maxProperties, memo);
|
||||
} catch (err) {
|
||||
// pass (The built-in `toJSON` failed, but we can still try to do it ourselves)
|
||||
}
|
||||
}
|
||||
|
||||
// At this point we know we either have an object or an array, we haven't seen it before, and we're going to recurse
|
||||
// because we haven't yet reached the max depth. Create an accumulator to hold the results of visiting each
|
||||
// property/entry, and keep track of the number of items we add to it.
|
||||
const normalized = (Array.isArray(value) ? [] : {}) ;
|
||||
let numAdded = 0;
|
||||
|
||||
// Before we begin, convert`Error` and`Event` instances into plain objects, since some of each of their relevant
|
||||
// properties are non-enumerable and otherwise would get missed.
|
||||
const visitable = convertToPlainObject(value );
|
||||
|
||||
for (const visitKey in visitable) {
|
||||
// Avoid iterating over fields in the prototype if they've somehow been exposed to enumeration.
|
||||
if (!Object.prototype.hasOwnProperty.call(visitable, visitKey)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (numAdded >= maxProperties) {
|
||||
normalized[visitKey] = '[MaxProperties ~]';
|
||||
break;
|
||||
}
|
||||
|
||||
// Recursively visit all the child nodes
|
||||
const visitValue = visitable[visitKey];
|
||||
normalized[visitKey] = visit(visitKey, visitValue, remainingDepth - 1, maxProperties, memo);
|
||||
|
||||
numAdded++;
|
||||
}
|
||||
|
||||
// Once we've visited all the branches, remove the parent from memo storage
|
||||
unmemoize(value);
|
||||
|
||||
// Return accumulated values
|
||||
return normalized;
|
||||
}
|
||||
|
||||
/* eslint-disable complexity */
|
||||
/**
|
||||
* Stringify the given value. Handles various known special values and types.
|
||||
*
|
||||
* Not meant to be used on simple primitives which already have a string representation, as it will, for example, turn
|
||||
* the number 1231 into "[Object Number]", nor on `null`, as it will throw.
|
||||
*
|
||||
* @param value The value to stringify
|
||||
* @returns A stringified representation of the given value
|
||||
*/
|
||||
function stringifyValue(
|
||||
key,
|
||||
// this type is a tiny bit of a cheat, since this function does handle NaN (which is technically a number), but for
|
||||
// our internal use, it'll do
|
||||
value,
|
||||
) {
|
||||
try {
|
||||
if (key === 'domain' && value && typeof value === 'object' && (value )._events) {
|
||||
return '[Domain]';
|
||||
}
|
||||
|
||||
if (key === 'domainEmitter') {
|
||||
return '[DomainEmitter]';
|
||||
}
|
||||
|
||||
// It's safe to use `global`, `window`, and `document` here in this manner, as we are asserting using `typeof` first
|
||||
// which won't throw if they are not present.
|
||||
|
||||
if (typeof global !== 'undefined' && value === global) {
|
||||
return '[Global]';
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
if (typeof window !== 'undefined' && value === window) {
|
||||
return '[Window]';
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
if (typeof document !== 'undefined' && value === document) {
|
||||
return '[Document]';
|
||||
}
|
||||
|
||||
// React's SyntheticEvent thingy
|
||||
if (isSyntheticEvent(value)) {
|
||||
return '[SyntheticEvent]';
|
||||
}
|
||||
|
||||
if (typeof value === 'number' && value !== value) {
|
||||
return '[NaN]';
|
||||
}
|
||||
|
||||
if (typeof value === 'function') {
|
||||
return `[Function: ${getFunctionName(value)}]`;
|
||||
}
|
||||
|
||||
if (typeof value === 'symbol') {
|
||||
return `[${String(value)}]`;
|
||||
}
|
||||
|
||||
// stringified BigInts are indistinguishable from regular numbers, so we need to label them to avoid confusion
|
||||
if (typeof value === 'bigint') {
|
||||
return `[BigInt: ${String(value)}]`;
|
||||
}
|
||||
|
||||
// Now that we've knocked out all the special cases and the primitives, all we have left are objects. Simply casting
|
||||
// them to strings means that instances of classes which haven't defined their `toStringTag` will just come out as
|
||||
// `"[object Object]"`. If we instead look at the constructor's name (which is the same as the name of the class),
|
||||
// we can make sure that only plain objects come out that way.
|
||||
const objName = getConstructorName(value);
|
||||
|
||||
// Handle HTML Elements
|
||||
if (/^HTML(\w*)Element$/.test(objName)) {
|
||||
return `[HTMLElement: ${objName}]`;
|
||||
}
|
||||
|
||||
return `[object ${objName}]`;
|
||||
} catch (err) {
|
||||
return `**non-serializable** (${err})`;
|
||||
}
|
||||
}
|
||||
/* eslint-enable complexity */
|
||||
|
||||
function getConstructorName(value) {
|
||||
const prototype = Object.getPrototypeOf(value);
|
||||
|
||||
return prototype ? prototype.constructor.name : 'null prototype';
|
||||
}
|
||||
|
||||
/** Calculates bytes size of input string */
|
||||
function utf8Length(value) {
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return ~-encodeURI(value).split(/%..|./).length;
|
||||
}
|
||||
|
||||
/** Calculates bytes size of input object */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function jsonSize(value) {
|
||||
return utf8Length(JSON.stringify(value));
|
||||
}
|
||||
|
||||
export { normalize, normalizeToSize, visit as walk };
|
||||
//# sourceMappingURL=normalize.js.map
|
||||
279
shared/logger/node_modules/@sentry/utils/esm/object.js
generated
vendored
Normal file
279
shared/logger/node_modules/@sentry/utils/esm/object.js
generated
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
import { htmlTreeAsString } from './browser.js';
|
||||
import { isError, isEvent, isInstanceOf, isElement, isPlainObject, isPrimitive } from './is.js';
|
||||
import { truncate } from './string.js';
|
||||
|
||||
/**
|
||||
* Replace a method in an object with a wrapped version of itself.
|
||||
*
|
||||
* @param source An object that contains a method to be wrapped.
|
||||
* @param name The name of the method to be wrapped.
|
||||
* @param replacementFactory A higher-order function that takes the original version of the given method and returns a
|
||||
* wrapped version. Note: The function returned by `replacementFactory` needs to be a non-arrow function, in order to
|
||||
* preserve the correct value of `this`, and the original method must be called using `origMethod.call(this, <other
|
||||
* args>)` or `origMethod.apply(this, [<other args>])` (rather than being called directly), again to preserve `this`.
|
||||
* @returns void
|
||||
*/
|
||||
function fill(source, name, replacementFactory) {
|
||||
if (!(name in source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const original = source[name] ;
|
||||
const wrapped = replacementFactory(original) ;
|
||||
|
||||
// Make sure it's a function first, as we need to attach an empty prototype for `defineProperties` to work
|
||||
// otherwise it'll throw "TypeError: Object.defineProperties called on non-object"
|
||||
if (typeof wrapped === 'function') {
|
||||
try {
|
||||
markFunctionWrapped(wrapped, original);
|
||||
} catch (_Oo) {
|
||||
// This can throw if multiple fill happens on a global object like XMLHttpRequest
|
||||
// Fixes https://github.com/getsentry/sentry-javascript/issues/2043
|
||||
}
|
||||
}
|
||||
|
||||
source[name] = wrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a non-enumerable property on the given object.
|
||||
*
|
||||
* @param obj The object on which to set the property
|
||||
* @param name The name of the property to be set
|
||||
* @param value The value to which to set the property
|
||||
*/
|
||||
function addNonEnumerableProperty(obj, name, value) {
|
||||
Object.defineProperty(obj, name, {
|
||||
// enumerable: false, // the default, so we can save on bundle size by not explicitly setting it
|
||||
value: value,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remembers the original function on the wrapped function and
|
||||
* patches up the prototype.
|
||||
*
|
||||
* @param wrapped the wrapper function
|
||||
* @param original the original function that gets wrapped
|
||||
*/
|
||||
function markFunctionWrapped(wrapped, original) {
|
||||
const proto = original.prototype || {};
|
||||
wrapped.prototype = original.prototype = proto;
|
||||
addNonEnumerableProperty(wrapped, '__sentry_original__', original);
|
||||
}
|
||||
|
||||
/**
|
||||
* This extracts the original function if available. See
|
||||
* `markFunctionWrapped` for more information.
|
||||
*
|
||||
* @param func the function to unwrap
|
||||
* @returns the unwrapped version of the function if available.
|
||||
*/
|
||||
function getOriginalFunction(func) {
|
||||
return func.__sentry_original__;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes given object into url-friendly format
|
||||
*
|
||||
* @param object An object that contains serializable values
|
||||
* @returns string Encoded
|
||||
*/
|
||||
function urlEncode(object) {
|
||||
return Object.keys(object)
|
||||
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(object[key])}`)
|
||||
.join('&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms any `Error` or `Event` into a plain object with all of their enumerable properties, and some of their
|
||||
* non-enumerable properties attached.
|
||||
*
|
||||
* @param value Initial source that we have to transform in order for it to be usable by the serializer
|
||||
* @returns An Event or Error turned into an object - or the value argurment itself, when value is neither an Event nor
|
||||
* an Error.
|
||||
*/
|
||||
function convertToPlainObject(value)
|
||||
|
||||
{
|
||||
if (isError(value)) {
|
||||
return {
|
||||
message: value.message,
|
||||
name: value.name,
|
||||
stack: value.stack,
|
||||
...getOwnProperties(value),
|
||||
};
|
||||
} else if (isEvent(value)) {
|
||||
const newObj
|
||||
|
||||
= {
|
||||
type: value.type,
|
||||
target: serializeEventTarget(value.target),
|
||||
currentTarget: serializeEventTarget(value.currentTarget),
|
||||
...getOwnProperties(value),
|
||||
};
|
||||
|
||||
if (typeof CustomEvent !== 'undefined' && isInstanceOf(value, CustomEvent)) {
|
||||
newObj.detail = value.detail;
|
||||
}
|
||||
|
||||
return newObj;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a string representation of the target of an `Event` object */
|
||||
function serializeEventTarget(target) {
|
||||
try {
|
||||
return isElement(target) ? htmlTreeAsString(target) : Object.prototype.toString.call(target);
|
||||
} catch (_oO) {
|
||||
return '<unknown>';
|
||||
}
|
||||
}
|
||||
|
||||
/** Filters out all but an object's own properties */
|
||||
function getOwnProperties(obj) {
|
||||
if (typeof obj === 'object' && obj !== null) {
|
||||
const extractedProps = {};
|
||||
for (const property in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, property)) {
|
||||
extractedProps[property] = (obj )[property];
|
||||
}
|
||||
}
|
||||
return extractedProps;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given any captured exception, extract its keys and create a sorted
|
||||
* and truncated list that will be used inside the event message.
|
||||
* eg. `Non-error exception captured with keys: foo, bar, baz`
|
||||
*/
|
||||
function extractExceptionKeysForMessage(exception, maxLength = 40) {
|
||||
const keys = Object.keys(convertToPlainObject(exception));
|
||||
keys.sort();
|
||||
|
||||
if (!keys.length) {
|
||||
return '[object has no keys]';
|
||||
}
|
||||
|
||||
if (keys[0].length >= maxLength) {
|
||||
return truncate(keys[0], maxLength);
|
||||
}
|
||||
|
||||
for (let includedKeys = keys.length; includedKeys > 0; includedKeys--) {
|
||||
const serialized = keys.slice(0, includedKeys).join(', ');
|
||||
if (serialized.length > maxLength) {
|
||||
continue;
|
||||
}
|
||||
if (includedKeys === keys.length) {
|
||||
return serialized;
|
||||
}
|
||||
return truncate(serialized, maxLength);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Given any object, return a new object having removed all fields whose value was `undefined`.
|
||||
* Works recursively on objects and arrays.
|
||||
*
|
||||
* Attention: This function keeps circular references in the returned object.
|
||||
*/
|
||||
function dropUndefinedKeys(inputValue) {
|
||||
// This map keeps track of what already visited nodes map to.
|
||||
// Our Set - based memoBuilder doesn't work here because we want to the output object to have the same circular
|
||||
// references as the input object.
|
||||
const memoizationMap = new Map();
|
||||
|
||||
// This function just proxies `_dropUndefinedKeys` to keep the `memoBuilder` out of this function's API
|
||||
return _dropUndefinedKeys(inputValue, memoizationMap);
|
||||
}
|
||||
|
||||
function _dropUndefinedKeys(inputValue, memoizationMap) {
|
||||
if (isPlainObject(inputValue)) {
|
||||
// If this node has already been visited due to a circular reference, return the object it was mapped to in the new object
|
||||
const memoVal = memoizationMap.get(inputValue);
|
||||
if (memoVal !== undefined) {
|
||||
return memoVal ;
|
||||
}
|
||||
|
||||
const returnValue = {};
|
||||
// Store the mapping of this value in case we visit it again, in case of circular data
|
||||
memoizationMap.set(inputValue, returnValue);
|
||||
|
||||
for (const key of Object.keys(inputValue)) {
|
||||
if (typeof inputValue[key] !== 'undefined') {
|
||||
returnValue[key] = _dropUndefinedKeys(inputValue[key], memoizationMap);
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue ;
|
||||
}
|
||||
|
||||
if (Array.isArray(inputValue)) {
|
||||
// If this node has already been visited due to a circular reference, return the array it was mapped to in the new object
|
||||
const memoVal = memoizationMap.get(inputValue);
|
||||
if (memoVal !== undefined) {
|
||||
return memoVal ;
|
||||
}
|
||||
|
||||
const returnValue = [];
|
||||
// Store the mapping of this value in case we visit it again, in case of circular data
|
||||
memoizationMap.set(inputValue, returnValue);
|
||||
|
||||
inputValue.forEach((item) => {
|
||||
returnValue.push(_dropUndefinedKeys(item, memoizationMap));
|
||||
});
|
||||
|
||||
return returnValue ;
|
||||
}
|
||||
|
||||
return inputValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that something is an object.
|
||||
*
|
||||
* Turns `undefined` and `null` into `String`s and all other primitives into instances of their respective wrapper
|
||||
* classes (String, Boolean, Number, etc.). Acts as the identity function on non-primitives.
|
||||
*
|
||||
* @param wat The subject of the objectification
|
||||
* @returns A version of `wat` which can safely be used with `Object` class methods
|
||||
*/
|
||||
function objectify(wat) {
|
||||
let objectified;
|
||||
switch (true) {
|
||||
case wat === undefined || wat === null:
|
||||
objectified = new String(wat);
|
||||
break;
|
||||
|
||||
// Though symbols and bigints do have wrapper classes (`Symbol` and `BigInt`, respectively), for whatever reason
|
||||
// those classes don't have constructors which can be used with the `new` keyword. We therefore need to cast each as
|
||||
// an object in order to wrap it.
|
||||
case typeof wat === 'symbol' || typeof wat === 'bigint':
|
||||
objectified = Object(wat);
|
||||
break;
|
||||
|
||||
// this will catch the remaining primitives: `String`, `Number`, and `Boolean`
|
||||
case isPrimitive(wat):
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
objectified = new (wat ).constructor(wat);
|
||||
break;
|
||||
|
||||
// by process of elimination, at this point we know that `wat` must already be an object
|
||||
default:
|
||||
objectified = wat;
|
||||
break;
|
||||
}
|
||||
return objectified;
|
||||
}
|
||||
|
||||
export { addNonEnumerableProperty, convertToPlainObject, dropUndefinedKeys, extractExceptionKeysForMessage, fill, getOriginalFunction, markFunctionWrapped, objectify, urlEncode };
|
||||
//# sourceMappingURL=object.js.map
|
||||
102
shared/logger/node_modules/@sentry/utils/esm/promisebuffer.js
generated
vendored
Normal file
102
shared/logger/node_modules/@sentry/utils/esm/promisebuffer.js
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
import { SentryError } from './error.js';
|
||||
import { rejectedSyncPromise, SyncPromise, resolvedSyncPromise } from './syncpromise.js';
|
||||
|
||||
/**
|
||||
* Creates an new PromiseBuffer object with the specified limit
|
||||
* @param limit max number of promises that can be stored in the buffer
|
||||
*/
|
||||
function makePromiseBuffer(limit) {
|
||||
const buffer = [];
|
||||
|
||||
function isReady() {
|
||||
return limit === undefined || buffer.length < limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a promise from the queue.
|
||||
*
|
||||
* @param task Can be any PromiseLike<T>
|
||||
* @returns Removed promise.
|
||||
*/
|
||||
function remove(task) {
|
||||
return buffer.splice(buffer.indexOf(task), 1)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a promise (representing an in-flight action) to the queue, and set it to remove itself on fulfillment.
|
||||
*
|
||||
* @param taskProducer A function producing any PromiseLike<T>; In previous versions this used to be `task:
|
||||
* PromiseLike<T>`, but under that model, Promises were instantly created on the call-site and their executor
|
||||
* functions therefore ran immediately. Thus, even if the buffer was full, the action still happened. By
|
||||
* requiring the promise to be wrapped in a function, we can defer promise creation until after the buffer
|
||||
* limit check.
|
||||
* @returns The original promise.
|
||||
*/
|
||||
function add(taskProducer) {
|
||||
if (!isReady()) {
|
||||
return rejectedSyncPromise(new SentryError('Not adding Promise because buffer limit was reached.'));
|
||||
}
|
||||
|
||||
// start the task and add its promise to the queue
|
||||
const task = taskProducer();
|
||||
if (buffer.indexOf(task) === -1) {
|
||||
buffer.push(task);
|
||||
}
|
||||
void task
|
||||
.then(() => remove(task))
|
||||
// Use `then(null, rejectionHandler)` rather than `catch(rejectionHandler)` so that we can use `PromiseLike`
|
||||
// rather than `Promise`. `PromiseLike` doesn't have a `.catch` method, making its polyfill smaller. (ES5 didn't
|
||||
// have promises, so TS has to polyfill when down-compiling.)
|
||||
.then(null, () =>
|
||||
remove(task).then(null, () => {
|
||||
// We have to add another catch here because `remove()` starts a new promise chain.
|
||||
}),
|
||||
);
|
||||
return task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for all promises in the queue to resolve or for timeout to expire, whichever comes first.
|
||||
*
|
||||
* @param timeout The time, in ms, after which to resolve to `false` if the queue is still non-empty. Passing `0` (or
|
||||
* not passing anything) will make the promise wait as long as it takes for the queue to drain before resolving to
|
||||
* `true`.
|
||||
* @returns A promise which will resolve to `true` if the queue is already empty or drains before the timeout, and
|
||||
* `false` otherwise
|
||||
*/
|
||||
function drain(timeout) {
|
||||
return new SyncPromise((resolve, reject) => {
|
||||
let counter = buffer.length;
|
||||
|
||||
if (!counter) {
|
||||
return resolve(true);
|
||||
}
|
||||
|
||||
// wait for `timeout` ms and then resolve to `false` (if not cancelled first)
|
||||
const capturedSetTimeout = setTimeout(() => {
|
||||
if (timeout && timeout > 0) {
|
||||
resolve(false);
|
||||
}
|
||||
}, timeout);
|
||||
|
||||
// if all promises resolve in time, cancel the timer and resolve to `true`
|
||||
buffer.forEach(item => {
|
||||
void resolvedSyncPromise(item).then(() => {
|
||||
if (!--counter) {
|
||||
clearTimeout(capturedSetTimeout);
|
||||
resolve(true);
|
||||
}
|
||||
}, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
$: buffer,
|
||||
add,
|
||||
drain,
|
||||
};
|
||||
}
|
||||
|
||||
export { makePromiseBuffer };
|
||||
//# sourceMappingURL=promisebuffer.js.map
|
||||
97
shared/logger/node_modules/@sentry/utils/esm/ratelimit.js
generated
vendored
Normal file
97
shared/logger/node_modules/@sentry/utils/esm/ratelimit.js
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
// Intentionally keeping the key broad, as we don't know for sure what rate limit headers get returned from backend
|
||||
|
||||
const DEFAULT_RETRY_AFTER = 60 * 1000; // 60 seconds
|
||||
|
||||
/**
|
||||
* Extracts Retry-After value from the request header or returns default value
|
||||
* @param header string representation of 'Retry-After' header
|
||||
* @param now current unix timestamp
|
||||
*
|
||||
*/
|
||||
function parseRetryAfterHeader(header, now = Date.now()) {
|
||||
const headerDelay = parseInt(`${header}`, 10);
|
||||
if (!isNaN(headerDelay)) {
|
||||
return headerDelay * 1000;
|
||||
}
|
||||
|
||||
const headerDate = Date.parse(`${header}`);
|
||||
if (!isNaN(headerDate)) {
|
||||
return headerDate - now;
|
||||
}
|
||||
|
||||
return DEFAULT_RETRY_AFTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time that the given category is disabled until for rate limiting.
|
||||
* In case no category-specific limit is set but a general rate limit across all categories is active,
|
||||
* that time is returned.
|
||||
*
|
||||
* @return the time in ms that the category is disabled until or 0 if there's no active rate limit.
|
||||
*/
|
||||
function disabledUntil(limits, category) {
|
||||
return limits[category] || limits.all || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a category is rate limited
|
||||
*/
|
||||
function isRateLimited(limits, category, now = Date.now()) {
|
||||
return disabledUntil(limits, category) > now;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update ratelimits from incoming headers.
|
||||
*
|
||||
* @return the updated RateLimits object.
|
||||
*/
|
||||
function updateRateLimits(
|
||||
limits,
|
||||
{ statusCode, headers },
|
||||
now = Date.now(),
|
||||
) {
|
||||
const updatedRateLimits = {
|
||||
...limits,
|
||||
};
|
||||
|
||||
// "The name is case-insensitive."
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Headers/get
|
||||
const rateLimitHeader = headers && headers['x-sentry-rate-limits'];
|
||||
const retryAfterHeader = headers && headers['retry-after'];
|
||||
|
||||
if (rateLimitHeader) {
|
||||
/**
|
||||
* rate limit headers are of the form
|
||||
* <header>,<header>,..
|
||||
* where each <header> is of the form
|
||||
* <retry_after>: <categories>: <scope>: <reason_code>
|
||||
* where
|
||||
* <retry_after> is a delay in seconds
|
||||
* <categories> is the event type(s) (error, transaction, etc) being rate limited and is of the form
|
||||
* <category>;<category>;...
|
||||
* <scope> is what's being limited (org, project, or key) - ignored by SDK
|
||||
* <reason_code> is an arbitrary string like "org_quota" - ignored by SDK
|
||||
*/
|
||||
for (const limit of rateLimitHeader.trim().split(',')) {
|
||||
const [retryAfter, categories] = limit.split(':', 2);
|
||||
const headerDelay = parseInt(retryAfter, 10);
|
||||
const delay = (!isNaN(headerDelay) ? headerDelay : 60) * 1000; // 60sec default
|
||||
if (!categories) {
|
||||
updatedRateLimits.all = now + delay;
|
||||
} else {
|
||||
for (const category of categories.split(';')) {
|
||||
updatedRateLimits[category] = now + delay;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (retryAfterHeader) {
|
||||
updatedRateLimits.all = now + parseRetryAfterHeader(retryAfterHeader, now);
|
||||
} else if (statusCode === 429) {
|
||||
updatedRateLimits.all = now + 60 * 1000;
|
||||
}
|
||||
|
||||
return updatedRateLimits;
|
||||
}
|
||||
|
||||
export { DEFAULT_RETRY_AFTER, disabledUntil, isRateLimited, parseRetryAfterHeader, updateRateLimits };
|
||||
//# sourceMappingURL=ratelimit.js.map
|
||||
36
shared/logger/node_modules/@sentry/utils/esm/severity.js
generated
vendored
Normal file
36
shared/logger/node_modules/@sentry/utils/esm/severity.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Note: Ideally the `SeverityLevel` type would be derived from `validSeverityLevels`, but that would mean either
|
||||
//
|
||||
// a) moving `validSeverityLevels` to `@sentry/types`,
|
||||
// b) moving the`SeverityLevel` type here, or
|
||||
// c) importing `validSeverityLevels` from here into `@sentry/types`.
|
||||
//
|
||||
// Option A would make `@sentry/types` a runtime dependency of `@sentry/utils` (not good), and options B and C would
|
||||
// create a circular dependency between `@sentry/types` and `@sentry/utils` (also not good). So a TODO accompanying the
|
||||
// type, reminding anyone who changes it to change this list also, will have to do.
|
||||
|
||||
const validSeverityLevels = ['fatal', 'error', 'warning', 'log', 'info', 'debug'];
|
||||
|
||||
/**
|
||||
* Converts a string-based level into a member of the deprecated {@link Severity} enum.
|
||||
*
|
||||
* @deprecated `severityFromString` is deprecated. Please use `severityLevelFromString` instead.
|
||||
*
|
||||
* @param level String representation of Severity
|
||||
* @returns Severity
|
||||
*/
|
||||
function severityFromString(level) {
|
||||
return severityLevelFromString(level) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string-based level into a `SeverityLevel`, normalizing it along the way.
|
||||
*
|
||||
* @param level String representation of desired `SeverityLevel`.
|
||||
* @returns The `SeverityLevel` corresponding to the given string, or 'log' if the string isn't a valid level.
|
||||
*/
|
||||
function severityLevelFromString(level) {
|
||||
return (level === 'warn' ? 'warning' : validSeverityLevels.includes(level) ? level : 'log') ;
|
||||
}
|
||||
|
||||
export { severityFromString, severityLevelFromString, validSeverityLevels };
|
||||
//# sourceMappingURL=severity.js.map
|
||||
136
shared/logger/node_modules/@sentry/utils/esm/stacktrace.js
generated
vendored
Normal file
136
shared/logger/node_modules/@sentry/utils/esm/stacktrace.js
generated
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
import { node } from './node-stack-trace.js';
|
||||
|
||||
const STACKTRACE_FRAME_LIMIT = 50;
|
||||
// Used to sanitize webpack (error: *) wrapped stack errors
|
||||
const WEBPACK_ERROR_REGEXP = /\(error: (.*)\)/;
|
||||
|
||||
/**
|
||||
* Creates a stack parser with the supplied line parsers
|
||||
*
|
||||
* StackFrames are returned in the correct order for Sentry Exception
|
||||
* frames and with Sentry SDK internal frames removed from the top and bottom
|
||||
*
|
||||
*/
|
||||
function createStackParser(...parsers) {
|
||||
const sortedParsers = parsers.sort((a, b) => a[0] - b[0]).map(p => p[1]);
|
||||
|
||||
return (stack, skipFirst = 0) => {
|
||||
const frames = [];
|
||||
const lines = stack.split('\n');
|
||||
|
||||
for (let i = skipFirst; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
// Ignore lines over 1kb as they are unlikely to be stack frames.
|
||||
// Many of the regular expressions use backtracking which results in run time that increases exponentially with
|
||||
// input size. Huge strings can result in hangs/Denial of Service:
|
||||
// https://github.com/getsentry/sentry-javascript/issues/2286
|
||||
if (line.length > 1024) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// https://github.com/getsentry/sentry-javascript/issues/5459
|
||||
// Remove webpack (error: *) wrappers
|
||||
const cleanedLine = WEBPACK_ERROR_REGEXP.test(line) ? line.replace(WEBPACK_ERROR_REGEXP, '$1') : line;
|
||||
|
||||
// https://github.com/getsentry/sentry-javascript/issues/7813
|
||||
// Skip Error: lines
|
||||
if (cleanedLine.match(/\S*Error: /)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const parser of sortedParsers) {
|
||||
const frame = parser(cleanedLine);
|
||||
|
||||
if (frame) {
|
||||
frames.push(frame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (frames.length >= STACKTRACE_FRAME_LIMIT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return stripSentryFramesAndReverse(frames);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a stack parser implementation from Options.stackParser
|
||||
* @see Options
|
||||
*
|
||||
* If options contains an array of line parsers, it is converted into a parser
|
||||
*/
|
||||
function stackParserFromStackParserOptions(stackParser) {
|
||||
if (Array.isArray(stackParser)) {
|
||||
return createStackParser(...stackParser);
|
||||
}
|
||||
return stackParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes Sentry frames from the top and bottom of the stack if present and enforces a limit of max number of frames.
|
||||
* Assumes stack input is ordered from top to bottom and returns the reverse representation so call site of the
|
||||
* function that caused the crash is the last frame in the array.
|
||||
* @hidden
|
||||
*/
|
||||
function stripSentryFramesAndReverse(stack) {
|
||||
if (!stack.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const localStack = stack.slice(0, STACKTRACE_FRAME_LIMIT);
|
||||
|
||||
const lastFrameFunction = localStack[localStack.length - 1].function;
|
||||
// If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call)
|
||||
if (lastFrameFunction && /sentryWrapped/.test(lastFrameFunction)) {
|
||||
localStack.pop();
|
||||
}
|
||||
|
||||
// Reversing in the middle of the procedure allows us to just pop the values off the stack
|
||||
localStack.reverse();
|
||||
|
||||
const firstFrameFunction = localStack[localStack.length - 1].function;
|
||||
// If stack ends with one of our internal API calls, remove it (ends, meaning it's the bottom of the stack - aka top-most call)
|
||||
if (firstFrameFunction && /captureMessage|captureException/.test(firstFrameFunction)) {
|
||||
localStack.pop();
|
||||
}
|
||||
|
||||
return localStack.map(frame => ({
|
||||
...frame,
|
||||
filename: frame.filename || localStack[localStack.length - 1].filename,
|
||||
function: frame.function || '?',
|
||||
}));
|
||||
}
|
||||
|
||||
const defaultFunctionName = '<anonymous>';
|
||||
|
||||
/**
|
||||
* Safely extract function name from itself
|
||||
*/
|
||||
function getFunctionName(fn) {
|
||||
try {
|
||||
if (!fn || typeof fn !== 'function') {
|
||||
return defaultFunctionName;
|
||||
}
|
||||
return fn.name || defaultFunctionName;
|
||||
} catch (e) {
|
||||
// Just accessing custom props in some Selenium environments
|
||||
// can cause a "Permission denied" exception (see raven-js#495).
|
||||
return defaultFunctionName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Node.js stack line parser
|
||||
*
|
||||
* This is in @sentry/utils so it can be used from the Electron SDK in the browser for when `nodeIntegration == true`.
|
||||
* This allows it to be used without referencing or importing any node specific code which causes bundlers to complain
|
||||
*/
|
||||
function nodeStackLineParser(getModule) {
|
||||
return [90, node(getModule)];
|
||||
}
|
||||
|
||||
export { createStackParser, getFunctionName, nodeStackLineParser, stackParserFromStackParserOptions, stripSentryFramesAndReverse };
|
||||
//# sourceMappingURL=stacktrace.js.map
|
||||
132
shared/logger/node_modules/@sentry/utils/esm/string.js
generated
vendored
Normal file
132
shared/logger/node_modules/@sentry/utils/esm/string.js
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
import { isString, isRegExp } from './is.js';
|
||||
|
||||
/**
|
||||
* Truncates given string to the maximum characters count
|
||||
*
|
||||
* @param str An object that contains serializable values
|
||||
* @param max Maximum number of characters in truncated string (0 = unlimited)
|
||||
* @returns string Encoded
|
||||
*/
|
||||
function truncate(str, max = 0) {
|
||||
if (typeof str !== 'string' || max === 0) {
|
||||
return str;
|
||||
}
|
||||
return str.length <= max ? str : `${str.slice(0, max)}...`;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is basically just `trim_line` from
|
||||
* https://github.com/getsentry/sentry/blob/master/src/sentry/lang/javascript/processor.py#L67
|
||||
*
|
||||
* @param str An object that contains serializable values
|
||||
* @param max Maximum number of characters in truncated string
|
||||
* @returns string Encoded
|
||||
*/
|
||||
function snipLine(line, colno) {
|
||||
let newLine = line;
|
||||
const lineLength = newLine.length;
|
||||
if (lineLength <= 150) {
|
||||
return newLine;
|
||||
}
|
||||
if (colno > lineLength) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
colno = lineLength;
|
||||
}
|
||||
|
||||
let start = Math.max(colno - 60, 0);
|
||||
if (start < 5) {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
let end = Math.min(start + 140, lineLength);
|
||||
if (end > lineLength - 5) {
|
||||
end = lineLength;
|
||||
}
|
||||
if (end === lineLength) {
|
||||
start = Math.max(end - 140, 0);
|
||||
}
|
||||
|
||||
newLine = newLine.slice(start, end);
|
||||
if (start > 0) {
|
||||
newLine = `'{snip} ${newLine}`;
|
||||
}
|
||||
if (end < lineLength) {
|
||||
newLine += ' {snip}';
|
||||
}
|
||||
|
||||
return newLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join values in array
|
||||
* @param input array of values to be joined together
|
||||
* @param delimiter string to be placed in-between values
|
||||
* @returns Joined values
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function safeJoin(input, delimiter) {
|
||||
if (!Array.isArray(input)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const output = [];
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
const value = input[i];
|
||||
try {
|
||||
output.push(String(value));
|
||||
} catch (e) {
|
||||
output.push('[value cannot be serialized]');
|
||||
}
|
||||
}
|
||||
|
||||
return output.join(delimiter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given value matches a regex or string
|
||||
*
|
||||
* @param value The string to test
|
||||
* @param pattern Either a regex or a string against which `value` will be matched
|
||||
* @param requireExactStringMatch If true, `value` must match `pattern` exactly. If false, `value` will match
|
||||
* `pattern` if it contains `pattern`. Only applies to string-type patterns.
|
||||
*/
|
||||
function isMatchingPattern(
|
||||
value,
|
||||
pattern,
|
||||
requireExactStringMatch = false,
|
||||
) {
|
||||
if (!isString(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isRegExp(pattern)) {
|
||||
return pattern.test(value);
|
||||
}
|
||||
if (isString(pattern)) {
|
||||
return requireExactStringMatch ? value === pattern : value.includes(pattern);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the given string against an array of strings and regexes. By default, string matching is done on a
|
||||
* substring-inclusion basis rather than a strict equality basis
|
||||
*
|
||||
* @param testString The string to test
|
||||
* @param patterns The patterns against which to test the string
|
||||
* @param requireExactStringMatch If true, `testString` must match one of the given string patterns exactly in order to
|
||||
* count. If false, `testString` will match a string pattern if it contains that pattern.
|
||||
* @returns
|
||||
*/
|
||||
function stringMatchesSomePattern(
|
||||
testString,
|
||||
patterns = [],
|
||||
requireExactStringMatch = false,
|
||||
) {
|
||||
return patterns.some(pattern => isMatchingPattern(testString, pattern, requireExactStringMatch));
|
||||
}
|
||||
|
||||
export { isMatchingPattern, safeJoin, snipLine, stringMatchesSomePattern, truncate };
|
||||
//# sourceMappingURL=string.js.map
|
||||
161
shared/logger/node_modules/@sentry/utils/esm/supports.js
generated
vendored
Normal file
161
shared/logger/node_modules/@sentry/utils/esm/supports.js
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
import { logger } from './logger.js';
|
||||
import { getGlobalObject } from './worldwide.js';
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const WINDOW = getGlobalObject();
|
||||
|
||||
/**
|
||||
* Tells whether current environment supports ErrorEvent objects
|
||||
* {@link supportsErrorEvent}.
|
||||
*
|
||||
* @returns Answer to the given question.
|
||||
*/
|
||||
function supportsErrorEvent() {
|
||||
try {
|
||||
new ErrorEvent('');
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether current environment supports DOMError objects
|
||||
* {@link supportsDOMError}.
|
||||
*
|
||||
* @returns Answer to the given question.
|
||||
*/
|
||||
function supportsDOMError() {
|
||||
try {
|
||||
// Chrome: VM89:1 Uncaught TypeError: Failed to construct 'DOMError':
|
||||
// 1 argument required, but only 0 present.
|
||||
// @ts-ignore It really needs 1 argument, not 0.
|
||||
new DOMError('');
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether current environment supports DOMException objects
|
||||
* {@link supportsDOMException}.
|
||||
*
|
||||
* @returns Answer to the given question.
|
||||
*/
|
||||
function supportsDOMException() {
|
||||
try {
|
||||
new DOMException('');
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether current environment supports Fetch API
|
||||
* {@link supportsFetch}.
|
||||
*
|
||||
* @returns Answer to the given question.
|
||||
*/
|
||||
function supportsFetch() {
|
||||
if (!('fetch' in WINDOW)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
new Headers();
|
||||
new Request('http://www.example.com');
|
||||
new Response();
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* isNativeFetch checks if the given function is a native implementation of fetch()
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
function isNativeFetch(func) {
|
||||
return func && /^function fetch\(\)\s+\{\s+\[native code\]\s+\}$/.test(func.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether current environment supports Fetch API natively
|
||||
* {@link supportsNativeFetch}.
|
||||
*
|
||||
* @returns true if `window.fetch` is natively implemented, false otherwise
|
||||
*/
|
||||
function supportsNativeFetch() {
|
||||
if (!supportsFetch()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fast path to avoid DOM I/O
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
if (isNativeFetch(WINDOW.fetch)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// window.fetch is implemented, but is polyfilled or already wrapped (e.g: by a chrome extension)
|
||||
// so create a "pure" iframe to see if that has native fetch
|
||||
let result = false;
|
||||
const doc = WINDOW.document;
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (doc && typeof (doc.createElement ) === 'function') {
|
||||
try {
|
||||
const sandbox = doc.createElement('iframe');
|
||||
sandbox.hidden = true;
|
||||
doc.head.appendChild(sandbox);
|
||||
if (sandbox.contentWindow && sandbox.contentWindow.fetch) {
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
result = isNativeFetch(sandbox.contentWindow.fetch);
|
||||
}
|
||||
doc.head.removeChild(sandbox);
|
||||
} catch (err) {
|
||||
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
|
||||
logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether current environment supports ReportingObserver API
|
||||
* {@link supportsReportingObserver}.
|
||||
*
|
||||
* @returns Answer to the given question.
|
||||
*/
|
||||
function supportsReportingObserver() {
|
||||
return 'ReportingObserver' in WINDOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether current environment supports Referrer Policy API
|
||||
* {@link supportsReferrerPolicy}.
|
||||
*
|
||||
* @returns Answer to the given question.
|
||||
*/
|
||||
function supportsReferrerPolicy() {
|
||||
// Despite all stars in the sky saying that Edge supports old draft syntax, aka 'never', 'always', 'origin' and 'default'
|
||||
// (see https://caniuse.com/#feat=referrer-policy),
|
||||
// it doesn't. And it throws an exception instead of ignoring this parameter...
|
||||
// REF: https://github.com/getsentry/raven-js/issues/1233
|
||||
|
||||
if (!supportsFetch()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
new Request('_', {
|
||||
referrerPolicy: 'origin' ,
|
||||
});
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export { isNativeFetch, supportsDOMError, supportsDOMException, supportsErrorEvent, supportsFetch, supportsNativeFetch, supportsReferrerPolicy, supportsReportingObserver };
|
||||
//# sourceMappingURL=supports.js.map
|
||||
191
shared/logger/node_modules/@sentry/utils/esm/syncpromise.js
generated
vendored
Normal file
191
shared/logger/node_modules/@sentry/utils/esm/syncpromise.js
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
import { isThenable } from './is.js';
|
||||
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
|
||||
/** SyncPromise internal states */
|
||||
var States; (function (States) {
|
||||
/** Pending */
|
||||
const PENDING = 0; States[States["PENDING"] = PENDING] = "PENDING";
|
||||
/** Resolved / OK */
|
||||
const RESOLVED = 1; States[States["RESOLVED"] = RESOLVED] = "RESOLVED";
|
||||
/** Rejected / Error */
|
||||
const REJECTED = 2; States[States["REJECTED"] = REJECTED] = "REJECTED";
|
||||
})(States || (States = {}));
|
||||
|
||||
// Overloads so we can call resolvedSyncPromise without arguments and generic argument
|
||||
|
||||
/**
|
||||
* Creates a resolved sync promise.
|
||||
*
|
||||
* @param value the value to resolve the promise with
|
||||
* @returns the resolved sync promise
|
||||
*/
|
||||
function resolvedSyncPromise(value) {
|
||||
return new SyncPromise(resolve => {
|
||||
resolve(value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a rejected sync promise.
|
||||
*
|
||||
* @param value the value to reject the promise with
|
||||
* @returns the rejected sync promise
|
||||
*/
|
||||
function rejectedSyncPromise(reason) {
|
||||
return new SyncPromise((_, reject) => {
|
||||
reject(reason);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Thenable class that behaves like a Promise and follows it's interface
|
||||
* but is not async internally
|
||||
*/
|
||||
class SyncPromise {
|
||||
__init() {this._state = States.PENDING;}
|
||||
__init2() {this._handlers = [];}
|
||||
|
||||
constructor(
|
||||
executor,
|
||||
) {SyncPromise.prototype.__init.call(this);SyncPromise.prototype.__init2.call(this);SyncPromise.prototype.__init3.call(this);SyncPromise.prototype.__init4.call(this);SyncPromise.prototype.__init5.call(this);SyncPromise.prototype.__init6.call(this);
|
||||
try {
|
||||
executor(this._resolve, this._reject);
|
||||
} catch (e) {
|
||||
this._reject(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
then(
|
||||
onfulfilled,
|
||||
onrejected,
|
||||
) {
|
||||
return new SyncPromise((resolve, reject) => {
|
||||
this._handlers.push([
|
||||
false,
|
||||
result => {
|
||||
if (!onfulfilled) {
|
||||
// TODO: ¯\_(ツ)_/¯
|
||||
// TODO: FIXME
|
||||
resolve(result );
|
||||
} else {
|
||||
try {
|
||||
resolve(onfulfilled(result));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
reason => {
|
||||
if (!onrejected) {
|
||||
reject(reason);
|
||||
} else {
|
||||
try {
|
||||
resolve(onrejected(reason));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
]);
|
||||
this._executeHandlers();
|
||||
});
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
catch(
|
||||
onrejected,
|
||||
) {
|
||||
return this.then(val => val, onrejected);
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
finally(onfinally) {
|
||||
return new SyncPromise((resolve, reject) => {
|
||||
let val;
|
||||
let isRejected;
|
||||
|
||||
return this.then(
|
||||
value => {
|
||||
isRejected = false;
|
||||
val = value;
|
||||
if (onfinally) {
|
||||
onfinally();
|
||||
}
|
||||
},
|
||||
reason => {
|
||||
isRejected = true;
|
||||
val = reason;
|
||||
if (onfinally) {
|
||||
onfinally();
|
||||
}
|
||||
},
|
||||
).then(() => {
|
||||
if (isRejected) {
|
||||
reject(val);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(val );
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
__init3() {this._resolve = (value) => {
|
||||
this._setResult(States.RESOLVED, value);
|
||||
};}
|
||||
|
||||
/** JSDoc */
|
||||
__init4() {this._reject = (reason) => {
|
||||
this._setResult(States.REJECTED, reason);
|
||||
};}
|
||||
|
||||
/** JSDoc */
|
||||
__init5() {this._setResult = (state, value) => {
|
||||
if (this._state !== States.PENDING) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isThenable(value)) {
|
||||
void (value ).then(this._resolve, this._reject);
|
||||
return;
|
||||
}
|
||||
|
||||
this._state = state;
|
||||
this._value = value;
|
||||
|
||||
this._executeHandlers();
|
||||
};}
|
||||
|
||||
/** JSDoc */
|
||||
__init6() {this._executeHandlers = () => {
|
||||
if (this._state === States.PENDING) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cachedHandlers = this._handlers.slice();
|
||||
this._handlers = [];
|
||||
|
||||
cachedHandlers.forEach(handler => {
|
||||
if (handler[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._state === States.RESOLVED) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
handler[1](this._value );
|
||||
}
|
||||
|
||||
if (this._state === States.REJECTED) {
|
||||
handler[2](this._value);
|
||||
}
|
||||
|
||||
handler[0] = true;
|
||||
});
|
||||
};}
|
||||
}
|
||||
|
||||
export { SyncPromise, rejectedSyncPromise, resolvedSyncPromise };
|
||||
//# sourceMappingURL=syncpromise.js.map
|
||||
183
shared/logger/node_modules/@sentry/utils/esm/time.js
generated
vendored
Normal file
183
shared/logger/node_modules/@sentry/utils/esm/time.js
generated
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
import { isNodeEnv, dynamicRequire } from './node.js';
|
||||
import { getGlobalObject } from './worldwide.js';
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const WINDOW = getGlobalObject();
|
||||
|
||||
/**
|
||||
* An object that can return the current timestamp in seconds since the UNIX epoch.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A TimestampSource implementation for environments that do not support the Performance Web API natively.
|
||||
*
|
||||
* Note that this TimestampSource does not use a monotonic clock. A call to `nowSeconds` may return a timestamp earlier
|
||||
* than a previously returned value. We do not try to emulate a monotonic behavior in order to facilitate debugging. It
|
||||
* is more obvious to explain "why does my span have negative duration" than "why my spans have zero duration".
|
||||
*/
|
||||
const dateTimestampSource = {
|
||||
nowSeconds: () => Date.now() / 1000,
|
||||
};
|
||||
|
||||
/**
|
||||
* A partial definition of the [Performance Web API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Performance}
|
||||
* for accessing a high-resolution monotonic clock.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a wrapper around the native Performance API browser implementation, or undefined for browsers that do not
|
||||
* support the API.
|
||||
*
|
||||
* Wrapping the native API works around differences in behavior from different browsers.
|
||||
*/
|
||||
function getBrowserPerformance() {
|
||||
const { performance } = WINDOW;
|
||||
if (!performance || !performance.now) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Replace performance.timeOrigin with our own timeOrigin based on Date.now().
|
||||
//
|
||||
// This is a partial workaround for browsers reporting performance.timeOrigin such that performance.timeOrigin +
|
||||
// performance.now() gives a date arbitrarily in the past.
|
||||
//
|
||||
// Additionally, computing timeOrigin in this way fills the gap for browsers where performance.timeOrigin is
|
||||
// undefined.
|
||||
//
|
||||
// The assumption that performance.timeOrigin + performance.now() ~= Date.now() is flawed, but we depend on it to
|
||||
// interact with data coming out of performance entries.
|
||||
//
|
||||
// Note that despite recommendations against it in the spec, browsers implement the Performance API with a clock that
|
||||
// might stop when the computer is asleep (and perhaps under other circumstances). Such behavior causes
|
||||
// performance.timeOrigin + performance.now() to have an arbitrary skew over Date.now(). In laptop computers, we have
|
||||
// observed skews that can be as long as days, weeks or months.
|
||||
//
|
||||
// See https://github.com/getsentry/sentry-javascript/issues/2590.
|
||||
//
|
||||
// BUG: despite our best intentions, this workaround has its limitations. It mostly addresses timings of pageload
|
||||
// transactions, but ignores the skew built up over time that can aversely affect timestamps of navigation
|
||||
// transactions of long-lived web pages.
|
||||
const timeOrigin = Date.now() - performance.now();
|
||||
|
||||
return {
|
||||
now: () => performance.now(),
|
||||
timeOrigin,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the native Performance API implementation from Node.js. Returns undefined in old Node.js versions that don't
|
||||
* implement the API.
|
||||
*/
|
||||
function getNodePerformance() {
|
||||
try {
|
||||
const perfHooks = dynamicRequire(module, 'perf_hooks') ;
|
||||
return perfHooks.performance;
|
||||
} catch (_) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Performance API implementation for the current platform, if available.
|
||||
*/
|
||||
const platformPerformance = isNodeEnv() ? getNodePerformance() : getBrowserPerformance();
|
||||
|
||||
const timestampSource =
|
||||
platformPerformance === undefined
|
||||
? dateTimestampSource
|
||||
: {
|
||||
nowSeconds: () => (platformPerformance.timeOrigin + platformPerformance.now()) / 1000,
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a timestamp in seconds since the UNIX epoch using the Date API.
|
||||
*/
|
||||
const dateTimestampInSeconds = dateTimestampSource.nowSeconds.bind(dateTimestampSource);
|
||||
|
||||
/**
|
||||
* Returns a timestamp in seconds since the UNIX epoch using either the Performance or Date APIs, depending on the
|
||||
* availability of the Performance API.
|
||||
*
|
||||
* See `usingPerformanceAPI` to test whether the Performance API is used.
|
||||
*
|
||||
* BUG: Note that because of how browsers implement the Performance API, the clock might stop when the computer is
|
||||
* asleep. This creates a skew between `dateTimestampInSeconds` and `timestampInSeconds`. The
|
||||
* skew can grow to arbitrary amounts like days, weeks or months.
|
||||
* See https://github.com/getsentry/sentry-javascript/issues/2590.
|
||||
*/
|
||||
const timestampInSeconds = timestampSource.nowSeconds.bind(timestampSource);
|
||||
|
||||
/**
|
||||
* Re-exported with an old name for backwards-compatibility.
|
||||
* TODO (v8): Remove this
|
||||
*
|
||||
* @deprecated Use `timestampInSeconds` instead.
|
||||
*/
|
||||
const timestampWithMs = timestampInSeconds;
|
||||
|
||||
/**
|
||||
* A boolean that is true when timestampInSeconds uses the Performance API to produce monotonic timestamps.
|
||||
*/
|
||||
const usingPerformanceAPI = platformPerformance !== undefined;
|
||||
|
||||
/**
|
||||
* Internal helper to store what is the source of browserPerformanceTimeOrigin below. For debugging only.
|
||||
*/
|
||||
let _browserPerformanceTimeOriginMode;
|
||||
|
||||
/**
|
||||
* The number of milliseconds since the UNIX epoch. This value is only usable in a browser, and only when the
|
||||
* performance API is available.
|
||||
*/
|
||||
const browserPerformanceTimeOrigin = (() => {
|
||||
// Unfortunately browsers may report an inaccurate time origin data, through either performance.timeOrigin or
|
||||
// performance.timing.navigationStart, which results in poor results in performance data. We only treat time origin
|
||||
// data as reliable if they are within a reasonable threshold of the current time.
|
||||
|
||||
const { performance } = WINDOW;
|
||||
if (!performance || !performance.now) {
|
||||
_browserPerformanceTimeOriginMode = 'none';
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const threshold = 3600 * 1000;
|
||||
const performanceNow = performance.now();
|
||||
const dateNow = Date.now();
|
||||
|
||||
// if timeOrigin isn't available set delta to threshold so it isn't used
|
||||
const timeOriginDelta = performance.timeOrigin
|
||||
? Math.abs(performance.timeOrigin + performanceNow - dateNow)
|
||||
: threshold;
|
||||
const timeOriginIsReliable = timeOriginDelta < threshold;
|
||||
|
||||
// While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin
|
||||
// is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.
|
||||
// Also as of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always
|
||||
// a valid fallback. In the absence of an initial time provided by the browser, fallback to the current time from the
|
||||
// Date API.
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const navigationStart = performance.timing && performance.timing.navigationStart;
|
||||
const hasNavigationStart = typeof navigationStart === 'number';
|
||||
// if navigationStart isn't available set delta to threshold so it isn't used
|
||||
const navigationStartDelta = hasNavigationStart ? Math.abs(navigationStart + performanceNow - dateNow) : threshold;
|
||||
const navigationStartIsReliable = navigationStartDelta < threshold;
|
||||
|
||||
if (timeOriginIsReliable || navigationStartIsReliable) {
|
||||
// Use the more reliable time origin
|
||||
if (timeOriginDelta <= navigationStartDelta) {
|
||||
_browserPerformanceTimeOriginMode = 'timeOrigin';
|
||||
return performance.timeOrigin;
|
||||
} else {
|
||||
_browserPerformanceTimeOriginMode = 'navigationStart';
|
||||
return navigationStart;
|
||||
}
|
||||
}
|
||||
|
||||
// Either both timeOrigin and navigationStart are skewed or neither is available, fallback to Date.
|
||||
_browserPerformanceTimeOriginMode = 'dateNow';
|
||||
return dateNow;
|
||||
})();
|
||||
|
||||
export { _browserPerformanceTimeOriginMode, browserPerformanceTimeOrigin, dateTimestampInSeconds, timestampInSeconds, timestampWithMs, usingPerformanceAPI };
|
||||
//# sourceMappingURL=time.js.map
|
||||
39
shared/logger/node_modules/@sentry/utils/esm/tracing.js
generated
vendored
Normal file
39
shared/logger/node_modules/@sentry/utils/esm/tracing.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
const TRACEPARENT_REGEXP = new RegExp(
|
||||
'^[ \\t]*' + // whitespace
|
||||
'([0-9a-f]{32})?' + // trace_id
|
||||
'-?([0-9a-f]{16})?' + // span_id
|
||||
'-?([01])?' + // sampled
|
||||
'[ \\t]*$', // whitespace
|
||||
);
|
||||
|
||||
/**
|
||||
* Extract transaction context data from a `sentry-trace` header.
|
||||
*
|
||||
* @param traceparent Traceparent string
|
||||
*
|
||||
* @returns Object containing data from the header, or undefined if traceparent string is malformed
|
||||
*/
|
||||
function extractTraceparentData(traceparent) {
|
||||
const matches = traceparent.match(TRACEPARENT_REGEXP);
|
||||
|
||||
if (!traceparent || !matches) {
|
||||
// empty string or no matches is invalid traceparent data
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let parentSampled;
|
||||
if (matches[3] === '1') {
|
||||
parentSampled = true;
|
||||
} else if (matches[3] === '0') {
|
||||
parentSampled = false;
|
||||
}
|
||||
|
||||
return {
|
||||
traceId: matches[1],
|
||||
parentSampled,
|
||||
parentSpanId: matches[2],
|
||||
};
|
||||
}
|
||||
|
||||
export { TRACEPARENT_REGEXP, extractTraceparentData };
|
||||
//# sourceMappingURL=tracing.js.map
|
||||
72
shared/logger/node_modules/@sentry/utils/esm/url.js
generated
vendored
Normal file
72
shared/logger/node_modules/@sentry/utils/esm/url.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Parses string form of URL into an object
|
||||
* // borrowed from https://tools.ietf.org/html/rfc3986#appendix-B
|
||||
* // intentionally using regex and not <a/> href parsing trick because React Native and other
|
||||
* // environments where DOM might not be available
|
||||
* @returns parsed URL object
|
||||
*/
|
||||
function parseUrl(url) {
|
||||
if (!url) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const match = url.match(/^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/);
|
||||
|
||||
if (!match) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// coerce to undefined values to empty string so we don't get 'undefined'
|
||||
const query = match[6] || '';
|
||||
const fragment = match[8] || '';
|
||||
return {
|
||||
host: match[4],
|
||||
path: match[5],
|
||||
protocol: match[2],
|
||||
search: query,
|
||||
hash: fragment,
|
||||
relative: match[5] + query + fragment, // everything minus origin
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip the query string and fragment off of a given URL or path (if present)
|
||||
*
|
||||
* @param urlPath Full URL or path, including possible query string and/or fragment
|
||||
* @returns URL or path without query string or fragment
|
||||
*/
|
||||
function stripUrlQueryAndFragment(urlPath) {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
return urlPath.split(/[\?#]/, 1)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns number of URL segments of a passed string URL.
|
||||
*/
|
||||
function getNumberOfUrlSegments(url) {
|
||||
// split at '/' or at '\/' to split regex urls correctly
|
||||
return url.split(/\\?\//).filter(s => s.length > 0 && s !== ',').length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a URL object and returns a sanitized string which is safe to use as span description
|
||||
* see: https://develop.sentry.dev/sdk/data-handling/#structuring-data
|
||||
*/
|
||||
function getSanitizedUrlString(url) {
|
||||
const { protocol, host, path } = url;
|
||||
|
||||
const filteredHost =
|
||||
(host &&
|
||||
host
|
||||
// Always filter out authority
|
||||
.replace(/^.*@/, '[filtered]:[filtered]@')
|
||||
// Don't show standard :80 (http) and :443 (https) ports to reduce the noise
|
||||
.replace(':80', '')
|
||||
.replace(':443', '')) ||
|
||||
'';
|
||||
|
||||
return `${protocol ? `${protocol}://` : ''}${filteredHost}${path}`;
|
||||
}
|
||||
|
||||
export { getNumberOfUrlSegments, getSanitizedUrlString, parseUrl, stripUrlQueryAndFragment };
|
||||
//# sourceMappingURL=url.js.map
|
||||
29
shared/logger/node_modules/@sentry/utils/esm/vendor/supportsHistory.js
generated
vendored
Normal file
29
shared/logger/node_modules/@sentry/utils/esm/vendor/supportsHistory.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
import { getGlobalObject } from '../worldwide.js';
|
||||
|
||||
// Based on https://github.com/angular/angular.js/pull/13945/files
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const WINDOW = getGlobalObject();
|
||||
|
||||
/**
|
||||
* Tells whether current environment supports History API
|
||||
* {@link supportsHistory}.
|
||||
*
|
||||
* @returns Answer to the given question.
|
||||
*/
|
||||
function supportsHistory() {
|
||||
// NOTE: in Chrome App environment, touching history.pushState, *even inside
|
||||
// a try/catch block*, will cause Chrome to output an error to console.error
|
||||
// borrowed from: https://github.com/angular/angular.js/pull/13945/files
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const chrome = (WINDOW ).chrome;
|
||||
const isChromePackagedApp = chrome && chrome.app && chrome.app.runtime;
|
||||
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
||||
const hasHistoryApi = 'history' in WINDOW && !!WINDOW.history.pushState && !!WINDOW.history.replaceState;
|
||||
|
||||
return !isChromePackagedApp && hasHistoryApi;
|
||||
}
|
||||
|
||||
export { supportsHistory };
|
||||
//# sourceMappingURL=supportsHistory.js.map
|
||||
70
shared/logger/node_modules/@sentry/utils/esm/worldwide.js
generated
vendored
Normal file
70
shared/logger/node_modules/@sentry/utils/esm/worldwide.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/** Internal global with common properties and Sentry extensions */
|
||||
|
||||
// The code below for 'isGlobalObj' and 'GLOBAL_OBJ' was copied from core-js before modification
|
||||
// https://github.com/zloirock/core-js/blob/1b944df55282cdc99c90db5f49eb0b6eda2cc0a3/packages/core-js/internals/global.js
|
||||
// core-js has the following licence:
|
||||
//
|
||||
// Copyright (c) 2014-2022 Denis Pushkarev
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
/** Returns 'obj' if it's the global object, otherwise returns undefined */
|
||||
function isGlobalObj(obj) {
|
||||
return obj && obj.Math == Math ? obj : undefined;
|
||||
}
|
||||
|
||||
/** Get's the global object for the current JavaScript runtime */
|
||||
const GLOBAL_OBJ =
|
||||
(typeof globalThis == 'object' && isGlobalObj(globalThis)) ||
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
(typeof window == 'object' && isGlobalObj(window)) ||
|
||||
(typeof self == 'object' && isGlobalObj(self)) ||
|
||||
(typeof global == 'object' && isGlobalObj(global)) ||
|
||||
(function () {
|
||||
return this;
|
||||
})() ||
|
||||
{};
|
||||
|
||||
/**
|
||||
* @deprecated Use GLOBAL_OBJ instead or WINDOW from @sentry/browser. This will be removed in v8
|
||||
*/
|
||||
function getGlobalObject() {
|
||||
return GLOBAL_OBJ ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a global singleton contained in the global `__SENTRY__` object.
|
||||
*
|
||||
* If the singleton doesn't already exist in `__SENTRY__`, it will be created using the given factory
|
||||
* function and added to the `__SENTRY__` object.
|
||||
*
|
||||
* @param name name of the global singleton on __SENTRY__
|
||||
* @param creator creator Factory function to create the singleton if it doesn't already exist on `__SENTRY__`
|
||||
* @param obj (Optional) The global object on which to look for `__SENTRY__`, if not `GLOBAL_OBJ`'s return value
|
||||
* @returns the singleton
|
||||
*/
|
||||
function getGlobalSingleton(name, creator, obj) {
|
||||
const gbl = (obj || GLOBAL_OBJ) ;
|
||||
const __SENTRY__ = (gbl.__SENTRY__ = gbl.__SENTRY__ || {});
|
||||
const singleton = __SENTRY__[name] || (__SENTRY__[name] = creator());
|
||||
return singleton;
|
||||
}
|
||||
|
||||
export { GLOBAL_OBJ, getGlobalObject, getGlobalSingleton };
|
||||
//# sourceMappingURL=worldwide.js.map
|
||||
Reference in New Issue
Block a user