helpers.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. Object.defineProperty(exports, '__esModule', { value: true });
  2. require('@sentry-internal/tracing');
  3. const core = require('@sentry/core');
  4. const utils = require('@sentry/utils');
  5. const WINDOW = utils.GLOBAL_OBJ ;
  6. let ignoreOnError = 0;
  7. /**
  8. * @hidden
  9. */
  10. function shouldIgnoreOnError() {
  11. return ignoreOnError > 0;
  12. }
  13. /**
  14. * @hidden
  15. */
  16. function ignoreNextOnError() {
  17. // onerror should trigger before setTimeout
  18. ignoreOnError++;
  19. setTimeout(() => {
  20. ignoreOnError--;
  21. });
  22. }
  23. /**
  24. * Instruments the given function and sends an event to Sentry every time the
  25. * function throws an exception.
  26. *
  27. * @param fn A function to wrap. It is generally safe to pass an unbound function, because the returned wrapper always
  28. * has a correct `this` context.
  29. * @returns The wrapped function.
  30. * @hidden
  31. */
  32. function wrap(
  33. fn,
  34. options
  35. = {},
  36. before,
  37. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  38. ) {
  39. // for future readers what this does is wrap a function and then create
  40. // a bi-directional wrapping between them.
  41. //
  42. // example: wrapped = wrap(original);
  43. // original.__sentry_wrapped__ -> wrapped
  44. // wrapped.__sentry_original__ -> original
  45. if (typeof fn !== 'function') {
  46. return fn;
  47. }
  48. try {
  49. // if we're dealing with a function that was previously wrapped, return
  50. // the original wrapper.
  51. const wrapper = fn.__sentry_wrapped__;
  52. if (wrapper) {
  53. return wrapper;
  54. }
  55. // We don't wanna wrap it twice
  56. if (utils.getOriginalFunction(fn)) {
  57. return fn;
  58. }
  59. } catch (e) {
  60. // Just accessing custom props in some Selenium environments
  61. // can cause a "Permission denied" exception (see raven-js#495).
  62. // Bail on wrapping and return the function as-is (defers to window.onerror).
  63. return fn;
  64. }
  65. /* eslint-disable prefer-rest-params */
  66. // It is important that `sentryWrapped` is not an arrow function to preserve the context of `this`
  67. const sentryWrapped = function () {
  68. const args = Array.prototype.slice.call(arguments);
  69. try {
  70. if (before && typeof before === 'function') {
  71. before.apply(this, arguments);
  72. }
  73. // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
  74. const wrappedArguments = args.map((arg) => wrap(arg, options));
  75. // Attempt to invoke user-land function
  76. // NOTE: If you are a Sentry user, and you are seeing this stack frame, it
  77. // means the sentry.javascript SDK caught an error invoking your application code. This
  78. // is expected behavior and NOT indicative of a bug with sentry.javascript.
  79. return fn.apply(this, wrappedArguments);
  80. } catch (ex) {
  81. ignoreNextOnError();
  82. core.withScope(scope => {
  83. scope.addEventProcessor(event => {
  84. if (options.mechanism) {
  85. utils.addExceptionTypeValue(event, undefined, undefined);
  86. utils.addExceptionMechanism(event, options.mechanism);
  87. }
  88. event.extra = {
  89. ...event.extra,
  90. arguments: args,
  91. };
  92. return event;
  93. });
  94. core.captureException(ex);
  95. });
  96. throw ex;
  97. }
  98. };
  99. /* eslint-enable prefer-rest-params */
  100. // Accessing some objects may throw
  101. // ref: https://github.com/getsentry/sentry-javascript/issues/1168
  102. try {
  103. for (const property in fn) {
  104. if (Object.prototype.hasOwnProperty.call(fn, property)) {
  105. sentryWrapped[property] = fn[property];
  106. }
  107. }
  108. } catch (_oO) {} // eslint-disable-line no-empty
  109. // Signal that this function has been wrapped/filled already
  110. // for both debugging and to prevent it to being wrapped/filled twice
  111. utils.markFunctionWrapped(sentryWrapped, fn);
  112. utils.addNonEnumerableProperty(fn, '__sentry_wrapped__', sentryWrapped);
  113. // Restore original function name (not all browsers allow that)
  114. try {
  115. const descriptor = Object.getOwnPropertyDescriptor(sentryWrapped, 'name') ;
  116. if (descriptor.configurable) {
  117. Object.defineProperty(sentryWrapped, 'name', {
  118. get() {
  119. return fn.name;
  120. },
  121. });
  122. }
  123. // eslint-disable-next-line no-empty
  124. } catch (_oO) {}
  125. return sentryWrapped;
  126. }
  127. exports.WINDOW = WINDOW;
  128. exports.ignoreNextOnError = ignoreNextOnError;
  129. exports.shouldIgnoreOnError = shouldIgnoreOnError;
  130. exports.wrap = wrap;
  131. //# sourceMappingURL=helpers.js.map