errorHandling.ts 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import { ComponentInstance } from './component'
  2. import { warn } from './warning'
  3. import { VNode } from './vdom'
  4. import { VNodeFlags } from './flags'
  5. export const enum ErrorTypes {
  6. BEFORE_CREATE = 1,
  7. CREATED,
  8. BEFORE_MOUNT,
  9. MOUNTED,
  10. BEFORE_UPDATE,
  11. UPDATED,
  12. BEFORE_DESTROY,
  13. DESTROYED,
  14. ERROR_CAPTURED,
  15. RENDER,
  16. WATCH_CALLBACK,
  17. NATIVE_EVENT_HANDLER,
  18. COMPONENT_EVENT_HANDLER
  19. }
  20. const ErrorTypeStrings: Record<number, string> = {
  21. [ErrorTypes.BEFORE_CREATE]: 'beforeCreate lifecycle hook',
  22. [ErrorTypes.CREATED]: 'created lifecycle hook',
  23. [ErrorTypes.BEFORE_MOUNT]: 'beforeMount lifecycle hook',
  24. [ErrorTypes.MOUNTED]: 'mounted lifecycle hook',
  25. [ErrorTypes.BEFORE_UPDATE]: 'beforeUpdate lifecycle hook',
  26. [ErrorTypes.UPDATED]: 'updated lifecycle hook',
  27. [ErrorTypes.BEFORE_DESTROY]: 'beforeDestroy lifecycle hook',
  28. [ErrorTypes.DESTROYED]: 'destroyed lifecycle hook',
  29. [ErrorTypes.ERROR_CAPTURED]: 'errorCaptured lifecycle hook',
  30. [ErrorTypes.RENDER]: 'render function',
  31. [ErrorTypes.WATCH_CALLBACK]: 'watcher callback',
  32. [ErrorTypes.NATIVE_EVENT_HANDLER]: 'native event handler',
  33. [ErrorTypes.COMPONENT_EVENT_HANDLER]: 'component event handler'
  34. }
  35. export function handleError(
  36. err: Error,
  37. instance: ComponentInstance | VNode,
  38. type: ErrorTypes
  39. ) {
  40. const isFunctional = (instance as VNode)._isVNode
  41. let cur: ComponentInstance | null = null
  42. if (isFunctional) {
  43. let vnode = instance as VNode | null
  44. while (vnode && !(vnode.flags & VNodeFlags.COMPONENT_STATEFUL)) {
  45. vnode = vnode.contextVNode
  46. }
  47. if (vnode) {
  48. cur = vnode.children as ComponentInstance
  49. }
  50. } else {
  51. cur = (instance as ComponentInstance).$parent
  52. }
  53. while (cur) {
  54. const handler = cur.errorCaptured
  55. if (handler) {
  56. try {
  57. const captured = handler.call(
  58. cur,
  59. err,
  60. type,
  61. isFunctional ? null : instance,
  62. isFunctional ? instance : (instance as ComponentInstance).$parentVNode
  63. )
  64. if (captured) return
  65. } catch (err2) {
  66. logError(err2, ErrorTypes.ERROR_CAPTURED)
  67. }
  68. }
  69. cur = cur.$parent
  70. }
  71. logError(err, type)
  72. }
  73. function logError(err: Error, type: ErrorTypes) {
  74. if (__DEV__) {
  75. const info = ErrorTypeStrings[type]
  76. warn(`Unhandled error${info ? ` in ${info}` : ``}`)
  77. console.error(err)
  78. } else {
  79. throw err
  80. }
  81. }