]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(transition): handle errors in CSSTransition onEnter & onLeave
authorEvan You <yyx990803@gmail.com>
Sat, 23 Nov 2019 04:42:04 +0000 (23:42 -0500)
committerEvan You <yyx990803@gmail.com>
Sat, 23 Nov 2019 04:42:04 +0000 (23:42 -0500)
packages/runtime-dom/src/components/CSSTransition.ts

index ba1d2eb55b708f9ad3da3cc7907c6731602f71e4..082cc48a4b21a2f2b1cb32301f86955716394729 100644 (file)
@@ -4,9 +4,11 @@ import {
   h,
   warn,
   FunctionalComponent,
-  getCurrentInstance
+  getCurrentInstance,
+  callWithAsyncErrorHandling
 } from '@vue/runtime-core'
 import { isObject } from '@vue/shared'
+import { ErrorCodes } from 'packages/runtime-core/src/errorHandling'
 
 const TRANSITION = 'transition'
 const ANIMATION = 'animation'
@@ -27,6 +29,8 @@ export interface CSSTransitionProps extends TransitionProps {
   leaveToClass?: string
 }
 
+// CSSTransition is a higher-order-component based on the platform-agnostic
+// base Transition component, with DOM-specific logic.
 export const CSSTransition: FunctionalComponent = (
   props: CSSTransitionProps,
   { slots }
@@ -65,6 +69,7 @@ function resolveCSSTransitionProps({
   leaveToClass = `${name}-leave-to`,
   ...baseProps
 }: CSSTransitionProps): TransitionProps {
+  const instance = getCurrentInstance()!
   const durations = normalizeDuration(duration)
   const enterDuration = durations && durations[0]
   const leaveDuration = durations && durations[1]
@@ -77,18 +82,26 @@ function resolveCSSTransitionProps({
     enterToClass = appearToClass
   }
 
-  function finishEnter(el: Element, done?: () => void) {
+  type Hook = (el: Element, done?: () => void) => void
+
+  const finishEnter: Hook = (el, done) => {
     removeTransitionClass(el, enterToClass)
     removeTransitionClass(el, enterActiveClass)
     done && done()
   }
 
-  function finishLeave(el: Element, done?: () => void) {
+  const finishLeave: Hook = (el, done) => {
     removeTransitionClass(el, leaveToClass)
     removeTransitionClass(el, leaveActiveClass)
     done && done()
   }
 
+  // only needed for user hooks called in nextFrame
+  // sync errors are already handled by BaseTransition
+  function callHookWithErrorHandling(hook: Hook, args: any[]) {
+    callWithAsyncErrorHandling(hook, instance, ErrorCodes.TRANSITION_HOOK, args)
+  }
+
   return {
     ...baseProps,
     onBeforeEnter(el) {
@@ -99,7 +112,7 @@ function resolveCSSTransitionProps({
     onEnter(el, done) {
       nextFrame(() => {
         const resolve = () => finishEnter(el, done)
-        onEnter && onEnter(el, resolve)
+        onEnter && callHookWithErrorHandling(onEnter, [el, resolve])
         removeTransitionClass(el, enterFromClass)
         addTransitionClass(el, enterToClass)
         if (!(onEnter && onEnter.length > 1)) {
@@ -116,7 +129,7 @@ function resolveCSSTransitionProps({
       addTransitionClass(el, leaveFromClass)
       nextFrame(() => {
         const resolve = () => finishLeave(el, done)
-        onLeave && onLeave(el, resolve)
+        onLeave && callHookWithErrorHandling(onLeave, [el, resolve])
         removeTransitionClass(el, leaveFromClass)
         addTransitionClass(el, leaveToClass)
         if (!(onLeave && onLeave.length > 1)) {