]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat: basic error handling
authorEvan You <yyx990803@gmail.com>
Mon, 24 Sep 2018 00:59:19 +0000 (20:59 -0400)
committerEvan You <yyx990803@gmail.com>
Mon, 24 Sep 2018 00:59:19 +0000 (20:59 -0400)
packages/core/src/component.ts
packages/core/src/errorHandling.ts

index 3ac07bde4feafda93cc77b95ec1795919deed037..a40a3488d6115c53cb5d4c7231a24ad5822a099d 100644 (file)
@@ -9,6 +9,7 @@ import {
 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] }
 
@@ -44,6 +45,7 @@ export interface MountedComponent<D = Data, P = Data> extends Component {
   updated?(): void
   beforeDestroy?(): void
   destroyed?(): void
+  errorCaptured?(): (err: Error, type: ErrorTypes) => boolean | void
 
   _updateHandle: Autorun
   _queueJob: ((fn: () => void) => void)
index 8a59d2ab0d5dcdafe6a275df23418beb712de170..464f628ec35b31fb7c486380c420844404db906f 100644 (file)
@@ -1,20 +1,37 @@
 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(
@@ -22,5 +39,30 @@ 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
+  }
 }