MCPcopy Index your code
hub / github.com/getsentry/sentry-javascript / wrap

Function wrap

packages/browser/src/helpers.ts:60–186  ·  view source on GitHub ↗
(
  fn: T | NonFunction,
  options: {
    mechanism?: Mechanism;
  } = {},
)

Source from the content-addressed store, hash-verified

58 * @hidden
59 */
60export function wrap<T extends WrappableFunction, NonFunction>(
61 fn: T | NonFunction,
62 options: {
63 mechanism?: Mechanism;
64 } = {},
65): NonFunction | WrappedFunction<T> {
66 // for future readers what this does is wrap a function and then create
67 // a bi-directional wrapping between them.
68 //
69 // example: wrapped = wrap(original);
70 // original.__sentry_wrapped__ -> wrapped
71 // wrapped.__sentry_original__ -> original
72
73 function isFunction(fn: T | NonFunction): fn is T {
74 return typeof fn === 'function';
75 }
76
77 if (!isFunction(fn)) {
78 return fn;
79 }
80
81 try {
82 // If we're dealing with a function that was previously wrapped, return the original wrapper.
83 // Check via hasOwnProperty so a `__sentry_wrapped__` inherited from a wrapped `Function.prototype`
84 // is not mistaken for a real wrapper.
85 const hasOwnWrapper = Object.prototype.hasOwnProperty.call(fn, '__sentry_wrapped__');
86 if (hasOwnWrapper) {
87 const wrapper = (fn as WrappedFunction<T>).__sentry_wrapped__;
88 if (typeof wrapper === 'function') {
89 return wrapper;
90 } else {
91 // If we find that the `__sentry_wrapped__` function is not a function at the time of accessing it, it means
92 // that something messed with it. In that case we want to return the originally passed function.
93 return fn;
94 }
95 }
96
97 // We don't wanna wrap it twice
98 if (getOriginalFunction(fn)) {
99 return fn;
100 }
101 } catch {
102 // Just accessing custom props in some Selenium environments
103 // can cause a "Permission denied" exception (see raven-js#495).
104 // Bail on wrapping and return the function as-is (defers to window.onerror).
105 return fn;
106 }
107
108 // Wrap the function itself
109 // It is important that `sentryWrapped` is not an arrow function to preserve the context of `this`
110 const sentryWrapped = function (this: unknown, ...args: unknown[]): unknown {
111 // Track depth on GLOBAL_OBJ so the thirdPartyErrorFilterIntegration (in @sentry/core) can detect
112 // that processEvent is running inside a sentryWrapped call, even with minified/bundled code.
113 GLOBAL_OBJ._sentryWrappedDepth = (GLOBAL_OBJ._sentryWrappedDepth || 0) + 1;
114 try {
115 // Also wrap arguments that are themselves functions
116 const wrappedArguments = args.map(arg => wrap(arg, options));
117

Callers 6

helpers.test.tsFile · 0.90
_wrapTimeFunctionFunction · 0.90
_wrapRAFFunction · 0.90
_wrapXHRFunction · 0.90
_wrapEventTargetFunction · 0.90
applyFunction · 0.50

Calls 12

isFunctionFunction · 0.85
getOriginalFunctionFunction · 0.85
ignoreNextOnErrorFunction · 0.85
addExceptionTypeValueFunction · 0.85
addExceptionMechanismFunction · 0.85
markFunctionWrappedFunction · 0.85
addNonEnumerablePropertyFunction · 0.85
callMethod · 0.80
addEventProcessorMethod · 0.80
withScopeFunction · 0.50
captureExceptionFunction · 0.50
applyMethod · 0.45

Tested by

no test coverage detected