aboutsummaryrefslogtreecommitdiff
path: root/node_modules/vue/src/platforms/web/runtime/modules
diff options
context:
space:
mode:
authorruki <waruqi@gmail.com>2018-11-08 00:38:48 +0800
committerruki <waruqi@gmail.com>2018-11-07 21:53:09 +0800
commit26105034da4fcce7ac883c899d781f016559310d (patch)
treec459a5dc4e3aa0972d9919033ece511ce76dd129 /node_modules/vue/src/platforms/web/runtime/modules
parent2c77f00f1a7ecb6c8192f9c16d3b2001b254a107 (diff)
downloadxmake-docs-26105034da4fcce7ac883c899d781f016559310d.tar.gz
xmake-docs-26105034da4fcce7ac883c899d781f016559310d.zip
switch to vuepress
Diffstat (limited to 'node_modules/vue/src/platforms/web/runtime/modules')
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/attrs.js118
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/class.js48
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/dom-props.js95
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/events.js87
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/index.js15
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/style.js93
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/transition.js343
7 files changed, 799 insertions, 0 deletions
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/attrs.js b/node_modules/vue/src/platforms/web/runtime/modules/attrs.js
new file mode 100644
index 00000000..78ef28a1
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/attrs.js
@@ -0,0 +1,118 @@
+/* @flow */
+
+import { isIE, isIE9, isEdge } from 'core/util/env'
+
+import {
+ extend,
+ isDef,
+ isUndef
+} from 'shared/util'
+
+import {
+ isXlink,
+ xlinkNS,
+ getXlinkProp,
+ isBooleanAttr,
+ isEnumeratedAttr,
+ isFalsyAttrValue
+} from 'web/util/index'
+
+function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ const opts = vnode.componentOptions
+ if (isDef(opts) && opts.Ctor.options.inheritAttrs === false) {
+ return
+ }
+ if (isUndef(oldVnode.data.attrs) && isUndef(vnode.data.attrs)) {
+ return
+ }
+ let key, cur, old
+ const elm = vnode.elm
+ const oldAttrs = oldVnode.data.attrs || {}
+ let attrs: any = vnode.data.attrs || {}
+ // clone observed objects, as the user probably wants to mutate it
+ if (isDef(attrs.__ob__)) {
+ attrs = vnode.data.attrs = extend({}, attrs)
+ }
+
+ for (key in attrs) {
+ cur = attrs[key]
+ old = oldAttrs[key]
+ if (old !== cur) {
+ setAttr(elm, key, cur)
+ }
+ }
+ // #4391: in IE9, setting type can reset value for input[type=radio]
+ // #6666: IE/Edge forces progress value down to 1 before setting a max
+ /* istanbul ignore if */
+ if ((isIE || isEdge) && attrs.value !== oldAttrs.value) {
+ setAttr(elm, 'value', attrs.value)
+ }
+ for (key in oldAttrs) {
+ if (isUndef(attrs[key])) {
+ if (isXlink(key)) {
+ elm.removeAttributeNS(xlinkNS, getXlinkProp(key))
+ } else if (!isEnumeratedAttr(key)) {
+ elm.removeAttribute(key)
+ }
+ }
+ }
+}
+
+function setAttr (el: Element, key: string, value: any) {
+ if (el.tagName.indexOf('-') > -1) {
+ baseSetAttr(el, key, value)
+ } else if (isBooleanAttr(key)) {
+ // set attribute for blank value
+ // e.g. <option disabled>Select one</option>
+ if (isFalsyAttrValue(value)) {
+ el.removeAttribute(key)
+ } else {
+ // technically allowfullscreen is a boolean attribute for <iframe>,
+ // but Flash expects a value of "true" when used on <embed> tag
+ value = key === 'allowfullscreen' && el.tagName === 'EMBED'
+ ? 'true'
+ : key
+ el.setAttribute(key, value)
+ }
+ } else if (isEnumeratedAttr(key)) {
+ el.setAttribute(key, isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true')
+ } else if (isXlink(key)) {
+ if (isFalsyAttrValue(value)) {
+ el.removeAttributeNS(xlinkNS, getXlinkProp(key))
+ } else {
+ el.setAttributeNS(xlinkNS, key, value)
+ }
+ } else {
+ baseSetAttr(el, key, value)
+ }
+}
+
+function baseSetAttr (el, key, value) {
+ if (isFalsyAttrValue(value)) {
+ el.removeAttribute(key)
+ } else {
+ // #7138: IE10 & 11 fires input event when setting placeholder on
+ // <textarea>... block the first input event and remove the blocker
+ // immediately.
+ /* istanbul ignore if */
+ if (
+ isIE && !isIE9 &&
+ el.tagName === 'TEXTAREA' &&
+ key === 'placeholder' && !el.__ieph
+ ) {
+ const blocker = e => {
+ e.stopImmediatePropagation()
+ el.removeEventListener('input', blocker)
+ }
+ el.addEventListener('input', blocker)
+ // $flow-disable-line
+ el.__ieph = true /* IE placeholder patched */
+ }
+ el.setAttribute(key, value)
+ }
+}
+
+export default {
+ create: updateAttrs,
+ update: updateAttrs
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/class.js b/node_modules/vue/src/platforms/web/runtime/modules/class.js
new file mode 100644
index 00000000..29fd2c11
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/class.js
@@ -0,0 +1,48 @@
+/* @flow */
+
+import {
+ isDef,
+ isUndef
+} from 'shared/util'
+
+import {
+ concat,
+ stringifyClass,
+ genClassForVnode
+} from 'web/util/index'
+
+function updateClass (oldVnode: any, vnode: any) {
+ const el = vnode.elm
+ const data: VNodeData = vnode.data
+ const oldData: VNodeData = oldVnode.data
+ if (
+ isUndef(data.staticClass) &&
+ isUndef(data.class) && (
+ isUndef(oldData) || (
+ isUndef(oldData.staticClass) &&
+ isUndef(oldData.class)
+ )
+ )
+ ) {
+ return
+ }
+
+ let cls = genClassForVnode(vnode)
+
+ // handle transition classes
+ const transitionClass = el._transitionClasses
+ if (isDef(transitionClass)) {
+ cls = concat(cls, stringifyClass(transitionClass))
+ }
+
+ // set the class
+ if (cls !== el._prevClass) {
+ el.setAttribute('class', cls)
+ el._prevClass = cls
+ }
+}
+
+export default {
+ create: updateClass,
+ update: updateClass
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/dom-props.js b/node_modules/vue/src/platforms/web/runtime/modules/dom-props.js
new file mode 100644
index 00000000..f3888aed
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/dom-props.js
@@ -0,0 +1,95 @@
+/* @flow */
+
+import { isDef, isUndef, extend, toNumber } from 'shared/util'
+
+function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (isUndef(oldVnode.data.domProps) && isUndef(vnode.data.domProps)) {
+ return
+ }
+ let key, cur
+ const elm: any = vnode.elm
+ const oldProps = oldVnode.data.domProps || {}
+ let props = vnode.data.domProps || {}
+ // clone observed objects, as the user probably wants to mutate it
+ if (isDef(props.__ob__)) {
+ props = vnode.data.domProps = extend({}, props)
+ }
+
+ for (key in oldProps) {
+ if (isUndef(props[key])) {
+ elm[key] = ''
+ }
+ }
+ for (key in props) {
+ cur = props[key]
+ // ignore children if the node has textContent or innerHTML,
+ // as these will throw away existing DOM nodes and cause removal errors
+ // on subsequent patches (#3360)
+ if (key === 'textContent' || key === 'innerHTML') {
+ if (vnode.children) vnode.children.length = 0
+ if (cur === oldProps[key]) continue
+ // #6601 work around Chrome version <= 55 bug where single textNode
+ // replaced by innerHTML/textContent retains its parentNode property
+ if (elm.childNodes.length === 1) {
+ elm.removeChild(elm.childNodes[0])
+ }
+ }
+
+ if (key === 'value') {
+ // store value as _value as well since
+ // non-string values will be stringified
+ elm._value = cur
+ // avoid resetting cursor position when value is the same
+ const strCur = isUndef(cur) ? '' : String(cur)
+ if (shouldUpdateValue(elm, strCur)) {
+ elm.value = strCur
+ }
+ } else {
+ elm[key] = cur
+ }
+ }
+}
+
+// check platforms/web/util/attrs.js acceptValue
+type acceptValueElm = HTMLInputElement | HTMLSelectElement | HTMLOptionElement;
+
+function shouldUpdateValue (elm: acceptValueElm, checkVal: string): boolean {
+ return (!elm.composing && (
+ elm.tagName === 'OPTION' ||
+ isNotInFocusAndDirty(elm, checkVal) ||
+ isDirtyWithModifiers(elm, checkVal)
+ ))
+}
+
+function isNotInFocusAndDirty (elm: acceptValueElm, checkVal: string): boolean {
+ // return true when textbox (.number and .trim) loses focus and its value is
+ // not equal to the updated value
+ let notInFocus = true
+ // #6157
+ // work around IE bug when accessing document.activeElement in an iframe
+ try { notInFocus = document.activeElement !== elm } catch (e) {}
+ return notInFocus && elm.value !== checkVal
+}
+
+function isDirtyWithModifiers (elm: any, newVal: string): boolean {
+ const value = elm.value
+ const modifiers = elm._vModifiers // injected by v-model runtime
+ if (isDef(modifiers)) {
+ if (modifiers.lazy) {
+ // inputs with lazy should only be updated when not in focus
+ return false
+ }
+ if (modifiers.number) {
+ return toNumber(value) !== toNumber(newVal)
+ }
+ if (modifiers.trim) {
+ return value.trim() !== newVal.trim()
+ }
+ }
+ return value !== newVal
+}
+
+export default {
+ create: updateDOMProps,
+ update: updateDOMProps
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/events.js b/node_modules/vue/src/platforms/web/runtime/modules/events.js
new file mode 100644
index 00000000..1e71b667
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/events.js
@@ -0,0 +1,87 @@
+/* @flow */
+
+import { isDef, isUndef } from 'shared/util'
+import { updateListeners } from 'core/vdom/helpers/index'
+import { withMacroTask, isIE, supportsPassive } from 'core/util/index'
+import { RANGE_TOKEN, CHECKBOX_RADIO_TOKEN } from 'web/compiler/directives/model'
+
+// normalize v-model event tokens that can only be determined at runtime.
+// it's important to place the event as the first in the array because
+// the whole point is ensuring the v-model callback gets called before
+// user-attached handlers.
+function normalizeEvents (on) {
+ /* istanbul ignore if */
+ if (isDef(on[RANGE_TOKEN])) {
+ // IE input[type=range] only supports `change` event
+ const event = isIE ? 'change' : 'input'
+ on[event] = [].concat(on[RANGE_TOKEN], on[event] || [])
+ delete on[RANGE_TOKEN]
+ }
+ // This was originally intended to fix #4521 but no longer necessary
+ // after 2.5. Keeping it for backwards compat with generated code from < 2.4
+ /* istanbul ignore if */
+ if (isDef(on[CHECKBOX_RADIO_TOKEN])) {
+ on.change = [].concat(on[CHECKBOX_RADIO_TOKEN], on.change || [])
+ delete on[CHECKBOX_RADIO_TOKEN]
+ }
+}
+
+let target: any
+
+function createOnceHandler (handler, event, capture) {
+ const _target = target // save current target element in closure
+ return function onceHandler () {
+ const res = handler.apply(null, arguments)
+ if (res !== null) {
+ remove(event, onceHandler, capture, _target)
+ }
+ }
+}
+
+function add (
+ event: string,
+ handler: Function,
+ once: boolean,
+ capture: boolean,
+ passive: boolean
+) {
+ handler = withMacroTask(handler)
+ if (once) handler = createOnceHandler(handler, event, capture)
+ target.addEventListener(
+ event,
+ handler,
+ supportsPassive
+ ? { capture, passive }
+ : capture
+ )
+}
+
+function remove (
+ event: string,
+ handler: Function,
+ capture: boolean,
+ _target?: HTMLElement
+) {
+ (_target || target).removeEventListener(
+ event,
+ handler._withTask || handler,
+ capture
+ )
+}
+
+function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (isUndef(oldVnode.data.on) && isUndef(vnode.data.on)) {
+ return
+ }
+ const on = vnode.data.on || {}
+ const oldOn = oldVnode.data.on || {}
+ target = vnode.elm
+ normalizeEvents(on)
+ updateListeners(on, oldOn, add, remove, vnode.context)
+ target = undefined
+}
+
+export default {
+ create: updateDOMListeners,
+ update: updateDOMListeners
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/index.js b/node_modules/vue/src/platforms/web/runtime/modules/index.js
new file mode 100644
index 00000000..9f6ad8f9
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/index.js
@@ -0,0 +1,15 @@
+import attrs from './attrs'
+import klass from './class'
+import events from './events'
+import domProps from './dom-props'
+import style from './style'
+import transition from './transition'
+
+export default [
+ attrs,
+ klass,
+ events,
+ domProps,
+ style,
+ transition
+]
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/style.js b/node_modules/vue/src/platforms/web/runtime/modules/style.js
new file mode 100644
index 00000000..29e1c3c1
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/style.js
@@ -0,0 +1,93 @@
+/* @flow */
+
+import { getStyle, normalizeStyleBinding } from 'web/util/style'
+import { cached, camelize, extend, isDef, isUndef } from 'shared/util'
+
+const cssVarRE = /^--/
+const importantRE = /\s*!important$/
+const setProp = (el, name, val) => {
+ /* istanbul ignore if */
+ if (cssVarRE.test(name)) {
+ el.style.setProperty(name, val)
+ } else if (importantRE.test(val)) {
+ el.style.setProperty(name, val.replace(importantRE, ''), 'important')
+ } else {
+ const normalizedName = normalize(name)
+ if (Array.isArray(val)) {
+ // Support values array created by autoprefixer, e.g.
+ // {display: ["-webkit-box", "-ms-flexbox", "flex"]}
+ // Set them one by one, and the browser will only set those it can recognize
+ for (let i = 0, len = val.length; i < len; i++) {
+ el.style[normalizedName] = val[i]
+ }
+ } else {
+ el.style[normalizedName] = val
+ }
+ }
+}
+
+const vendorNames = ['Webkit', 'Moz', 'ms']
+
+let emptyStyle
+const normalize = cached(function (prop) {
+ emptyStyle = emptyStyle || document.createElement('div').style
+ prop = camelize(prop)
+ if (prop !== 'filter' && (prop in emptyStyle)) {
+ return prop
+ }
+ const capName = prop.charAt(0).toUpperCase() + prop.slice(1)
+ for (let i = 0; i < vendorNames.length; i++) {
+ const name = vendorNames[i] + capName
+ if (name in emptyStyle) {
+ return name
+ }
+ }
+})
+
+function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ const data = vnode.data
+ const oldData = oldVnode.data
+
+ if (isUndef(data.staticStyle) && isUndef(data.style) &&
+ isUndef(oldData.staticStyle) && isUndef(oldData.style)
+ ) {
+ return
+ }
+
+ let cur, name
+ const el: any = vnode.elm
+ const oldStaticStyle: any = oldData.staticStyle
+ const oldStyleBinding: any = oldData.normalizedStyle || oldData.style || {}
+
+ // if static style exists, stylebinding already merged into it when doing normalizeStyleData
+ const oldStyle = oldStaticStyle || oldStyleBinding
+
+ const style = normalizeStyleBinding(vnode.data.style) || {}
+
+ // store normalized style under a different key for next diff
+ // make sure to clone it if it's reactive, since the user likely wants
+ // to mutate it.
+ vnode.data.normalizedStyle = isDef(style.__ob__)
+ ? extend({}, style)
+ : style
+
+ const newStyle = getStyle(vnode, true)
+
+ for (name in oldStyle) {
+ if (isUndef(newStyle[name])) {
+ setProp(el, name, '')
+ }
+ }
+ for (name in newStyle) {
+ cur = newStyle[name]
+ if (cur !== oldStyle[name]) {
+ // ie9 setting to null has no effect, must use empty string
+ setProp(el, name, cur == null ? '' : cur)
+ }
+ }
+}
+
+export default {
+ create: updateStyle,
+ update: updateStyle
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/transition.js b/node_modules/vue/src/platforms/web/runtime/modules/transition.js
new file mode 100644
index 00000000..0796b5da
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/transition.js
@@ -0,0 +1,343 @@
+/* @flow */
+
+import { inBrowser, isIE9, warn } from 'core/util/index'
+import { mergeVNodeHook } from 'core/vdom/helpers/index'
+import { activeInstance } from 'core/instance/lifecycle'
+
+import {
+ once,
+ isDef,
+ isUndef,
+ isObject,
+ toNumber
+} from 'shared/util'
+
+import {
+ nextFrame,
+ resolveTransition,
+ whenTransitionEnds,
+ addTransitionClass,
+ removeTransitionClass
+} from '../transition-util'
+
+export function enter (vnode: VNodeWithData, toggleDisplay: ?() => void) {
+ const el: any = vnode.elm
+
+ // call leave callback now
+ if (isDef(el._leaveCb)) {
+ el._leaveCb.cancelled = true
+ el._leaveCb()
+ }
+
+ const data = resolveTransition(vnode.data.transition)
+ if (isUndef(data)) {
+ return
+ }
+
+ /* istanbul ignore if */
+ if (isDef(el._enterCb) || el.nodeType !== 1) {
+ return
+ }
+
+ const {
+ css,
+ type,
+ enterClass,
+ enterToClass,
+ enterActiveClass,
+ appearClass,
+ appearToClass,
+ appearActiveClass,
+ beforeEnter,
+ enter,
+ afterEnter,
+ enterCancelled,
+ beforeAppear,
+ appear,
+ afterAppear,
+ appearCancelled,
+ duration
+ } = data
+
+ // activeInstance will always be the <transition> component managing this
+ // transition. One edge case to check is when the <transition> is placed
+ // as the root node of a child component. In that case we need to check
+ // <transition>'s parent for appear check.
+ let context = activeInstance
+ let transitionNode = activeInstance.$vnode
+ while (transitionNode && transitionNode.parent) {
+ transitionNode = transitionNode.parent
+ context = transitionNode.context
+ }
+
+ const isAppear = !context._isMounted || !vnode.isRootInsert
+
+ if (isAppear && !appear && appear !== '') {
+ return
+ }
+
+ const startClass = isAppear && appearClass
+ ? appearClass
+ : enterClass
+ const activeClass = isAppear && appearActiveClass
+ ? appearActiveClass
+ : enterActiveClass
+ const toClass = isAppear && appearToClass
+ ? appearToClass
+ : enterToClass
+
+ const beforeEnterHook = isAppear
+ ? (beforeAppear || beforeEnter)
+ : beforeEnter
+ const enterHook = isAppear
+ ? (typeof appear === 'function' ? appear : enter)
+ : enter
+ const afterEnterHook = isAppear
+ ? (afterAppear || afterEnter)
+ : afterEnter
+ const enterCancelledHook = isAppear
+ ? (appearCancelled || enterCancelled)
+ : enterCancelled
+
+ const explicitEnterDuration: any = toNumber(
+ isObject(duration)
+ ? duration.enter
+ : duration
+ )
+
+ if (process.env.NODE_ENV !== 'production' && explicitEnterDuration != null) {
+ checkDuration(explicitEnterDuration, 'enter', vnode)
+ }
+
+ const expectsCSS = css !== false && !isIE9
+ const userWantsControl = getHookArgumentsLength(enterHook)
+
+ const cb = el._enterCb = once(() => {
+ if (expectsCSS) {
+ removeTransitionClass(el, toClass)
+ removeTransitionClass(el, activeClass)
+ }
+ if (cb.cancelled) {
+ if (expectsCSS) {
+ removeTransitionClass(el, startClass)
+ }
+ enterCancelledHook && enterCancelledHook(el)
+ } else {
+ afterEnterHook && afterEnterHook(el)
+ }
+ el._enterCb = null
+ })
+
+ if (!vnode.data.show) {
+ // remove pending leave element on enter by injecting an insert hook
+ mergeVNodeHook(vnode, 'insert', () => {
+ const parent = el.parentNode
+ const pendingNode = parent && parent._pending && parent._pending[vnode.key]
+ if (pendingNode &&
+ pendingNode.tag === vnode.tag &&
+ pendingNode.elm._leaveCb
+ ) {
+ pendingNode.elm._leaveCb()
+ }
+ enterHook && enterHook(el, cb)
+ })
+ }
+
+ // start enter transition
+ beforeEnterHook && beforeEnterHook(el)
+ if (expectsCSS) {
+ addTransitionClass(el, startClass)
+ addTransitionClass(el, activeClass)
+ nextFrame(() => {
+ removeTransitionClass(el, startClass)
+ if (!cb.cancelled) {
+ addTransitionClass(el, toClass)
+ if (!userWantsControl) {
+ if (isValidDuration(explicitEnterDuration)) {
+ setTimeout(cb, explicitEnterDuration)
+ } else {
+ whenTransitionEnds(el, type, cb)
+ }
+ }
+ }
+ })
+ }
+
+ if (vnode.data.show) {
+ toggleDisplay && toggleDisplay()
+ enterHook && enterHook(el, cb)
+ }
+
+ if (!expectsCSS && !userWantsControl) {
+ cb()
+ }
+}
+
+export function leave (vnode: VNodeWithData, rm: Function) {
+ const el: any = vnode.elm
+
+ // call enter callback now
+ if (isDef(el._enterCb)) {
+ el._enterCb.cancelled = true
+ el._enterCb()
+ }
+
+ const data = resolveTransition(vnode.data.transition)
+ if (isUndef(data) || el.nodeType !== 1) {
+ return rm()
+ }
+
+ /* istanbul ignore if */
+ if (isDef(el._leaveCb)) {
+ return
+ }
+
+ const {
+ css,
+ type,
+ leaveClass,
+ leaveToClass,
+ leaveActiveClass,
+ beforeLeave,
+ leave,
+ afterLeave,
+ leaveCancelled,
+ delayLeave,
+ duration
+ } = data
+
+ const expectsCSS = css !== false && !isIE9
+ const userWantsControl = getHookArgumentsLength(leave)
+
+ const explicitLeaveDuration: any = toNumber(
+ isObject(duration)
+ ? duration.leave
+ : duration
+ )
+
+ if (process.env.NODE_ENV !== 'production' && isDef(explicitLeaveDuration)) {
+ checkDuration(explicitLeaveDuration, 'leave', vnode)
+ }
+
+ const cb = el._leaveCb = once(() => {
+ if (el.parentNode && el.parentNode._pending) {
+ el.parentNode._pending[vnode.key] = null
+ }
+ if (expectsCSS) {
+ removeTransitionClass(el, leaveToClass)
+ removeTransitionClass(el, leaveActiveClass)
+ }
+ if (cb.cancelled) {
+ if (expectsCSS) {
+ removeTransitionClass(el, leaveClass)
+ }
+ leaveCancelled && leaveCancelled(el)
+ } else {
+ rm()
+ afterLeave && afterLeave(el)
+ }
+ el._leaveCb = null
+ })
+
+ if (delayLeave) {
+ delayLeave(performLeave)
+ } else {
+ performLeave()
+ }
+
+ function performLeave () {
+ // the delayed leave may have already been cancelled
+ if (cb.cancelled) {
+ return
+ }
+ // record leaving element
+ if (!vnode.data.show) {
+ (el.parentNode._pending || (el.parentNode._pending = {}))[(vnode.key: any)] = vnode
+ }
+ beforeLeave && beforeLeave(el)
+ if (expectsCSS) {
+ addTransitionClass(el, leaveClass)
+ addTransitionClass(el, leaveActiveClass)
+ nextFrame(() => {
+ removeTransitionClass(el, leaveClass)
+ if (!cb.cancelled) {
+ addTransitionClass(el, leaveToClass)
+ if (!userWantsControl) {
+ if (isValidDuration(explicitLeaveDuration)) {
+ setTimeout(cb, explicitLeaveDuration)
+ } else {
+ whenTransitionEnds(el, type, cb)
+ }
+ }
+ }
+ })
+ }
+ leave && leave(el, cb)
+ if (!expectsCSS && !userWantsControl) {
+ cb()
+ }
+ }
+}
+
+// only used in dev mode
+function checkDuration (val, name, vnode) {
+ if (typeof val !== 'number') {
+ warn(
+ `<transition> explicit ${name} duration is not a valid number - ` +
+ `got ${JSON.stringify(val)}.`,
+ vnode.context
+ )
+ } else if (isNaN(val)) {
+ warn(
+ `<transition> explicit ${name} duration is NaN - ` +
+ 'the duration expression might be incorrect.',
+ vnode.context
+ )
+ }
+}
+
+function isValidDuration (val) {
+ return typeof val === 'number' && !isNaN(val)
+}
+
+/**
+ * Normalize a transition hook's argument length. The hook may be:
+ * - a merged hook (invoker) with the original in .fns
+ * - a wrapped component method (check ._length)
+ * - a plain function (.length)
+ */
+function getHookArgumentsLength (fn: Function): boolean {
+ if (isUndef(fn)) {
+ return false
+ }
+ const invokerFns = fn.fns
+ if (isDef(invokerFns)) {
+ // invoker
+ return getHookArgumentsLength(
+ Array.isArray(invokerFns)
+ ? invokerFns[0]
+ : invokerFns
+ )
+ } else {
+ return (fn._length || fn.length) > 1
+ }
+}
+
+function _enter (_: any, vnode: VNodeWithData) {
+ if (vnode.data.show !== true) {
+ enter(vnode)
+ }
+}
+
+export default inBrowser ? {
+ create: _enter,
+ activate: _enter,
+ remove (vnode: VNode, rm: Function) {
+ /* istanbul ignore else */
+ if (vnode.data.show !== true) {
+ leave(vnode, rm)
+ } else {
+ rm()
+ }
+ }
+} : {}