vue3-core/packages/runtime-core/src/errorHandling.ts

86 lines
2.3 KiB
TypeScript
Raw Normal View History

2018-10-09 23:37:24 +08:00
import { ComponentInstance } from './component'
import { warn } from './warning'
import { VNode } from './vdom'
import { VNodeFlags } from './flags'
2018-09-19 23:35:38 +08:00
export const enum ErrorTypes {
2018-09-24 08:59:19 +08:00
BEFORE_CREATE = 1,
CREATED,
BEFORE_MOUNT,
MOUNTED,
BEFORE_UPDATE,
UPDATED,
BEFORE_DESTROY,
DESTROYED,
ERROR_CAPTURED,
2018-09-24 08:30:26 +08:00
RENDER,
2018-09-24 08:59:19 +08:00
WATCH_CALLBACK,
2018-09-24 08:30:26 +08:00
NATIVE_EVENT_HANDLER,
COMPONENT_EVENT_HANDLER
2018-09-19 23:35:38 +08:00
}
2018-09-24 08:59:19 +08:00
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.WATCH_CALLBACK]: 'watcher callback',
[ErrorTypes.NATIVE_EVENT_HANDLER]: 'native event handler',
[ErrorTypes.COMPONENT_EVENT_HANDLER]: 'component event handler'
2018-09-19 23:35:38 +08:00
}
export function handleError(
err: Error,
instance: ComponentInstance | VNode,
2018-09-24 08:30:26 +08:00
type: ErrorTypes
2018-09-19 23:35:38 +08:00
) {
const isFunctional = (instance as VNode)._isVNode
let cur: ComponentInstance | null = null
if (isFunctional) {
let vnode = instance as VNode | null
while (vnode && !(vnode.flags & VNodeFlags.COMPONENT_STATEFUL)) {
vnode = vnode.contextVNode
}
if (vnode) {
cur = vnode.children as ComponentInstance
}
} else {
cur = (instance as ComponentInstance).$parent
}
while (cur) {
2018-09-24 08:59:19 +08:00
const handler = cur.errorCaptured
if (handler) {
try {
const captured = handler.call(
cur,
err,
type,
isFunctional ? null : instance,
isFunctional ? instance : (instance as ComponentInstance).$parentVNode
)
2018-09-24 08:59:19 +08:00
if (captured) return
} catch (err2) {
logError(err2, ErrorTypes.ERROR_CAPTURED)
2018-09-24 08:59:19 +08:00
}
}
cur = cur.$parent
2018-09-24 08:59:19 +08:00
}
logError(err, type)
2018-09-24 08:59:19 +08:00
}
function logError(err: Error, type: ErrorTypes) {
2018-09-24 08:59:19 +08:00
if (__DEV__) {
const info = ErrorTypeStrings[type]
warn(`Unhandled error${info ? ` in ${info}` : ``}`)
2018-10-04 01:00:13 +08:00
console.error(err)
2018-09-24 08:59:19 +08:00
} else {
throw err
}
2018-09-19 23:35:38 +08:00
}