import { setupWatcher } from './componentWatch'
import { Autorun, DebuggerEvent, ComputedGetter } from '@vue/observer'
import { nextTick } from '@vue/scheduler'
+import { ErrorTypes } from './errorHandling'
type Flatten<T> = { [K in keyof T]: T[K] }
updated?(): void
beforeDestroy?(): void
destroyed?(): void
+ errorCaptured?(): (err: Error, type: ErrorTypes) => boolean | void
_updateHandle: Autorun
_queueJob: ((fn: () => void) => void)
import { MountedComponent } from './component'
export const enum ErrorTypes {
- LIFECYCLE = 1,
+ BEFORE_CREATE = 1,
+ CREATED,
+ BEFORE_MOUNT,
+ MOUNTED,
+ BEFORE_UPDATE,
+ UPDATED,
+ BEFORE_DESTROY,
+ DESTROYED,
+ ERROR_CAPTURED,
RENDER,
RENDER_ERROR,
+ WATCH_CALLBACK,
NATIVE_EVENT_HANDLER,
COMPONENT_EVENT_HANDLER
}
-const globalHandlers: Function[] = []
-
-export function globalHandleError(handler: () => void) {
- globalHandlers.push(handler)
- return () => {
- globalHandlers.splice(globalHandlers.indexOf(handler), 1)
- }
+const ErrorTypeStrings: Record<number, string> = {
+ [ErrorTypes.BEFORE_CREATE]: 'beforeCreate lifecycle hook',
+ [ErrorTypes.CREATED]: 'created lifecycle hook',
+ [ErrorTypes.BEFORE_MOUNT]: 'beforeMount lifecycle hook',
+ [ErrorTypes.MOUNTED]: 'mounted lifecycle hook',
+ [ErrorTypes.BEFORE_UPDATE]: 'beforeUpdate lifecycle hook',
+ [ErrorTypes.UPDATED]: 'updated lifecycle hook',
+ [ErrorTypes.BEFORE_DESTROY]: 'beforeDestroy lifecycle hook',
+ [ErrorTypes.DESTROYED]: 'destroyed lifecycle hook',
+ [ErrorTypes.ERROR_CAPTURED]: 'errorCaptured lifecycle hook',
+ [ErrorTypes.RENDER]: 'render function',
+ [ErrorTypes.RENDER_ERROR]: 'renderError function',
+ [ErrorTypes.WATCH_CALLBACK]: 'watcher callback',
+ [ErrorTypes.NATIVE_EVENT_HANDLER]: 'native event handler',
+ [ErrorTypes.COMPONENT_EVENT_HANDLER]: 'component event handler'
}
export function handleError(
instance: MountedComponent,
type: ErrorTypes
) {
- // TODO
+ let cur = instance
+ while (cur.$parent) {
+ cur = cur.$parent
+ const handler = cur.errorCaptured
+ if (handler) {
+ try {
+ const captured = handler.call(cur, err, type)
+ if (captured) return
+ } catch (err2) {
+ logError(err2, cur, ErrorTypes.ERROR_CAPTURED)
+ }
+ }
+ }
+ logError(err, instance, type)
+}
+
+function logError(err: Error, instance: MountedComponent, type: ErrorTypes) {
+ if (__DEV__) {
+ const info = ErrorTypeStrings[type]
+ console.warn(
+ `Unhandled error${info ? ` in ${info}` : ``}: "${err.toString()}"`,
+ instance
+ )
+ } else {
+ throw err
+ }
}