aboutsummaryrefslogtreecommitdiff
path: root/node_modules/vue/src/platforms/weex
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/vue/src/platforms/weex')
-rwxr-xr-xnode_modules/vue/src/platforms/weex/compiler/directives/index.js5
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/directives/model.js34
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/index.js52
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/append.js27
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/class.js73
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/index.js13
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/props.js32
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/component-root.js16
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/component.js16
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/index.js60
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/recycle-list.js50
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/text.js23
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-bind.js21
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-for.js33
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-if.js63
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-on.js25
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-once.js19
-rw-r--r--node_modules/vue/src/platforms/weex/compiler/modules/style.js86
-rw-r--r--node_modules/vue/src/platforms/weex/entry-compiler.js1
-rw-r--r--node_modules/vue/src/platforms/weex/entry-framework.js187
-rw-r--r--node_modules/vue/src/platforms/weex/entry-runtime-factory.js6
-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
-rw-r--r--node_modules/vue/src/platforms/weex/util/element.js52
-rwxr-xr-xnode_modules/vue/src/platforms/weex/util/index.js40
-rw-r--r--node_modules/vue/src/platforms/weex/util/parser.js60
41 files changed, 2115 insertions, 0 deletions
diff --git a/node_modules/vue/src/platforms/weex/compiler/directives/index.js b/node_modules/vue/src/platforms/weex/compiler/directives/index.js
new file mode 100755
index 00000000..12ced224
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/directives/index.js
@@ -0,0 +1,5 @@
+import model from './model'
+
+export default {
+ model
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/directives/model.js b/node_modules/vue/src/platforms/weex/compiler/directives/model.js
new file mode 100644
index 00000000..6c9b7685
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/directives/model.js
@@ -0,0 +1,34 @@
+/* @flow */
+
+import { addHandler, addAttr } from 'compiler/helpers'
+import { genComponentModel, genAssignmentCode } from 'compiler/directives/model'
+
+export default function model (
+ el: ASTElement,
+ dir: ASTDirective,
+ _warn: Function
+): ?boolean {
+ if (el.tag === 'input' || el.tag === 'textarea') {
+ genDefaultModel(el, dir.value, dir.modifiers)
+ } else {
+ genComponentModel(el, dir.value, dir.modifiers)
+ }
+}
+
+function genDefaultModel (
+ el: ASTElement,
+ value: string,
+ modifiers: ?ASTModifiers
+): ?boolean {
+ const { lazy, trim, number } = modifiers || {}
+ const event = lazy ? 'change' : 'input'
+
+ let valueExpression = `$event.target.attr.value${trim ? '.trim()' : ''}`
+ if (number) {
+ valueExpression = `_n(${valueExpression})`
+ }
+
+ const code = genAssignmentCode(value, valueExpression)
+ addAttr(el, 'value', `(${value})`)
+ addHandler(el, event, code, null, true)
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/index.js b/node_modules/vue/src/platforms/weex/compiler/index.js
new file mode 100644
index 00000000..94f350b8
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/index.js
@@ -0,0 +1,52 @@
+/* @flow */
+
+import { genStaticKeys } from 'shared/util'
+import { createCompiler } from 'compiler/index'
+
+import modules from './modules/index'
+import directives from './directives/index'
+
+import {
+ isUnaryTag,
+ mustUseProp,
+ isReservedTag,
+ canBeLeftOpenTag,
+ getTagNamespace
+} from '../util/element'
+
+export const baseOptions: WeexCompilerOptions = {
+ modules,
+ directives,
+ isUnaryTag,
+ mustUseProp,
+ canBeLeftOpenTag,
+ isReservedTag,
+ getTagNamespace,
+ preserveWhitespace: false,
+ recyclable: false,
+ staticKeys: genStaticKeys(modules)
+}
+
+const compiler = createCompiler(baseOptions)
+
+export function compile (
+ template: string,
+ options?: WeexCompilerOptions
+): WeexCompiledResult {
+ let generateAltRender = false
+ if (options && options.recyclable === true) {
+ generateAltRender = true
+ options.recyclable = false
+ }
+ const result = compiler.compile(template, options)
+
+ // generate @render function for <recycle-list>
+ if (options && generateAltRender) {
+ options.recyclable = true
+ // disable static optimizations
+ options.optimize = false
+ const { render } = compiler.compile(template, options)
+ result['@render'] = render
+ }
+ return result
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/append.js b/node_modules/vue/src/platforms/weex/compiler/modules/append.js
new file mode 100644
index 00000000..6e7be267
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/append.js
@@ -0,0 +1,27 @@
+/* @flow */
+
+import { makeMap } from 'shared/util'
+
+// The "unitary tag" means that the tag node and its children
+// must be sent to the native together.
+const isUnitaryTag = makeMap('cell,header,cell-slot,recycle-list', true)
+
+function preTransformNode (el: ASTElement, options: CompilerOptions) {
+ if (isUnitaryTag(el.tag) && !el.attrsList.some(item => item.name === 'append')) {
+ el.attrsMap.append = 'tree'
+ el.attrsList.push({ name: 'append', value: 'tree' })
+ }
+ if (el.attrsMap.append === 'tree') {
+ el.appendAsTree = true
+ }
+}
+
+function genData (el: ASTElement): string {
+ return el.appendAsTree ? `appendAsTree:true,` : ''
+}
+
+export default {
+ staticKeys: ['appendAsTree'],
+ preTransformNode,
+ genData
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/class.js b/node_modules/vue/src/platforms/weex/compiler/modules/class.js
new file mode 100644
index 00000000..371a08ea
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/class.js
@@ -0,0 +1,73 @@
+/* @flow */
+
+import { parseText } from 'compiler/parser/text-parser'
+import {
+ getAndRemoveAttr,
+ getBindingAttr,
+ baseWarn
+} from 'compiler/helpers'
+
+type StaticClassResult = {
+ dynamic: boolean,
+ classResult: string
+};
+
+function transformNode (el: ASTElement, options: CompilerOptions) {
+ const warn = options.warn || baseWarn
+ const staticClass = getAndRemoveAttr(el, 'class')
+ const { dynamic, classResult } = parseStaticClass(staticClass, options)
+ if (process.env.NODE_ENV !== 'production' && dynamic && staticClass) {
+ warn(
+ `class="${staticClass}": ` +
+ 'Interpolation inside attributes has been deprecated. ' +
+ 'Use v-bind or the colon shorthand instead.'
+ )
+ }
+ if (!dynamic && classResult) {
+ el.staticClass = classResult
+ }
+ const classBinding = getBindingAttr(el, 'class', false /* getStatic */)
+ if (classBinding) {
+ el.classBinding = classBinding
+ } else if (dynamic) {
+ el.classBinding = classResult
+ }
+}
+
+function genData (el: ASTElement): string {
+ let data = ''
+ if (el.staticClass) {
+ data += `staticClass:${el.staticClass},`
+ }
+ if (el.classBinding) {
+ data += `class:${el.classBinding},`
+ }
+ return data
+}
+
+function parseStaticClass (staticClass: ?string, options: CompilerOptions): StaticClassResult {
+ // "a b c" -> ["a", "b", "c"] => staticClass: ["a", "b", "c"]
+ // "a {{x}} c" -> ["a", x, "c"] => classBinding: '["a", x, "c"]'
+ let dynamic = false
+ let classResult = ''
+ if (staticClass) {
+ const classList = staticClass.trim().split(' ').map(name => {
+ const result = parseText(name, options.delimiters)
+ if (result) {
+ dynamic = true
+ return result.expression
+ }
+ return JSON.stringify(name)
+ })
+ if (classList.length) {
+ classResult = '[' + classList.join(',') + ']'
+ }
+ }
+ return { dynamic, classResult }
+}
+
+export default {
+ staticKeys: ['staticClass'],
+ transformNode,
+ genData
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/index.js b/node_modules/vue/src/platforms/weex/compiler/modules/index.js
new file mode 100644
index 00000000..ac17809e
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/index.js
@@ -0,0 +1,13 @@
+import klass from './class'
+import style from './style'
+import props from './props'
+import append from './append'
+import recycleList from './recycle-list/index'
+
+export default [
+ recycleList,
+ klass,
+ style,
+ props,
+ append
+]
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/props.js b/node_modules/vue/src/platforms/weex/compiler/modules/props.js
new file mode 100644
index 00000000..8b0bb5f2
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/props.js
@@ -0,0 +1,32 @@
+/* @flow */
+
+import { cached, camelize } from 'shared/util'
+
+const normalize = cached(camelize)
+
+function normalizeKeyName (str: string): string {
+ if (str.match(/^v\-/)) {
+ return str.replace(/(v-[a-z\-]+\:)([a-z\-]+)$/i, ($, directive, prop) => {
+ return directive + normalize(prop)
+ })
+ }
+ return normalize(str)
+}
+
+function transformNode (el: ASTElement, options: CompilerOptions) {
+ if (Array.isArray(el.attrsList)) {
+ el.attrsList.forEach(attr => {
+ if (attr.name && attr.name.match(/\-/)) {
+ const realName = normalizeKeyName(attr.name)
+ if (el.attrsMap) {
+ el.attrsMap[realName] = el.attrsMap[attr.name]
+ delete el.attrsMap[attr.name]
+ }
+ attr.name = realName
+ }
+ })
+ }
+}
+export default {
+ transformNode
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/component-root.js b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/component-root.js
new file mode 100644
index 00000000..7d9fedea
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/component-root.js
@@ -0,0 +1,16 @@
+/* @flow */
+
+import { addAttr } from 'compiler/helpers'
+
+// mark component root nodes as
+export function postTransformComponentRoot (
+ el: ASTElement,
+ options: WeexCompilerOptions
+) {
+ if (!el.parent) {
+ // component root
+ addAttr(el, '@isComponentRoot', 'true')
+ addAttr(el, '@templateId', '_uid')
+ addAttr(el, '@componentProps', '$props || {}')
+ }
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/component.js b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/component.js
new file mode 100644
index 00000000..36d7dfd5
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/component.js
@@ -0,0 +1,16 @@
+/* @flow */
+
+import { addAttr } from 'compiler/helpers'
+import { RECYCLE_LIST_MARKER } from 'weex/util/index'
+
+// mark components as inside recycle-list so that we know we need to invoke
+// their special @render function instead of render in create-component.js
+export function postTransformComponent (
+ el: ASTElement,
+ options: WeexCompilerOptions
+) {
+ // $flow-disable-line (we know isReservedTag is there)
+ if (!options.isReservedTag(el.tag) && el.tag !== 'cell-slot') {
+ addAttr(el, RECYCLE_LIST_MARKER, 'true')
+ }
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/index.js b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/index.js
new file mode 100644
index 00000000..502cc782
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/index.js
@@ -0,0 +1,60 @@
+/* @flow */
+
+import { preTransformRecycleList } from './recycle-list'
+import { postTransformComponent } from './component'
+import { postTransformComponentRoot } from './component-root'
+import { postTransformText } from './text'
+import { preTransformVBind } from './v-bind'
+import { preTransformVIf } from './v-if'
+import { preTransformVFor } from './v-for'
+import { postTransformVOn } from './v-on'
+import { preTransformVOnce } from './v-once'
+
+let currentRecycleList = null
+
+function shouldCompile (el: ASTElement, options: WeexCompilerOptions) {
+ return options.recyclable ||
+ (currentRecycleList && el !== currentRecycleList)
+}
+
+function preTransformNode (el: ASTElement, options: WeexCompilerOptions) {
+ if (el.tag === 'recycle-list') {
+ preTransformRecycleList(el, options)
+ currentRecycleList = el
+ }
+ if (shouldCompile(el, options)) {
+ preTransformVBind(el, options)
+ preTransformVIf(el, options) // also v-else-if and v-else
+ preTransformVFor(el, options)
+ preTransformVOnce(el, options)
+ }
+}
+
+function transformNode (el: ASTElement, options: WeexCompilerOptions) {
+ if (shouldCompile(el, options)) {
+ // do nothing yet
+ }
+}
+
+function postTransformNode (el: ASTElement, options: WeexCompilerOptions) {
+ if (shouldCompile(el, options)) {
+ // mark child component in parent template
+ postTransformComponent(el, options)
+ // mark root in child component template
+ postTransformComponentRoot(el, options)
+ // <text>: transform children text into value attr
+ if (el.tag === 'text') {
+ postTransformText(el, options)
+ }
+ postTransformVOn(el, options)
+ }
+ if (el === currentRecycleList) {
+ currentRecycleList = null
+ }
+}
+
+export default {
+ preTransformNode,
+ transformNode,
+ postTransformNode
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/recycle-list.js b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/recycle-list.js
new file mode 100644
index 00000000..7fb65167
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/recycle-list.js
@@ -0,0 +1,50 @@
+/* @flow */
+
+import { parseFor } from 'compiler/parser/index'
+import { getAndRemoveAttr, addRawAttr } from 'compiler/helpers'
+
+/**
+ * Map the following syntax to corresponding attrs:
+ *
+ * <recycle-list for="(item, i) in longList" switch="cellType">
+ * <cell-slot case="A"> ... </cell-slot>
+ * <cell-slot case="B"> ... </cell-slot>
+ * </recycle-list>
+ */
+
+export function preTransformRecycleList (
+ el: ASTElement,
+ options: WeexCompilerOptions
+) {
+ const exp = getAndRemoveAttr(el, 'for')
+ if (!exp) {
+ if (options.warn) {
+ options.warn(`Invalid <recycle-list> syntax: missing "for" expression.`)
+ }
+ return
+ }
+
+ const res = parseFor(exp)
+ if (!res) {
+ if (options.warn) {
+ options.warn(`Invalid <recycle-list> syntax: ${exp}.`)
+ }
+ return
+ }
+
+ addRawAttr(el, ':list-data', res.for)
+ addRawAttr(el, 'binding-expression', res.for)
+ addRawAttr(el, 'alias', res.alias)
+ if (res.iterator2) {
+ // (item, key, index) for object iteration
+ // is this even supported?
+ addRawAttr(el, 'index', res.iterator2)
+ } else if (res.iterator1) {
+ addRawAttr(el, 'index', res.iterator1)
+ }
+
+ const switchKey = getAndRemoveAttr(el, 'switch')
+ if (switchKey) {
+ addRawAttr(el, 'switch', switchKey)
+ }
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/text.js b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/text.js
new file mode 100644
index 00000000..575ec7f6
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/text.js
@@ -0,0 +1,23 @@
+/* @flow */
+
+import { addAttr } from 'compiler/helpers'
+
+function genText (node: ASTNode) {
+ const value = node.type === 3
+ ? node.text
+ : node.type === 2
+ ? node.tokens.length === 1
+ ? node.tokens[0]
+ : node.tokens
+ : ''
+ return JSON.stringify(value)
+}
+
+export function postTransformText (el: ASTElement, options: WeexCompilerOptions) {
+ // weex <text> can only contain text, so the parser
+ // always generates a single child.
+ if (el.children.length) {
+ addAttr(el, 'value', genText(el.children[0]))
+ el.children = []
+ }
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-bind.js b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-bind.js
new file mode 100644
index 00000000..effdf351
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-bind.js
@@ -0,0 +1,21 @@
+/* @flow */
+
+import { camelize } from 'shared/util'
+import { generateBinding } from 'weex/util/parser'
+import { bindRE } from 'compiler/parser/index'
+import { getAndRemoveAttr, addRawAttr } from 'compiler/helpers'
+
+function parseAttrName (name: string): string {
+ return camelize(name.replace(bindRE, ''))
+}
+
+export function preTransformVBind (el: ASTElement, options: WeexCompilerOptions) {
+ for (const attr in el.attrsMap) {
+ if (bindRE.test(attr)) {
+ const name: string = parseAttrName(attr)
+ const value = generateBinding(getAndRemoveAttr(el, attr))
+ delete el.attrsMap[attr]
+ addRawAttr(el, name, value)
+ }
+ }
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-for.js b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-for.js
new file mode 100644
index 00000000..9f09e4b4
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-for.js
@@ -0,0 +1,33 @@
+/* @flow */
+
+import { parseFor } from 'compiler/parser/index'
+import { getAndRemoveAttr, addRawAttr } from 'compiler/helpers'
+
+export function preTransformVFor (el: ASTElement, options: WeexCompilerOptions) {
+ const exp = getAndRemoveAttr(el, 'v-for')
+ if (!exp) {
+ return
+ }
+
+ const res = parseFor(exp)
+ if (!res) {
+ if (process.env.NODE_ENV !== 'production' && options.warn) {
+ options.warn(`Invalid v-for expression: ${exp}`)
+ }
+ return
+ }
+
+ const desc: Object = {
+ '@expression': res.for,
+ '@alias': res.alias
+ }
+ if (res.iterator2) {
+ desc['@key'] = res.iterator1
+ desc['@index'] = res.iterator2
+ } else {
+ desc['@index'] = res.iterator1
+ }
+
+ delete el.attrsMap['v-for']
+ addRawAttr(el, '[[repeat]]', desc)
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-if.js b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-if.js
new file mode 100644
index 00000000..d82ba632
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-if.js
@@ -0,0 +1,63 @@
+/* @flow */
+
+import { addIfCondition } from 'compiler/parser/index'
+import { getAndRemoveAttr, addRawAttr } from 'compiler/helpers'
+
+function hasConditionDirective (el: ASTElement): boolean {
+ for (const attr in el.attrsMap) {
+ if (/^v\-if|v\-else|v\-else\-if$/.test(attr)) {
+ return true
+ }
+ }
+ return false
+}
+
+function getPreviousConditions (el: ASTElement): Array<string> {
+ const conditions = []
+ if (el.parent && el.parent.children) {
+ for (let c = 0, n = el.parent.children.length; c < n; ++c) {
+ // $flow-disable-line
+ const ifConditions = el.parent.children[c].ifConditions
+ if (ifConditions) {
+ for (let i = 0, l = ifConditions.length; i < l; ++i) {
+ const condition = ifConditions[i]
+ if (condition && condition.exp) {
+ conditions.push(condition.exp)
+ }
+ }
+ }
+ }
+ }
+ return conditions
+}
+
+export function preTransformVIf (el: ASTElement, options: WeexCompilerOptions) {
+ if (hasConditionDirective(el)) {
+ let exp
+ const ifExp = getAndRemoveAttr(el, 'v-if', true /* remove from attrsMap */)
+ const elseifExp = getAndRemoveAttr(el, 'v-else-if', true)
+ // don't need the value, but remove it to avoid being generated as a
+ // custom directive
+ getAndRemoveAttr(el, 'v-else', true)
+ if (ifExp) {
+ exp = ifExp
+ addIfCondition(el, { exp: ifExp, block: el })
+ } else {
+ elseifExp && addIfCondition(el, { exp: elseifExp, block: el })
+ const prevConditions = getPreviousConditions(el)
+ if (prevConditions.length) {
+ const prevMatch = prevConditions.join(' || ')
+ exp = elseifExp
+ ? `!(${prevMatch}) && (${elseifExp})` // v-else-if
+ : `!(${prevMatch})` // v-else
+ } else if (process.env.NODE_ENV !== 'production' && options.warn) {
+ options.warn(
+ `v-${elseifExp ? ('else-if="' + elseifExp + '"') : 'else'} ` +
+ `used on element <${el.tag}> without corresponding v-if.`
+ )
+ return
+ }
+ }
+ addRawAttr(el, '[[match]]', exp)
+ }
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-on.js b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-on.js
new file mode 100644
index 00000000..b1ba262c
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-on.js
@@ -0,0 +1,25 @@
+/* @flow */
+
+const inlineStatementRE = /^\s*([A-Za-z_$0-9\['\."\]]+)*\s*\(\s*(([A-Za-z_$0-9\['\."\]]+)?(\s*,\s*([A-Za-z_$0-9\['\."\]]+))*)\s*\)$/
+
+function parseHandlerParams (handler: ASTElementHandler) {
+ const res = inlineStatementRE.exec(handler.value)
+ if (res && res[2]) {
+ handler.params = res[2].split(/\s*,\s*/)
+ }
+}
+
+export function postTransformVOn (el: ASTElement, options: WeexCompilerOptions) {
+ const events: ASTElementHandlers | void = el.events
+ if (!events) {
+ return
+ }
+ for (const name in events) {
+ const handler: ASTElementHandler | Array<ASTElementHandler> = events[name]
+ if (Array.isArray(handler)) {
+ handler.map(fn => parseHandlerParams(fn))
+ } else {
+ parseHandlerParams(handler)
+ }
+ }
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-once.js b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-once.js
new file mode 100644
index 00000000..baff838a
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-once.js
@@ -0,0 +1,19 @@
+/* @flow */
+
+import { getAndRemoveAttr, addRawAttr } from 'compiler/helpers'
+
+function containVOnce (el: ASTElement): boolean {
+ for (const attr in el.attrsMap) {
+ if (/^v\-once$/i.test(attr)) {
+ return true
+ }
+ }
+ return false
+}
+
+export function preTransformVOnce (el: ASTElement, options: WeexCompilerOptions) {
+ if (containVOnce(el)) {
+ getAndRemoveAttr(el, 'v-once', true)
+ addRawAttr(el, '[[once]]', true)
+ }
+}
diff --git a/node_modules/vue/src/platforms/weex/compiler/modules/style.js b/node_modules/vue/src/platforms/weex/compiler/modules/style.js
new file mode 100644
index 00000000..7bf5027f
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/compiler/modules/style.js
@@ -0,0 +1,86 @@
+/* @flow */
+
+import { cached, camelize, isPlainObject } from 'shared/util'
+import { parseText } from 'compiler/parser/text-parser'
+import {
+ getAndRemoveAttr,
+ getBindingAttr,
+ baseWarn
+} from 'compiler/helpers'
+
+type StaticStyleResult = {
+ dynamic: boolean,
+ styleResult: string | Object | void
+};
+
+const normalize = cached(camelize)
+
+function transformNode (el: ASTElement, options: CompilerOptions) {
+ const warn = options.warn || baseWarn
+ const staticStyle = getAndRemoveAttr(el, 'style')
+ const { dynamic, styleResult } = parseStaticStyle(staticStyle, options)
+ if (process.env.NODE_ENV !== 'production' && dynamic) {
+ warn(
+ `style="${String(staticStyle)}": ` +
+ 'Interpolation inside attributes has been deprecated. ' +
+ 'Use v-bind or the colon shorthand instead.'
+ )
+ }
+ if (!dynamic && styleResult) {
+ // $flow-disable-line
+ el.staticStyle = styleResult
+ }
+ const styleBinding = getBindingAttr(el, 'style', false /* getStatic */)
+ if (styleBinding) {
+ el.styleBinding = styleBinding
+ } else if (dynamic) {
+ // $flow-disable-line
+ el.styleBinding = styleResult
+ }
+}
+
+function genData (el: ASTElement): string {
+ let data = ''
+ if (el.staticStyle) {
+ data += `staticStyle:${el.staticStyle},`
+ }
+ if (el.styleBinding) {
+ data += `style:${el.styleBinding},`
+ }
+ return data
+}
+
+function parseStaticStyle (staticStyle: ?string, options: CompilerOptions): StaticStyleResult {
+ // "width: 200px; height: 200px;" -> {width: 200, height: 200}
+ // "width: 200px; height: {{y}}" -> {width: 200, height: y}
+ let dynamic = false
+ let styleResult = ''
+ if (typeof staticStyle === 'string') {
+ const styleList = staticStyle.trim().split(';').map(style => {
+ const result = style.trim().split(':')
+ if (result.length !== 2) {
+ return
+ }
+ const key = normalize(result[0].trim())
+ const value = result[1].trim()
+ const dynamicValue = parseText(value, options.delimiters)
+ if (dynamicValue) {
+ dynamic = true
+ return key + ':' + dynamicValue.expression
+ }
+ return key + ':' + JSON.stringify(value)
+ }).filter(result => result)
+ if (styleList.length) {
+ styleResult = '{' + styleList.join(',') + '}'
+ }
+ } else if (isPlainObject(staticStyle)) {
+ styleResult = JSON.stringify(staticStyle) || ''
+ }
+ return { dynamic, styleResult }
+}
+
+export default {
+ staticKeys: ['staticStyle'],
+ transformNode,
+ genData
+}
diff --git a/node_modules/vue/src/platforms/weex/entry-compiler.js b/node_modules/vue/src/platforms/weex/entry-compiler.js
new file mode 100644
index 00000000..18d79ab7
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/entry-compiler.js
@@ -0,0 +1 @@
+export { compile } from 'weex/compiler/index'
diff --git a/node_modules/vue/src/platforms/weex/entry-framework.js b/node_modules/vue/src/platforms/weex/entry-framework.js
new file mode 100644
index 00000000..a23775d4
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/entry-framework.js
@@ -0,0 +1,187 @@
+/* @flow */
+
+// this will be preserved during build
+// $flow-disable-line
+const VueFactory = require('./factory')
+
+const instanceOptions: { [key: string]: WeexInstanceOption } = {}
+
+/**
+ * Create instance context.
+ */
+export function createInstanceContext (
+ instanceId: string,
+ runtimeContext: WeexRuntimeContext,
+ data: Object = {}
+): WeexInstanceContext {
+ const weex: Weex = runtimeContext.weex
+ const instance: WeexInstanceOption = instanceOptions[instanceId] = {
+ instanceId,
+ config: weex.config,
+ document: weex.document,
+ data
+ }
+
+ // Each instance has a independent `Vue` module instance
+ const Vue = instance.Vue = createVueModuleInstance(instanceId, weex)
+
+ // DEPRECATED
+ const timerAPIs = getInstanceTimer(instanceId, weex.requireModule)
+
+ const instanceContext = Object.assign({ Vue }, timerAPIs)
+ Object.freeze(instanceContext)
+ return instanceContext
+}
+
+/**
+ * Destroy an instance with id. It will make sure all memory of
+ * this instance released and no more leaks.
+ */
+export function destroyInstance (instanceId: string): void {
+ const instance = instanceOptions[instanceId]
+ if (instance && instance.app instanceof instance.Vue) {
+ try {
+ instance.app.$destroy()
+ instance.document.destroy()
+ } catch (e) {}
+ delete instance.document
+ delete instance.app
+ }
+ delete instanceOptions[instanceId]
+}
+
+/**
+ * Refresh an instance with id and new top-level component data.
+ * It will use `Vue.set` on all keys of the new data. So it's better
+ * define all possible meaningful keys when instance created.
+ */
+export function refreshInstance (
+ instanceId: string,
+ data: Object
+): Error | void {
+ const instance = instanceOptions[instanceId]
+ if (!instance || !(instance.app instanceof instance.Vue)) {
+ return new Error(`refreshInstance: instance ${instanceId} not found!`)
+ }
+ if (instance.Vue && instance.Vue.set) {
+ for (const key in data) {
+ instance.Vue.set(instance.app, key, data[key])
+ }
+ }
+ // Finally `refreshFinish` signal needed.
+ instance.document.taskCenter.send('dom', { action: 'refreshFinish' }, [])
+}
+
+/**
+ * Create a fresh instance of Vue for each Weex instance.
+ */
+function createVueModuleInstance (
+ instanceId: string,
+ weex: Weex
+): GlobalAPI {
+ const exports = {}
+ VueFactory(exports, weex.document)
+ const Vue = exports.Vue
+
+ const instance = instanceOptions[instanceId]
+
+ // patch reserved tag detection to account for dynamically registered
+ // components
+ const weexRegex = /^weex:/i
+ const isReservedTag = Vue.config.isReservedTag || (() => false)
+ const isRuntimeComponent = Vue.config.isRuntimeComponent || (() => false)
+ Vue.config.isReservedTag = name => {
+ return (!isRuntimeComponent(name) && weex.supports(`@component/${name}`)) ||
+ isReservedTag(name) ||
+ weexRegex.test(name)
+ }
+ Vue.config.parsePlatformTagName = name => name.replace(weexRegex, '')
+
+ // expose weex-specific info
+ Vue.prototype.$instanceId = instanceId
+ Vue.prototype.$document = instance.document
+
+ // expose weex native module getter on subVue prototype so that
+ // vdom runtime modules can access native modules via vnode.context
+ Vue.prototype.$requireWeexModule = weex.requireModule
+
+ // Hack `Vue` behavior to handle instance information and data
+ // before root component created.
+ Vue.mixin({
+ beforeCreate () {
+ const options = this.$options
+ // root component (vm)
+ if (options.el) {
+ // set external data of instance
+ const dataOption = options.data
+ const internalData = (typeof dataOption === 'function' ? dataOption() : dataOption) || {}
+ options.data = Object.assign(internalData, instance.data)
+ // record instance by id
+ instance.app = this
+ }
+ },
+ mounted () {
+ const options = this.$options
+ // root component (vm)
+ if (options.el && weex.document && instance.app === this) {
+ try {
+ // Send "createFinish" signal to native.
+ weex.document.taskCenter.send('dom', { action: 'createFinish' }, [])
+ } catch (e) {}
+ }
+ }
+ })
+
+ /**
+ * @deprecated Just instance variable `weex.config`
+ * Get instance config.
+ * @return {object}
+ */
+ Vue.prototype.$getConfig = function () {
+ if (instance.app instanceof Vue) {
+ return instance.config
+ }
+ }
+
+ return Vue
+}
+
+/**
+ * DEPRECATED
+ * Generate HTML5 Timer APIs. An important point is that the callback
+ * will be converted into callback id when sent to native. So the
+ * framework can make sure no side effect of the callback happened after
+ * an instance destroyed.
+ */
+function getInstanceTimer (
+ instanceId: string,
+ moduleGetter: Function
+): Object {
+ const instance = instanceOptions[instanceId]
+ const timer = moduleGetter('timer')
+ const timerAPIs = {
+ setTimeout: (...args) => {
+ const handler = function () {
+ args[0](...args.slice(2))
+ }
+
+ timer.setTimeout(handler, args[1])
+ return instance.document.taskCenter.callbackManager.lastCallbackId.toString()
+ },
+ setInterval: (...args) => {
+ const handler = function () {
+ args[0](...args.slice(2))
+ }
+
+ timer.setInterval(handler, args[1])
+ return instance.document.taskCenter.callbackManager.lastCallbackId.toString()
+ },
+ clearTimeout: (n) => {
+ timer.clearTimeout(n)
+ },
+ clearInterval: (n) => {
+ timer.clearInterval(n)
+ }
+ }
+ return timerAPIs
+}
diff --git a/node_modules/vue/src/platforms/weex/entry-runtime-factory.js b/node_modules/vue/src/platforms/weex/entry-runtime-factory.js
new file mode 100644
index 00000000..166ddf2d
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/entry-runtime-factory.js
@@ -0,0 +1,6 @@
+// this entry is built and wrapped with a factory function
+// used to generate a fresh copy of Vue for every Weex instance.
+
+import Vue from './runtime/index'
+
+exports.Vue = Vue
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
+}
diff --git a/node_modules/vue/src/platforms/weex/util/element.js b/node_modules/vue/src/platforms/weex/util/element.js
new file mode 100644
index 00000000..97e97feb
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/util/element.js
@@ -0,0 +1,52 @@
+/* @flow */
+
+// These util functions are split into its own file because Rollup cannot drop
+// makeMap() due to potential side effects, so these variables end up
+// bloating the web builds.
+
+import { makeMap } from 'shared/util'
+
+export const isReservedTag = makeMap(
+ 'template,script,style,element,content,slot,link,meta,svg,view,' +
+ 'a,div,img,image,text,span,input,switch,textarea,spinner,select,' +
+ 'slider,slider-neighbor,indicator,canvas,' +
+ 'list,cell,header,loading,loading-indicator,refresh,scrollable,scroller,' +
+ 'video,web,embed,tabbar,tabheader,datepicker,timepicker,marquee,countdown',
+ true
+)
+
+// Elements that you can, intentionally, leave open (and which close themselves)
+// more flexible than web
+export const canBeLeftOpenTag = makeMap(
+ 'web,spinner,switch,video,textarea,canvas,' +
+ 'indicator,marquee,countdown',
+ true
+)
+
+export const isRuntimeComponent = makeMap(
+ 'richtext,transition,transition-group',
+ true
+)
+
+export const isUnaryTag = makeMap(
+ 'embed,img,image,input,link,meta',
+ true
+)
+
+export function mustUseProp (tag: string, type: ?string, name: string): boolean {
+ return false
+}
+
+export function getTagNamespace (tag?: string): string | void { }
+
+export function isUnknownElement (tag?: string): boolean {
+ return false
+}
+
+export function query (el: string | Element, document: Object) {
+ // document is injected by weex factory wrapper
+ const placeholder = document.createComment('root')
+ placeholder.hasAttribute = placeholder.removeAttribute = function () {} // hack for patch
+ document.documentElement.appendChild(placeholder)
+ return placeholder
+}
diff --git a/node_modules/vue/src/platforms/weex/util/index.js b/node_modules/vue/src/platforms/weex/util/index.js
new file mode 100755
index 00000000..8181d70e
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/util/index.js
@@ -0,0 +1,40 @@
+/* @flow */
+declare var document: WeexDocument;
+
+import { warn } from 'core/util/index'
+
+export const RECYCLE_LIST_MARKER = '@inRecycleList'
+
+// Register the component hook to weex native render engine.
+// The hook will be triggered by native, not javascript.
+export function registerComponentHook (
+ componentId: string,
+ type: string, // hook type, could be "lifecycle" or "instance"
+ hook: string, // hook name
+ fn: Function
+) {
+ if (!document || !document.taskCenter) {
+ warn(`Can't find available "document" or "taskCenter".`)
+ return
+ }
+ if (typeof document.taskCenter.registerHook === 'function') {
+ return document.taskCenter.registerHook(componentId, type, hook, fn)
+ }
+ warn(`Failed to register component hook "${type}@${hook}#${componentId}".`)
+}
+
+// Updates the state of the component to weex native render engine.
+export function updateComponentData (
+ componentId: string,
+ newData: Object | void,
+ callback?: Function
+) {
+ if (!document || !document.taskCenter) {
+ warn(`Can't find available "document" or "taskCenter".`)
+ return
+ }
+ if (typeof document.taskCenter.updateData === 'function') {
+ return document.taskCenter.updateData(componentId, newData, callback)
+ }
+ warn(`Failed to update component data (${componentId}).`)
+}
diff --git a/node_modules/vue/src/platforms/weex/util/parser.js b/node_modules/vue/src/platforms/weex/util/parser.js
new file mode 100644
index 00000000..081908e8
--- /dev/null
+++ b/node_modules/vue/src/platforms/weex/util/parser.js
@@ -0,0 +1,60 @@
+/* @flow */
+
+// import { warn } from 'core/util/index'
+
+// this will be preserved during build
+// $flow-disable-line
+const acorn = require('acorn') // $flow-disable-line
+const walk = require('acorn/dist/walk') // $flow-disable-line
+const escodegen = require('escodegen')
+
+export function nodeToBinding (node: Object): any {
+ switch (node.type) {
+ case 'Literal': return node.value
+ case 'Identifier':
+ case 'UnaryExpression':
+ case 'BinaryExpression':
+ case 'LogicalExpression':
+ case 'ConditionalExpression':
+ case 'MemberExpression': return { '@binding': escodegen.generate(node) }
+ case 'ArrayExpression': return node.elements.map(_ => nodeToBinding(_))
+ case 'ObjectExpression': {
+ const object = {}
+ node.properties.forEach(prop => {
+ if (!prop.key || prop.key.type !== 'Identifier') {
+ return
+ }
+ const key = escodegen.generate(prop.key)
+ const value = nodeToBinding(prop.value)
+ if (key && value) {
+ object[key] = value
+ }
+ })
+ return object
+ }
+ default: {
+ // warn(`Not support ${node.type}: "${escodegen.generate(node)}"`)
+ return ''
+ }
+ }
+}
+
+export function generateBinding (exp: ?string): any {
+ if (exp && typeof exp === 'string') {
+ let ast = null
+ try {
+ ast = acorn.parse(`(${exp})`)
+ } catch (e) {
+ // warn(`Failed to parse the expression: "${exp}"`)
+ return ''
+ }
+
+ let output = ''
+ walk.simple(ast, {
+ Expression (node) {
+ output = nodeToBinding(node)
+ }
+ })
+ return output
+ }
+}