UNPKG

sentry-uniapp

Version:

用于Uniapp/小程序/快应用等平台的 Sentry SDK

236 lines 8.73 kB
Object.defineProperty(exports, "__esModule", { value: true }); exports.keypressEventHandler = exports.breadcrumbEventHandler = exports.wrap = exports.ignoreNextOnError = exports.shouldIgnoreOnError = void 0; var tslib_1 = require("tslib"); var core_1 = require("@sentry/core"); var utils_1 = require("@sentry/utils"); var debounceDuration = 1000; var keypressTimeout; var lastCapturedEvent; var ignoreOnError = 0; /** * @hidden */ function shouldIgnoreOnError() { return ignoreOnError > 0; } exports.shouldIgnoreOnError = shouldIgnoreOnError; /** * @hidden */ function ignoreNextOnError() { // onerror should trigger before setTimeout ignoreOnError += 1; setTimeout(function () { ignoreOnError -= 1; }); } exports.ignoreNextOnError = ignoreNextOnError; /** * Instruments the given function and sends an event to Sentry every time the * function throws an exception. * * @param fn A function to wrap. * @returns The wrapped function. * @hidden */ function wrap(fn, options, before) { if (options === void 0) { options = {}; } // tslint:disable-next-line:strict-type-predicates if (typeof fn !== 'function') { return fn; } try { // We don't wanna wrap it twice if (fn.__sentry__) { return fn; } // If this has already been wrapped in the past, return that wrapped function if (fn.__sentry_wrapped__) { return fn.__sentry_wrapped__; } } catch (e) { // Just accessing custom props in some Selenium environments // can cause a "Permission denied" exception (see raven-js#495). // Bail on wrapping and return the function as-is (defers to window.onerror). return fn; } var sentryWrapped = function () { // tslint:disable-next-line:strict-type-predicates if (before && typeof before === 'function') { before.apply(this, arguments); } var args = Array.prototype.slice.call(arguments); // tslint:disable:no-unsafe-any try { var wrappedArguments = args.map(function (arg) { return wrap(arg, options); }); if (fn.handleEvent) { // Attempt to invoke user-land function // NOTE: If you are a Sentry user, and you are seeing this stack frame, it // means the sentry.javascript SDK caught an error invoking your application code. This // is expected behavior and NOT indicative of a bug with sentry.javascript. return fn.handleEvent.apply(this, wrappedArguments); } // Attempt to invoke user-land function // NOTE: If you are a Sentry user, and you are seeing this stack frame, it // means the sentry.javascript SDK caught an error invoking your application code. This // is expected behavior and NOT indicative of a bug with sentry.javascript. return fn.apply(this, wrappedArguments); // tslint:enable:no-unsafe-any } catch (ex) { ignoreNextOnError(); core_1.withScope(function (scope) { scope.addEventProcessor(function (event) { var processedEvent = tslib_1.__assign({}, event); if (options.mechanism) { utils_1.addExceptionTypeValue(processedEvent, undefined, undefined); utils_1.addExceptionMechanism(processedEvent, options.mechanism); } processedEvent.extra = tslib_1.__assign(tslib_1.__assign({}, processedEvent.extra), { arguments: utils_1.normalize(args, 3) }); return processedEvent; }); core_1.captureException(ex); }); throw ex; } }; // Accessing some objects may throw // ref: https://github.com/getsentry/sentry-javascript/issues/1168 try { // tslint:disable-next-line: no-for-in for (var property in fn) { if (Object.prototype.hasOwnProperty.call(fn, property)) { sentryWrapped[property] = fn[property]; } } } catch (_oO) { } // tslint:disable-line:no-empty fn.prototype = fn.prototype || {}; sentryWrapped.prototype = fn.prototype; Object.defineProperty(fn, '__sentry_wrapped__', { enumerable: false, value: sentryWrapped, }); // Signal that this function has been wrapped/filled already // for both debugging and to prevent it to being wrapped/filled twice Object.defineProperties(sentryWrapped, { __sentry__: { enumerable: false, value: true, }, __sentry_original__: { enumerable: false, value: fn, }, }); // Restore original function name (not all browsers allow that) try { var descriptor = Object.getOwnPropertyDescriptor(sentryWrapped, 'name'); if (descriptor.configurable) { Object.defineProperty(sentryWrapped, 'name', { get: function () { return fn.name; }, }); } } catch (_oO) { /*no-empty*/ } return sentryWrapped; } exports.wrap = wrap; var debounceTimer = 0; /** * Wraps addEventListener to capture UI breadcrumbs * @param eventName the event name (e.g. "click") * @returns wrapped breadcrumb events handler * @hidden */ function breadcrumbEventHandler(eventName, debounce) { if (debounce === void 0) { debounce = false; } return function (event) { // reset keypress timeout; e.g. triggering a 'click' after // a 'keypress' will reset the keypress debounce so that a new // set of keypresses can be recorded keypressTimeout = undefined; // It's possible this handler might trigger multiple times for the same // event (e.g. event propagation through node ancestors). Ignore if we've // already captured the event. // tslint:disable-next-line: strict-comparisons if (!event || lastCapturedEvent === event) { return; } lastCapturedEvent = event; var captureBreadcrumb = function () { var target; // Accessing event.target can throw (see getsentry/raven-js#838, #768) try { target = event.target ? utils_1.htmlTreeAsString(event.target) : utils_1.htmlTreeAsString(event); } catch (e) { target = '<unknown>'; } if (target.length === 0) { return; } core_1.getCurrentHub().addBreadcrumb({ category: "ui." + eventName, message: target, }, { event: event, name: eventName, }); }; if (debounceTimer) { clearTimeout(debounceTimer); } if (debounce) { debounceTimer = setTimeout(captureBreadcrumb); } else { captureBreadcrumb(); } }; } exports.breadcrumbEventHandler = breadcrumbEventHandler; /** * Wraps addEventListener to capture keypress UI events * @returns wrapped keypress events handler * @hidden */ function keypressEventHandler() { // TODO: if somehow user switches keypress target before // debounce timeout is triggered, we will only capture // a single breadcrumb from the FIRST target (acceptable?) return function (event) { var target; try { target = event.target; } catch (e) { // just accessing event properties can throw an exception in some rare circumstances // see: https://github.com/getsentry/raven-js/issues/838 return; } var tagName = target && target.tagName; // only consider keypress events on actual input elements // this will disregard keypresses targeting body (e.g. tabbing // through elements, hotkeys, etc) if (!tagName || (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && !target.isContentEditable)) { return; } // record first keypress in a series, but ignore subsequent // keypresses until debounce clears if (!keypressTimeout) { breadcrumbEventHandler('input')(event); } clearTimeout(keypressTimeout); keypressTimeout = setTimeout(function () { keypressTimeout = undefined; }, debounceDuration); }; } exports.keypressEventHandler = keypressEventHandler; //# sourceMappingURL=helpers.js.map