refactor: improve error logging

This commit is contained in:
Evan You 2018-10-28 12:09:38 -04:00
parent ebf67ad208
commit a7bcb7898f
2 changed files with 26 additions and 15 deletions

View File

@ -1,5 +1,5 @@
import { ComponentInstance } from './component' import { ComponentInstance } from './component'
import { warn } from './warning' import { warn, pushWarningContext, popWarningContext } from './warning'
import { VNode } from './vdom' import { VNode } from './vdom'
import { VNodeFlags } from './flags' import { VNodeFlags } from './flags'
@ -16,7 +16,8 @@ export const enum ErrorTypes {
RENDER, RENDER,
WATCH_CALLBACK, WATCH_CALLBACK,
NATIVE_EVENT_HANDLER, NATIVE_EVENT_HANDLER,
COMPONENT_EVENT_HANDLER COMPONENT_EVENT_HANDLER,
SCHEDULER
} }
const ErrorTypeStrings: Record<number, string> = { const ErrorTypeStrings: Record<number, string> = {
@ -32,7 +33,8 @@ const ErrorTypeStrings: Record<number, string> = {
[ErrorTypes.RENDER]: 'render function', [ErrorTypes.RENDER]: 'render function',
[ErrorTypes.WATCH_CALLBACK]: 'watcher callback', [ErrorTypes.WATCH_CALLBACK]: 'watcher callback',
[ErrorTypes.NATIVE_EVENT_HANDLER]: 'native event handler', [ErrorTypes.NATIVE_EVENT_HANDLER]: 'native event handler',
[ErrorTypes.COMPONENT_EVENT_HANDLER]: 'component event handler' [ErrorTypes.COMPONENT_EVENT_HANDLER]: 'component event handler',
[ErrorTypes.SCHEDULER]: 'scheduler'
} }
export function handleError( export function handleError(
@ -41,6 +43,9 @@ export function handleError(
type: ErrorTypes type: ErrorTypes
) { ) {
const isFunctional = (instance as VNode)._isVNode const isFunctional = (instance as VNode)._isVNode
const contextVNode = (isFunctional
? instance
: (instance as ComponentInstance).$parentVNode) as VNode | null
let cur: ComponentInstance | null = null let cur: ComponentInstance | null = null
if (isFunctional) { if (isFunctional) {
let vnode = instance as VNode | null let vnode = instance as VNode | null
@ -61,23 +66,28 @@ export function handleError(
cur, cur,
err, err,
type, type,
isFunctional ? null : instance, isFunctional ? null : instance
isFunctional ? instance : (instance as ComponentInstance).$parentVNode
) )
if (captured) return if (captured) return
} catch (err2) { } catch (err2) {
logError(err2, ErrorTypes.ERROR_CAPTURED) logError(err2, ErrorTypes.ERROR_CAPTURED, contextVNode)
} }
} }
cur = cur.$parent cur = cur.$parent
} }
logError(err, type) logError(err, type, contextVNode)
} }
function logError(err: Error, type: ErrorTypes) { function logError(err: Error, type: ErrorTypes, contextVNode: VNode | null) {
if (__DEV__) { if (__DEV__) {
const info = ErrorTypeStrings[type] const info = ErrorTypeStrings[type]
if (contextVNode) {
pushWarningContext(contextVNode)
}
warn(`Unhandled error${info ? ` in ${info}` : ``}`) warn(`Unhandled error${info ? ` in ${info}` : ``}`)
if (contextVNode) {
popWarningContext()
}
console.error(err) console.error(err)
} else { } else {
throw err throw err

View File

@ -24,15 +24,16 @@ export function warn(msg: string, ...args: any[]) {
// TODO warn handler // TODO warn handler
console.warn(`[Vue warn]: ${msg}`, ...args) console.warn(`[Vue warn]: ${msg}`, ...args)
const trace = getComponentTrace() const trace = getComponentTrace()
if (console.groupCollapsed) { if (!trace.length) {
trace.forEach((entry, i) => { return
const formatted = formatTraceEntry(entry, i)
if (i === 0) {
console.groupCollapsed('at', ...formatted)
} else {
console.log(...formatted)
} }
if (console.groupCollapsed) {
console.groupCollapsed('at', ...formatTraceEntry(trace[0]))
const logs: string[] = []
trace.slice(1).forEach((entry, i) => {
logs.push(...formatTraceEntry(entry, i + 1))
}) })
console.log(...logs)
console.groupEnd() console.groupEnd()
} else { } else {
const logs: string[] = [] const logs: string[] = []