PluginProbe
HubSpot All-In-One Marketing – Forms, Popups, Live Chat / 11.3.61
HubSpot All-In-One Marketing – Forms, Popups, Live Chat v11.3.61
11.3.75 11.3.73 11.3.71 11.3.70 11.3.69 11.3.64 11.3.65 11.3.62 11.3.61 11.3.56 11.3.58 11.0.31 11.0.52 11.0.54 11.0.56 11.0.58 11.0.7 11.1.10 11.1.11 11.1.13 11.1.14 11.1.15 11.1.2 11.1.20 11.1.21 All 73 releases
leadin / build / feedback.js

feedback.js in HubSpot All-In-One Marketing – Forms, Popups, Live Chat 11.3.61, at build/feedback.js

4,018 lines 133.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ (() => { // webpackBootstrap
2 /******/ var __webpack_modules__ = ({
3
4 /***/ "./scripts/api/wordpressApiClient.ts":
5 /*!*******************************************!*\
6 !*** ./scripts/api/wordpressApiClient.ts ***!
7 \*******************************************/
8 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9
10 "use strict";
11 __webpack_require__.r(__webpack_exports__);
12 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
13 /* harmony export */ "disableInternalTracking": () => (/* binding */ disableInternalTracking),
14 /* harmony export */ "fetchAccessToken": () => (/* binding */ fetchAccessToken),
15 /* harmony export */ "fetchDisableInternalTracking": () => (/* binding */ fetchDisableInternalTracking),
16 /* harmony export */ "fetchProxyMappingsEnabled": () => (/* binding */ fetchProxyMappingsEnabled),
17 /* harmony export */ "fetchRefreshToken": () => (/* binding */ fetchRefreshToken),
18 /* harmony export */ "getBusinessUnitId": () => (/* binding */ getBusinessUnitId),
19 /* harmony export */ "healthcheckRestApi": () => (/* binding */ healthcheckRestApi),
20 /* harmony export */ "refreshProxyMappingsCache": () => (/* binding */ refreshProxyMappingsCache),
21 /* harmony export */ "setBusinessUnitId": () => (/* binding */ setBusinessUnitId),
22 /* harmony export */ "skipReview": () => (/* binding */ skipReview),
23 /* harmony export */ "toggleProxyMappingsEnabled": () => (/* binding */ toggleProxyMappingsEnabled),
24 /* harmony export */ "trackConsent": () => (/* binding */ trackConsent),
25 /* harmony export */ "updateHublet": () => (/* binding */ updateHublet)
26 /* harmony export */ });
27 /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! jquery */ "jquery");
28 /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
29 /* harmony import */ var _lib_Raven__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../lib/Raven */ "./scripts/lib/Raven.ts");
30 /* harmony import */ var _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../constants/leadinConfig */ "./scripts/constants/leadinConfig.ts");
31 /* harmony import */ var _utils_queryParams__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/queryParams */ "./scripts/utils/queryParams.ts");
32
33
34
35
36 function makeRequest(method, path) {
37 var data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
38 var queryParams = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
39 // eslint-disable-next-line compat/compat
40 var restApiUrl = new URL("".concat(_constants_leadinConfig__WEBPACK_IMPORTED_MODULE_2__.restUrl, "leadin/v1").concat(path));
41 (0,_utils_queryParams__WEBPACK_IMPORTED_MODULE_3__.addQueryObjectToUrl)(restApiUrl, queryParams);
42 return new Promise(function (resolve, reject) {
43 var payload = {
44 url: restApiUrl.toString(),
45 method: method,
46 contentType: 'application/json',
47 beforeSend: function beforeSend(xhr) {
48 return xhr.setRequestHeader('X-WP-Nonce', _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_2__.restNonce);
49 },
50 success: resolve,
51 error: function error(response) {
52 _lib_Raven__WEBPACK_IMPORTED_MODULE_1__["default"].captureMessage("HTTP Request to ".concat(restApiUrl, " failed with error ").concat(response.status, ": ").concat(response.responseText), {
53 fingerprint: ['{{ default }}', path, response.status, response.responseText]
54 });
55 reject(response);
56 }
57 };
58 if (method !== 'get') {
59 payload.data = JSON.stringify(data);
60 }
61 jquery__WEBPACK_IMPORTED_MODULE_0___default().ajax(payload);
62 });
63 }
64 function healthcheckRestApi() {
65 return makeRequest('get', '/healthcheck');
66 }
67 function disableInternalTracking(value) {
68 return makeRequest('put', '/internal-tracking', value ? '1' : '0');
69 }
70 function fetchDisableInternalTracking() {
71 return makeRequest('get', '/internal-tracking').then(function (message) {
72 return {
73 message: message
74 };
75 });
76 }
77 function updateHublet(hublet) {
78 return makeRequest('put', '/hublet', {
79 hublet: hublet
80 });
81 }
82 function skipReview() {
83 return makeRequest('post', '/skip-review');
84 }
85 function trackConsent(canTrack) {
86 return makeRequest('post', '/track-consent', {
87 canTrack: canTrack
88 }).then(function (message) {
89 return {
90 message: message
91 };
92 });
93 }
94 function setBusinessUnitId(businessUnitId) {
95 return makeRequest('put', '/business-unit', {
96 businessUnitId: businessUnitId
97 });
98 }
99 function getBusinessUnitId() {
100 return makeRequest('get', '/business-unit');
101 }
102 function refreshProxyMappingsCache() {
103 return makeRequest('post', '/wp-mappings-cache-reset');
104 }
105 function fetchProxyMappingsEnabled() {
106 return makeRequest('get', '/wp-mappings-proxy-enabled');
107 }
108 function toggleProxyMappingsEnabled(value) {
109 return makeRequest('put', '/wp-mappings-proxy-enabled', value);
110 }
111 var refreshTokenRequest = null;
112 function fetchRefreshToken() {
113 if (!refreshTokenRequest) {
114 refreshTokenRequest = makeRequest('get', '/refresh-token')["catch"](function (err) {
115 refreshTokenRequest = null;
116 throw err;
117 });
118 }
119 return refreshTokenRequest;
120 }
121 var ACCESS_TOKEN_CACHE_KEY = 'leadin_access_token';
122 var ACCESS_TOKEN_MIN_TTL_SECONDS = 300;
123 var accessTokenRequest = null;
124 function fetchAccessToken() {
125 try {
126 var cached = sessionStorage.getItem(ACCESS_TOKEN_CACHE_KEY);
127 if (cached) {
128 var _JSON$parse = JSON.parse(cached),
129 accessToken = _JSON$parse.accessToken,
130 expiresAt = _JSON$parse.expiresAt;
131 if (accessToken && expiresAt > Math.floor(Date.now() / 1000) + ACCESS_TOKEN_MIN_TTL_SECONDS) {
132 return Promise.resolve({
133 accessToken: accessToken,
134 expiresIn: expiresAt - Math.floor(Date.now() / 1000)
135 });
136 }
137 }
138 } catch (_) {}
139 if (!accessTokenRequest) {
140 accessTokenRequest = makeRequest('get', '/access-token').then(function (response) {
141 try {
142 sessionStorage.setItem(ACCESS_TOKEN_CACHE_KEY, JSON.stringify({
143 accessToken: response.accessToken,
144 expiresAt: Math.floor(Date.now() / 1000) + response.expiresIn
145 }));
146 } catch (_) {}
147 return response;
148 })["finally"](function () {
149 accessTokenRequest = null;
150 });
151 }
152 return accessTokenRequest;
153 }
154
155 /***/ }),
156
157 /***/ "./scripts/constants/leadinConfig.ts":
158 /*!*******************************************!*\
159 !*** ./scripts/constants/leadinConfig.ts ***!
160 \*******************************************/
161 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
162
163 "use strict";
164 __webpack_require__.r(__webpack_exports__);
165 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
166 /* harmony export */ "accountName": () => (/* binding */ accountName),
167 /* harmony export */ "activationTime": () => (/* binding */ activationTime),
168 /* harmony export */ "adminUrl": () => (/* binding */ adminUrl),
169 /* harmony export */ "connectionStatus": () => (/* binding */ connectionStatus),
170 /* harmony export */ "contentEmbed": () => (/* binding */ contentEmbed),
171 /* harmony export */ "decryptError": () => (/* binding */ decryptError),
172 /* harmony export */ "deviceId": () => (/* binding */ deviceId),
173 /* harmony export */ "didDisconnect": () => (/* binding */ didDisconnect),
174 /* harmony export */ "env": () => (/* binding */ env),
175 /* harmony export */ "formsScript": () => (/* binding */ formsScript),
176 /* harmony export */ "formsScriptPayload": () => (/* binding */ formsScriptPayload),
177 /* harmony export */ "hublet": () => (/* binding */ hublet),
178 /* harmony export */ "hubspotBaseUrl": () => (/* binding */ hubspotBaseUrl),
179 /* harmony export */ "hubspotNonce": () => (/* binding */ hubspotNonce),
180 /* harmony export */ "iframeUrl": () => (/* binding */ iframeUrl),
181 /* harmony export */ "impactLink": () => (/* binding */ impactLink),
182 /* harmony export */ "lastAuthorizeTime": () => (/* binding */ lastAuthorizeTime),
183 /* harmony export */ "lastDeauthorizeTime": () => (/* binding */ lastDeauthorizeTime),
184 /* harmony export */ "lastDisconnectTime": () => (/* binding */ lastDisconnectTime),
185 /* harmony export */ "leadinPluginVersion": () => (/* binding */ leadinPluginVersion),
186 /* harmony export */ "leadinQueryParams": () => (/* binding */ leadinQueryParams),
187 /* harmony export */ "locale": () => (/* binding */ locale),
188 /* harmony export */ "loginUrl": () => (/* binding */ loginUrl),
189 /* harmony export */ "meetingsScript": () => (/* binding */ meetingsScript),
190 /* harmony export */ "phpVersion": () => (/* binding */ phpVersion),
191 /* harmony export */ "pluginPath": () => (/* binding */ pluginPath),
192 /* harmony export */ "plugins": () => (/* binding */ plugins),
193 /* harmony export */ "portalDomain": () => (/* binding */ portalDomain),
194 /* harmony export */ "portalEmail": () => (/* binding */ portalEmail),
195 /* harmony export */ "portalId": () => (/* binding */ portalId),
196 /* harmony export */ "redirectNonce": () => (/* binding */ redirectNonce),
197 /* harmony export */ "refreshToken": () => (/* binding */ refreshToken),
198 /* harmony export */ "requiresContentEmbedScope": () => (/* binding */ requiresContentEmbedScope),
199 /* harmony export */ "restNonce": () => (/* binding */ restNonce),
200 /* harmony export */ "restUrl": () => (/* binding */ restUrl),
201 /* harmony export */ "reviewSkippedDate": () => (/* binding */ reviewSkippedDate),
202 /* harmony export */ "theme": () => (/* binding */ theme),
203 /* harmony export */ "trackConsent": () => (/* binding */ trackConsent),
204 /* harmony export */ "wpVersion": () => (/* binding */ wpVersion)
205 /* harmony export */ });
206 var _window$leadinConfig = window.leadinConfig,
207 accountName = _window$leadinConfig.accountName,
208 adminUrl = _window$leadinConfig.adminUrl,
209 activationTime = _window$leadinConfig.activationTime,
210 connectionStatus = _window$leadinConfig.connectionStatus,
211 deviceId = _window$leadinConfig.deviceId,
212 didDisconnect = _window$leadinConfig.didDisconnect,
213 env = _window$leadinConfig.env,
214 formsScript = _window$leadinConfig.formsScript,
215 meetingsScript = _window$leadinConfig.meetingsScript,
216 formsScriptPayload = _window$leadinConfig.formsScriptPayload,
217 hublet = _window$leadinConfig.hublet,
218 hubspotBaseUrl = _window$leadinConfig.hubspotBaseUrl,
219 hubspotNonce = _window$leadinConfig.hubspotNonce,
220 iframeUrl = _window$leadinConfig.iframeUrl,
221 impactLink = _window$leadinConfig.impactLink,
222 lastAuthorizeTime = _window$leadinConfig.lastAuthorizeTime,
223 lastDeauthorizeTime = _window$leadinConfig.lastDeauthorizeTime,
224 lastDisconnectTime = _window$leadinConfig.lastDisconnectTime,
225 leadinPluginVersion = _window$leadinConfig.leadinPluginVersion,
226 leadinQueryParams = _window$leadinConfig.leadinQueryParams,
227 locale = _window$leadinConfig.locale,
228 loginUrl = _window$leadinConfig.loginUrl,
229 phpVersion = _window$leadinConfig.phpVersion,
230 pluginPath = _window$leadinConfig.pluginPath,
231 plugins = _window$leadinConfig.plugins,
232 portalDomain = _window$leadinConfig.portalDomain,
233 portalEmail = _window$leadinConfig.portalEmail,
234 portalId = _window$leadinConfig.portalId,
235 redirectNonce = _window$leadinConfig.redirectNonce,
236 restNonce = _window$leadinConfig.restNonce,
237 restUrl = _window$leadinConfig.restUrl,
238 refreshToken = _window$leadinConfig.refreshToken,
239 reviewSkippedDate = _window$leadinConfig.reviewSkippedDate,
240 theme = _window$leadinConfig.theme,
241 trackConsent = _window$leadinConfig.trackConsent,
242 wpVersion = _window$leadinConfig.wpVersion,
243 contentEmbed = _window$leadinConfig.contentEmbed,
244 requiresContentEmbedScope = _window$leadinConfig.requiresContentEmbedScope,
245 decryptError = _window$leadinConfig.decryptError;
246
247
248 /***/ }),
249
250 /***/ "./scripts/constants/selectors.ts":
251 /*!****************************************!*\
252 !*** ./scripts/constants/selectors.ts ***!
253 \****************************************/
254 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
255
256 "use strict";
257 __webpack_require__.r(__webpack_exports__);
258 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
259 /* harmony export */ "domElements": () => (/* binding */ domElements)
260 /* harmony export */ });
261 var domElements = {
262 iframe: '#leadin-iframe',
263 subMenu: '.toplevel_page_leadin > ul',
264 subMenuLinks: '.toplevel_page_leadin > ul a',
265 subMenuButtons: '.toplevel_page_leadin > ul > li',
266 deactivatePluginButton: '[data-slug="leadin"] .deactivate a',
267 deactivateFeedbackForm: 'form.leadin-deactivate-form',
268 deactivateFeedbackSubmit: 'button#leadin-feedback-submit',
269 deactivateFeedbackSkip: 'button#leadin-feedback-skip',
270 thickboxModalClose: '.leadin-modal-close',
271 thickboxModalWindow: 'div#TB_window.thickbox-loading',
272 thickboxModalContent: 'div#TB_ajaxContent.TB_modal',
273 reviewBannerContainer: '#leadin-review-banner',
274 reviewBannerLeaveReviewLink: 'a#leave-review-button',
275 reviewBannerDismissButton: 'a#dismiss-review-banner-button',
276 leadinIframeContainer: 'leadin-iframe-container',
277 leadinIframe: 'leadin-iframe',
278 leadinIframeFallbackContainer: 'leadin-iframe-fallback-container'
279 };
280
281 /***/ }),
282
283 /***/ "./scripts/feedback/ThickBoxModal.ts":
284 /*!*******************************************!*\
285 !*** ./scripts/feedback/ThickBoxModal.ts ***!
286 \*******************************************/
287 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
288
289 "use strict";
290 __webpack_require__.r(__webpack_exports__);
291 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
292 /* harmony export */ "default": () => (/* binding */ ThickBoxModal)
293 /* harmony export */ });
294 /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! jquery */ "jquery");
295 /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
296 /* harmony import */ var _constants_selectors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../constants/selectors */ "./scripts/constants/selectors.ts");
297 function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
298 function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
299 function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
300 function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
301 function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
302 function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
303 function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
304
305
306 var ThickBoxModal = /*#__PURE__*/function () {
307 function ThickBoxModal(openTriggerSelector, inlineContentId, windowCssClass, contentCssClass) {
308 _classCallCheck(this, ThickBoxModal);
309 _defineProperty(this, "openTriggerSelector", void 0);
310 _defineProperty(this, "inlineContentId", void 0);
311 _defineProperty(this, "windowCssClass", void 0);
312 _defineProperty(this, "contentCssClass", void 0);
313 this.openTriggerSelector = openTriggerSelector;
314 this.inlineContentId = inlineContentId;
315 this.windowCssClass = windowCssClass;
316 this.contentCssClass = contentCssClass;
317 jquery__WEBPACK_IMPORTED_MODULE_0___default()(openTriggerSelector).on('click', this.init.bind(this));
318 }
319 return _createClass(ThickBoxModal, [{
320 key: "close",
321 value: function close() {
322 //@ts-expect-error global
323 window.tb_remove();
324 }
325 }, {
326 key: "init",
327 value: function init(e) {
328 //@ts-expect-error global
329 window.tb_show('', "#TB_inline?inlineId=".concat(this.inlineContentId, "&modal=true"));
330 // thickbox doesn't respect the width and height url parameters https://core.trac.wordpress.org/ticket/17249
331 // We override thickboxes css with !important in the css
332 jquery__WEBPACK_IMPORTED_MODULE_0___default()(_constants_selectors__WEBPACK_IMPORTED_MODULE_1__.domElements.thickboxModalWindow).addClass(this.windowCssClass);
333 // have to modify the css of the thickbox content container as well
334 jquery__WEBPACK_IMPORTED_MODULE_0___default()(_constants_selectors__WEBPACK_IMPORTED_MODULE_1__.domElements.thickboxModalContent).addClass(this.contentCssClass);
335 // we unbind previous handlers because a thickbox modal is a single global object.
336 // Everytime it is re-opened, it still has old handlers bound
337 jquery__WEBPACK_IMPORTED_MODULE_0___default()(_constants_selectors__WEBPACK_IMPORTED_MODULE_1__.domElements.thickboxModalClose).off('click').on('click', this.close);
338 e.preventDefault();
339 }
340 }]);
341 }();
342
343
344 /***/ }),
345
346 /***/ "./scripts/feedback/feedbackFormApi.ts":
347 /*!*********************************************!*\
348 !*** ./scripts/feedback/feedbackFormApi.ts ***!
349 \*********************************************/
350 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
351
352 "use strict";
353 __webpack_require__.r(__webpack_exports__);
354 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
355 /* harmony export */ "submitFeedbackForm": () => (/* binding */ submitFeedbackForm)
356 /* harmony export */ });
357 /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! jquery */ "jquery");
358 /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
359
360 var portalId = '6275621';
361 var formId = '0e8807f8-2ac3-4664-b742-44552bfa09e2';
362 var formSubmissionUrl = "https://api.hsforms.com/submissions/v3/integration/submit/".concat(portalId, "/").concat(formId);
363 function submitFeedbackForm(formSelector) {
364 var formSubmissionPayload = {
365 fields: jquery__WEBPACK_IMPORTED_MODULE_0___default()(formSelector).serializeArray(),
366 skipValidation: true
367 };
368 return new Promise(function (resolve, reject) {
369 jquery__WEBPACK_IMPORTED_MODULE_0___default().ajax({
370 type: 'POST',
371 url: formSubmissionUrl,
372 contentType: 'application/json',
373 data: JSON.stringify(formSubmissionPayload),
374 success: resolve,
375 error: reject
376 });
377 });
378 }
379
380 /***/ }),
381
382 /***/ "./scripts/iframe/integratedMessages/core/CoreMessages.ts":
383 /*!****************************************************************!*\
384 !*** ./scripts/iframe/integratedMessages/core/CoreMessages.ts ***!
385 \****************************************************************/
386 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
387
388 "use strict";
389 __webpack_require__.r(__webpack_exports__);
390 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
391 /* harmony export */ "CoreMessages": () => (/* binding */ CoreMessages)
392 /* harmony export */ });
393 var CoreMessages = {
394 HandshakeReceive: 'INTEGRATED_APP_EMBEDDER_HANDSHAKE_RECEIVED',
395 SendRefreshToken: 'INTEGRATED_APP_EMBEDDER_SEND_REFRESH_TOKEN',
396 ReloadParentFrame: 'INTEGRATED_APP_EMBEDDER_RELOAD_PARENT_FRAME',
397 RedirectParentFrame: 'INTEGRATED_APP_EMBEDDER_REDIRECT_PARENT_FRAME',
398 SendLocale: 'INTEGRATED_APP_EMBEDDER_SEND_LOCALE',
399 SendDeviceId: 'INTEGRATED_APP_EMBEDDER_SEND_DEVICE_ID',
400 SendIntegratedAppConfig: 'INTEGRATED_APP_EMBEDDER_CONFIG'
401 };
402
403 /***/ }),
404
405 /***/ "./scripts/iframe/integratedMessages/forms/FormsMessages.ts":
406 /*!******************************************************************!*\
407 !*** ./scripts/iframe/integratedMessages/forms/FormsMessages.ts ***!
408 \******************************************************************/
409 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
410
411 "use strict";
412 __webpack_require__.r(__webpack_exports__);
413 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
414 /* harmony export */ "FormMessages": () => (/* binding */ FormMessages)
415 /* harmony export */ });
416 var FormMessages = {
417 CreateFormAppNavigation: 'CREATE_FORM_APP_NAVIGATION'
418 };
419
420 /***/ }),
421
422 /***/ "./scripts/iframe/integratedMessages/index.ts":
423 /*!****************************************************!*\
424 !*** ./scripts/iframe/integratedMessages/index.ts ***!
425 \****************************************************/
426 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
427
428 "use strict";
429 __webpack_require__.r(__webpack_exports__);
430 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
431 /* harmony export */ "CoreMessages": () => (/* reexport safe */ _core_CoreMessages__WEBPACK_IMPORTED_MODULE_0__.CoreMessages),
432 /* harmony export */ "FormMessages": () => (/* reexport safe */ _forms_FormsMessages__WEBPACK_IMPORTED_MODULE_1__.FormMessages),
433 /* harmony export */ "LiveChatMessages": () => (/* reexport safe */ _livechat_LiveChatMessages__WEBPACK_IMPORTED_MODULE_2__.LiveChatMessages),
434 /* harmony export */ "PluginMessages": () => (/* reexport safe */ _plugin_PluginMessages__WEBPACK_IMPORTED_MODULE_3__.PluginMessages),
435 /* harmony export */ "ProxyMessages": () => (/* reexport safe */ _proxy_ProxyMessages__WEBPACK_IMPORTED_MODULE_4__.ProxyMessages)
436 /* harmony export */ });
437 /* harmony import */ var _core_CoreMessages__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core/CoreMessages */ "./scripts/iframe/integratedMessages/core/CoreMessages.ts");
438 /* harmony import */ var _forms_FormsMessages__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./forms/FormsMessages */ "./scripts/iframe/integratedMessages/forms/FormsMessages.ts");
439 /* harmony import */ var _livechat_LiveChatMessages__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./livechat/LiveChatMessages */ "./scripts/iframe/integratedMessages/livechat/LiveChatMessages.ts");
440 /* harmony import */ var _plugin_PluginMessages__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./plugin/PluginMessages */ "./scripts/iframe/integratedMessages/plugin/PluginMessages.ts");
441 /* harmony import */ var _proxy_ProxyMessages__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./proxy/ProxyMessages */ "./scripts/iframe/integratedMessages/proxy/ProxyMessages.ts");
442
443
444
445
446
447
448 /***/ }),
449
450 /***/ "./scripts/iframe/integratedMessages/livechat/LiveChatMessages.ts":
451 /*!************************************************************************!*\
452 !*** ./scripts/iframe/integratedMessages/livechat/LiveChatMessages.ts ***!
453 \************************************************************************/
454 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
455
456 "use strict";
457 __webpack_require__.r(__webpack_exports__);
458 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
459 /* harmony export */ "LiveChatMessages": () => (/* binding */ LiveChatMessages)
460 /* harmony export */ });
461 var LiveChatMessages = {
462 CreateLiveChatAppNavigation: 'CREATE_LIVE_CHAT_APP_NAVIGATION'
463 };
464
465 /***/ }),
466
467 /***/ "./scripts/iframe/integratedMessages/plugin/PluginMessages.ts":
468 /*!********************************************************************!*\
469 !*** ./scripts/iframe/integratedMessages/plugin/PluginMessages.ts ***!
470 \********************************************************************/
471 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
472
473 "use strict";
474 __webpack_require__.r(__webpack_exports__);
475 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
476 /* harmony export */ "PluginMessages": () => (/* binding */ PluginMessages)
477 /* harmony export */ });
478 var PluginMessages = {
479 PluginSettingsNavigation: 'PLUGIN_SETTINGS_NAVIGATION',
480 PluginLeadinConfig: 'PLUGIN_LEADIN_CONFIG',
481 TrackConsent: 'INTEGRATED_APP_EMBEDDER_TRACK_CONSENT',
482 InternalTrackingFetchRequest: 'INTEGRATED_TRACKING_FETCH_REQUEST',
483 InternalTrackingFetchResponse: 'INTEGRATED_TRACKING_FETCH_RESPONSE',
484 InternalTrackingFetchError: 'INTEGRATED_TRACKING_FETCH_ERROR',
485 InternalTrackingChangeRequest: 'INTEGRATED_TRACKING_CHANGE_REQUEST',
486 InternalTrackingChangeError: 'INTEGRATED_TRACKING_CHANGE_ERROR',
487 BusinessUnitFetchRequest: 'BUSINESS_UNIT_FETCH_REQUEST',
488 BusinessUnitFetchResponse: 'BUSINESS_UNIT_FETCH_FETCH_RESPONSE',
489 BusinessUnitFetchError: 'BUSINESS_UNIT_FETCH_FETCH_ERROR',
490 BusinessUnitChangeRequest: 'BUSINESS_UNIT_CHANGE_REQUEST',
491 BusinessUnitChangeError: 'BUSINESS_UNIT_CHANGE_ERROR',
492 SkipReviewRequest: 'SKIP_REVIEW_REQUEST',
493 SkipReviewResponse: 'SKIP_REVIEW_RESPONSE',
494 SkipReviewError: 'SKIP_REVIEW_ERROR',
495 RemoveParentQueryParam: 'REMOVE_PARENT_QUERY_PARAM',
496 ContentEmbedInstallRequest: 'CONTENT_EMBED_INSTALL_REQUEST',
497 ContentEmbedInstallResponse: 'CONTENT_EMBED_INSTALL_RESPONSE',
498 ContentEmbedInstallError: 'CONTENT_EMBED_INSTALL_ERROR',
499 ContentEmbedActivationRequest: 'CONTENT_EMBED_ACTIVATION_REQUEST',
500 ContentEmbedActivationResponse: 'CONTENT_EMBED_ACTIVATION_RESPONSE',
501 ContentEmbedActivationError: 'CONTENT_EMBED_ACTIVATION_ERROR',
502 ProxyMappingsEnabledRequest: 'PROXY_MAPPINGS_ENABLED_REQUEST',
503 ProxyMappingsEnabledResponse: 'PROXY_MAPPINGS_ENABLED_RESPONSE',
504 ProxyMappingsEnabledError: 'PROXY_MAPPINGS_ENABLED_ERROR',
505 ProxyMappingsEnabledChangeRequest: 'PROXY_MAPPINGS_ENABLED_CHANGE_REQUEST',
506 ProxyMappingsEnabledChangeError: 'PROXY_MAPPINGS_ENABLED_CHANGE_ERROR',
507 RefreshProxyMappingsRequest: 'REFRESH_PROXY_MAPPINGS_REQUEST',
508 RefreshProxyMappingsResponse: 'REFRESH_PROXY_MAPPINGS_RESPONSE',
509 RefreshProxyMappingsError: 'REFRESH_PROXY_MAPPINGS_ERROR'
510 };
511
512 /***/ }),
513
514 /***/ "./scripts/iframe/integratedMessages/proxy/ProxyMessages.ts":
515 /*!******************************************************************!*\
516 !*** ./scripts/iframe/integratedMessages/proxy/ProxyMessages.ts ***!
517 \******************************************************************/
518 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
519
520 "use strict";
521 __webpack_require__.r(__webpack_exports__);
522 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
523 /* harmony export */ "ProxyMessages": () => (/* binding */ ProxyMessages)
524 /* harmony export */ });
525 var ProxyMessages = {
526 FetchForms: 'FETCH_FORMS',
527 FetchForm: 'FETCH_FORM',
528 CreateFormFromTemplate: 'CREATE_FORM_FROM_TEMPLATE',
529 GetTemplateAvailability: 'GET_TEMPLATE_AVAILABILITY',
530 FetchAuth: 'FETCH_AUTH',
531 FetchMeetingsAndUsers: 'FETCH_MEETINGS_AND_USERS',
532 FetchContactsCreateSinceActivation: 'FETCH_CONTACTS_CREATED_SINCE_ACTIVATION',
533 FetchOrCreateMeetingUser: 'FETCH_OR_CREATE_MEETING_USER',
534 ConnectMeetingsCalendar: 'CONNECT_MEETINGS_CALENDAR',
535 TrackFormPreviewRender: 'TRACK_FORM_PREVIEW_RENDER',
536 TrackFormCreatedFromTemplate: 'TRACK_FORM_CREATED_FROM_TEMPLATE',
537 TrackFormCreationFailed: 'TRACK_FORM_CREATION_FAILED',
538 TrackMeetingPreviewRender: 'TRACK_MEETING_PREVIEW_RENDER',
539 TrackSidebarMetaChange: 'TRACK_SIDEBAR_META_CHANGE',
540 TrackReviewBannerRender: 'TRACK_REVIEW_BANNER_RENDER',
541 TrackReviewBannerInteraction: 'TRACK_REVIEW_BANNER_INTERACTION',
542 TrackReviewBannerDismissed: 'TRACK_REVIEW_BANNER_DISMISSED',
543 TrackPluginDeactivation: 'TRACK_PLUGIN_DEACTIVATION'
544 };
545
546 /***/ }),
547
548 /***/ "./scripts/lib/Raven.ts":
549 /*!******************************!*\
550 !*** ./scripts/lib/Raven.ts ***!
551 \******************************/
552 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
553
554 "use strict";
555 __webpack_require__.r(__webpack_exports__);
556 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
557 /* harmony export */ "configureRaven": () => (/* binding */ configureRaven),
558 /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
559 /* harmony export */ });
560 /* harmony import */ var raven_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! raven-js */ "./node_modules/raven-js/src/singleton.js");
561 /* harmony import */ var raven_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(raven_js__WEBPACK_IMPORTED_MODULE_0__);
562 /* harmony import */ var _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../constants/leadinConfig */ "./scripts/constants/leadinConfig.ts");
563
564
565 function configureRaven() {
566 if (_constants_leadinConfig__WEBPACK_IMPORTED_MODULE_1__.hubspotBaseUrl.indexOf('local') !== -1) {
567 return;
568 }
569 var domain = _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_1__.hubspotBaseUrl.replace(/https?:\/\/app/, '');
570 raven_js__WEBPACK_IMPORTED_MODULE_0___default().config("https://a9f08e536ef66abb0bf90becc905b09e@exceptions".concat(domain, "/v2/1"), {
571 instrument: {
572 tryCatch: false
573 },
574 shouldSendCallback: function shouldSendCallback(data) {
575 return !!data && !!data.culprit && /plugins\/leadin\//.test(data.culprit);
576 },
577 release: _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_1__.leadinPluginVersion
578 }).install();
579 raven_js__WEBPACK_IMPORTED_MODULE_0___default().setTagsContext({
580 v: _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_1__.leadinPluginVersion,
581 php: _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_1__.phpVersion,
582 wordpress: _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_1__.wpVersion
583 });
584 raven_js__WEBPACK_IMPORTED_MODULE_0___default().setExtraContext({
585 hub: _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_1__.portalId,
586 plugins: Object.keys(_constants_leadinConfig__WEBPACK_IMPORTED_MODULE_1__.plugins).map(function (name) {
587 return "".concat(name, "#").concat(_constants_leadinConfig__WEBPACK_IMPORTED_MODULE_1__.plugins[name]);
588 }).join(',')
589 });
590 }
591 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ((raven_js__WEBPACK_IMPORTED_MODULE_0___default()));
592
593 /***/ }),
594
595 /***/ "./scripts/utils/appUtils.ts":
596 /*!***********************************!*\
597 !*** ./scripts/utils/appUtils.ts ***!
598 \***********************************/
599 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
600
601 "use strict";
602 __webpack_require__.r(__webpack_exports__);
603 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
604 /* harmony export */ "initApp": () => (/* binding */ initApp),
605 /* harmony export */ "initAppOnReady": () => (/* binding */ initAppOnReady)
606 /* harmony export */ });
607 /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! jquery */ "jquery");
608 /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
609 /* harmony import */ var _lib_Raven__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../lib/Raven */ "./scripts/lib/Raven.ts");
610
611
612 function initApp(initFn) {
613 (0,_lib_Raven__WEBPACK_IMPORTED_MODULE_1__.configureRaven)();
614 _lib_Raven__WEBPACK_IMPORTED_MODULE_1__["default"].context(initFn);
615 }
616 function initAppOnReady(initFn) {
617 function main() {
618 jquery__WEBPACK_IMPORTED_MODULE_0___default()(initFn);
619 }
620 initApp(main);
621 }
622
623 /***/ }),
624
625 /***/ "./scripts/utils/backgroundAppUtils.ts":
626 /*!*********************************************!*\
627 !*** ./scripts/utils/backgroundAppUtils.ts ***!
628 \*********************************************/
629 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
630
631 "use strict";
632 __webpack_require__.r(__webpack_exports__);
633 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
634 /* harmony export */ "getOrCreateBackgroundApp": () => (/* binding */ getOrCreateBackgroundApp),
635 /* harmony export */ "initBackgroundApp": () => (/* binding */ initBackgroundApp)
636 /* harmony export */ });
637 /* harmony import */ var _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../constants/leadinConfig */ "./scripts/constants/leadinConfig.ts");
638 /* harmony import */ var _appUtils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./appUtils */ "./scripts/utils/appUtils.ts");
639 /* harmony import */ var _api_wordpressApiClient__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../api/wordpressApiClient */ "./scripts/api/wordpressApiClient.ts");
640
641
642
643 function initBackgroundApp(initFn) {
644 function main() {
645 if (Array.isArray(initFn)) {
646 initFn.forEach(function (callback) {
647 return callback();
648 });
649 } else {
650 initFn();
651 }
652 }
653 (0,_appUtils__WEBPACK_IMPORTED_MODULE_1__.initApp)(main);
654 }
655 var getLeadinConfig = function getLeadinConfig() {
656 return {
657 leadinPluginVersion: _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_0__.leadinPluginVersion
658 };
659 };
660 var getOrCreateBackgroundApp = function getOrCreateBackgroundApp() {
661 var accessToken = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
662 var expiresIn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
663 if (window.LeadinBackgroundApp) {
664 return window.LeadinBackgroundApp;
665 }
666 var _window = window,
667 IntegratedAppEmbedder = _window.IntegratedAppEmbedder,
668 IntegratedAppOptions = _window.IntegratedAppOptions;
669 var options = new IntegratedAppOptions().setLocale(_constants_leadinConfig__WEBPACK_IMPORTED_MODULE_0__.locale).setDeviceId(_constants_leadinConfig__WEBPACK_IMPORTED_MODULE_0__.deviceId).setLeadinConfig(getLeadinConfig()).setAccessToken(accessToken, expiresIn);
670 var embedder = new IntegratedAppEmbedder('integrated-plugin-proxy', _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_0__.portalId, _constants_leadinConfig__WEBPACK_IMPORTED_MODULE_0__.hubspotBaseUrl, function () {}).setOptions(options);
671 embedder.attachTo(document.body, false);
672 embedder.setTokenRenewalCallback(_api_wordpressApiClient__WEBPACK_IMPORTED_MODULE_2__.fetchAccessToken);
673 embedder.postStartAppMessage(); // lets the app know all data has been passed to it
674 window.LeadinBackgroundApp = embedder;
675 return window.LeadinBackgroundApp;
676 };
677
678 /***/ }),
679
680 /***/ "./scripts/utils/queryParams.ts":
681 /*!**************************************!*\
682 !*** ./scripts/utils/queryParams.ts ***!
683 \**************************************/
684 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
685
686 "use strict";
687 __webpack_require__.r(__webpack_exports__);
688 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
689 /* harmony export */ "addQueryObjectToUrl": () => (/* binding */ addQueryObjectToUrl),
690 /* harmony export */ "removeQueryParamFromLocation": () => (/* binding */ removeQueryParamFromLocation)
691 /* harmony export */ });
692 function addQueryObjectToUrl(urlObject, queryParams) {
693 Object.keys(queryParams).forEach(function (key) {
694 urlObject.searchParams.append(key, queryParams[key]);
695 });
696 }
697 function removeQueryParamFromLocation(key) {
698 var location = new URL(window.location.href);
699 location.searchParams["delete"](key);
700 window.history.replaceState(null, '', location.href);
701 }
702
703 /***/ }),
704
705 /***/ "./node_modules/raven-js/src/configError.js":
706 /*!**************************************************!*\
707 !*** ./node_modules/raven-js/src/configError.js ***!
708 \**************************************************/
709 /***/ ((module) => {
710
711 function RavenConfigError(message) {
712 this.name = 'RavenConfigError';
713 this.message = message;
714 }
715 RavenConfigError.prototype = new Error();
716 RavenConfigError.prototype.constructor = RavenConfigError;
717
718 module.exports = RavenConfigError;
719
720
721 /***/ }),
722
723 /***/ "./node_modules/raven-js/src/console.js":
724 /*!**********************************************!*\
725 !*** ./node_modules/raven-js/src/console.js ***!
726 \**********************************************/
727 /***/ ((module) => {
728
729 var wrapMethod = function(console, level, callback) {
730 var originalConsoleLevel = console[level];
731 var originalConsole = console;
732
733 if (!(level in console)) {
734 return;
735 }
736
737 var sentryLevel = level === 'warn' ? 'warning' : level;
738
739 console[level] = function() {
740 var args = [].slice.call(arguments);
741
742 var msg = '' + args.join(' ');
743 var data = {level: sentryLevel, logger: 'console', extra: {arguments: args}};
744
745 if (level === 'assert') {
746 if (args[0] === false) {
747 // Default browsers message
748 msg = 'Assertion failed: ' + (args.slice(1).join(' ') || 'console.assert');
749 data.extra.arguments = args.slice(1);
750 callback && callback(msg, data);
751 }
752 } else {
753 callback && callback(msg, data);
754 }
755
756 // this fails for some browsers. :(
757 if (originalConsoleLevel) {
758 // IE9 doesn't allow calling apply on console functions directly
759 // See: https://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function#answer-5473193
760 Function.prototype.apply.call(originalConsoleLevel, originalConsole, args);
761 }
762 };
763 };
764
765 module.exports = {
766 wrapMethod: wrapMethod
767 };
768
769
770 /***/ }),
771
772 /***/ "./node_modules/raven-js/src/raven.js":
773 /*!********************************************!*\
774 !*** ./node_modules/raven-js/src/raven.js ***!
775 \********************************************/
776 /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
777
778 /*global XDomainRequest:false */
779
780 var TraceKit = __webpack_require__(/*! ../vendor/TraceKit/tracekit */ "./node_modules/raven-js/vendor/TraceKit/tracekit.js");
781 var stringify = __webpack_require__(/*! ../vendor/json-stringify-safe/stringify */ "./node_modules/raven-js/vendor/json-stringify-safe/stringify.js");
782 var RavenConfigError = __webpack_require__(/*! ./configError */ "./node_modules/raven-js/src/configError.js");
783
784 var utils = __webpack_require__(/*! ./utils */ "./node_modules/raven-js/src/utils.js");
785 var isError = utils.isError;
786 var isObject = utils.isObject;
787 var isObject = utils.isObject;
788 var isErrorEvent = utils.isErrorEvent;
789 var isUndefined = utils.isUndefined;
790 var isFunction = utils.isFunction;
791 var isString = utils.isString;
792 var isEmptyObject = utils.isEmptyObject;
793 var each = utils.each;
794 var objectMerge = utils.objectMerge;
795 var truncate = utils.truncate;
796 var objectFrozen = utils.objectFrozen;
797 var hasKey = utils.hasKey;
798 var joinRegExp = utils.joinRegExp;
799 var urlencode = utils.urlencode;
800 var uuid4 = utils.uuid4;
801 var htmlTreeAsString = utils.htmlTreeAsString;
802 var isSameException = utils.isSameException;
803 var isSameStacktrace = utils.isSameStacktrace;
804 var parseUrl = utils.parseUrl;
805 var fill = utils.fill;
806
807 var wrapConsoleMethod = (__webpack_require__(/*! ./console */ "./node_modules/raven-js/src/console.js").wrapMethod);
808
809 var dsnKeys = 'source protocol user pass host port path'.split(' '),
810 dsnPattern = /^(?:(\w+):)?\/\/(?:(\w+)(:\w+)?@)?([\w\.-]+)(?::(\d+))?(\/.*)/;
811
812 function now() {
813 return +new Date();
814 }
815
816 // This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)
817 var _window =
818 typeof window !== 'undefined'
819 ? window
820 : typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g : typeof self !== 'undefined' ? self : {};
821 var _document = _window.document;
822 var _navigator = _window.navigator;
823
824 function keepOriginalCallback(original, callback) {
825 return isFunction(callback)
826 ? function(data) {
827 return callback(data, original);
828 }
829 : callback;
830 }
831
832 // First, check for JSON support
833 // If there is no JSON, we no-op the core features of Raven
834 // since JSON is required to encode the payload
835 function Raven() {
836 this._hasJSON = !!(typeof JSON === 'object' && JSON.stringify);
837 // Raven can run in contexts where there's no document (react-native)
838 this._hasDocument = !isUndefined(_document);
839 this._hasNavigator = !isUndefined(_navigator);
840 this._lastCapturedException = null;
841 this._lastData = null;
842 this._lastEventId = null;
843 this._globalServer = null;
844 this._globalKey = null;
845 this._globalProject = null;
846 this._globalContext = {};
847 this._globalOptions = {
848 logger: 'javascript',
849 ignoreErrors: [],
850 ignoreUrls: [],
851 whitelistUrls: [],
852 includePaths: [],
853 collectWindowErrors: true,
854 maxMessageLength: 0,
855
856 // By default, truncates URL values to 250 chars
857 maxUrlLength: 250,
858 stackTraceLimit: 50,
859 autoBreadcrumbs: true,
860 instrument: true,
861 sampleRate: 1
862 };
863 this._ignoreOnError = 0;
864 this._isRavenInstalled = false;
865 this._originalErrorStackTraceLimit = Error.stackTraceLimit;
866 // capture references to window.console *and* all its methods first
867 // before the console plugin has a chance to monkey patch
868 this._originalConsole = _window.console || {};
869 this._originalConsoleMethods = {};
870 this._plugins = [];
871 this._startTime = now();
872 this._wrappedBuiltIns = [];
873 this._breadcrumbs = [];
874 this._lastCapturedEvent = null;
875 this._keypressTimeout;
876 this._location = _window.location;
877 this._lastHref = this._location && this._location.href;
878 this._resetBackoff();
879
880 // eslint-disable-next-line guard-for-in
881 for (var method in this._originalConsole) {
882 this._originalConsoleMethods[method] = this._originalConsole[method];
883 }
884 }
885
886 /*
887 * The core Raven singleton
888 *
889 * @this {Raven}
890 */
891
892 Raven.prototype = {
893 // Hardcode version string so that raven source can be loaded directly via
894 // webpack (using a build step causes webpack #1617). Grunt verifies that
895 // this value matches package.json during build.
896 // See: https://github.com/getsentry/raven-js/issues/465
897 VERSION: '3.19.1',
898
899 debug: false,
900
901 TraceKit: TraceKit, // alias to TraceKit
902
903 /*
904 * Configure Raven with a DSN and extra options
905 *
906 * @param {string} dsn The public Sentry DSN
907 * @param {object} options Set of global options [optional]
908 * @return {Raven}
909 */
910 config: function(dsn, options) {
911 var self = this;
912
913 if (self._globalServer) {
914 this._logDebug('error', 'Error: Raven has already been configured');
915 return self;
916 }
917 if (!dsn) return self;
918
919 var globalOptions = self._globalOptions;
920
921 // merge in options
922 if (options) {
923 each(options, function(key, value) {
924 // tags and extra are special and need to be put into context
925 if (key === 'tags' || key === 'extra' || key === 'user') {
926 self._globalContext[key] = value;
927 } else {
928 globalOptions[key] = value;
929 }
930 });
931 }
932
933 self.setDSN(dsn);
934
935 // "Script error." is hard coded into browsers for errors that it can't read.
936 // this is the result of a script being pulled in from an external domain and CORS.
937 globalOptions.ignoreErrors.push(/^Script error\.?$/);
938 globalOptions.ignoreErrors.push(/^Javascript error: Script error\.? on line 0$/);
939
940 // join regexp rules into one big rule
941 globalOptions.ignoreErrors = joinRegExp(globalOptions.ignoreErrors);
942 globalOptions.ignoreUrls = globalOptions.ignoreUrls.length
943 ? joinRegExp(globalOptions.ignoreUrls)
944 : false;
945 globalOptions.whitelistUrls = globalOptions.whitelistUrls.length
946 ? joinRegExp(globalOptions.whitelistUrls)
947 : false;
948 globalOptions.includePaths = joinRegExp(globalOptions.includePaths);
949 globalOptions.maxBreadcrumbs = Math.max(
950 0,
951 Math.min(globalOptions.maxBreadcrumbs || 100, 100)
952 ); // default and hard limit is 100
953
954 var autoBreadcrumbDefaults = {
955 xhr: true,
956 console: true,
957 dom: true,
958 location: true
959 };
960
961 var autoBreadcrumbs = globalOptions.autoBreadcrumbs;
962 if ({}.toString.call(autoBreadcrumbs) === '[object Object]') {
963 autoBreadcrumbs = objectMerge(autoBreadcrumbDefaults, autoBreadcrumbs);
964 } else if (autoBreadcrumbs !== false) {
965 autoBreadcrumbs = autoBreadcrumbDefaults;
966 }
967 globalOptions.autoBreadcrumbs = autoBreadcrumbs;
968
969 var instrumentDefaults = {
970 tryCatch: true
971 };
972
973 var instrument = globalOptions.instrument;
974 if ({}.toString.call(instrument) === '[object Object]') {
975 instrument = objectMerge(instrumentDefaults, instrument);
976 } else if (instrument !== false) {
977 instrument = instrumentDefaults;
978 }
979 globalOptions.instrument = instrument;
980
981 TraceKit.collectWindowErrors = !!globalOptions.collectWindowErrors;
982
983 // return for chaining
984 return self;
985 },
986
987 /*
988 * Installs a global window.onerror error handler
989 * to capture and report uncaught exceptions.
990 * At this point, install() is required to be called due
991 * to the way TraceKit is set up.
992 *
993 * @return {Raven}
994 */
995 install: function() {
996 var self = this;
997 if (self.isSetup() && !self._isRavenInstalled) {
998 TraceKit.report.subscribe(function() {
999 self._handleOnErrorStackInfo.apply(self, arguments);
1000 });
1001 if (self._globalOptions.instrument && self._globalOptions.instrument.tryCatch) {
1002 self._instrumentTryCatch();
1003 }
1004
1005 if (self._globalOptions.autoBreadcrumbs) self._instrumentBreadcrumbs();
1006
1007 // Install all of the plugins
1008 self._drainPlugins();
1009
1010 self._isRavenInstalled = true;
1011 }
1012
1013 Error.stackTraceLimit = self._globalOptions.stackTraceLimit;
1014 return this;
1015 },
1016
1017 /*
1018 * Set the DSN (can be called multiple time unlike config)
1019 *
1020 * @param {string} dsn The public Sentry DSN
1021 */
1022 setDSN: function(dsn) {
1023 var self = this,
1024 uri = self._parseDSN(dsn),
1025 lastSlash = uri.path.lastIndexOf('/'),
1026 path = uri.path.substr(1, lastSlash);
1027
1028 self._dsn = dsn;
1029 self._globalKey = uri.user;
1030 self._globalSecret = uri.pass && uri.pass.substr(1);
1031 self._globalProject = uri.path.substr(lastSlash + 1);
1032
1033 self._globalServer = self._getGlobalServer(uri);
1034
1035 self._globalEndpoint =
1036 self._globalServer + '/' + path + 'api/' + self._globalProject + '/store/';
1037
1038 // Reset backoff state since we may be pointing at a
1039 // new project/server
1040 this._resetBackoff();
1041 },
1042
1043 /*
1044 * Wrap code within a context so Raven can capture errors
1045 * reliably across domains that is executed immediately.
1046 *
1047 * @param {object} options A specific set of options for this context [optional]
1048 * @param {function} func The callback to be immediately executed within the context
1049 * @param {array} args An array of arguments to be called with the callback [optional]
1050 */
1051 context: function(options, func, args) {
1052 if (isFunction(options)) {
1053 args = func || [];
1054 func = options;
1055 options = undefined;
1056 }
1057
1058 return this.wrap(options, func).apply(this, args);
1059 },
1060
1061 /*
1062 * Wrap code within a context and returns back a new function to be executed
1063 *
1064 * @param {object} options A specific set of options for this context [optional]
1065 * @param {function} func The function to be wrapped in a new context
1066 * @param {function} func A function to call before the try/catch wrapper [optional, private]
1067 * @return {function} The newly wrapped functions with a context
1068 */
1069 wrap: function(options, func, _before) {
1070 var self = this;
1071 // 1 argument has been passed, and it's not a function
1072 // so just return it
1073 if (isUndefined(func) && !isFunction(options)) {
1074 return options;
1075 }
1076
1077 // options is optional
1078 if (isFunction(options)) {
1079 func = options;
1080 options = undefined;
1081 }
1082
1083 // At this point, we've passed along 2 arguments, and the second one
1084 // is not a function either, so we'll just return the second argument.
1085 if (!isFunction(func)) {
1086 return func;
1087 }
1088
1089 // We don't wanna wrap it twice!
1090 try {
1091 if (func.__raven__) {
1092 return func;
1093 }
1094
1095 // If this has already been wrapped in the past, return that
1096 if (func.__raven_wrapper__) {
1097 return func.__raven_wrapper__;
1098 }
1099 } catch (e) {
1100 // Just accessing custom props in some Selenium environments
1101 // can cause a "Permission denied" exception (see raven-js#495).
1102 // Bail on wrapping and return the function as-is (defers to window.onerror).
1103 return func;
1104 }
1105
1106 function wrapped() {
1107 var args = [],
1108 i = arguments.length,
1109 deep = !options || (options && options.deep !== false);
1110
1111 if (_before && isFunction(_before)) {
1112 _before.apply(this, arguments);
1113 }
1114
1115 // Recursively wrap all of a function's arguments that are
1116 // functions themselves.
1117 while (i--) args[i] = deep ? self.wrap(options, arguments[i]) : arguments[i];
1118
1119 try {
1120 // Attempt to invoke user-land function
1121 // NOTE: If you are a Sentry user, and you are seeing this stack frame, it
1122 // means Raven caught an error invoking your application code. This is
1123 // expected behavior and NOT indicative of a bug with Raven.js.
1124 return func.apply(this, args);
1125 } catch (e) {
1126 self._ignoreNextOnError();
1127 self.captureException(e, options);
1128 throw e;
1129 }
1130 }
1131
1132 // copy over properties of the old function
1133 for (var property in func) {
1134 if (hasKey(func, property)) {
1135 wrapped[property] = func[property];
1136 }
1137 }
1138 wrapped.prototype = func.prototype;
1139
1140 func.__raven_wrapper__ = wrapped;
1141 // Signal that this function has been wrapped already
1142 // for both debugging and to prevent it to being wrapped twice
1143 wrapped.__raven__ = true;
1144 wrapped.__inner__ = func;
1145
1146 return wrapped;
1147 },
1148
1149 /*
1150 * Uninstalls the global error handler.
1151 *
1152 * @return {Raven}
1153 */
1154 uninstall: function() {
1155 TraceKit.report.uninstall();
1156
1157 this._restoreBuiltIns();
1158
1159 Error.stackTraceLimit = this._originalErrorStackTraceLimit;
1160 this._isRavenInstalled = false;
1161
1162 return this;
1163 },
1164
1165 /*
1166 * Manually capture an exception and send it over to Sentry
1167 *
1168 * @param {error} ex An exception to be logged
1169 * @param {object} options A specific set of options for this error [optional]
1170 * @return {Raven}
1171 */
1172 captureException: function(ex, options) {
1173 // Cases for sending ex as a message, rather than an exception
1174 var isNotError = !isError(ex);
1175 var isNotErrorEvent = !isErrorEvent(ex);
1176 var isErrorEventWithoutError = isErrorEvent(ex) && !ex.error;
1177
1178 if ((isNotError && isNotErrorEvent) || isErrorEventWithoutError) {
1179 return this.captureMessage(
1180 ex,
1181 objectMerge(
1182 {
1183 trimHeadFrames: 1,
1184 stacktrace: true // if we fall back to captureMessage, default to attempting a new trace
1185 },
1186 options
1187 )
1188 );
1189 }
1190
1191 // Get actual Error from ErrorEvent
1192 if (isErrorEvent(ex)) ex = ex.error;
1193
1194 // Store the raw exception object for potential debugging and introspection
1195 this._lastCapturedException = ex;
1196
1197 // TraceKit.report will re-raise any exception passed to it,
1198 // which means you have to wrap it in try/catch. Instead, we
1199 // can wrap it here and only re-raise if TraceKit.report
1200 // raises an exception different from the one we asked to
1201 // report on.
1202 try {
1203 var stack = TraceKit.computeStackTrace(ex);
1204 this._handleStackInfo(stack, options);
1205 } catch (ex1) {
1206 if (ex !== ex1) {
1207 throw ex1;
1208 }
1209 }
1210
1211 return this;
1212 },
1213
1214 /*
1215 * Manually send a message to Sentry
1216 *
1217 * @param {string} msg A plain message to be captured in Sentry
1218 * @param {object} options A specific set of options for this message [optional]
1219 * @return {Raven}
1220 */
1221 captureMessage: function(msg, options) {
1222 // config() automagically converts ignoreErrors from a list to a RegExp so we need to test for an
1223 // early call; we'll error on the side of logging anything called before configuration since it's
1224 // probably something you should see:
1225 if (
1226 !!this._globalOptions.ignoreErrors.test &&
1227 this._globalOptions.ignoreErrors.test(msg)
1228 ) {
1229 return;
1230 }
1231
1232 options = options || {};
1233
1234 var data = objectMerge(
1235 {
1236 message: msg + '' // Make sure it's actually a string
1237 },
1238 options
1239 );
1240
1241 var ex;
1242 // Generate a "synthetic" stack trace from this point.
1243 // NOTE: If you are a Sentry user, and you are seeing this stack frame, it is NOT indicative
1244 // of a bug with Raven.js. Sentry generates synthetic traces either by configuration,
1245 // or if it catches a thrown object without a "stack" property.
1246 try {
1247 throw new Error(msg);
1248 } catch (ex1) {
1249 ex = ex1;
1250 }
1251
1252 // null exception name so `Error` isn't prefixed to msg
1253 ex.name = null;
1254 var stack = TraceKit.computeStackTrace(ex);
1255
1256 // stack[0] is `throw new Error(msg)` call itself, we are interested in the frame that was just before that, stack[1]
1257 var initialCall = stack.stack[1];
1258
1259 var fileurl = (initialCall && initialCall.url) || '';
1260
1261 if (
1262 !!this._globalOptions.ignoreUrls.test &&
1263 this._globalOptions.ignoreUrls.test(fileurl)
1264 ) {
1265 return;
1266 }
1267
1268 if (
1269 !!this._globalOptions.whitelistUrls.test &&
1270 !this._globalOptions.whitelistUrls.test(fileurl)
1271 ) {
1272 return;
1273 }
1274
1275 if (this._globalOptions.stacktrace || (options && options.stacktrace)) {
1276 options = objectMerge(
1277 {
1278 // fingerprint on msg, not stack trace (legacy behavior, could be
1279 // revisited)
1280 fingerprint: msg,
1281 // since we know this is a synthetic trace, the top N-most frames
1282 // MUST be from Raven.js, so mark them as in_app later by setting
1283 // trimHeadFrames
1284 trimHeadFrames: (options.trimHeadFrames || 0) + 1
1285 },
1286 options
1287 );
1288
1289 var frames = this._prepareFrames(stack, options);
1290 data.stacktrace = {
1291 // Sentry expects frames oldest to newest
1292 frames: frames.reverse()
1293 };
1294 }
1295
1296 // Fire away!
1297 this._send(data);
1298
1299 return this;
1300 },
1301
1302 captureBreadcrumb: function(obj) {
1303 var crumb = objectMerge(
1304 {
1305 timestamp: now() / 1000
1306 },
1307 obj
1308 );
1309
1310 if (isFunction(this._globalOptions.breadcrumbCallback)) {
1311 var result = this._globalOptions.breadcrumbCallback(crumb);
1312
1313 if (isObject(result) && !isEmptyObject(result)) {
1314 crumb = result;
1315 } else if (result === false) {
1316 return this;
1317 }
1318 }
1319
1320 this._breadcrumbs.push(crumb);
1321 if (this._breadcrumbs.length > this._globalOptions.maxBreadcrumbs) {
1322 this._breadcrumbs.shift();
1323 }
1324 return this;
1325 },
1326
1327 addPlugin: function(plugin /*arg1, arg2, ... argN*/) {
1328 var pluginArgs = [].slice.call(arguments, 1);
1329
1330 this._plugins.push([plugin, pluginArgs]);
1331 if (this._isRavenInstalled) {
1332 this._drainPlugins();
1333 }
1334
1335 return this;
1336 },
1337
1338 /*
1339 * Set/clear a user to be sent along with the payload.
1340 *
1341 * @param {object} user An object representing user data [optional]
1342 * @return {Raven}
1343 */
1344 setUserContext: function(user) {
1345 // Intentionally do not merge here since that's an unexpected behavior.
1346 this._globalContext.user = user;
1347
1348 return this;
1349 },
1350
1351 /*
1352 * Merge extra attributes to be sent along with the payload.
1353 *
1354 * @param {object} extra An object representing extra data [optional]
1355 * @return {Raven}
1356 */
1357 setExtraContext: function(extra) {
1358 this._mergeContext('extra', extra);
1359
1360 return this;
1361 },
1362
1363 /*
1364 * Merge tags to be sent along with the payload.
1365 *
1366 * @param {object} tags An object representing tags [optional]
1367 * @return {Raven}
1368 */
1369 setTagsContext: function(tags) {
1370 this._mergeContext('tags', tags);
1371
1372 return this;
1373 },
1374
1375 /*
1376 * Clear all of the context.
1377 *
1378 * @return {Raven}
1379 */
1380 clearContext: function() {
1381 this._globalContext = {};
1382
1383 return this;
1384 },
1385
1386 /*
1387 * Get a copy of the current context. This cannot be mutated.
1388 *
1389 * @return {object} copy of context
1390 */
1391 getContext: function() {
1392 // lol javascript
1393 return JSON.parse(stringify(this._globalContext));
1394 },
1395
1396 /*
1397 * Set environment of application
1398 *
1399 * @param {string} environment Typically something like 'production'.
1400 * @return {Raven}
1401 */
1402 setEnvironment: function(environment) {
1403 this._globalOptions.environment = environment;
1404
1405 return this;
1406 },
1407
1408 /*
1409 * Set release version of application
1410 *
1411 * @param {string} release Typically something like a git SHA to identify version
1412 * @return {Raven}
1413 */
1414 setRelease: function(release) {
1415 this._globalOptions.release = release;
1416
1417 return this;
1418 },
1419
1420 /*
1421 * Set the dataCallback option
1422 *
1423 * @param {function} callback The callback to run which allows the
1424 * data blob to be mutated before sending
1425 * @return {Raven}
1426 */
1427 setDataCallback: function(callback) {
1428 var original = this._globalOptions.dataCallback;
1429 this._globalOptions.dataCallback = keepOriginalCallback(original, callback);
1430 return this;
1431 },
1432
1433 /*
1434 * Set the breadcrumbCallback option
1435 *
1436 * @param {function} callback The callback to run which allows filtering
1437 * or mutating breadcrumbs
1438 * @return {Raven}
1439 */
1440 setBreadcrumbCallback: function(callback) {
1441 var original = this._globalOptions.breadcrumbCallback;
1442 this._globalOptions.breadcrumbCallback = keepOriginalCallback(original, callback);
1443 return this;
1444 },
1445
1446 /*
1447 * Set the shouldSendCallback option
1448 *
1449 * @param {function} callback The callback to run which allows
1450 * introspecting the blob before sending
1451 * @return {Raven}
1452 */
1453 setShouldSendCallback: function(callback) {
1454 var original = this._globalOptions.shouldSendCallback;
1455 this._globalOptions.shouldSendCallback = keepOriginalCallback(original, callback);
1456 return this;
1457 },
1458
1459 /**
1460 * Override the default HTTP transport mechanism that transmits data
1461 * to the Sentry server.
1462 *
1463 * @param {function} transport Function invoked instead of the default
1464 * `makeRequest` handler.
1465 *
1466 * @return {Raven}
1467 */
1468 setTransport: function(transport) {
1469 this._globalOptions.transport = transport;
1470
1471 return this;
1472 },
1473
1474 /*
1475 * Get the latest raw exception that was captured by Raven.
1476 *
1477 * @return {error}
1478 */
1479 lastException: function() {
1480 return this._lastCapturedException;
1481 },
1482
1483 /*
1484 * Get the last event id
1485 *
1486 * @return {string}
1487 */
1488 lastEventId: function() {
1489 return this._lastEventId;
1490 },
1491
1492 /*
1493 * Determine if Raven is setup and ready to go.
1494 *
1495 * @return {boolean}
1496 */
1497 isSetup: function() {
1498 if (!this._hasJSON) return false; // needs JSON support
1499 if (!this._globalServer) {
1500 if (!this.ravenNotConfiguredError) {
1501 this.ravenNotConfiguredError = true;
1502 this._logDebug('error', 'Error: Raven has not been configured.');
1503 }
1504 return false;
1505 }
1506 return true;
1507 },
1508
1509 afterLoad: function() {
1510 // TODO: remove window dependence?
1511
1512 // Attempt to initialize Raven on load
1513 var RavenConfig = _window.RavenConfig;
1514 if (RavenConfig) {
1515 this.config(RavenConfig.dsn, RavenConfig.config).install();
1516 }
1517 },
1518
1519 showReportDialog: function(options) {
1520 if (
1521 !_document // doesn't work without a document (React native)
1522 )
1523 return;
1524
1525 options = options || {};
1526
1527 var lastEventId = options.eventId || this.lastEventId();
1528 if (!lastEventId) {
1529 throw new RavenConfigError('Missing eventId');
1530 }
1531
1532 var dsn = options.dsn || this._dsn;
1533 if (!dsn) {
1534 throw new RavenConfigError('Missing DSN');
1535 }
1536
1537 var encode = encodeURIComponent;
1538 var qs = '';
1539 qs += '?eventId=' + encode(lastEventId);
1540 qs += '&dsn=' + encode(dsn);
1541
1542 var user = options.user || this._globalContext.user;
1543 if (user) {
1544 if (user.name) qs += '&name=' + encode(user.name);
1545 if (user.email) qs += '&email=' + encode(user.email);
1546 }
1547
1548 var globalServer = this._getGlobalServer(this._parseDSN(dsn));
1549
1550 var script = _document.createElement('script');
1551 script.async = true;
1552 script.src = globalServer + '/api/embed/error-page/' + qs;
1553 (_document.head || _document.body).appendChild(script);
1554 },
1555
1556 /**** Private functions ****/
1557 _ignoreNextOnError: function() {
1558 var self = this;
1559 this._ignoreOnError += 1;
1560 setTimeout(function() {
1561 // onerror should trigger before setTimeout
1562 self._ignoreOnError -= 1;
1563 });
1564 },
1565
1566 _triggerEvent: function(eventType, options) {
1567 // NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it
1568 var evt, key;
1569
1570 if (!this._hasDocument) return;
1571
1572 options = options || {};
1573
1574 eventType = 'raven' + eventType.substr(0, 1).toUpperCase() + eventType.substr(1);
1575
1576 if (_document.createEvent) {
1577 evt = _document.createEvent('HTMLEvents');
1578 evt.initEvent(eventType, true, true);
1579 } else {
1580 evt = _document.createEventObject();
1581 evt.eventType = eventType;
1582 }
1583
1584 for (key in options)
1585 if (hasKey(options, key)) {
1586 evt[key] = options[key];
1587 }
1588
1589 if (_document.createEvent) {
1590 // IE9 if standards
1591 _document.dispatchEvent(evt);
1592 } else {
1593 // IE8 regardless of Quirks or Standards
1594 // IE9 if quirks
1595 try {
1596 _document.fireEvent('on' + evt.eventType.toLowerCase(), evt);
1597 } catch (e) {
1598 // Do nothing
1599 }
1600 }
1601 },
1602
1603 /**
1604 * Wraps addEventListener to capture UI breadcrumbs
1605 * @param evtName the event name (e.g. "click")
1606 * @returns {Function}
1607 * @private
1608 */
1609 _breadcrumbEventHandler: function(evtName) {
1610 var self = this;
1611 return function(evt) {
1612 // reset keypress timeout; e.g. triggering a 'click' after
1613 // a 'keypress' will reset the keypress debounce so that a new
1614 // set of keypresses can be recorded
1615 self._keypressTimeout = null;
1616
1617 // It's possible this handler might trigger multiple times for the same
1618 // event (e.g. event propagation through node ancestors). Ignore if we've
1619 // already captured the event.
1620 if (self._lastCapturedEvent === evt) return;
1621
1622 self._lastCapturedEvent = evt;
1623
1624 // try/catch both:
1625 // - accessing evt.target (see getsentry/raven-js#838, #768)
1626 // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly
1627 // can throw an exception in some circumstances.
1628 var target;
1629 try {
1630 target = htmlTreeAsString(evt.target);
1631 } catch (e) {
1632 target = '<unknown>';
1633 }
1634
1635 self.captureBreadcrumb({
1636 category: 'ui.' + evtName, // e.g. ui.click, ui.input
1637 message: target
1638 });
1639 };
1640 },
1641
1642 /**
1643 * Wraps addEventListener to capture keypress UI events
1644 * @returns {Function}
1645 * @private
1646 */
1647 _keypressEventHandler: function() {
1648 var self = this,
1649 debounceDuration = 1000; // milliseconds
1650
1651 // TODO: if somehow user switches keypress target before
1652 // debounce timeout is triggered, we will only capture
1653 // a single breadcrumb from the FIRST target (acceptable?)
1654 return function(evt) {
1655 var target;
1656 try {
1657 target = evt.target;
1658 } catch (e) {
1659 // just accessing event properties can throw an exception in some rare circumstances
1660 // see: https://github.com/getsentry/raven-js/issues/838
1661 return;
1662 }
1663 var tagName = target && target.tagName;
1664
1665 // only consider keypress events on actual input elements
1666 // this will disregard keypresses targeting body (e.g. tabbing
1667 // through elements, hotkeys, etc)
1668 if (
1669 !tagName ||
1670 (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && !target.isContentEditable)
1671 )
1672 return;
1673
1674 // record first keypress in a series, but ignore subsequent
1675 // keypresses until debounce clears
1676 var timeout = self._keypressTimeout;
1677 if (!timeout) {
1678 self._breadcrumbEventHandler('input')(evt);
1679 }
1680 clearTimeout(timeout);
1681 self._keypressTimeout = setTimeout(function() {
1682 self._keypressTimeout = null;
1683 }, debounceDuration);
1684 };
1685 },
1686
1687 /**
1688 * Captures a breadcrumb of type "navigation", normalizing input URLs
1689 * @param to the originating URL
1690 * @param from the target URL
1691 * @private
1692 */
1693 _captureUrlChange: function(from, to) {
1694 var parsedLoc = parseUrl(this._location.href);
1695 var parsedTo = parseUrl(to);
1696 var parsedFrom = parseUrl(from);
1697
1698 // because onpopstate only tells you the "new" (to) value of location.href, and
1699 // not the previous (from) value, we need to track the value of the current URL
1700 // state ourselves
1701 this._lastHref = to;
1702
1703 // Use only the path component of the URL if the URL matches the current
1704 // document (almost all the time when using pushState)
1705 if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host)
1706 to = parsedTo.relative;
1707 if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host)
1708 from = parsedFrom.relative;
1709
1710 this.captureBreadcrumb({
1711 category: 'navigation',
1712 data: {
1713 to: to,
1714 from: from
1715 }
1716 });
1717 },
1718
1719 /**
1720 * Wrap timer functions and event targets to catch errors and provide
1721 * better metadata.
1722 */
1723 _instrumentTryCatch: function() {
1724 var self = this;
1725
1726 var wrappedBuiltIns = self._wrappedBuiltIns;
1727
1728 function wrapTimeFn(orig) {
1729 return function(fn, t) {
1730 // preserve arity
1731 // Make a copy of the arguments to prevent deoptimization
1732 // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
1733 var args = new Array(arguments.length);
1734 for (var i = 0; i < args.length; ++i) {
1735 args[i] = arguments[i];
1736 }
1737 var originalCallback = args[0];
1738 if (isFunction(originalCallback)) {
1739 args[0] = self.wrap(originalCallback);
1740 }
1741
1742 // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it
1743 // also supports only two arguments and doesn't care what this is, so we
1744 // can just call the original function directly.
1745 if (orig.apply) {
1746 return orig.apply(this, args);
1747 } else {
1748 return orig(args[0], args[1]);
1749 }
1750 };
1751 }
1752
1753 var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;
1754
1755 function wrapEventTarget(global) {
1756 var proto = _window[global] && _window[global].prototype;
1757 if (proto && proto.hasOwnProperty && proto.hasOwnProperty('addEventListener')) {
1758 fill(
1759 proto,
1760 'addEventListener',
1761 function(orig) {
1762 return function(evtName, fn, capture, secure) {
1763 // preserve arity
1764 try {
1765 if (fn && fn.handleEvent) {
1766 fn.handleEvent = self.wrap(fn.handleEvent);
1767 }
1768 } catch (err) {
1769 // can sometimes get 'Permission denied to access property "handle Event'
1770 }
1771
1772 // More breadcrumb DOM capture ... done here and not in `_instrumentBreadcrumbs`
1773 // so that we don't have more than one wrapper function
1774 var before, clickHandler, keypressHandler;
1775
1776 if (
1777 autoBreadcrumbs &&
1778 autoBreadcrumbs.dom &&
1779 (global === 'EventTarget' || global === 'Node')
1780 ) {
1781 // NOTE: generating multiple handlers per addEventListener invocation, should
1782 // revisit and verify we can just use one (almost certainly)
1783 clickHandler = self._breadcrumbEventHandler('click');
1784 keypressHandler = self._keypressEventHandler();
1785 before = function(evt) {
1786 // need to intercept every DOM event in `before` argument, in case that
1787 // same wrapped method is re-used for different events (e.g. mousemove THEN click)
1788 // see #724
1789 if (!evt) return;
1790
1791 var eventType;
1792 try {
1793 eventType = evt.type;
1794 } catch (e) {
1795 // just accessing event properties can throw an exception in some rare circumstances
1796 // see: https://github.com/getsentry/raven-js/issues/838
1797 return;
1798 }
1799 if (eventType === 'click') return clickHandler(evt);
1800 else if (eventType === 'keypress') return keypressHandler(evt);
1801 };
1802 }
1803 return orig.call(
1804 this,
1805 evtName,
1806 self.wrap(fn, undefined, before),
1807 capture,
1808 secure
1809 );
1810 };
1811 },
1812 wrappedBuiltIns
1813 );
1814 fill(
1815 proto,
1816 'removeEventListener',
1817 function(orig) {
1818 return function(evt, fn, capture, secure) {
1819 try {
1820 fn = fn && (fn.__raven_wrapper__ ? fn.__raven_wrapper__ : fn);
1821 } catch (e) {
1822 // ignore, accessing __raven_wrapper__ will throw in some Selenium environments
1823 }
1824 return orig.call(this, evt, fn, capture, secure);
1825 };
1826 },
1827 wrappedBuiltIns
1828 );
1829 }
1830 }
1831
1832 fill(_window, 'setTimeout', wrapTimeFn, wrappedBuiltIns);
1833 fill(_window, 'setInterval', wrapTimeFn, wrappedBuiltIns);
1834 if (_window.requestAnimationFrame) {
1835 fill(
1836 _window,
1837 'requestAnimationFrame',
1838 function(orig) {
1839 return function(cb) {
1840 return orig(self.wrap(cb));
1841 };
1842 },
1843 wrappedBuiltIns
1844 );
1845 }
1846
1847 // event targets borrowed from bugsnag-js:
1848 // https://github.com/bugsnag/bugsnag-js/blob/master/src/bugsnag.js#L666
1849 var eventTargets = [
1850 'EventTarget',
1851 'Window',
1852 'Node',
1853 'ApplicationCache',
1854 'AudioTrackList',
1855 'ChannelMergerNode',
1856 'CryptoOperation',
1857 'EventSource',
1858 'FileReader',
1859 'HTMLUnknownElement',
1860 'IDBDatabase',
1861 'IDBRequest',
1862 'IDBTransaction',
1863 'KeyOperation',
1864 'MediaController',
1865 'MessagePort',
1866 'ModalWindow',
1867 'Notification',
1868 'SVGElementInstance',
1869 'Screen',
1870 'TextTrack',
1871 'TextTrackCue',
1872 'TextTrackList',
1873 'WebSocket',
1874 'WebSocketWorker',
1875 'Worker',
1876 'XMLHttpRequest',
1877 'XMLHttpRequestEventTarget',
1878 'XMLHttpRequestUpload'
1879 ];
1880 for (var i = 0; i < eventTargets.length; i++) {
1881 wrapEventTarget(eventTargets[i]);
1882 }
1883 },
1884
1885 /**
1886 * Instrument browser built-ins w/ breadcrumb capturing
1887 * - XMLHttpRequests
1888 * - DOM interactions (click/typing)
1889 * - window.location changes
1890 * - console
1891 *
1892 * Can be disabled or individually configured via the `autoBreadcrumbs` config option
1893 */
1894 _instrumentBreadcrumbs: function() {
1895 var self = this;
1896 var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs;
1897
1898 var wrappedBuiltIns = self._wrappedBuiltIns;
1899
1900 function wrapProp(prop, xhr) {
1901 if (prop in xhr && isFunction(xhr[prop])) {
1902 fill(xhr, prop, function(orig) {
1903 return self.wrap(orig);
1904 }); // intentionally don't track filled methods on XHR instances
1905 }
1906 }
1907
1908 if (autoBreadcrumbs.xhr && 'XMLHttpRequest' in _window) {
1909 var xhrproto = XMLHttpRequest.prototype;
1910 fill(
1911 xhrproto,
1912 'open',
1913 function(origOpen) {
1914 return function(method, url) {
1915 // preserve arity
1916
1917 // if Sentry key appears in URL, don't capture
1918 if (isString(url) && url.indexOf(self._globalKey) === -1) {
1919 this.__raven_xhr = {
1920 method: method,
1921 url: url,
1922 status_code: null
1923 };
1924 }
1925
1926 return origOpen.apply(this, arguments);
1927 };
1928 },
1929 wrappedBuiltIns
1930 );
1931
1932 fill(
1933 xhrproto,
1934 'send',
1935 function(origSend) {
1936 return function(data) {
1937 // preserve arity
1938 var xhr = this;
1939
1940 function onreadystatechangeHandler() {
1941 if (xhr.__raven_xhr && xhr.readyState === 4) {
1942 try {
1943 // touching statusCode in some platforms throws
1944 // an exception
1945 xhr.__raven_xhr.status_code = xhr.status;
1946 } catch (e) {
1947 /* do nothing */
1948 }
1949
1950 self.captureBreadcrumb({
1951 type: 'http',
1952 category: 'xhr',
1953 data: xhr.__raven_xhr
1954 });
1955 }
1956 }
1957
1958 var props = ['onload', 'onerror', 'onprogress'];
1959 for (var j = 0; j < props.length; j++) {
1960 wrapProp(props[j], xhr);
1961 }
1962
1963 if ('onreadystatechange' in xhr && isFunction(xhr.onreadystatechange)) {
1964 fill(
1965 xhr,
1966 'onreadystatechange',
1967 function(orig) {
1968 return self.wrap(orig, undefined, onreadystatechangeHandler);
1969 } /* intentionally don't track this instrumentation */
1970 );
1971 } else {
1972 // if onreadystatechange wasn't actually set by the page on this xhr, we
1973 // are free to set our own and capture the breadcrumb
1974 xhr.onreadystatechange = onreadystatechangeHandler;
1975 }
1976
1977 return origSend.apply(this, arguments);
1978 };
1979 },
1980 wrappedBuiltIns
1981 );
1982 }
1983
1984 if (autoBreadcrumbs.xhr && 'fetch' in _window) {
1985 fill(
1986 _window,
1987 'fetch',
1988 function(origFetch) {
1989 return function(fn, t) {
1990 // preserve arity
1991 // Make a copy of the arguments to prevent deoptimization
1992 // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
1993 var args = new Array(arguments.length);
1994 for (var i = 0; i < args.length; ++i) {
1995 args[i] = arguments[i];
1996 }
1997
1998 var fetchInput = args[0];
1999 var method = 'GET';
2000 var url;
2001
2002 if (typeof fetchInput === 'string') {
2003 url = fetchInput;
2004 } else if ('Request' in _window && fetchInput instanceof _window.Request) {
2005 url = fetchInput.url;
2006 if (fetchInput.method) {
2007 method = fetchInput.method;
2008 }
2009 } else {
2010 url = '' + fetchInput;
2011 }
2012
2013 if (args[1] && args[1].method) {
2014 method = args[1].method;
2015 }
2016
2017 var fetchData = {
2018 method: method,
2019 url: url,
2020 status_code: null
2021 };
2022
2023 self.captureBreadcrumb({
2024 type: 'http',
2025 category: 'fetch',
2026 data: fetchData
2027 });
2028
2029 return origFetch.apply(this, args).then(function(response) {
2030 fetchData.status_code = response.status;
2031
2032 return response;
2033 });
2034 };
2035 },
2036 wrappedBuiltIns
2037 );
2038 }
2039
2040 // Capture breadcrumbs from any click that is unhandled / bubbled up all the way
2041 // to the document. Do this before we instrument addEventListener.
2042 if (autoBreadcrumbs.dom && this._hasDocument) {
2043 if (_document.addEventListener) {
2044 _document.addEventListener('click', self._breadcrumbEventHandler('click'), false);
2045 _document.addEventListener('keypress', self._keypressEventHandler(), false);
2046 } else {
2047 // IE8 Compatibility
2048 _document.attachEvent('onclick', self._breadcrumbEventHandler('click'));
2049 _document.attachEvent('onkeypress', self._keypressEventHandler());
2050 }
2051 }
2052
2053 // record navigation (URL) changes
2054 // NOTE: in Chrome App environment, touching history.pushState, *even inside
2055 // a try/catch block*, will cause Chrome to output an error to console.error
2056 // borrowed from: https://github.com/angular/angular.js/pull/13945/files
2057 var chrome = _window.chrome;
2058 var isChromePackagedApp = chrome && chrome.app && chrome.app.runtime;
2059 var hasPushAndReplaceState =
2060 !isChromePackagedApp &&
2061 _window.history &&
2062 history.pushState &&
2063 history.replaceState;
2064 if (autoBreadcrumbs.location && hasPushAndReplaceState) {
2065 // TODO: remove onpopstate handler on uninstall()
2066 var oldOnPopState = _window.onpopstate;
2067 _window.onpopstate = function() {
2068 var currentHref = self._location.href;
2069 self._captureUrlChange(self._lastHref, currentHref);
2070
2071 if (oldOnPopState) {
2072 return oldOnPopState.apply(this, arguments);
2073 }
2074 };
2075
2076 var historyReplacementFunction = function(origHistFunction) {
2077 // note history.pushState.length is 0; intentionally not declaring
2078 // params to preserve 0 arity
2079 return function(/* state, title, url */) {
2080 var url = arguments.length > 2 ? arguments[2] : undefined;
2081
2082 // url argument is optional
2083 if (url) {
2084 // coerce to string (this is what pushState does)
2085 self._captureUrlChange(self._lastHref, url + '');
2086 }
2087
2088 return origHistFunction.apply(this, arguments);
2089 };
2090 };
2091
2092 fill(history, 'pushState', historyReplacementFunction, wrappedBuiltIns);
2093 fill(history, 'replaceState', historyReplacementFunction, wrappedBuiltIns);
2094 }
2095
2096 if (autoBreadcrumbs.console && 'console' in _window && console.log) {
2097 // console
2098 var consoleMethodCallback = function(msg, data) {
2099 self.captureBreadcrumb({
2100 message: msg,
2101 level: data.level,
2102 category: 'console'
2103 });
2104 };
2105
2106 each(['debug', 'info', 'warn', 'error', 'log'], function(_, level) {
2107 wrapConsoleMethod(console, level, consoleMethodCallback);
2108 });
2109 }
2110 },
2111
2112 _restoreBuiltIns: function() {
2113 // restore any wrapped builtins
2114 var builtin;
2115 while (this._wrappedBuiltIns.length) {
2116 builtin = this._wrappedBuiltIns.shift();
2117
2118 var obj = builtin[0],
2119 name = builtin[1],
2120 orig = builtin[2];
2121
2122 obj[name] = orig;
2123 }
2124 },
2125
2126 _drainPlugins: function() {
2127 var self = this;
2128
2129 // FIX ME TODO
2130 each(this._plugins, function(_, plugin) {
2131 var installer = plugin[0];
2132 var args = plugin[1];
2133 installer.apply(self, [self].concat(args));
2134 });
2135 },
2136
2137 _parseDSN: function(str) {
2138 var m = dsnPattern.exec(str),
2139 dsn = {},
2140 i = 7;
2141
2142 try {
2143 while (i--) dsn[dsnKeys[i]] = m[i] || '';
2144 } catch (e) {
2145 throw new RavenConfigError('Invalid DSN: ' + str);
2146 }
2147
2148 if (dsn.pass && !this._globalOptions.allowSecretKey) {
2149 throw new RavenConfigError(
2150 'Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key'
2151 );
2152 }
2153
2154 return dsn;
2155 },
2156
2157 _getGlobalServer: function(uri) {
2158 // assemble the endpoint from the uri pieces
2159 var globalServer = '//' + uri.host + (uri.port ? ':' + uri.port : '');
2160
2161 if (uri.protocol) {
2162 globalServer = uri.protocol + ':' + globalServer;
2163 }
2164 return globalServer;
2165 },
2166
2167 _handleOnErrorStackInfo: function() {
2168 // if we are intentionally ignoring errors via onerror, bail out
2169 if (!this._ignoreOnError) {
2170 this._handleStackInfo.apply(this, arguments);
2171 }
2172 },
2173
2174 _handleStackInfo: function(stackInfo, options) {
2175 var frames = this._prepareFrames(stackInfo, options);
2176
2177 this._triggerEvent('handle', {
2178 stackInfo: stackInfo,
2179 options: options
2180 });
2181
2182 this._processException(
2183 stackInfo.name,
2184 stackInfo.message,
2185 stackInfo.url,
2186 stackInfo.lineno,
2187 frames,
2188 options
2189 );
2190 },
2191
2192 _prepareFrames: function(stackInfo, options) {
2193 var self = this;
2194 var frames = [];
2195 if (stackInfo.stack && stackInfo.stack.length) {
2196 each(stackInfo.stack, function(i, stack) {
2197 var frame = self._normalizeFrame(stack, stackInfo.url);
2198 if (frame) {
2199 frames.push(frame);
2200 }
2201 });
2202
2203 // e.g. frames captured via captureMessage throw
2204 if (options && options.trimHeadFrames) {
2205 for (var j = 0; j < options.trimHeadFrames && j < frames.length; j++) {
2206 frames[j].in_app = false;
2207 }
2208 }
2209 }
2210 frames = frames.slice(0, this._globalOptions.stackTraceLimit);
2211 return frames;
2212 },
2213
2214 _normalizeFrame: function(frame, stackInfoUrl) {
2215 // normalize the frames data
2216 var normalized = {
2217 filename: frame.url,
2218 lineno: frame.line,
2219 colno: frame.column,
2220 function: frame.func || '?'
2221 };
2222
2223 // Case when we don't have any information about the error
2224 // E.g. throwing a string or raw object, instead of an `Error` in Firefox
2225 // Generating synthetic error doesn't add any value here
2226 //
2227 // We should probably somehow let a user know that they should fix their code
2228 if (!frame.url) {
2229 normalized.filename = stackInfoUrl; // fallback to whole stacks url from onerror handler
2230 }
2231
2232 normalized.in_app = !// determine if an exception came from outside of our app
2233 // first we check the global includePaths list.
2234 (
2235 (!!this._globalOptions.includePaths.test &&
2236 !this._globalOptions.includePaths.test(normalized.filename)) ||
2237 // Now we check for fun, if the function name is Raven or TraceKit
2238 /(Raven|TraceKit)\./.test(normalized['function']) ||
2239 // finally, we do a last ditch effort and check for raven.min.js
2240 /raven\.(min\.)?js$/.test(normalized.filename)
2241 );
2242
2243 return normalized;
2244 },
2245
2246 _processException: function(type, message, fileurl, lineno, frames, options) {
2247 var prefixedMessage = (type ? type + ': ' : '') + (message || '');
2248 if (
2249 !!this._globalOptions.ignoreErrors.test &&
2250 (this._globalOptions.ignoreErrors.test(message) ||
2251 this._globalOptions.ignoreErrors.test(prefixedMessage))
2252 ) {
2253 return;
2254 }
2255
2256 var stacktrace;
2257
2258 if (frames && frames.length) {
2259 fileurl = frames[0].filename || fileurl;
2260 // Sentry expects frames oldest to newest
2261 // and JS sends them as newest to oldest
2262 frames.reverse();
2263 stacktrace = {frames: frames};
2264 } else if (fileurl) {
2265 stacktrace = {
2266 frames: [
2267 {
2268 filename: fileurl,
2269 lineno: lineno,
2270 in_app: true
2271 }
2272 ]
2273 };
2274 }
2275
2276 if (
2277 !!this._globalOptions.ignoreUrls.test &&
2278 this._globalOptions.ignoreUrls.test(fileurl)
2279 ) {
2280 return;
2281 }
2282
2283 if (
2284 !!this._globalOptions.whitelistUrls.test &&
2285 !this._globalOptions.whitelistUrls.test(fileurl)
2286 ) {
2287 return;
2288 }
2289
2290 var data = objectMerge(
2291 {
2292 // sentry.interfaces.Exception
2293 exception: {
2294 values: [
2295 {
2296 type: type,
2297 value: message,
2298 stacktrace: stacktrace
2299 }
2300 ]
2301 },
2302 culprit: fileurl
2303 },
2304 options
2305 );
2306
2307 // Fire away!
2308 this._send(data);
2309 },
2310
2311 _trimPacket: function(data) {
2312 // For now, we only want to truncate the two different messages
2313 // but this could/should be expanded to just trim everything
2314 var max = this._globalOptions.maxMessageLength;
2315 if (data.message) {
2316 data.message = truncate(data.message, max);
2317 }
2318 if (data.exception) {
2319 var exception = data.exception.values[0];
2320 exception.value = truncate(exception.value, max);
2321 }
2322
2323 var request = data.request;
2324 if (request) {
2325 if (request.url) {
2326 request.url = truncate(request.url, this._globalOptions.maxUrlLength);
2327 }
2328 if (request.Referer) {
2329 request.Referer = truncate(request.Referer, this._globalOptions.maxUrlLength);
2330 }
2331 }
2332
2333 if (data.breadcrumbs && data.breadcrumbs.values)
2334 this._trimBreadcrumbs(data.breadcrumbs);
2335
2336 return data;
2337 },
2338
2339 /**
2340 * Truncate breadcrumb values (right now just URLs)
2341 */
2342 _trimBreadcrumbs: function(breadcrumbs) {
2343 // known breadcrumb properties with urls
2344 // TODO: also consider arbitrary prop values that start with (https?)?://
2345 var urlProps = ['to', 'from', 'url'],
2346 urlProp,
2347 crumb,
2348 data;
2349
2350 for (var i = 0; i < breadcrumbs.values.length; ++i) {
2351 crumb = breadcrumbs.values[i];
2352 if (
2353 !crumb.hasOwnProperty('data') ||
2354 !isObject(crumb.data) ||
2355 objectFrozen(crumb.data)
2356 )
2357 continue;
2358
2359 data = objectMerge({}, crumb.data);
2360 for (var j = 0; j < urlProps.length; ++j) {
2361 urlProp = urlProps[j];
2362 if (data.hasOwnProperty(urlProp) && data[urlProp]) {
2363 data[urlProp] = truncate(data[urlProp], this._globalOptions.maxUrlLength);
2364 }
2365 }
2366 breadcrumbs.values[i].data = data;
2367 }
2368 },
2369
2370 _getHttpData: function() {
2371 if (!this._hasNavigator && !this._hasDocument) return;
2372 var httpData = {};
2373
2374 if (this._hasNavigator && _navigator.userAgent) {
2375 httpData.headers = {
2376 'User-Agent': navigator.userAgent
2377 };
2378 }
2379
2380 if (this._hasDocument) {
2381 if (_document.location && _document.location.href) {
2382 httpData.url = _document.location.href;
2383 }
2384 if (_document.referrer) {
2385 if (!httpData.headers) httpData.headers = {};
2386 httpData.headers.Referer = _document.referrer;
2387 }
2388 }
2389
2390 return httpData;
2391 },
2392
2393 _resetBackoff: function() {
2394 this._backoffDuration = 0;
2395 this._backoffStart = null;
2396 },
2397
2398 _shouldBackoff: function() {
2399 return this._backoffDuration && now() - this._backoffStart < this._backoffDuration;
2400 },
2401
2402 /**
2403 * Returns true if the in-process data payload matches the signature
2404 * of the previously-sent data
2405 *
2406 * NOTE: This has to be done at this level because TraceKit can generate
2407 * data from window.onerror WITHOUT an exception object (IE8, IE9,
2408 * other old browsers). This can take the form of an "exception"
2409 * data object with a single frame (derived from the onerror args).
2410 */
2411 _isRepeatData: function(current) {
2412 var last = this._lastData;
2413
2414 if (
2415 !last ||
2416 current.message !== last.message || // defined for captureMessage
2417 current.culprit !== last.culprit // defined for captureException/onerror
2418 )
2419 return false;
2420
2421 // Stacktrace interface (i.e. from captureMessage)
2422 if (current.stacktrace || last.stacktrace) {
2423 return isSameStacktrace(current.stacktrace, last.stacktrace);
2424 } else if (current.exception || last.exception) {
2425 // Exception interface (i.e. from captureException/onerror)
2426 return isSameException(current.exception, last.exception);
2427 }
2428
2429 return true;
2430 },
2431
2432 _setBackoffState: function(request) {
2433 // If we are already in a backoff state, don't change anything
2434 if (this._shouldBackoff()) {
2435 return;
2436 }
2437
2438 var status = request.status;
2439
2440 // 400 - project_id doesn't exist or some other fatal
2441 // 401 - invalid/revoked dsn
2442 // 429 - too many requests
2443 if (!(status === 400 || status === 401 || status === 429)) return;
2444
2445 var retry;
2446 try {
2447 // If Retry-After is not in Access-Control-Expose-Headers, most
2448 // browsers will throw an exception trying to access it
2449 retry = request.getResponseHeader('Retry-After');
2450 retry = parseInt(retry, 10) * 1000; // Retry-After is returned in seconds
2451 } catch (e) {
2452 /* eslint no-empty:0 */
2453 }
2454
2455 this._backoffDuration = retry
2456 ? // If Sentry server returned a Retry-After value, use it
2457 retry
2458 : // Otherwise, double the last backoff duration (starts at 1 sec)
2459 this._backoffDuration * 2 || 1000;
2460
2461 this._backoffStart = now();
2462 },
2463
2464 _send: function(data) {
2465 var globalOptions = this._globalOptions;
2466
2467 var baseData = {
2468 project: this._globalProject,
2469 logger: globalOptions.logger,
2470 platform: 'javascript'
2471 },
2472 httpData = this._getHttpData();
2473
2474 if (httpData) {
2475 baseData.request = httpData;
2476 }
2477
2478 // HACK: delete `trimHeadFrames` to prevent from appearing in outbound payload
2479 if (data.trimHeadFrames) delete data.trimHeadFrames;
2480
2481 data = objectMerge(baseData, data);
2482
2483 // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge
2484 data.tags = objectMerge(objectMerge({}, this._globalContext.tags), data.tags);
2485 data.extra = objectMerge(objectMerge({}, this._globalContext.extra), data.extra);
2486
2487 // Send along our own collected metadata with extra
2488 data.extra['session:duration'] = now() - this._startTime;
2489
2490 if (this._breadcrumbs && this._breadcrumbs.length > 0) {
2491 // intentionally make shallow copy so that additions
2492 // to breadcrumbs aren't accidentally sent in this request
2493 data.breadcrumbs = {
2494 values: [].slice.call(this._breadcrumbs, 0)
2495 };
2496 }
2497
2498 // If there are no tags/extra, strip the key from the payload alltogther.
2499 if (isEmptyObject(data.tags)) delete data.tags;
2500
2501 if (this._globalContext.user) {
2502 // sentry.interfaces.User
2503 data.user = this._globalContext.user;
2504 }
2505
2506 // Include the environment if it's defined in globalOptions
2507 if (globalOptions.environment) data.environment = globalOptions.environment;
2508
2509 // Include the release if it's defined in globalOptions
2510 if (globalOptions.release) data.release = globalOptions.release;
2511
2512 // Include server_name if it's defined in globalOptions
2513 if (globalOptions.serverName) data.server_name = globalOptions.serverName;
2514
2515 if (isFunction(globalOptions.dataCallback)) {
2516 data = globalOptions.dataCallback(data) || data;
2517 }
2518
2519 // Why??????????
2520 if (!data || isEmptyObject(data)) {
2521 return;
2522 }
2523
2524 // Check if the request should be filtered or not
2525 if (
2526 isFunction(globalOptions.shouldSendCallback) &&
2527 !globalOptions.shouldSendCallback(data)
2528 ) {
2529 return;
2530 }
2531
2532 // Backoff state: Sentry server previously responded w/ an error (e.g. 429 - too many requests),
2533 // so drop requests until "cool-off" period has elapsed.
2534 if (this._shouldBackoff()) {
2535 this._logDebug('warn', 'Raven dropped error due to backoff: ', data);
2536 return;
2537 }
2538
2539 if (typeof globalOptions.sampleRate === 'number') {
2540 if (Math.random() < globalOptions.sampleRate) {
2541 this._sendProcessedPayload(data);
2542 }
2543 } else {
2544 this._sendProcessedPayload(data);
2545 }
2546 },
2547
2548 _getUuid: function() {
2549 return uuid4();
2550 },
2551
2552 _sendProcessedPayload: function(data, callback) {
2553 var self = this;
2554 var globalOptions = this._globalOptions;
2555
2556 if (!this.isSetup()) return;
2557
2558 // Try and clean up the packet before sending by truncating long values
2559 data = this._trimPacket(data);
2560
2561 // ideally duplicate error testing should occur *before* dataCallback/shouldSendCallback,
2562 // but this would require copying an un-truncated copy of the data packet, which can be
2563 // arbitrarily deep (extra_data) -- could be worthwhile? will revisit
2564 if (!this._globalOptions.allowDuplicates && this._isRepeatData(data)) {
2565 this._logDebug('warn', 'Raven dropped repeat event: ', data);
2566 return;
2567 }
2568
2569 // Send along an event_id if not explicitly passed.
2570 // This event_id can be used to reference the error within Sentry itself.
2571 // Set lastEventId after we know the error should actually be sent
2572 this._lastEventId = data.event_id || (data.event_id = this._getUuid());
2573
2574 // Store outbound payload after trim
2575 this._lastData = data;
2576
2577 this._logDebug('debug', 'Raven about to send:', data);
2578
2579 var auth = {
2580 sentry_version: '7',
2581 sentry_client: 'raven-js/' + this.VERSION,
2582 sentry_key: this._globalKey
2583 };
2584
2585 if (this._globalSecret) {
2586 auth.sentry_secret = this._globalSecret;
2587 }
2588
2589 var exception = data.exception && data.exception.values[0];
2590 this.captureBreadcrumb({
2591 category: 'sentry',
2592 message: exception
2593 ? (exception.type ? exception.type + ': ' : '') + exception.value
2594 : data.message,
2595 event_id: data.event_id,
2596 level: data.level || 'error' // presume error unless specified
2597 });
2598
2599 var url = this._globalEndpoint;
2600 (globalOptions.transport || this._makeRequest).call(this, {
2601 url: url,
2602 auth: auth,
2603 data: data,
2604 options: globalOptions,
2605 onSuccess: function success() {
2606 self._resetBackoff();
2607
2608 self._triggerEvent('success', {
2609 data: data,
2610 src: url
2611 });
2612 callback && callback();
2613 },
2614 onError: function failure(error) {
2615 self._logDebug('error', 'Raven transport failed to send: ', error);
2616
2617 if (error.request) {
2618 self._setBackoffState(error.request);
2619 }
2620
2621 self._triggerEvent('failure', {
2622 data: data,
2623 src: url
2624 });
2625 error = error || new Error('Raven send failed (no additional details provided)');
2626 callback && callback(error);
2627 }
2628 });
2629 },
2630
2631 _makeRequest: function(opts) {
2632 var request = _window.XMLHttpRequest && new _window.XMLHttpRequest();
2633 if (!request) return;
2634
2635 // if browser doesn't support CORS (e.g. IE7), we are out of luck
2636 var hasCORS = 'withCredentials' in request || typeof XDomainRequest !== 'undefined';
2637
2638 if (!hasCORS) return;
2639
2640 var url = opts.url;
2641
2642 if ('withCredentials' in request) {
2643 request.onreadystatechange = function() {
2644 if (request.readyState !== 4) {
2645 return;
2646 } else if (request.status === 200) {
2647 opts.onSuccess && opts.onSuccess();
2648 } else if (opts.onError) {
2649 var err = new Error('Sentry error code: ' + request.status);
2650 err.request = request;
2651 opts.onError(err);
2652 }
2653 };
2654 } else {
2655 request = new XDomainRequest();
2656 // xdomainrequest cannot go http -> https (or vice versa),
2657 // so always use protocol relative
2658 url = url.replace(/^https?:/, '');
2659
2660 // onreadystatechange not supported by XDomainRequest
2661 if (opts.onSuccess) {
2662 request.onload = opts.onSuccess;
2663 }
2664 if (opts.onError) {
2665 request.onerror = function() {
2666 var err = new Error('Sentry error code: XDomainRequest');
2667 err.request = request;
2668 opts.onError(err);
2669 };
2670 }
2671 }
2672
2673 // NOTE: auth is intentionally sent as part of query string (NOT as custom
2674 // HTTP header) so as to avoid preflight CORS requests
2675 request.open('POST', url + '?' + urlencode(opts.auth));
2676 request.send(stringify(opts.data));
2677 },
2678
2679 _logDebug: function(level) {
2680 if (this._originalConsoleMethods[level] && this.debug) {
2681 // In IE<10 console methods do not have their own 'apply' method
2682 Function.prototype.apply.call(
2683 this._originalConsoleMethods[level],
2684 this._originalConsole,
2685 [].slice.call(arguments, 1)
2686 );
2687 }
2688 },
2689
2690 _mergeContext: function(key, context) {
2691 if (isUndefined(context)) {
2692 delete this._globalContext[key];
2693 } else {
2694 this._globalContext[key] = objectMerge(this._globalContext[key] || {}, context);
2695 }
2696 }
2697 };
2698
2699 // Deprecations
2700 Raven.prototype.setUser = Raven.prototype.setUserContext;
2701 Raven.prototype.setReleaseContext = Raven.prototype.setRelease;
2702
2703 module.exports = Raven;
2704
2705
2706 /***/ }),
2707
2708 /***/ "./node_modules/raven-js/src/singleton.js":
2709 /*!************************************************!*\
2710 !*** ./node_modules/raven-js/src/singleton.js ***!
2711 \************************************************/
2712 /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
2713
2714 /**
2715 * Enforces a single instance of the Raven client, and the
2716 * main entry point for Raven. If you are a consumer of the
2717 * Raven library, you SHOULD load this file (vs raven.js).
2718 **/
2719
2720 var RavenConstructor = __webpack_require__(/*! ./raven */ "./node_modules/raven-js/src/raven.js");
2721
2722 // This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)
2723 var _window =
2724 typeof window !== 'undefined'
2725 ? window
2726 : typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g : typeof self !== 'undefined' ? self : {};
2727 var _Raven = _window.Raven;
2728
2729 var Raven = new RavenConstructor();
2730
2731 /*
2732 * Allow multiple versions of Raven to be installed.
2733 * Strip Raven from the global context and returns the instance.
2734 *
2735 * @return {Raven}
2736 */
2737 Raven.noConflict = function() {
2738 _window.Raven = _Raven;
2739 return Raven;
2740 };
2741
2742 Raven.afterLoad();
2743
2744 module.exports = Raven;
2745
2746
2747 /***/ }),
2748
2749 /***/ "./node_modules/raven-js/src/utils.js":
2750 /*!********************************************!*\
2751 !*** ./node_modules/raven-js/src/utils.js ***!
2752 \********************************************/
2753 /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
2754
2755 var _window =
2756 typeof window !== 'undefined'
2757 ? window
2758 : typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g : typeof self !== 'undefined' ? self : {};
2759
2760 function isObject(what) {
2761 return typeof what === 'object' && what !== null;
2762 }
2763
2764 // Yanked from https://git.io/vS8DV re-used under CC0
2765 // with some tiny modifications
2766 function isError(value) {
2767 switch ({}.toString.call(value)) {
2768 case '[object Error]':
2769 return true;
2770 case '[object Exception]':
2771 return true;
2772 case '[object DOMException]':
2773 return true;
2774 default:
2775 return value instanceof Error;
2776 }
2777 }
2778
2779 function isErrorEvent(value) {
2780 return supportsErrorEvent() && {}.toString.call(value) === '[object ErrorEvent]';
2781 }
2782
2783 function isUndefined(what) {
2784 return what === void 0;
2785 }
2786
2787 function isFunction(what) {
2788 return typeof what === 'function';
2789 }
2790
2791 function isString(what) {
2792 return Object.prototype.toString.call(what) === '[object String]';
2793 }
2794
2795 function isEmptyObject(what) {
2796 for (var _ in what) return false; // eslint-disable-line guard-for-in, no-unused-vars
2797 return true;
2798 }
2799
2800 function supportsErrorEvent() {
2801 try {
2802 new ErrorEvent(''); // eslint-disable-line no-new
2803 return true;
2804 } catch (e) {
2805 return false;
2806 }
2807 }
2808
2809 function wrappedCallback(callback) {
2810 function dataCallback(data, original) {
2811 var normalizedData = callback(data) || data;
2812 if (original) {
2813 return original(normalizedData) || normalizedData;
2814 }
2815 return normalizedData;
2816 }
2817
2818 return dataCallback;
2819 }
2820
2821 function each(obj, callback) {
2822 var i, j;
2823
2824 if (isUndefined(obj.length)) {
2825 for (i in obj) {
2826 if (hasKey(obj, i)) {
2827 callback.call(null, i, obj[i]);
2828 }
2829 }
2830 } else {
2831 j = obj.length;
2832 if (j) {
2833 for (i = 0; i < j; i++) {
2834 callback.call(null, i, obj[i]);
2835 }
2836 }
2837 }
2838 }
2839
2840 function objectMerge(obj1, obj2) {
2841 if (!obj2) {
2842 return obj1;
2843 }
2844 each(obj2, function(key, value) {
2845 obj1[key] = value;
2846 });
2847 return obj1;
2848 }
2849
2850 /**
2851 * This function is only used for react-native.
2852 * react-native freezes object that have already been sent over the
2853 * js bridge. We need this function in order to check if the object is frozen.
2854 * So it's ok that objectFrozen returns false if Object.isFrozen is not
2855 * supported because it's not relevant for other "platforms". See related issue:
2856 * https://github.com/getsentry/react-native-sentry/issues/57
2857 */
2858 function objectFrozen(obj) {
2859 if (!Object.isFrozen) {
2860 return false;
2861 }
2862 return Object.isFrozen(obj);
2863 }
2864
2865 function truncate(str, max) {
2866 return !max || str.length <= max ? str : str.substr(0, max) + '\u2026';
2867 }
2868
2869 /**
2870 * hasKey, a better form of hasOwnProperty
2871 * Example: hasKey(MainHostObject, property) === true/false
2872 *
2873 * @param {Object} host object to check property
2874 * @param {string} key to check
2875 */
2876 function hasKey(object, key) {
2877 return Object.prototype.hasOwnProperty.call(object, key);
2878 }
2879
2880 function joinRegExp(patterns) {
2881 // Combine an array of regular expressions and strings into one large regexp
2882 // Be mad.
2883 var sources = [],
2884 i = 0,
2885 len = patterns.length,
2886 pattern;
2887
2888 for (; i < len; i++) {
2889 pattern = patterns[i];
2890 if (isString(pattern)) {
2891 // If it's a string, we need to escape it
2892 // Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
2893 sources.push(pattern.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'));
2894 } else if (pattern && pattern.source) {
2895 // If it's a regexp already, we want to extract the source
2896 sources.push(pattern.source);
2897 }
2898 // Intentionally skip other cases
2899 }
2900 return new RegExp(sources.join('|'), 'i');
2901 }
2902
2903 function urlencode(o) {
2904 var pairs = [];
2905 each(o, function(key, value) {
2906 pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
2907 });
2908 return pairs.join('&');
2909 }
2910
2911 // borrowed from https://tools.ietf.org/html/rfc3986#appendix-B
2912 // intentionally using regex and not <a/> href parsing trick because React Native and other
2913 // environments where DOM might not be available
2914 function parseUrl(url) {
2915 var match = url.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/);
2916 if (!match) return {};
2917
2918 // coerce to undefined values to empty string so we don't get 'undefined'
2919 var query = match[6] || '';
2920 var fragment = match[8] || '';
2921 return {
2922 protocol: match[2],
2923 host: match[4],
2924 path: match[5],
2925 relative: match[5] + query + fragment // everything minus origin
2926 };
2927 }
2928 function uuid4() {
2929 var crypto = _window.crypto || _window.msCrypto;
2930
2931 if (!isUndefined(crypto) && crypto.getRandomValues) {
2932 // Use window.crypto API if available
2933 // eslint-disable-next-line no-undef
2934 var arr = new Uint16Array(8);
2935 crypto.getRandomValues(arr);
2936
2937 // set 4 in byte 7
2938 arr[3] = (arr[3] & 0xfff) | 0x4000;
2939 // set 2 most significant bits of byte 9 to '10'
2940 arr[4] = (arr[4] & 0x3fff) | 0x8000;
2941
2942 var pad = function(num) {
2943 var v = num.toString(16);
2944 while (v.length < 4) {
2945 v = '0' + v;
2946 }
2947 return v;
2948 };
2949
2950 return (
2951 pad(arr[0]) +
2952 pad(arr[1]) +
2953 pad(arr[2]) +
2954 pad(arr[3]) +
2955 pad(arr[4]) +
2956 pad(arr[5]) +
2957 pad(arr[6]) +
2958 pad(arr[7])
2959 );
2960 } else {
2961 // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
2962 return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
2963 var r = (Math.random() * 16) | 0,
2964 v = c === 'x' ? r : (r & 0x3) | 0x8;
2965 return v.toString(16);
2966 });
2967 }
2968 }
2969
2970 /**
2971 * Given a child DOM element, returns a query-selector statement describing that
2972 * and its ancestors
2973 * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]
2974 * @param elem
2975 * @returns {string}
2976 */
2977 function htmlTreeAsString(elem) {
2978 /* eslint no-extra-parens:0*/
2979 var MAX_TRAVERSE_HEIGHT = 5,
2980 MAX_OUTPUT_LEN = 80,
2981 out = [],
2982 height = 0,
2983 len = 0,
2984 separator = ' > ',
2985 sepLength = separator.length,
2986 nextStr;
2987
2988 while (elem && height++ < MAX_TRAVERSE_HEIGHT) {
2989 nextStr = htmlElementAsString(elem);
2990 // bail out if
2991 // - nextStr is the 'html' element
2992 // - the length of the string that would be created exceeds MAX_OUTPUT_LEN
2993 // (ignore this limit if we are on the first iteration)
2994 if (
2995 nextStr === 'html' ||
2996 (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN)
2997 ) {
2998 break;
2999 }
3000
3001 out.push(nextStr);
3002
3003 len += nextStr.length;
3004 elem = elem.parentNode;
3005 }
3006
3007 return out.reverse().join(separator);
3008 }
3009
3010 /**
3011 * Returns a simple, query-selector representation of a DOM element
3012 * e.g. [HTMLElement] => input#foo.btn[name=baz]
3013 * @param HTMLElement
3014 * @returns {string}
3015 */
3016 function htmlElementAsString(elem) {
3017 var out = [],
3018 className,
3019 classes,
3020 key,
3021 attr,
3022 i;
3023
3024 if (!elem || !elem.tagName) {
3025 return '';
3026 }
3027
3028 out.push(elem.tagName.toLowerCase());
3029 if (elem.id) {
3030 out.push('#' + elem.id);
3031 }
3032
3033 className = elem.className;
3034 if (className && isString(className)) {
3035 classes = className.split(/\s+/);
3036 for (i = 0; i < classes.length; i++) {
3037 out.push('.' + classes[i]);
3038 }
3039 }
3040 var attrWhitelist = ['type', 'name', 'title', 'alt'];
3041 for (i = 0; i < attrWhitelist.length; i++) {
3042 key = attrWhitelist[i];
3043 attr = elem.getAttribute(key);
3044 if (attr) {
3045 out.push('[' + key + '="' + attr + '"]');
3046 }
3047 }
3048 return out.join('');
3049 }
3050
3051 /**
3052 * Returns true if either a OR b is truthy, but not both
3053 */
3054 function isOnlyOneTruthy(a, b) {
3055 return !!(!!a ^ !!b);
3056 }
3057
3058 /**
3059 * Returns true if the two input exception interfaces have the same content
3060 */
3061 function isSameException(ex1, ex2) {
3062 if (isOnlyOneTruthy(ex1, ex2)) return false;
3063
3064 ex1 = ex1.values[0];
3065 ex2 = ex2.values[0];
3066
3067 if (ex1.type !== ex2.type || ex1.value !== ex2.value) return false;
3068
3069 return isSameStacktrace(ex1.stacktrace, ex2.stacktrace);
3070 }
3071
3072 /**
3073 * Returns true if the two input stack trace interfaces have the same content
3074 */
3075 function isSameStacktrace(stack1, stack2) {
3076 if (isOnlyOneTruthy(stack1, stack2)) return false;
3077
3078 var frames1 = stack1.frames;
3079 var frames2 = stack2.frames;
3080
3081 // Exit early if frame count differs
3082 if (frames1.length !== frames2.length) return false;
3083
3084 // Iterate through every frame; bail out if anything differs
3085 var a, b;
3086 for (var i = 0; i < frames1.length; i++) {
3087 a = frames1[i];
3088 b = frames2[i];
3089 if (
3090 a.filename !== b.filename ||
3091 a.lineno !== b.lineno ||
3092 a.colno !== b.colno ||
3093 a['function'] !== b['function']
3094 )
3095 return false;
3096 }
3097 return true;
3098 }
3099
3100 /**
3101 * Polyfill a method
3102 * @param obj object e.g. `document`
3103 * @param name method name present on object e.g. `addEventListener`
3104 * @param replacement replacement function
3105 * @param track {optional} record instrumentation to an array
3106 */
3107 function fill(obj, name, replacement, track) {
3108 var orig = obj[name];
3109 obj[name] = replacement(orig);
3110 if (track) {
3111 track.push([obj, name, orig]);
3112 }
3113 }
3114
3115 module.exports = {
3116 isObject: isObject,
3117 isError: isError,
3118 isErrorEvent: isErrorEvent,
3119 isUndefined: isUndefined,
3120 isFunction: isFunction,
3121 isString: isString,
3122 isEmptyObject: isEmptyObject,
3123 supportsErrorEvent: supportsErrorEvent,
3124 wrappedCallback: wrappedCallback,
3125 each: each,
3126 objectMerge: objectMerge,
3127 truncate: truncate,
3128 objectFrozen: objectFrozen,
3129 hasKey: hasKey,
3130 joinRegExp: joinRegExp,
3131 urlencode: urlencode,
3132 uuid4: uuid4,
3133 htmlTreeAsString: htmlTreeAsString,
3134 htmlElementAsString: htmlElementAsString,
3135 isSameException: isSameException,
3136 isSameStacktrace: isSameStacktrace,
3137 parseUrl: parseUrl,
3138 fill: fill
3139 };
3140
3141
3142 /***/ }),
3143
3144 /***/ "./node_modules/raven-js/vendor/TraceKit/tracekit.js":
3145 /*!***********************************************************!*\
3146 !*** ./node_modules/raven-js/vendor/TraceKit/tracekit.js ***!
3147 \***********************************************************/
3148 /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
3149
3150 var utils = __webpack_require__(/*! ../../src/utils */ "./node_modules/raven-js/src/utils.js");
3151
3152 /*
3153 TraceKit - Cross brower stack traces
3154
3155 This was originally forked from github.com/occ/TraceKit, but has since been
3156 largely re-written and is now maintained as part of raven-js. Tests for
3157 this are in test/vendor.
3158
3159 MIT license
3160 */
3161
3162 var TraceKit = {
3163 collectWindowErrors: true,
3164 debug: false
3165 };
3166
3167 // This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785)
3168 var _window =
3169 typeof window !== 'undefined'
3170 ? window
3171 : typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g : typeof self !== 'undefined' ? self : {};
3172
3173 // global reference to slice
3174 var _slice = [].slice;
3175 var UNKNOWN_FUNCTION = '?';
3176
3177 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types
3178 var ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/;
3179
3180 function getLocationHref() {
3181 if (typeof document === 'undefined' || document.location == null) return '';
3182
3183 return document.location.href;
3184 }
3185
3186 /**
3187 * TraceKit.report: cross-browser processing of unhandled exceptions
3188 *
3189 * Syntax:
3190 * TraceKit.report.subscribe(function(stackInfo) { ... })
3191 * TraceKit.report.unsubscribe(function(stackInfo) { ... })
3192 * TraceKit.report(exception)
3193 * try { ...code... } catch(ex) { TraceKit.report(ex); }
3194 *
3195 * Supports:
3196 * - Firefox: full stack trace with line numbers, plus column number
3197 * on top frame; column number is not guaranteed
3198 * - Opera: full stack trace with line and column numbers
3199 * - Chrome: full stack trace with line and column numbers
3200 * - Safari: line and column number for the top frame only; some frames
3201 * may be missing, and column number is not guaranteed
3202 * - IE: line and column number for the top frame only; some frames
3203 * may be missing, and column number is not guaranteed
3204 *
3205 * In theory, TraceKit should work on all of the following versions:
3206 * - IE5.5+ (only 8.0 tested)
3207 * - Firefox 0.9+ (only 3.5+ tested)
3208 * - Opera 7+ (only 10.50 tested; versions 9 and earlier may require
3209 * Exceptions Have Stacktrace to be enabled in opera:config)
3210 * - Safari 3+ (only 4+ tested)
3211 * - Chrome 1+ (only 5+ tested)
3212 * - Konqueror 3.5+ (untested)
3213 *
3214 * Requires TraceKit.computeStackTrace.
3215 *
3216 * Tries to catch all unhandled exceptions and report them to the
3217 * subscribed handlers. Please note that TraceKit.report will rethrow the
3218 * exception. This is REQUIRED in order to get a useful stack trace in IE.
3219 * If the exception does not reach the top of the browser, you will only
3220 * get a stack trace from the point where TraceKit.report was called.
3221 *
3222 * Handlers receive a stackInfo object as described in the
3223 * TraceKit.computeStackTrace docs.
3224 */
3225 TraceKit.report = (function reportModuleWrapper() {
3226 var handlers = [],
3227 lastArgs = null,
3228 lastException = null,
3229 lastExceptionStack = null;
3230
3231 /**
3232 * Add a crash handler.
3233 * @param {Function} handler
3234 */
3235 function subscribe(handler) {
3236 installGlobalHandler();
3237 handlers.push(handler);
3238 }
3239
3240 /**
3241 * Remove a crash handler.
3242 * @param {Function} handler
3243 */
3244 function unsubscribe(handler) {
3245 for (var i = handlers.length - 1; i >= 0; --i) {
3246 if (handlers[i] === handler) {
3247 handlers.splice(i, 1);
3248 }
3249 }
3250 }
3251
3252 /**
3253 * Remove all crash handlers.
3254 */
3255 function unsubscribeAll() {
3256 uninstallGlobalHandler();
3257 handlers = [];
3258 }
3259
3260 /**
3261 * Dispatch stack information to all handlers.
3262 * @param {Object.<string, *>} stack
3263 */
3264 function notifyHandlers(stack, isWindowError) {
3265 var exception = null;
3266 if (isWindowError && !TraceKit.collectWindowErrors) {
3267 return;
3268 }
3269 for (var i in handlers) {
3270 if (handlers.hasOwnProperty(i)) {
3271 try {
3272 handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2)));
3273 } catch (inner) {
3274 exception = inner;
3275 }
3276 }
3277 }
3278
3279 if (exception) {
3280 throw exception;
3281 }
3282 }
3283
3284 var _oldOnerrorHandler, _onErrorHandlerInstalled;
3285
3286 /**
3287 * Ensures all global unhandled exceptions are recorded.
3288 * Supported by Gecko and IE.
3289 * @param {string} message Error message.
3290 * @param {string} url URL of script that generated the exception.
3291 * @param {(number|string)} lineNo The line number at which the error
3292 * occurred.
3293 * @param {?(number|string)} colNo The column number at which the error
3294 * occurred.
3295 * @param {?Error} ex The actual Error object.
3296 */
3297 function traceKitWindowOnError(message, url, lineNo, colNo, ex) {
3298 var stack = null;
3299
3300 if (lastExceptionStack) {
3301 TraceKit.computeStackTrace.augmentStackTraceWithInitialElement(
3302 lastExceptionStack,
3303 url,
3304 lineNo,
3305 message
3306 );
3307 processLastException();
3308 } else if (ex && utils.isError(ex)) {
3309 // non-string `ex` arg; attempt to extract stack trace
3310
3311 // New chrome and blink send along a real error object
3312 // Let's just report that like a normal error.
3313 // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror
3314 stack = TraceKit.computeStackTrace(ex);
3315 notifyHandlers(stack, true);
3316 } else {
3317 var location = {
3318 url: url,
3319 line: lineNo,
3320 column: colNo
3321 };
3322
3323 var name = undefined;
3324 var msg = message; // must be new var or will modify original `arguments`
3325 var groups;
3326 if ({}.toString.call(message) === '[object String]') {
3327 var groups = message.match(ERROR_TYPES_RE);
3328 if (groups) {
3329 name = groups[1];
3330 msg = groups[2];
3331 }
3332 }
3333
3334 location.func = UNKNOWN_FUNCTION;
3335
3336 stack = {
3337 name: name,
3338 message: msg,
3339 url: getLocationHref(),
3340 stack: [location]
3341 };
3342 notifyHandlers(stack, true);
3343 }
3344
3345 if (_oldOnerrorHandler) {
3346 return _oldOnerrorHandler.apply(this, arguments);
3347 }
3348
3349 return false;
3350 }
3351
3352 function installGlobalHandler() {
3353 if (_onErrorHandlerInstalled) {
3354 return;
3355 }
3356 _oldOnerrorHandler = _window.onerror;
3357 _window.onerror = traceKitWindowOnError;
3358 _onErrorHandlerInstalled = true;
3359 }
3360
3361 function uninstallGlobalHandler() {
3362 if (!_onErrorHandlerInstalled) {
3363 return;
3364 }
3365 _window.onerror = _oldOnerrorHandler;
3366 _onErrorHandlerInstalled = false;
3367 _oldOnerrorHandler = undefined;
3368 }
3369
3370 function processLastException() {
3371 var _lastExceptionStack = lastExceptionStack,
3372 _lastArgs = lastArgs;
3373 lastArgs = null;
3374 lastExceptionStack = null;
3375 lastException = null;
3376 notifyHandlers.apply(null, [_lastExceptionStack, false].concat(_lastArgs));
3377 }
3378
3379 /**
3380 * Reports an unhandled Error to TraceKit.
3381 * @param {Error} ex
3382 * @param {?boolean} rethrow If false, do not re-throw the exception.
3383 * Only used for window.onerror to not cause an infinite loop of
3384 * rethrowing.
3385 */
3386 function report(ex, rethrow) {
3387 var args = _slice.call(arguments, 1);
3388 if (lastExceptionStack) {
3389 if (lastException === ex) {
3390 return; // already caught by an inner catch block, ignore
3391 } else {
3392 processLastException();
3393 }
3394 }
3395
3396 var stack = TraceKit.computeStackTrace(ex);
3397 lastExceptionStack = stack;
3398 lastException = ex;
3399 lastArgs = args;
3400
3401 // If the stack trace is incomplete, wait for 2 seconds for
3402 // slow slow IE to see if onerror occurs or not before reporting
3403 // this exception; otherwise, we will end up with an incomplete
3404 // stack trace
3405 setTimeout(function() {
3406 if (lastException === ex) {
3407 processLastException();
3408 }
3409 }, stack.incomplete ? 2000 : 0);
3410
3411 if (rethrow !== false) {
3412 throw ex; // re-throw to propagate to the top level (and cause window.onerror)
3413 }
3414 }
3415
3416 report.subscribe = subscribe;
3417 report.unsubscribe = unsubscribe;
3418 report.uninstall = unsubscribeAll;
3419 return report;
3420 })();
3421
3422 /**
3423 * TraceKit.computeStackTrace: cross-browser stack traces in JavaScript
3424 *
3425 * Syntax:
3426 * s = TraceKit.computeStackTrace(exception) // consider using TraceKit.report instead (see below)
3427 * Returns:
3428 * s.name - exception name
3429 * s.message - exception message
3430 * s.stack[i].url - JavaScript or HTML file URL
3431 * s.stack[i].func - function name, or empty for anonymous functions (if guessing did not work)
3432 * s.stack[i].args - arguments passed to the function, if known
3433 * s.stack[i].line - line number, if known
3434 * s.stack[i].column - column number, if known
3435 *
3436 * Supports:
3437 * - Firefox: full stack trace with line numbers and unreliable column
3438 * number on top frame
3439 * - Opera 10: full stack trace with line and column numbers
3440 * - Opera 9-: full stack trace with line numbers
3441 * - Chrome: full stack trace with line and column numbers
3442 * - Safari: line and column number for the topmost stacktrace element
3443 * only
3444 * - IE: no line numbers whatsoever
3445 *
3446 * Tries to guess names of anonymous functions by looking for assignments
3447 * in the source code. In IE and Safari, we have to guess source file names
3448 * by searching for function bodies inside all page scripts. This will not
3449 * work for scripts that are loaded cross-domain.
3450 * Here be dragons: some function names may be guessed incorrectly, and
3451 * duplicate functions may be mismatched.
3452 *
3453 * TraceKit.computeStackTrace should only be used for tracing purposes.
3454 * Logging of unhandled exceptions should be done with TraceKit.report,
3455 * which builds on top of TraceKit.computeStackTrace and provides better
3456 * IE support by utilizing the window.onerror event to retrieve information
3457 * about the top of the stack.
3458 *
3459 * Note: In IE and Safari, no stack trace is recorded on the Error object,
3460 * so computeStackTrace instead walks its *own* chain of callers.
3461 * This means that:
3462 * * in Safari, some methods may be missing from the stack trace;
3463 * * in IE, the topmost function in the stack trace will always be the
3464 * caller of computeStackTrace.
3465 *
3466 * This is okay for tracing (because you are likely to be calling
3467 * computeStackTrace from the function you want to be the topmost element
3468 * of the stack trace anyway), but not okay for logging unhandled
3469 * exceptions (because your catch block will likely be far away from the
3470 * inner function that actually caused the exception).
3471 *
3472 */
3473 TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
3474 // Contents of Exception in various browsers.
3475 //
3476 // SAFARI:
3477 // ex.message = Can't find variable: qq
3478 // ex.line = 59
3479 // ex.sourceId = 580238192
3480 // ex.sourceURL = http://...
3481 // ex.expressionBeginOffset = 96
3482 // ex.expressionCaretOffset = 98
3483 // ex.expressionEndOffset = 98
3484 // ex.name = ReferenceError
3485 //
3486 // FIREFOX:
3487 // ex.message = qq is not defined
3488 // ex.fileName = http://...
3489 // ex.lineNumber = 59
3490 // ex.columnNumber = 69
3491 // ex.stack = ...stack trace... (see the example below)
3492 // ex.name = ReferenceError
3493 //
3494 // CHROME:
3495 // ex.message = qq is not defined
3496 // ex.name = ReferenceError
3497 // ex.type = not_defined
3498 // ex.arguments = ['aa']
3499 // ex.stack = ...stack trace...
3500 //
3501 // INTERNET EXPLORER:
3502 // ex.message = ...
3503 // ex.name = ReferenceError
3504 //
3505 // OPERA:
3506 // ex.message = ...message... (see the example below)
3507 // ex.name = ReferenceError
3508 // ex.opera#sourceloc = 11 (pretty much useless, duplicates the info in ex.message)
3509 // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace'
3510
3511 /**
3512 * Computes stack trace information from the stack property.
3513 * Chrome and Gecko use this property.
3514 * @param {Error} ex
3515 * @return {?Object.<string, *>} Stack trace information.
3516 */
3517 function computeStackTraceFromStackProp(ex) {
3518 if (typeof ex.stack === 'undefined' || !ex.stack) return;
3519
3520 var chrome = /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,
3521 gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i,
3522 winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
3523 // Used to additionally parse URL/line/column from eval frames
3524 geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i,
3525 chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/,
3526 lines = ex.stack.split('\n'),
3527 stack = [],
3528 submatch,
3529 parts,
3530 element,
3531 reference = /^(.*) is undefined$/.exec(ex.message);
3532
3533 for (var i = 0, j = lines.length; i < j; ++i) {
3534 if ((parts = chrome.exec(lines[i]))) {
3535 var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line
3536 var isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line
3537 if (isEval && (submatch = chromeEval.exec(parts[2]))) {
3538 // throw out eval line/column and use top-most line/column number
3539 parts[2] = submatch[1]; // url
3540 parts[3] = submatch[2]; // line
3541 parts[4] = submatch[3]; // column
3542 }
3543 element = {
3544 url: !isNative ? parts[2] : null,
3545 func: parts[1] || UNKNOWN_FUNCTION,
3546 args: isNative ? [parts[2]] : [],
3547 line: parts[3] ? +parts[3] : null,
3548 column: parts[4] ? +parts[4] : null
3549 };
3550 } else if ((parts = winjs.exec(lines[i]))) {
3551 element = {
3552 url: parts[2],
3553 func: parts[1] || UNKNOWN_FUNCTION,
3554 args: [],
3555 line: +parts[3],
3556 column: parts[4] ? +parts[4] : null
3557 };
3558 } else if ((parts = gecko.exec(lines[i]))) {
3559 var isEval = parts[3] && parts[3].indexOf(' > eval') > -1;
3560 if (isEval && (submatch = geckoEval.exec(parts[3]))) {
3561 // throw out eval line/column and use top-most line number
3562 parts[3] = submatch[1];
3563 parts[4] = submatch[2];
3564 parts[5] = null; // no column when eval
3565 } else if (i === 0 && !parts[5] && typeof ex.columnNumber !== 'undefined') {
3566 // FireFox uses this awesome columnNumber property for its top frame
3567 // Also note, Firefox's column number is 0-based and everything else expects 1-based,
3568 // so adding 1
3569 // NOTE: this hack doesn't work if top-most frame is eval
3570 stack[0].column = ex.columnNumber + 1;
3571 }
3572 element = {
3573 url: parts[3],
3574 func: parts[1] || UNKNOWN_FUNCTION,
3575 args: parts[2] ? parts[2].split(',') : [],
3576 line: parts[4] ? +parts[4] : null,
3577 column: parts[5] ? +parts[5] : null
3578 };
3579 } else {
3580 continue;
3581 }
3582
3583 if (!element.func && element.line) {
3584 element.func = UNKNOWN_FUNCTION;
3585 }
3586
3587 stack.push(element);
3588 }
3589
3590 if (!stack.length) {
3591 return null;
3592 }
3593
3594 return {
3595 name: ex.name,
3596 message: ex.message,
3597 url: getLocationHref(),
3598 stack: stack
3599 };
3600 }
3601
3602 /**
3603 * Adds information about the first frame to incomplete stack traces.
3604 * Safari and IE require this to get complete data on the first frame.
3605 * @param {Object.<string, *>} stackInfo Stack trace information from
3606 * one of the compute* methods.
3607 * @param {string} url The URL of the script that caused an error.
3608 * @param {(number|string)} lineNo The line number of the script that
3609 * caused an error.
3610 * @param {string=} message The error generated by the browser, which
3611 * hopefully contains the name of the object that caused the error.
3612 * @return {boolean} Whether or not the stack information was
3613 * augmented.
3614 */
3615 function augmentStackTraceWithInitialElement(stackInfo, url, lineNo, message) {
3616 var initial = {
3617 url: url,
3618 line: lineNo
3619 };
3620
3621 if (initial.url && initial.line) {
3622 stackInfo.incomplete = false;
3623
3624 if (!initial.func) {
3625 initial.func = UNKNOWN_FUNCTION;
3626 }
3627
3628 if (stackInfo.stack.length > 0) {
3629 if (stackInfo.stack[0].url === initial.url) {
3630 if (stackInfo.stack[0].line === initial.line) {
3631 return false; // already in stack trace
3632 } else if (
3633 !stackInfo.stack[0].line &&
3634 stackInfo.stack[0].func === initial.func
3635 ) {
3636 stackInfo.stack[0].line = initial.line;
3637 return false;
3638 }
3639 }
3640 }
3641
3642 stackInfo.stack.unshift(initial);
3643 stackInfo.partial = true;
3644 return true;
3645 } else {
3646 stackInfo.incomplete = true;
3647 }
3648
3649 return false;
3650 }
3651
3652 /**
3653 * Computes stack trace information by walking the arguments.caller
3654 * chain at the time the exception occurred. This will cause earlier
3655 * frames to be missed but is the only way to get any stack trace in
3656 * Safari and IE. The top frame is restored by
3657 * {@link augmentStackTraceWithInitialElement}.
3658 * @param {Error} ex
3659 * @return {?Object.<string, *>} Stack trace information.
3660 */
3661 function computeStackTraceByWalkingCallerChain(ex, depth) {
3662 var functionName = /function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i,
3663 stack = [],
3664 funcs = {},
3665 recursion = false,
3666 parts,
3667 item,
3668 source;
3669
3670 for (
3671 var curr = computeStackTraceByWalkingCallerChain.caller;
3672 curr && !recursion;
3673 curr = curr.caller
3674 ) {
3675 if (curr === computeStackTrace || curr === TraceKit.report) {
3676 // console.log('skipping internal function');
3677 continue;
3678 }
3679
3680 item = {
3681 url: null,
3682 func: UNKNOWN_FUNCTION,
3683 line: null,
3684 column: null
3685 };
3686
3687 if (curr.name) {
3688 item.func = curr.name;
3689 } else if ((parts = functionName.exec(curr.toString()))) {
3690 item.func = parts[1];
3691 }
3692
3693 if (typeof item.func === 'undefined') {
3694 try {
3695 item.func = parts.input.substring(0, parts.input.indexOf('{'));
3696 } catch (e) {}
3697 }
3698
3699 if (funcs['' + curr]) {
3700 recursion = true;
3701 } else {
3702 funcs['' + curr] = true;
3703 }
3704
3705 stack.push(item);
3706 }
3707
3708 if (depth) {
3709 // console.log('depth is ' + depth);
3710 // console.log('stack is ' + stack.length);
3711 stack.splice(0, depth);
3712 }
3713
3714 var result = {
3715 name: ex.name,
3716 message: ex.message,
3717 url: getLocationHref(),
3718 stack: stack
3719 };
3720 augmentStackTraceWithInitialElement(
3721 result,
3722 ex.sourceURL || ex.fileName,
3723 ex.line || ex.lineNumber,
3724 ex.message || ex.description
3725 );
3726 return result;
3727 }
3728
3729 /**
3730 * Computes a stack trace for an exception.
3731 * @param {Error} ex
3732 * @param {(string|number)=} depth
3733 */
3734 function computeStackTrace(ex, depth) {
3735 var stack = null;
3736 depth = depth == null ? 0 : +depth;
3737
3738 try {
3739 stack = computeStackTraceFromStackProp(ex);
3740 if (stack) {
3741 return stack;
3742 }
3743 } catch (e) {
3744 if (TraceKit.debug) {
3745 throw e;
3746 }
3747 }
3748
3749 try {
3750 stack = computeStackTraceByWalkingCallerChain(ex, depth + 1);
3751 if (stack) {
3752 return stack;
3753 }
3754 } catch (e) {
3755 if (TraceKit.debug) {
3756 throw e;
3757 }
3758 }
3759 return {
3760 name: ex.name,
3761 message: ex.message,
3762 url: getLocationHref()
3763 };
3764 }
3765
3766 computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement;
3767 computeStackTrace.computeStackTraceFromStackProp = computeStackTraceFromStackProp;
3768
3769 return computeStackTrace;
3770 })();
3771
3772 module.exports = TraceKit;
3773
3774
3775 /***/ }),
3776
3777 /***/ "./node_modules/raven-js/vendor/json-stringify-safe/stringify.js":
3778 /*!***********************************************************************!*\
3779 !*** ./node_modules/raven-js/vendor/json-stringify-safe/stringify.js ***!
3780 \***********************************************************************/
3781 /***/ ((module, exports) => {
3782
3783 /*
3784 json-stringify-safe
3785 Like JSON.stringify, but doesn't throw on circular references.
3786
3787 Originally forked from https://github.com/isaacs/json-stringify-safe
3788 version 5.0.1 on 3/8/2017 and modified to handle Errors serialization
3789 and IE8 compatibility. Tests for this are in test/vendor.
3790
3791 ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE
3792 */
3793
3794 exports = module.exports = stringify;
3795 exports.getSerialize = serializer;
3796
3797 function indexOf(haystack, needle) {
3798 for (var i = 0; i < haystack.length; ++i) {
3799 if (haystack[i] === needle) return i;
3800 }
3801 return -1;
3802 }
3803
3804 function stringify(obj, replacer, spaces, cycleReplacer) {
3805 return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces);
3806 }
3807
3808 // https://github.com/ftlabs/js-abbreviate/blob/fa709e5f139e7770a71827b1893f22418097fbda/index.js#L95-L106
3809 function stringifyError(value) {
3810 var err = {
3811 // These properties are implemented as magical getters and don't show up in for in
3812 stack: value.stack,
3813 message: value.message,
3814 name: value.name
3815 };
3816
3817 for (var i in value) {
3818 if (Object.prototype.hasOwnProperty.call(value, i)) {
3819 err[i] = value[i];
3820 }
3821 }
3822
3823 return err;
3824 }
3825
3826 function serializer(replacer, cycleReplacer) {
3827 var stack = [];
3828 var keys = [];
3829
3830 if (cycleReplacer == null) {
3831 cycleReplacer = function(key, value) {
3832 if (stack[0] === value) {
3833 return '[Circular ~]';
3834 }
3835 return '[Circular ~.' + keys.slice(0, indexOf(stack, value)).join('.') + ']';
3836 };
3837 }
3838
3839 return function(key, value) {
3840 if (stack.length > 0) {
3841 var thisPos = indexOf(stack, this);
3842 ~thisPos ? stack.splice(thisPos + 1) : stack.push(this);
3843 ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key);
3844
3845 if (~indexOf(stack, value)) {
3846 value = cycleReplacer.call(this, key, value);
3847 }
3848 } else {
3849 stack.push(value);
3850 }
3851
3852 return replacer == null
3853 ? value instanceof Error ? stringifyError(value) : value
3854 : replacer.call(this, key, value);
3855 };
3856 }
3857
3858
3859 /***/ }),
3860
3861 /***/ "jquery":
3862 /*!*************************!*\
3863 !*** external "jQuery" ***!
3864 \*************************/
3865 /***/ ((module) => {
3866
3867 "use strict";
3868 module.exports = window["jQuery"];
3869
3870 /***/ })
3871
3872 /******/ });
3873 /************************************************************************/
3874 /******/ // The module cache
3875 /******/ var __webpack_module_cache__ = {};
3876 /******/
3877 /******/ // The require function
3878 /******/ function __webpack_require__(moduleId) {
3879 /******/ // Check if module is in cache
3880 /******/ var cachedModule = __webpack_module_cache__[moduleId];
3881 /******/ if (cachedModule !== undefined) {
3882 /******/ return cachedModule.exports;
3883 /******/ }
3884 /******/ // Create a new module (and put it into the cache)
3885 /******/ var module = __webpack_module_cache__[moduleId] = {
3886 /******/ // no module.id needed
3887 /******/ // no module.loaded needed
3888 /******/ exports: {}
3889 /******/ };
3890 /******/
3891 /******/ // Execute the module function
3892 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
3893 /******/
3894 /******/ // Return the exports of the module
3895 /******/ return module.exports;
3896 /******/ }
3897 /******/
3898 /************************************************************************/
3899 /******/ /* webpack/runtime/compat get default export */
3900 /******/ (() => {
3901 /******/ // getDefaultExport function for compatibility with non-harmony modules
3902 /******/ __webpack_require__.n = (module) => {
3903 /******/ var getter = module && module.__esModule ?
3904 /******/ () => (module['default']) :
3905 /******/ () => (module);
3906 /******/ __webpack_require__.d(getter, { a: getter });
3907 /******/ return getter;
3908 /******/ };
3909 /******/ })();
3910 /******/
3911 /******/ /* webpack/runtime/define property getters */
3912 /******/ (() => {
3913 /******/ // define getter functions for harmony exports
3914 /******/ __webpack_require__.d = (exports, definition) => {
3915 /******/ for(var key in definition) {
3916 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
3917 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
3918 /******/ }
3919 /******/ }
3920 /******/ };
3921 /******/ })();
3922 /******/
3923 /******/ /* webpack/runtime/global */
3924 /******/ (() => {
3925 /******/ __webpack_require__.g = (function() {
3926 /******/ if (typeof globalThis === 'object') return globalThis;
3927 /******/ try {
3928 /******/ return this || new Function('return this')();
3929 /******/ } catch (e) {
3930 /******/ if (typeof window === 'object') return window;
3931 /******/ }
3932 /******/ })();
3933 /******/ })();
3934 /******/
3935 /******/ /* webpack/runtime/hasOwnProperty shorthand */
3936 /******/ (() => {
3937 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
3938 /******/ })();
3939 /******/
3940 /******/ /* webpack/runtime/make namespace object */
3941 /******/ (() => {
3942 /******/ // define __esModule on exports
3943 /******/ __webpack_require__.r = (exports) => {
3944 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
3945 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3946 /******/ }
3947 /******/ Object.defineProperty(exports, '__esModule', { value: true });
3948 /******/ };
3949 /******/ })();
3950 /******/
3951 /************************************************************************/
3952 var __webpack_exports__ = {};
3953 // This entry need to be wrapped in an IIFE because it need to be in strict mode.
3954 (() => {
3955 "use strict";
3956 /*!*************************************!*\
3957 !*** ./scripts/entries/feedback.ts ***!
3958 \*************************************/
3959 __webpack_require__.r(__webpack_exports__);
3960 /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! jquery */ "jquery");
3961 /* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
3962 /* harmony import */ var _lib_Raven__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../lib/Raven */ "./scripts/lib/Raven.ts");
3963 /* harmony import */ var _constants_selectors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../constants/selectors */ "./scripts/constants/selectors.ts");
3964 /* harmony import */ var _feedback_ThickBoxModal__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../feedback/ThickBoxModal */ "./scripts/feedback/ThickBoxModal.ts");
3965 /* harmony import */ var _feedback_feedbackFormApi__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../feedback/feedbackFormApi */ "./scripts/feedback/feedbackFormApi.ts");
3966 /* harmony import */ var _utils_backgroundAppUtils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/backgroundAppUtils */ "./scripts/utils/backgroundAppUtils.ts");
3967 /* harmony import */ var _iframe_integratedMessages__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../iframe/integratedMessages */ "./scripts/iframe/integratedMessages/index.ts");
3968
3969
3970
3971
3972
3973
3974
3975 var embedder;
3976 function deactivatePlugin() {
3977 var href = jquery__WEBPACK_IMPORTED_MODULE_0___default()(_constants_selectors__WEBPACK_IMPORTED_MODULE_2__.domElements.deactivatePluginButton).attr('href');
3978 if (href) {
3979 window.location.href = href;
3980 }
3981 }
3982 function setLoadingState() {
3983 jquery__WEBPACK_IMPORTED_MODULE_0___default()(_constants_selectors__WEBPACK_IMPORTED_MODULE_2__.domElements.deactivateFeedbackSubmit).addClass('loading');
3984 }
3985 function submitAndDeactivate(e) {
3986 e.preventDefault();
3987 setLoadingState();
3988 var feedback = jquery__WEBPACK_IMPORTED_MODULE_0___default()(_constants_selectors__WEBPACK_IMPORTED_MODULE_2__.domElements.deactivateFeedbackForm).serializeArray().find(function (field) {
3989 return field.name === 'feedback';
3990 });
3991 (0,_feedback_feedbackFormApi__WEBPACK_IMPORTED_MODULE_4__.submitFeedbackForm)(_constants_selectors__WEBPACK_IMPORTED_MODULE_2__.domElements.deactivateFeedbackForm).then(function () {
3992 if (feedback) {
3993 embedder.postMessage({
3994 key: _iframe_integratedMessages__WEBPACK_IMPORTED_MODULE_6__.ProxyMessages.TrackPluginDeactivation,
3995 payload: {
3996 type: feedback.value.trim().replace(/[\s']+/g, '_')
3997 }
3998 });
3999 }
4000 })["catch"](function (err) {
4001 _lib_Raven__WEBPACK_IMPORTED_MODULE_1__["default"].captureException(err);
4002 })["finally"](function () {
4003 deactivatePlugin();
4004 });
4005 }
4006 function init() {
4007 embedder = (0,_utils_backgroundAppUtils__WEBPACK_IMPORTED_MODULE_5__.getOrCreateBackgroundApp)();
4008 // eslint-disable-next-line no-new
4009 new _feedback_ThickBoxModal__WEBPACK_IMPORTED_MODULE_3__["default"](_constants_selectors__WEBPACK_IMPORTED_MODULE_2__.domElements.deactivatePluginButton, 'leadin-feedback-container', 'leadin-feedback-window', 'leadin-feedback-content');
4010 jquery__WEBPACK_IMPORTED_MODULE_0___default()(_constants_selectors__WEBPACK_IMPORTED_MODULE_2__.domElements.deactivateFeedbackForm).off('submit').on('submit', submitAndDeactivate);
4011 jquery__WEBPACK_IMPORTED_MODULE_0___default()(_constants_selectors__WEBPACK_IMPORTED_MODULE_2__.domElements.deactivateFeedbackSkip).off('click').on('click', deactivatePlugin);
4012 }
4013 (0,_utils_backgroundAppUtils__WEBPACK_IMPORTED_MODULE_5__.initBackgroundApp)(init);
4014 })();
4015
4016 /******/ })()
4017 ;
4018 //# sourceMappingURL=feedback.js.map