| 5 | type UnknownFunc = (...args: unknown[]) => void; |
| 6 | |
| 7 | export const attachErrorHandler = (app: Vue, options?: Partial<VueOptions>): void => { |
| 8 | const { errorHandler: originalErrorHandler } = app.config; |
| 9 | |
| 10 | app.config.errorHandler = (error: Error, vm: ViewModel, lifecycleHook: string): void => { |
| 11 | const componentName = formatComponentName(vm, false); |
| 12 | const trace = vm ? generateComponentTrace(vm) : ''; |
| 13 | const metadata: Record<string, unknown> = { |
| 14 | componentName, |
| 15 | lifecycleHook, |
| 16 | trace, |
| 17 | }; |
| 18 | |
| 19 | if (options?.attachProps !== false && vm) { |
| 20 | // Vue2 - $options.propsData |
| 21 | // Vue3 - $props |
| 22 | if (vm.$options?.propsData) { |
| 23 | metadata.propsData = vm.$options.propsData; |
| 24 | } else if (vm.$props) { |
| 25 | metadata.propsData = vm.$props; |
| 26 | } |
| 27 | } |
| 28 | |
| 29 | // Capture exception in the next event loop, to make sure that all breadcrumbs are recorded in time. |
| 30 | setTimeout(() => { |
| 31 | captureException(error, { |
| 32 | captureContext: { contexts: { vue: metadata } }, |
| 33 | mechanism: { handled: !!originalErrorHandler, type: 'auto.function.vue.error_handler' }, |
| 34 | }); |
| 35 | }); |
| 36 | |
| 37 | // Check if the current `app.config.errorHandler` is explicitly set by the user before calling it. |
| 38 | if (typeof originalErrorHandler === 'function' && app.config.errorHandler) { |
| 39 | (originalErrorHandler as UnknownFunc).call(app, error, vm, lifecycleHook); |
| 40 | } else { |
| 41 | throw error; |
| 42 | } |
| 43 | }; |
| 44 | }; |