PluginProbe
HubSpot All-In-One Marketing – Forms, Popups, Live Chat / 11.3.56
HubSpot All-In-One Marketing – Forms, Popups, Live Chat v11.3.56
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 / reviewBanner.js

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

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