UNPKG

@sentry/browser

Version:
166 lines (162 loc) 5.81 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const browser = require('@sentry/core/browser'); const helpers = require('../helpers.js'); const DEFAULT_EVENT_TARGET = "EventTarget,Window,Node,ApplicationCache,AudioTrackList,BroadcastChannel,ChannelMergerNode,CryptoOperation,EventSource,FileReader,HTMLUnknownElement,IDBDatabase,IDBRequest,IDBTransaction,KeyOperation,MediaController,MessagePort,ModalWindow,Notification,SVGElementInstance,Screen,SharedWorker,TextTrack,TextTrackCue,TextTrackList,WebSocket,WebSocketWorker,Worker,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload".split( "," ); const INTEGRATION_NAME = "BrowserApiErrors"; const _browserApiErrorsIntegration = ((options = {}) => { const _options = { XMLHttpRequest: true, eventTarget: true, requestAnimationFrame: true, setInterval: true, setTimeout: true, unregisterOriginalCallbacks: false, ...options }; return { name: INTEGRATION_NAME, // TODO: This currently only works for the first client this is setup // We may want to adjust this to check for client etc. setupOnce() { if (_options.setTimeout) { browser.fill(helpers.WINDOW, "setTimeout", _wrapTimeFunction); } if (_options.setInterval) { browser.fill(helpers.WINDOW, "setInterval", _wrapTimeFunction); } if (_options.requestAnimationFrame) { browser.fill(helpers.WINDOW, "requestAnimationFrame", _wrapRAF); } if (_options.XMLHttpRequest && "XMLHttpRequest" in helpers.WINDOW) { browser.fill(XMLHttpRequest.prototype, "send", _wrapXHR); } const eventTargetOption = _options.eventTarget; if (eventTargetOption) { const eventTarget = Array.isArray(eventTargetOption) ? eventTargetOption : DEFAULT_EVENT_TARGET; eventTarget.forEach((target) => _wrapEventTarget(target, _options)); } } }; }); const browserApiErrorsIntegration = browser.defineIntegration(_browserApiErrorsIntegration); function _wrapTimeFunction(original) { return function(...args) { const originalCallback = args[0]; args[0] = helpers.wrap(originalCallback, { mechanism: { handled: false, type: `auto.browser.browserapierrors.${browser.getFunctionName(original)}` } }); return original.apply(this, args); }; } function _wrapRAF(original) { return function(callback) { return original.apply(this, [ helpers.wrap(callback, { mechanism: { data: { handler: browser.getFunctionName(original) }, handled: false, type: "auto.browser.browserapierrors.requestAnimationFrame" } }) ]); }; } function _wrapXHR(originalSend) { return function(...args) { const xhr = this; const xmlHttpRequestProps = ["onload", "onerror", "onprogress", "onreadystatechange"]; xmlHttpRequestProps.forEach((prop) => { if (prop in xhr && typeof xhr[prop] === "function") { browser.fill(xhr, prop, function(original) { const wrapOptions = { mechanism: { data: { handler: browser.getFunctionName(original) }, handled: false, type: `auto.browser.browserapierrors.xhr.${prop}` } }; const originalFunction = browser.getOriginalFunction(original); if (originalFunction) { wrapOptions.mechanism.data.handler = browser.getFunctionName(originalFunction); } return helpers.wrap(original, wrapOptions); }); } }); return originalSend.apply(this, args); }; } function _wrapEventTarget(target, integrationOptions) { const globalObject = helpers.WINDOW; const proto = globalObject[target]?.prototype; if (!proto?.hasOwnProperty?.("addEventListener")) { return; } browser.fill(proto, "addEventListener", function(original) { return function(eventName, fn, options) { try { if (isEventListenerObject(fn)) { fn.handleEvent = helpers.wrap(fn.handleEvent, { mechanism: { data: { handler: browser.getFunctionName(fn), target }, handled: false, type: "auto.browser.browserapierrors.handleEvent" } }); } } catch { } if (integrationOptions.unregisterOriginalCallbacks) { unregisterOriginalCallback(this, eventName, fn); } return original.apply(this, [ eventName, helpers.wrap(fn, { mechanism: { data: { handler: browser.getFunctionName(fn), target }, handled: false, type: "auto.browser.browserapierrors.addEventListener" } }), options ]); }; }); browser.fill(proto, "removeEventListener", function(originalRemoveEventListener) { return function(eventName, fn, options) { try { const originalEventHandler = fn.__sentry_wrapped__; if (originalEventHandler) { originalRemoveEventListener.call(this, eventName, originalEventHandler, options); } } catch { } return originalRemoveEventListener.call(this, eventName, fn, options); }; }); } function isEventListenerObject(obj) { return typeof obj.handleEvent === "function"; } function unregisterOriginalCallback(target, eventName, fn) { if (target && typeof target === "object" && "removeEventListener" in target && typeof target.removeEventListener === "function") { target.removeEventListener(eventName, fn); } } exports.browserApiErrorsIntegration = browserApiErrorsIntegration; //# sourceMappingURL=browserapierrors.js.map