1 | Object.defineProperty(exports, "__esModule", { value: true });
|
2 | var tslib_1 = require("tslib");
|
3 | var utils_1 = require("@sentry/utils");
|
4 | var helpers_1 = require("../helpers");
|
5 | var DEFAULT_EVENT_TARGET = [
|
6 | 'EventTarget',
|
7 | 'Window',
|
8 | 'Node',
|
9 | 'ApplicationCache',
|
10 | 'AudioTrackList',
|
11 | 'ChannelMergerNode',
|
12 | 'CryptoOperation',
|
13 | 'EventSource',
|
14 | 'FileReader',
|
15 | 'HTMLUnknownElement',
|
16 | 'IDBDatabase',
|
17 | 'IDBRequest',
|
18 | 'IDBTransaction',
|
19 | 'KeyOperation',
|
20 | 'MediaController',
|
21 | 'MessagePort',
|
22 | 'ModalWindow',
|
23 | 'Notification',
|
24 | 'SVGElementInstance',
|
25 | 'Screen',
|
26 | 'TextTrack',
|
27 | 'TextTrackCue',
|
28 | 'TextTrackList',
|
29 | 'WebSocket',
|
30 | 'WebSocketWorker',
|
31 | 'Worker',
|
32 | 'XMLHttpRequest',
|
33 | 'XMLHttpRequestEventTarget',
|
34 | 'XMLHttpRequestUpload',
|
35 | ];
|
36 | /** Wrap timer functions and event targets to catch errors and provide better meta data */
|
37 | var TryCatch = /** @class */ (function () {
|
38 | /**
|
39 | * @inheritDoc
|
40 | */
|
41 | function TryCatch(options) {
|
42 | /**
|
43 | * @inheritDoc
|
44 | */
|
45 | this.name = TryCatch.id;
|
46 | this._options = tslib_1.__assign({ XMLHttpRequest: true, eventTarget: true, requestAnimationFrame: true, setInterval: true, setTimeout: true }, options);
|
47 | }
|
48 | /**
|
49 | * Wrap timer functions and event targets to catch errors
|
50 | * and provide better metadata.
|
51 | */
|
52 | TryCatch.prototype.setupOnce = function () {
|
53 | var global = utils_1.getGlobalObject();
|
54 | if (this._options.setTimeout) {
|
55 | utils_1.fill(global, 'setTimeout', this._wrapTimeFunction.bind(this));
|
56 | }
|
57 | if (this._options.setInterval) {
|
58 | utils_1.fill(global, 'setInterval', this._wrapTimeFunction.bind(this));
|
59 | }
|
60 | if (this._options.requestAnimationFrame) {
|
61 | utils_1.fill(global, 'requestAnimationFrame', this._wrapRAF.bind(this));
|
62 | }
|
63 | if (this._options.XMLHttpRequest && 'XMLHttpRequest' in global) {
|
64 | utils_1.fill(XMLHttpRequest.prototype, 'send', this._wrapXHR.bind(this));
|
65 | }
|
66 | if (this._options.eventTarget) {
|
67 | var eventTarget = Array.isArray(this._options.eventTarget) ? this._options.eventTarget : DEFAULT_EVENT_TARGET;
|
68 | eventTarget.forEach(this._wrapEventTarget.bind(this));
|
69 | }
|
70 | };
|
71 | /** JSDoc */
|
72 | TryCatch.prototype._wrapTimeFunction = function (original) {
|
73 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
74 | return function () {
|
75 | var args = [];
|
76 | for (var _i = 0; _i < arguments.length; _i++) {
|
77 | args[_i] = arguments[_i];
|
78 | }
|
79 | var originalCallback = args[0];
|
80 | args[0] = helpers_1.wrap(originalCallback, {
|
81 | mechanism: {
|
82 | data: { function: utils_1.getFunctionName(original) },
|
83 | handled: true,
|
84 | type: 'instrument',
|
85 | },
|
86 | });
|
87 | return original.apply(this, args);
|
88 | };
|
89 | };
|
90 | /** JSDoc */
|
91 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
92 | TryCatch.prototype._wrapRAF = function (original) {
|
93 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
94 | return function (callback) {
|
95 | // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
96 | return original.call(this, helpers_1.wrap(callback, {
|
97 | mechanism: {
|
98 | data: {
|
99 | function: 'requestAnimationFrame',
|
100 | handler: utils_1.getFunctionName(original),
|
101 | },
|
102 | handled: true,
|
103 | type: 'instrument',
|
104 | },
|
105 | }));
|
106 | };
|
107 | };
|
108 | /** JSDoc */
|
109 | TryCatch.prototype._wrapEventTarget = function (target) {
|
110 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
111 | var global = utils_1.getGlobalObject();
|
112 | // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
113 | var proto = global[target] && global[target].prototype;
|
114 | // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
115 | if (!proto || !proto.hasOwnProperty || !proto.hasOwnProperty('addEventListener')) {
|
116 | return;
|
117 | }
|
118 | utils_1.fill(proto, 'addEventListener', function (original) {
|
119 | return function (eventName, fn, options) {
|
120 | try {
|
121 | if (typeof fn.handleEvent === 'function') {
|
122 | fn.handleEvent = helpers_1.wrap(fn.handleEvent.bind(fn), {
|
123 | mechanism: {
|
124 | data: {
|
125 | function: 'handleEvent',
|
126 | handler: utils_1.getFunctionName(fn),
|
127 | target: target,
|
128 | },
|
129 | handled: true,
|
130 | type: 'instrument',
|
131 | },
|
132 | });
|
133 | }
|
134 | }
|
135 | catch (err) {
|
136 | // can sometimes get 'Permission denied to access property "handle Event'
|
137 | }
|
138 | return original.call(this, eventName,
|
139 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
140 | helpers_1.wrap(fn, {
|
141 | mechanism: {
|
142 | data: {
|
143 | function: 'addEventListener',
|
144 | handler: utils_1.getFunctionName(fn),
|
145 | target: target,
|
146 | },
|
147 | handled: true,
|
148 | type: 'instrument',
|
149 | },
|
150 | }), options);
|
151 | };
|
152 | });
|
153 | utils_1.fill(proto, 'removeEventListener', function (originalRemoveEventListener) {
|
154 | return function (eventName, fn, options) {
|
155 | var _a;
|
156 | /**
|
157 | * There are 2 possible scenarios here:
|
158 | *
|
159 | * 1. Someone passes a callback, which was attached prior to Sentry initialization, or by using unmodified
|
160 | * method, eg. `document.addEventListener.call(el, name, handler). In this case, we treat this function
|
161 | * as a pass-through, and call original `removeEventListener` with it.
|
162 | *
|
163 | * 2. Someone passes a callback, which was attached after Sentry was initialized, which means that it was using
|
164 | * our wrapped version of `addEventListener`, which internally calls `wrap` helper.
|
165 | * This helper "wraps" whole callback inside a try/catch statement, and attached appropriate metadata to it,
|
166 | * in order for us to make a distinction between wrapped/non-wrapped functions possible.
|
167 | * If a function was wrapped, it has additional property of `__sentry_wrapped__`, holding the handler.
|
168 | *
|
169 | * When someone adds a handler prior to initialization, and then do it again, but after,
|
170 | * then we have to detach both of them. Otherwise, if we'd detach only wrapped one, it'd be impossible
|
171 | * to get rid of the initial handler and it'd stick there forever.
|
172 | */
|
173 | var wrappedEventHandler = fn;
|
174 | try {
|
175 | var originalEventHandler = (_a = wrappedEventHandler) === null || _a === void 0 ? void 0 : _a.__sentry_wrapped__;
|
176 | if (originalEventHandler) {
|
177 | originalRemoveEventListener.call(this, eventName, originalEventHandler, options);
|
178 | }
|
179 | }
|
180 | catch (e) {
|
181 | // ignore, accessing __sentry_wrapped__ will throw in some Selenium environments
|
182 | }
|
183 | return originalRemoveEventListener.call(this, eventName, wrappedEventHandler, options);
|
184 | };
|
185 | });
|
186 | };
|
187 | /** JSDoc */
|
188 | TryCatch.prototype._wrapXHR = function (originalSend) {
|
189 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
190 | return function () {
|
191 | var args = [];
|
192 | for (var _i = 0; _i < arguments.length; _i++) {
|
193 | args[_i] = arguments[_i];
|
194 | }
|
195 | // eslint-disable-next-line @typescript-eslint/no-this-alias
|
196 | var xhr = this;
|
197 | var xmlHttpRequestProps = ['onload', 'onerror', 'onprogress', 'onreadystatechange'];
|
198 | xmlHttpRequestProps.forEach(function (prop) {
|
199 | if (prop in xhr && typeof xhr[prop] === 'function') {
|
200 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
201 | utils_1.fill(xhr, prop, function (original) {
|
202 | var wrapOptions = {
|
203 | mechanism: {
|
204 | data: {
|
205 | function: prop,
|
206 | handler: utils_1.getFunctionName(original),
|
207 | },
|
208 | handled: true,
|
209 | type: 'instrument',
|
210 | },
|
211 | };
|
212 | // If Instrument integration has been called before TryCatch, get the name of original function
|
213 | if (original.__sentry_original__) {
|
214 | wrapOptions.mechanism.data.handler = utils_1.getFunctionName(original.__sentry_original__);
|
215 | }
|
216 | // Otherwise wrap directly
|
217 | return helpers_1.wrap(original, wrapOptions);
|
218 | });
|
219 | }
|
220 | });
|
221 | return originalSend.apply(this, args);
|
222 | };
|
223 | };
|
224 | /**
|
225 | * @inheritDoc
|
226 | */
|
227 | TryCatch.id = 'TryCatch';
|
228 | return TryCatch;
|
229 | }());
|
230 | exports.TryCatch = TryCatch;
|
231 | //# sourceMappingURL=trycatch.js.map |
\ | No newline at end of file |