aboutsummaryrefslogtreecommitdiff
path: root/node_modules/vue/src/platforms/weex/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/vue/src/platforms/weex/runtime')
-rw-r--r--node_modules/vue/src/platforms/weex/runtime/components/index.js9
-rw-r--r--node_modules/vue/src/platforms/weex/runtime/components/richtext.js82
-rw-r--r--node_modules/vue/src/platforms/weex/runtime/components/transition-group.js148
-rw-r--r--node_modules/vue/src/platforms/weex/runtime/components/transition.js9
-rwxr-xr-xnode_modules/vue/src/platforms/weex/runtime/directives/index.js2
-rwxr-xr-xnode_modules/vue/src/platforms/weex/runtime/index.js42
-rwxr-xr-xnode_modules/vue/src/platforms/weex/runtime/modules/attrs.js44
-rwxr-xr-xnode_modules/vue/src/platforms/weex/runtime/modules/class.js75
-rwxr-xr-xnode_modules/vue/src/platforms/weex/runtime/modules/events.js57
-rwxr-xr-xnode_modules/vue/src/platforms/weex/runtime/modules/index.js13
-rwxr-xr-xnode_modules/vue/src/platforms/weex/runtime/modules/style.js84
-rw-r--r--node_modules/vue/src/platforms/weex/runtime/modules/transition.js270
-rwxr-xr-xnode_modules/vue/src/platforms/weex/runtime/node-ops.js91
-rw-r--r--node_modules/vue/src/platforms/weex/runtime/patch.js16
-rw-r--r--node_modules/vue/src/platforms/weex/runtime/recycle-list/render-component-template.js34
-rw-r--r--node_modules/vue/src/platforms/weex/runtime/recycle-list/virtual-component.js136
-rw-r--r--node_modules/vue/src/platforms/weex/runtime/text-node.js9
17 files changed, 1121 insertions, 0 deletions
diff --git a/node_modules/vue/src/platforms/weex/runtime/components/index.js b/node_modules/vue/src/platforms/weex/runtime/components/index.js
new file mode 100644
index 00000000..449db1ad
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/components/index.js
@@ -0,0 +1,9 @@
+import Richtext from './richtext'
+import Transition from './transition'
+import TransitionGroup from './transition-group'
+
+export default {
+ Richtext,
+ Transition,
+ TransitionGroup
+}
diff --git a/node_modules/vue/src/platforms/weex/runtime/components/richtext.js b/node_modules/vue/src/platforms/weex/runtime/components/richtext.js
new file mode 100644
index 00000000..a9164c7a
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/components/richtext.js
@@ -0,0 +1,82 @@
+/* @flow */
+
+function getVNodeType (vnode: VNode): string {
+ if (!vnode.tag) {
+ return ''
+ }
+ return vnode.tag.replace(/vue\-component\-(\d+\-)?/, '')
+}
+
+function isSimpleSpan (vnode: VNode): boolean {
+ return vnode.children &&
+ vnode.children.length === 1 &&
+ !vnode.children[0].tag
+}
+
+function parseStyle (vnode: VNode): Object | void {
+ if (!vnode || !vnode.data) {
+ return
+ }
+ const { staticStyle, staticClass } = vnode.data
+ if (vnode.data.style || vnode.data.class || staticStyle || staticClass) {
+ const styles = Object.assign({}, staticStyle, vnode.data.style)
+ const cssMap = vnode.context.$options.style || {}
+ const classList = [].concat(staticClass, vnode.data.class)
+ classList.forEach(name => {
+ if (name && cssMap[name]) {
+ Object.assign(styles, cssMap[name])
+ }
+ })
+ return styles
+ }
+}
+
+function convertVNodeChildren (children: Array<VNode>): Array<VNode> | void {
+ if (!children.length) {
+ return
+ }
+
+ return children.map(vnode => {
+ const type: string = getVNodeType(vnode)
+ const props: Object = { type }
+
+ // convert raw text node
+ if (!type) {
+ props.type = 'span'
+ props.attr = {
+ value: (vnode.text || '').trim()
+ }
+ } else {
+ props.style = parseStyle(vnode)
+ if (vnode.data) {
+ props.attr = vnode.data.attrs
+ if (vnode.data.on) {
+ props.events = vnode.data.on
+ }
+ }
+ if (type === 'span' && isSimpleSpan(vnode)) {
+ props.attr = props.attr || {}
+ props.attr.value = vnode.children[0].text.trim()
+ return props
+ }
+ }
+
+ if (vnode.children && vnode.children.length) {
+ props.children = convertVNodeChildren(vnode.children)
+ }
+
+ return props
+ })
+}
+
+export default {
+ name: 'richtext',
+ render (h: Function) {
+ return h('weex:richtext', {
+ on: this._events,
+ attrs: {
+ value: convertVNodeChildren(this.$options._renderChildren || [])
+ }
+ })
+ }
+}
diff --git a/node_modules/vue/src/platforms/weex/runtime/components/transition-group.js b/node_modules/vue/src/platforms/weex/runtime/components/transition-group.js
new file mode 100644
index 00000000..4a65965f
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/components/transition-group.js
@@ -0,0 +1,148 @@
+import { warn, extend } from 'core/util/index'
+import { transitionProps, extractTransitionData } from './transition'
+
+const props = extend({
+ tag: String,
+ moveClass: String
+}, transitionProps)
+
+delete props.mode
+
+export default {
+ props,
+
+ created () {
+ const dom = this.$requireWeexModule('dom')
+ this.getPosition = el => new Promise((resolve, reject) => {
+ dom.getComponentRect(el.ref, res => {
+ if (!res.result) {
+ reject(new Error(`failed to get rect for element: ${el.tag}`))
+ } else {
+ resolve(res.size)
+ }
+ })
+ })
+
+ const animation = this.$requireWeexModule('animation')
+ this.animate = (el, options) => new Promise(resolve => {
+ animation.transition(el.ref, options, resolve)
+ })
+ },
+
+ render (h) {
+ const tag = this.tag || this.$vnode.data.tag || 'span'
+ const map = Object.create(null)
+ const prevChildren = this.prevChildren = this.children
+ const rawChildren = this.$slots.default || []
+ const children = this.children = []
+ const transitionData = extractTransitionData(this)
+
+ for (let i = 0; i < rawChildren.length; i++) {
+ const c = rawChildren[i]
+ if (c.tag) {
+ if (c.key != null && String(c.key).indexOf('__vlist') !== 0) {
+ children.push(c)
+ map[c.key] = c
+ ;(c.data || (c.data = {})).transition = transitionData
+ } else if (process.env.NODE_ENV !== 'production') {
+ const opts = c.componentOptions
+ const name = opts
+ ? (opts.Ctor.options.name || opts.tag)
+ : c.tag
+ warn(`<transition-group> children must be keyed: <${name}>`)
+ }
+ }
+ }
+
+ if (prevChildren) {
+ const kept = []
+ const removed = []
+ prevChildren.forEach(c => {
+ c.data.transition = transitionData
+
+ // TODO: record before patch positions
+
+ if (map[c.key]) {
+ kept.push(c)
+ } else {
+ removed.push(c)
+ }
+ })
+ this.kept = h(tag, null, kept)
+ this.removed = removed
+ }
+
+ return h(tag, null, children)
+ },
+
+ beforeUpdate () {
+ // force removing pass
+ this.__patch__(
+ this._vnode,
+ this.kept,
+ false, // hydrating
+ true // removeOnly (!important, avoids unnecessary moves)
+ )
+ this._vnode = this.kept
+ },
+
+ updated () {
+ const children = this.prevChildren
+ const moveClass = this.moveClass || ((this.name || 'v') + '-move')
+ const moveData = children.length && this.getMoveData(children[0].context, moveClass)
+ if (!moveData) {
+ return
+ }
+
+ // TODO: finish implementing move animations once
+ // we have access to sync getComponentRect()
+
+ // children.forEach(callPendingCbs)
+
+ // Promise.all(children.map(c => {
+ // const oldPos = c.data.pos
+ // const newPos = c.data.newPos
+ // const dx = oldPos.left - newPos.left
+ // const dy = oldPos.top - newPos.top
+ // if (dx || dy) {
+ // c.data.moved = true
+ // return this.animate(c.elm, {
+ // styles: {
+ // transform: `translate(${dx}px,${dy}px)`
+ // }
+ // })
+ // }
+ // })).then(() => {
+ // children.forEach(c => {
+ // if (c.data.moved) {
+ // this.animate(c.elm, {
+ // styles: {
+ // transform: ''
+ // },
+ // duration: moveData.duration || 0,
+ // delay: moveData.delay || 0,
+ // timingFunction: moveData.timingFunction || 'linear'
+ // })
+ // }
+ // })
+ // })
+ },
+
+ methods: {
+ getMoveData (context, moveClass) {
+ const stylesheet = context.$options.style || {}
+ return stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][moveClass]
+ }
+ }
+}
+
+// function callPendingCbs (c) {
+// /* istanbul ignore if */
+// if (c.elm._moveCb) {
+// c.elm._moveCb()
+// }
+// /* istanbul ignore if */
+// if (c.elm._enterCb) {
+// c.elm._enterCb()
+// }
+// }
diff --git a/node_modules/vue/src/platforms/weex/runtime/components/transition.js b/node_modules/vue/src/platforms/weex/runtime/components/transition.js
new file mode 100644
index 00000000..20ba632d
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/components/transition.js
@@ -0,0 +1,9 @@
+// reuse same transition component logic from web
+export {
+ transitionProps,
+ extractTransitionData
+} from 'web/runtime/components/transition'
+
+import Transition from 'web/runtime/components/transition'
+
+export default Transition
diff --git a/node_modules/vue/src/platforms/weex/runtime/directives/index.js b/node_modules/vue/src/platforms/weex/runtime/directives/index.js
new file mode 100755
index 00000000..efba7fa6
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/directives/index.js
@@ -0,0 +1,2 @@
+export default {
+}
diff --git a/node_modules/vue/src/platforms/weex/runtime/index.js b/node_modules/vue/src/platforms/weex/runtime/index.js
new file mode 100755
index 00000000..b8e09305
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/index.js
@@ -0,0 +1,42 @@
+/* @flow */
+
+import Vue from 'core/index'
+import { patch } from 'weex/runtime/patch'
+import { mountComponent } from 'core/instance/lifecycle'
+import platformDirectives from 'weex/runtime/directives/index'
+import platformComponents from 'weex/runtime/components/index'
+
+import {
+ query,
+ mustUseProp,
+ isReservedTag,
+ isRuntimeComponent,
+ isUnknownElement
+} from 'weex/util/element'
+
+// install platform specific utils
+Vue.config.mustUseProp = mustUseProp
+Vue.config.isReservedTag = isReservedTag
+Vue.config.isRuntimeComponent = isRuntimeComponent
+Vue.config.isUnknownElement = isUnknownElement
+
+// install platform runtime directives and components
+Vue.options.directives = platformDirectives
+Vue.options.components = platformComponents
+
+// install platform patch function
+Vue.prototype.__patch__ = patch
+
+// wrap mount
+Vue.prototype.$mount = function (
+ el?: any,
+ hydrating?: boolean
+): Component {
+ return mountComponent(
+ this,
+ el && query(el, this.$document),
+ hydrating
+ )
+}
+
+export default Vue
diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/attrs.js b/node_modules/vue/src/platforms/weex/runtime/modules/attrs.js
new file mode 100755
index 00000000..1b6185ca
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/modules/attrs.js
@@ -0,0 +1,44 @@
+/* @flow */
+
+import { extend } from 'shared/util'
+
+function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (!oldVnode.data.attrs && !vnode.data.attrs) {
+ return
+ }
+ let key, cur, old
+ const elm = vnode.elm
+ const oldAttrs = oldVnode.data.attrs || {}
+ let attrs = vnode.data.attrs || {}
+ // clone observed objects, as the user probably wants to mutate it
+ if (attrs.__ob__) {
+ attrs = vnode.data.attrs = extend({}, attrs)
+ }
+
+ const supportBatchUpdate = typeof elm.setAttrs === 'function'
+ const batchedAttrs = {}
+ for (key in attrs) {
+ cur = attrs[key]
+ old = oldAttrs[key]
+ if (old !== cur) {
+ supportBatchUpdate
+ ? (batchedAttrs[key] = cur)
+ : elm.setAttr(key, cur)
+ }
+ }
+ for (key in oldAttrs) {
+ if (attrs[key] == null) {
+ supportBatchUpdate
+ ? (batchedAttrs[key] = undefined)
+ : elm.setAttr(key)
+ }
+ }
+ if (supportBatchUpdate) {
+ elm.setAttrs(batchedAttrs)
+ }
+}
+
+export default {
+ create: updateAttrs,
+ update: updateAttrs
+}
diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/class.js b/node_modules/vue/src/platforms/weex/runtime/modules/class.js
new file mode 100755
index 00000000..029b9e9e
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/modules/class.js
@@ -0,0 +1,75 @@
+/* @flow */
+
+import { extend } from 'shared/util'
+
+function updateClass (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ const el = vnode.elm
+ const ctx = vnode.context
+
+ const data: VNodeData = vnode.data
+ const oldData: VNodeData = oldVnode.data
+ if (!data.staticClass &&
+ !data.class &&
+ (!oldData || (!oldData.staticClass && !oldData.class))
+ ) {
+ return
+ }
+
+ const oldClassList = []
+ // unlike web, weex vnode staticClass is an Array
+ const oldStaticClass: any = oldData.staticClass
+ if (oldStaticClass) {
+ oldClassList.push.apply(oldClassList, oldStaticClass)
+ }
+ if (oldData.class) {
+ oldClassList.push.apply(oldClassList, oldData.class)
+ }
+
+ const classList = []
+ // unlike web, weex vnode staticClass is an Array
+ const staticClass: any = data.staticClass
+ if (staticClass) {
+ classList.push.apply(classList, staticClass)
+ }
+ if (data.class) {
+ classList.push.apply(classList, data.class)
+ }
+
+ if (typeof el.setClassList === 'function') {
+ el.setClassList(classList)
+ } else {
+ const style = getStyle(oldClassList, classList, ctx)
+ if (typeof el.setStyles === 'function') {
+ el.setStyles(style)
+ } else {
+ for (const key in style) {
+ el.setStyle(key, style[key])
+ }
+ }
+ }
+}
+
+function getStyle (oldClassList: Array<string>, classList: Array<string>, ctx: Component): Object {
+ // style is a weex-only injected object
+ // compiled from <style> tags in weex files
+ const stylesheet: any = ctx.$options.style || {}
+ const result = {}
+ classList.forEach(name => {
+ const style = stylesheet[name]
+ extend(result, style)
+ })
+ oldClassList.forEach(name => {
+ const style = stylesheet[name]
+ for (const key in style) {
+ if (!result.hasOwnProperty(key)) {
+ result[key] = ''
+ }
+ }
+ })
+ return result
+}
+
+export default {
+ create: updateClass,
+ update: updateClass
+}
diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/events.js b/node_modules/vue/src/platforms/weex/runtime/modules/events.js
new file mode 100755
index 00000000..a3f9e25a
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/modules/events.js
@@ -0,0 +1,57 @@
+/* @flow */
+
+import { updateListeners } from 'core/vdom/helpers/update-listeners'
+
+let target: any
+
+function add (
+ event: string,
+ handler: Function,
+ once: boolean,
+ capture: boolean,
+ passive?: boolean,
+ params?: Array<any>
+) {
+ if (capture) {
+ console.log('Weex do not support event in bubble phase.')
+ return
+ }
+ if (once) {
+ const oldHandler = handler
+ const _target = target // save current target element in closure
+ handler = function (ev) {
+ const res = arguments.length === 1
+ ? oldHandler(ev)
+ : oldHandler.apply(null, arguments)
+ if (res !== null) {
+ remove(event, null, null, _target)
+ }
+ }
+ }
+ target.addEvent(event, handler, params)
+}
+
+function remove (
+ event: string,
+ handler: any,
+ capture: any,
+ _target?: any
+) {
+ (_target || target).removeEvent(event)
+}
+
+function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (!oldVnode.data.on && !vnode.data.on) {
+ return
+ }
+ const on = vnode.data.on || {}
+ const oldOn = oldVnode.data.on || {}
+ target = vnode.elm
+ updateListeners(on, oldOn, add, remove, vnode.context)
+ target = undefined
+}
+
+export default {
+ create: updateDOMListeners,
+ update: updateDOMListeners
+}
diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/index.js b/node_modules/vue/src/platforms/weex/runtime/modules/index.js
new file mode 100755
index 00000000..dd384484
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/modules/index.js
@@ -0,0 +1,13 @@
+import attrs from './attrs'
+import klass from './class'
+import events from './events'
+import style from './style'
+import transition from './transition'
+
+export default [
+ attrs,
+ klass,
+ events,
+ style,
+ transition
+]
diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/style.js b/node_modules/vue/src/platforms/weex/runtime/modules/style.js
new file mode 100755
index 00000000..bdabd17b
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/modules/style.js
@@ -0,0 +1,84 @@
+/* @flow */
+
+import { extend, cached, camelize } from 'shared/util'
+
+const normalize = cached(camelize)
+
+function createStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (!vnode.data.staticStyle) {
+ updateStyle(oldVnode, vnode)
+ return
+ }
+ const elm = vnode.elm
+ const staticStyle = vnode.data.staticStyle
+ const supportBatchUpdate = typeof elm.setStyles === 'function'
+ const batchedStyles = {}
+ for (const name in staticStyle) {
+ if (staticStyle[name]) {
+ supportBatchUpdate
+ ? (batchedStyles[normalize(name)] = staticStyle[name])
+ : elm.setStyle(normalize(name), staticStyle[name])
+ }
+ }
+ if (supportBatchUpdate) {
+ elm.setStyles(batchedStyles)
+ }
+ updateStyle(oldVnode, vnode)
+}
+
+function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (!oldVnode.data.style && !vnode.data.style) {
+ return
+ }
+ let cur, name
+ const elm = vnode.elm
+ const oldStyle: any = oldVnode.data.style || {}
+ let style: any = vnode.data.style || {}
+
+ const needClone = style.__ob__
+
+ // handle array syntax
+ if (Array.isArray(style)) {
+ style = vnode.data.style = toObject(style)
+ }
+
+ // clone the style for future updates,
+ // in case the user mutates the style object in-place.
+ if (needClone) {
+ style = vnode.data.style = extend({}, style)
+ }
+
+ const supportBatchUpdate = typeof elm.setStyles === 'function'
+ const batchedStyles = {}
+ for (name in oldStyle) {
+ if (!style[name]) {
+ supportBatchUpdate
+ ? (batchedStyles[normalize(name)] = '')
+ : elm.setStyle(normalize(name), '')
+ }
+ }
+ for (name in style) {
+ cur = style[name]
+ supportBatchUpdate
+ ? (batchedStyles[normalize(name)] = cur)
+ : elm.setStyle(normalize(name), cur)
+ }
+ if (supportBatchUpdate) {
+ elm.setStyles(batchedStyles)
+ }
+}
+
+function toObject (arr) {
+ const res = {}
+ for (var i = 0; i < arr.length; i++) {
+ if (arr[i]) {
+ extend(res, arr[i])
+ }
+ }
+ return res
+}
+
+export default {
+ create: createStyle,
+ update: updateStyle
+}
diff --git a/node_modules/vue/src/platforms/weex/runtime/modules/transition.js b/node_modules/vue/src/platforms/weex/runtime/modules/transition.js
new file mode 100644
index 00000000..e474c2b3
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/modules/transition.js
@@ -0,0 +1,270 @@
+import { warn } from 'core/util/debug'
+import { extend, once, noop } from 'shared/util'
+import { activeInstance } from 'core/instance/lifecycle'
+import { resolveTransition } from 'web/runtime/transition-util'
+
+export default {
+ create: enter,
+ activate: enter,
+ remove: leave
+}
+
+function enter (_, vnode) {
+ const el = vnode.elm
+
+ // call leave callback now
+ if (el._leaveCb) {
+ el._leaveCb.cancelled = true
+ el._leaveCb()
+ }
+
+ const data = resolveTransition(vnode.data.transition)
+ if (!data) {
+ return
+ }
+
+ /* istanbul ignore if */
+ if (el._enterCb) {
+ return
+ }
+
+ const {
+ enterClass,
+ enterToClass,
+ enterActiveClass,
+ appearClass,
+ appearToClass,
+ appearActiveClass,
+ beforeEnter,
+ enter,
+ afterEnter,
+ enterCancelled,
+ beforeAppear,
+ appear,
+ afterAppear,
+ appearCancelled
+ } = data
+
+ 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 : enterClass
+ const toClass = isAppear ? appearToClass : enterToClass
+ const activeClass = isAppear ? appearActiveClass : enterActiveClass
+ 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 userWantsControl =
+ enterHook &&
+ // enterHook may be a bound method which exposes
+ // the length of original fn as _length
+ (enterHook._length || enterHook.length) > 1
+
+ const stylesheet = vnode.context.$options.style || {}
+ const startState = stylesheet[startClass]
+ const transitionProperties = (stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][activeClass]) || {}
+ const endState = getEnterTargetState(el, stylesheet, startClass, toClass, activeClass, vnode.context)
+ const needAnimation = Object.keys(endState).length > 0
+
+ const cb = el._enterCb = once(() => {
+ if (cb.cancelled) {
+ enterCancelledHook && enterCancelledHook(el)
+ } else {
+ afterEnterHook && afterEnterHook(el)
+ }
+ el._enterCb = null
+ })
+
+ // We need to wait until the native element has been inserted, but currently
+ // there's no API to do that. So we have to wait "one frame" - not entirely
+ // sure if this is guaranteed to be enough (e.g. on slow devices?)
+ setTimeout(() => {
+ const parent = el.parentNode
+ const pendingNode = parent && parent._pending && parent._pending[vnode.key]
+ if (pendingNode &&
+ pendingNode.context === vnode.context &&
+ pendingNode.tag === vnode.tag &&
+ pendingNode.elm._leaveCb
+ ) {
+ pendingNode.elm._leaveCb()
+ }
+ enterHook && enterHook(el, cb)
+
+ if (needAnimation) {
+ const animation = vnode.context.$requireWeexModule('animation')
+ animation.transition(el.ref, {
+ styles: endState,
+ duration: transitionProperties.duration || 0,
+ delay: transitionProperties.delay || 0,
+ timingFunction: transitionProperties.timingFunction || 'linear'
+ }, userWantsControl ? noop : cb)
+ } else if (!userWantsControl) {
+ cb()
+ }
+ }, 16)
+
+ // start enter transition
+ beforeEnterHook && beforeEnterHook(el)
+
+ if (startState) {
+ if (typeof el.setStyles === 'function') {
+ el.setStyles(startState)
+ } else {
+ for (const key in startState) {
+ el.setStyle(key, startState[key])
+ }
+ }
+ }
+
+ if (!needAnimation && !userWantsControl) {
+ cb()
+ }
+}
+
+function leave (vnode, rm) {
+ const el = vnode.elm
+
+ // call enter callback now
+ if (el._enterCb) {
+ el._enterCb.cancelled = true
+ el._enterCb()
+ }
+
+ const data = resolveTransition(vnode.data.transition)
+ if (!data) {
+ return rm()
+ }
+
+ if (el._leaveCb) {
+ return
+ }
+
+ const {
+ leaveClass,
+ leaveToClass,
+ leaveActiveClass,
+ beforeLeave,
+ leave,
+ afterLeave,
+ leaveCancelled,
+ delayLeave
+ } = data
+
+ const userWantsControl =
+ leave &&
+ // leave hook may be a bound method which exposes
+ // the length of original fn as _length
+ (leave._length || leave.length) > 1
+
+ const stylesheet = vnode.context.$options.style || {}
+ const startState = stylesheet[leaveClass]
+ const endState = stylesheet[leaveToClass] || stylesheet[leaveActiveClass]
+ const transitionProperties = (stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][leaveActiveClass]) || {}
+
+ const cb = el._leaveCb = once(() => {
+ if (el.parentNode && el.parentNode._pending) {
+ el.parentNode._pending[vnode.key] = null
+ }
+ if (cb.cancelled) {
+ leaveCancelled && leaveCancelled(el)
+ } else {
+ rm()
+ afterLeave && afterLeave(el)
+ }
+ el._leaveCb = null
+ })
+
+ if (delayLeave) {
+ delayLeave(performLeave)
+ } else {
+ performLeave()
+ }
+
+ function performLeave () {
+ const animation = vnode.context.$requireWeexModule('animation')
+ // 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] = vnode
+ }
+ beforeLeave && beforeLeave(el)
+
+ if (startState) {
+ animation.transition(el.ref, {
+ styles: startState
+ }, next)
+ } else {
+ next()
+ }
+
+ function next () {
+ animation.transition(el.ref, {
+ styles: endState,
+ duration: transitionProperties.duration || 0,
+ delay: transitionProperties.delay || 0,
+ timingFunction: transitionProperties.timingFunction || 'linear'
+ }, userWantsControl ? noop : cb)
+ }
+
+ leave && leave(el, cb)
+ if (!endState && !userWantsControl) {
+ cb()
+ }
+ }
+}
+
+// determine the target animation style for an entering transition.
+function getEnterTargetState (el, stylesheet, startClass, endClass, activeClass, vm) {
+ const targetState = {}
+ const startState = stylesheet[startClass]
+ const endState = stylesheet[endClass]
+ const activeState = stylesheet[activeClass]
+ // 1. fallback to element's default styling
+ if (startState) {
+ for (const key in startState) {
+ targetState[key] = el.style[key]
+ if (
+ process.env.NODE_ENV !== 'production' &&
+ targetState[key] == null &&
+ (!activeState || activeState[key] == null) &&
+ (!endState || endState[key] == null)
+ ) {
+ warn(
+ `transition property "${key}" is declared in enter starting class (.${startClass}), ` +
+ `but not declared anywhere in enter ending class (.${endClass}), ` +
+ `enter active cass (.${activeClass}) or the element's default styling. ` +
+ `Note in Weex, CSS properties need explicit values to be transitionable.`
+ )
+ }
+ }
+ }
+ // 2. if state is mixed in active state, extract them while excluding
+ // transition properties
+ if (activeState) {
+ for (const key in activeState) {
+ if (key.indexOf('transition') !== 0) {
+ targetState[key] = activeState[key]
+ }
+ }
+ }
+ // 3. explicit endState has highest priority
+ if (endState) {
+ extend(targetState, endState)
+ }
+ return targetState
+}
diff --git a/node_modules/vue/src/platforms/weex/runtime/node-ops.js b/node_modules/vue/src/platforms/weex/runtime/node-ops.js
new file mode 100755
index 00000000..0438ec5c
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/node-ops.js
@@ -0,0 +1,91 @@
+/* @flow */
+declare var document: WeexDocument;
+
+import TextNode from 'weex/runtime/text-node'
+
+export const namespaceMap = {}
+
+export function createElement (tagName: string): WeexElement {
+ return document.createElement(tagName)
+}
+
+export function createElementNS (namespace: string, tagName: string): WeexElement {
+ return document.createElement(namespace + ':' + tagName)
+}
+
+export function createTextNode (text: string) {
+ return new TextNode(text)
+}
+
+export function createComment (text: string) {
+ return document.createComment(text)
+}
+
+export function insertBefore (
+ node: WeexElement,
+ target: WeexElement,
+ before: WeexElement
+) {
+ if (target.nodeType === 3) {
+ if (node.type === 'text') {
+ node.setAttr('value', target.text)
+ target.parentNode = node
+ } else {
+ const text = createElement('text')
+ text.setAttr('value', target.text)
+ node.insertBefore(text, before)
+ }
+ return
+ }
+ node.insertBefore(target, before)
+}
+
+export function removeChild (node: WeexElement, child: WeexElement) {
+ if (child.nodeType === 3) {
+ node.setAttr('value', '')
+ return
+ }
+ node.removeChild(child)
+}
+
+export function appendChild (node: WeexElement, child: WeexElement) {
+ if (child.nodeType === 3) {
+ if (node.type === 'text') {
+ node.setAttr('value', child.text)
+ child.parentNode = node
+ } else {
+ const text = createElement('text')
+ text.setAttr('value', child.text)
+ node.appendChild(text)
+ }
+ return
+ }
+
+ node.appendChild(child)
+}
+
+export function parentNode (node: WeexElement): WeexElement | void {
+ return node.parentNode
+}
+
+export function nextSibling (node: WeexElement): WeexElement | void {
+ return node.nextSibling
+}
+
+export function tagName (node: WeexElement): string {
+ return node.type
+}
+
+export function setTextContent (node: WeexElement, text: string) {
+ if (node.parentNode) {
+ node.parentNode.setAttr('value', text)
+ }
+}
+
+export function setAttribute (node: WeexElement, key: string, val: any) {
+ node.setAttr(key, val)
+}
+
+export function setStyleScope (node: WeexElement, scopeId: string) {
+ node.setAttr('@styleScope', scopeId)
+}
diff --git a/node_modules/vue/src/platforms/weex/runtime/patch.js b/node_modules/vue/src/platforms/weex/runtime/patch.js
new file mode 100644
index 00000000..5e70d143
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/patch.js
@@ -0,0 +1,16 @@
+/* @flow */
+
+import * as nodeOps from 'weex/runtime/node-ops'
+import { createPatchFunction } from 'core/vdom/patch'
+import baseModules from 'core/vdom/modules/index'
+import platformModules from 'weex/runtime/modules/index'
+
+// the directive module should be applied last, after all
+// built-in modules have been applied.
+const modules = platformModules.concat(baseModules)
+
+export const patch: Function = createPatchFunction({
+ nodeOps,
+ modules,
+ LONG_LIST_THRESHOLD: 10
+})
diff --git a/node_modules/vue/src/platforms/weex/runtime/recycle-list/render-component-template.js b/node_modules/vue/src/platforms/weex/runtime/recycle-list/render-component-template.js
new file mode 100644
index 00000000..17e8c018
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/recycle-list/render-component-template.js
@@ -0,0 +1,34 @@
+/* @flow */
+
+import { warn } from 'core/util/debug'
+import { handleError } from 'core/util/error'
+import { RECYCLE_LIST_MARKER } from 'weex/util/index'
+import { createComponentInstanceForVnode } from 'core/vdom/create-component'
+import { resolveVirtualComponent } from './virtual-component'
+
+export function isRecyclableComponent (vnode: VNodeWithData): boolean {
+ return vnode.data.attrs
+ ? (RECYCLE_LIST_MARKER in vnode.data.attrs)
+ : false
+}
+
+export function renderRecyclableComponentTemplate (vnode: MountedComponentVNode): VNode {
+ // $flow-disable-line
+ delete vnode.data.attrs[RECYCLE_LIST_MARKER]
+ resolveVirtualComponent(vnode)
+ const vm = createComponentInstanceForVnode(vnode)
+ const render = (vm.$options: any)['@render']
+ if (render) {
+ try {
+ return render.call(vm)
+ } catch (err) {
+ handleError(err, vm, `@render`)
+ }
+ } else {
+ warn(
+ `@render function not defined on component used in <recycle-list>. ` +
+ `Make sure to declare \`recyclable="true"\` on the component's template.`,
+ vm
+ )
+ }
+}
diff --git a/node_modules/vue/src/platforms/weex/runtime/recycle-list/virtual-component.js b/node_modules/vue/src/platforms/weex/runtime/recycle-list/virtual-component.js
new file mode 100644
index 00000000..e5498d26
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/recycle-list/virtual-component.js
@@ -0,0 +1,136 @@
+/* @flow */
+
+// https://github.com/Hanks10100/weex-native-directive/tree/master/component
+
+import { mergeOptions, isPlainObject, noop } from 'core/util/index'
+import Watcher from 'core/observer/watcher'
+import { initProxy } from 'core/instance/proxy'
+import { initState, getData } from 'core/instance/state'
+import { initRender } from 'core/instance/render'
+import { initEvents } from 'core/instance/events'
+import { initProvide, initInjections } from 'core/instance/inject'
+import { initLifecycle, callHook } from 'core/instance/lifecycle'
+import { initInternalComponent, resolveConstructorOptions } from 'core/instance/init'
+import { registerComponentHook, updateComponentData } from '../../util/index'
+
+let uid = 0
+
+// override Vue.prototype._init
+function initVirtualComponent (options: Object = {}) {
+ const vm: Component = this
+ const componentId = options.componentId
+
+ // virtual component uid
+ vm._uid = `virtual-component-${uid++}`
+
+ // a flag to avoid this being observed
+ vm._isVue = true
+ // merge options
+ if (options && options._isComponent) {
+ // optimize internal component instantiation
+ // since dynamic options merging is pretty slow, and none of the
+ // internal component options needs special treatment.
+ initInternalComponent(vm, options)
+ } else {
+ vm.$options = mergeOptions(
+ resolveConstructorOptions(vm.constructor),
+ options || {},
+ vm
+ )
+ }
+
+ /* istanbul ignore else */
+ if (process.env.NODE_ENV !== 'production') {
+ initProxy(vm)
+ } else {
+ vm._renderProxy = vm
+ }
+
+ vm._self = vm
+ initLifecycle(vm)
+ initEvents(vm)
+ initRender(vm)
+ callHook(vm, 'beforeCreate')
+ initInjections(vm) // resolve injections before data/props
+ initState(vm)
+ initProvide(vm) // resolve provide after data/props
+ callHook(vm, 'created')
+
+ // send initial data to native
+ const data = vm.$options.data
+ const params = typeof data === 'function'
+ ? getData(data, vm)
+ : data || {}
+ if (isPlainObject(params)) {
+ updateComponentData(componentId, params)
+ }
+
+ registerComponentHook(componentId, 'lifecycle', 'attach', () => {
+ callHook(vm, 'beforeMount')
+
+ const updateComponent = () => {
+ vm._update(vm._vnode, false)
+ }
+ new Watcher(vm, updateComponent, noop, null, true)
+
+ vm._isMounted = true
+ callHook(vm, 'mounted')
+ })
+
+ registerComponentHook(componentId, 'lifecycle', 'detach', () => {
+ vm.$destroy()
+ })
+}
+
+// override Vue.prototype._update
+function updateVirtualComponent (vnode?: VNode) {
+ const vm: Component = this
+ const componentId = vm.$options.componentId
+ if (vm._isMounted) {
+ callHook(vm, 'beforeUpdate')
+ }
+ vm._vnode = vnode
+ if (vm._isMounted && componentId) {
+ // TODO: data should be filtered and without bindings
+ const data = Object.assign({}, vm._data)
+ updateComponentData(componentId, data, () => {
+ callHook(vm, 'updated')
+ })
+ }
+}
+
+// listening on native callback
+export function resolveVirtualComponent (vnode: MountedComponentVNode): VNode {
+ const BaseCtor = vnode.componentOptions.Ctor
+ const VirtualComponent = BaseCtor.extend({})
+ const cid = VirtualComponent.cid
+ VirtualComponent.prototype._init = initVirtualComponent
+ VirtualComponent.prototype._update = updateVirtualComponent
+
+ vnode.componentOptions.Ctor = BaseCtor.extend({
+ beforeCreate () {
+ // const vm: Component = this
+
+ // TODO: listen on all events and dispatch them to the
+ // corresponding virtual components according to the componentId.
+ // vm._virtualComponents = {}
+ const createVirtualComponent = (componentId, propsData) => {
+ // create virtual component
+ // const subVm =
+ new VirtualComponent({
+ componentId,
+ propsData
+ })
+ // if (vm._virtualComponents) {
+ // vm._virtualComponents[componentId] = subVm
+ // }
+ }
+
+ registerComponentHook(cid, 'lifecycle', 'create', createVirtualComponent)
+ },
+ beforeDestroy () {
+ delete this._virtualComponents
+ }
+ })
+}
+
diff --git a/node_modules/vue/src/platforms/weex/runtime/text-node.js b/node_modules/vue/src/platforms/weex/runtime/text-node.js
new file mode 100644
index 00000000..0720a05a
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/runtime/text-node.js
@@ -0,0 +1,9 @@
+let latestNodeId = 1
+
+export default function TextNode (text) {
+ this.instanceId = ''
+ this.nodeId = latestNodeId++
+ this.parentNode = null
+ this.nodeType = 3
+ this.text = text
+}