forked from off-topic/apps.apple.com
init commit
This commit is contained in:
281
shared/logger/node_modules/@sentry/browser/esm/integrations/trycatch.js
generated
vendored
Normal file
281
shared/logger/node_modules/@sentry/browser/esm/integrations/trycatch.js
generated
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
import { fill, getFunctionName, getOriginalFunction } from '@sentry/utils';
|
||||
import { WINDOW, wrap } from '../helpers.js';
|
||||
|
||||
const DEFAULT_EVENT_TARGET = [
|
||||
'EventTarget',
|
||||
'Window',
|
||||
'Node',
|
||||
'ApplicationCache',
|
||||
'AudioTrackList',
|
||||
'ChannelMergerNode',
|
||||
'CryptoOperation',
|
||||
'EventSource',
|
||||
'FileReader',
|
||||
'HTMLUnknownElement',
|
||||
'IDBDatabase',
|
||||
'IDBRequest',
|
||||
'IDBTransaction',
|
||||
'KeyOperation',
|
||||
'MediaController',
|
||||
'MessagePort',
|
||||
'ModalWindow',
|
||||
'Notification',
|
||||
'SVGElementInstance',
|
||||
'Screen',
|
||||
'TextTrack',
|
||||
'TextTrackCue',
|
||||
'TextTrackList',
|
||||
'WebSocket',
|
||||
'WebSocketWorker',
|
||||
'Worker',
|
||||
'XMLHttpRequest',
|
||||
'XMLHttpRequestEventTarget',
|
||||
'XMLHttpRequestUpload',
|
||||
];
|
||||
|
||||
/** Wrap timer functions and event targets to catch errors and provide better meta data */
|
||||
class TryCatch {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
static __initStatic() {this.id = 'TryCatch';}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
__init() {this.name = TryCatch.id;}
|
||||
|
||||
/** JSDoc */
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
constructor(options) {TryCatch.prototype.__init.call(this);
|
||||
this._options = {
|
||||
XMLHttpRequest: true,
|
||||
eventTarget: true,
|
||||
requestAnimationFrame: true,
|
||||
setInterval: true,
|
||||
setTimeout: true,
|
||||
...options,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap timer functions and event targets to catch errors
|
||||
* and provide better metadata.
|
||||
*/
|
||||
setupOnce() {
|
||||
if (this._options.setTimeout) {
|
||||
fill(WINDOW, 'setTimeout', _wrapTimeFunction);
|
||||
}
|
||||
|
||||
if (this._options.setInterval) {
|
||||
fill(WINDOW, 'setInterval', _wrapTimeFunction);
|
||||
}
|
||||
|
||||
if (this._options.requestAnimationFrame) {
|
||||
fill(WINDOW, 'requestAnimationFrame', _wrapRAF);
|
||||
}
|
||||
|
||||
if (this._options.XMLHttpRequest && 'XMLHttpRequest' in WINDOW) {
|
||||
fill(XMLHttpRequest.prototype, 'send', _wrapXHR);
|
||||
}
|
||||
|
||||
const eventTargetOption = this._options.eventTarget;
|
||||
if (eventTargetOption) {
|
||||
const eventTarget = Array.isArray(eventTargetOption) ? eventTargetOption : DEFAULT_EVENT_TARGET;
|
||||
eventTarget.forEach(_wrapEventTarget);
|
||||
}
|
||||
}
|
||||
} TryCatch.__initStatic();
|
||||
|
||||
/** JSDoc */
|
||||
function _wrapTimeFunction(original) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return function ( ...args) {
|
||||
const originalCallback = args[0];
|
||||
args[0] = wrap(originalCallback, {
|
||||
mechanism: {
|
||||
data: { function: getFunctionName(original) },
|
||||
handled: true,
|
||||
type: 'instrument',
|
||||
},
|
||||
});
|
||||
return original.apply(this, args);
|
||||
};
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function _wrapRAF(original) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return function ( callback) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
return original.apply(this, [
|
||||
wrap(callback, {
|
||||
mechanism: {
|
||||
data: {
|
||||
function: 'requestAnimationFrame',
|
||||
handler: getFunctionName(original),
|
||||
},
|
||||
handled: true,
|
||||
type: 'instrument',
|
||||
},
|
||||
}),
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
function _wrapXHR(originalSend) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return function ( ...args) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const xhr = this;
|
||||
const xmlHttpRequestProps = ['onload', 'onerror', 'onprogress', 'onreadystatechange'];
|
||||
|
||||
xmlHttpRequestProps.forEach(prop => {
|
||||
if (prop in xhr && typeof xhr[prop] === 'function') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
fill(xhr, prop, function (original) {
|
||||
const wrapOptions = {
|
||||
mechanism: {
|
||||
data: {
|
||||
function: prop,
|
||||
handler: getFunctionName(original),
|
||||
},
|
||||
handled: true,
|
||||
type: 'instrument',
|
||||
},
|
||||
};
|
||||
|
||||
// If Instrument integration has been called before TryCatch, get the name of original function
|
||||
const originalFunction = getOriginalFunction(original);
|
||||
if (originalFunction) {
|
||||
wrapOptions.mechanism.data.handler = getFunctionName(originalFunction);
|
||||
}
|
||||
|
||||
// Otherwise wrap directly
|
||||
return wrap(original, wrapOptions);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return originalSend.apply(this, args);
|
||||
};
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
function _wrapEventTarget(target) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const globalObject = WINDOW ;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
const proto = globalObject[target] && globalObject[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 (original)
|
||||
|
||||
{
|
||||
return function (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
eventName,
|
||||
fn,
|
||||
options,
|
||||
) {
|
||||
try {
|
||||
if (typeof fn.handleEvent === 'function') {
|
||||
// ESlint disable explanation:
|
||||
// First, it is generally safe to call `wrap` with an unbound function. Furthermore, using `.bind()` would
|
||||
// introduce a bug here, because bind returns a new function that doesn't have our
|
||||
// flags(like __sentry_original__) attached. `wrap` checks for those flags to avoid unnecessary wrapping.
|
||||
// Without those flags, every call to addEventListener wraps the function again, causing a memory leak.
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
fn.handleEvent = wrap(fn.handleEvent, {
|
||||
mechanism: {
|
||||
data: {
|
||||
function: 'handleEvent',
|
||||
handler: getFunctionName(fn),
|
||||
target,
|
||||
},
|
||||
handled: true,
|
||||
type: 'instrument',
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
// can sometimes get 'Permission denied to access property "handle Event'
|
||||
}
|
||||
|
||||
return original.apply(this, [
|
||||
eventName,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
wrap(fn , {
|
||||
mechanism: {
|
||||
data: {
|
||||
function: 'addEventListener',
|
||||
handler: getFunctionName(fn),
|
||||
target,
|
||||
},
|
||||
handled: true,
|
||||
type: 'instrument',
|
||||
},
|
||||
}),
|
||||
options,
|
||||
]);
|
||||
};
|
||||
});
|
||||
|
||||
fill(
|
||||
proto,
|
||||
'removeEventListener',
|
||||
function (
|
||||
originalRemoveEventListener,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
) {
|
||||
return function (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
eventName,
|
||||
fn,
|
||||
options,
|
||||
) {
|
||||
/**
|
||||
* There are 2 possible scenarios here:
|
||||
*
|
||||
* 1. Someone passes a callback, which was attached prior to Sentry initialization, or by using unmodified
|
||||
* method, eg. `document.addEventListener.call(el, name, handler). In this case, we treat this function
|
||||
* as a pass-through, and call original `removeEventListener` with it.
|
||||
*
|
||||
* 2. Someone passes a callback, which was attached after Sentry was initialized, which means that it was using
|
||||
* our wrapped version of `addEventListener`, which internally calls `wrap` helper.
|
||||
* This helper "wraps" whole callback inside a try/catch statement, and attached appropriate metadata to it,
|
||||
* in order for us to make a distinction between wrapped/non-wrapped functions possible.
|
||||
* If a function was wrapped, it has additional property of `__sentry_wrapped__`, holding the handler.
|
||||
*
|
||||
* When someone adds a handler prior to initialization, and then do it again, but after,
|
||||
* then we have to detach both of them. Otherwise, if we'd detach only wrapped one, it'd be impossible
|
||||
* to get rid of the initial handler and it'd stick there forever.
|
||||
*/
|
||||
const wrappedEventHandler = fn ;
|
||||
try {
|
||||
const originalEventHandler = wrappedEventHandler && wrappedEventHandler.__sentry_wrapped__;
|
||||
if (originalEventHandler) {
|
||||
originalRemoveEventListener.call(this, eventName, originalEventHandler, options);
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore, accessing __sentry_wrapped__ will throw in some Selenium environments
|
||||
}
|
||||
return originalRemoveEventListener.call(this, eventName, wrappedEventHandler, options);
|
||||
};
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export { TryCatch };
|
||||
//# sourceMappingURL=trycatch.js.map
|
||||
Reference in New Issue
Block a user