aboutsummaryrefslogtreecommitdiff
path: root/node_modules/vue/src
diff options
context:
space:
mode:
authorruki <waruqi@gmail.com>2018-11-08 00:38:48 +0800
committerruki <waruqi@gmail.com>2018-11-07 21:53:09 +0800
commit26105034da4fcce7ac883c899d781f016559310d (patch)
treec459a5dc4e3aa0972d9919033ece511ce76dd129 /node_modules/vue/src
parent2c77f00f1a7ecb6c8192f9c16d3b2001b254a107 (diff)
downloadxmake-docs-26105034da4fcce7ac883c899d781f016559310d.tar.gz
xmake-docs-26105034da4fcce7ac883c899d781f016559310d.zip
switch to vuepress
Diffstat (limited to 'node_modules/vue/src')
-rw-r--r--node_modules/vue/src/compiler/codegen/events.js167
-rw-r--r--node_modules/vue/src/compiler/codegen/index.js513
-rw-r--r--node_modules/vue/src/compiler/create-compiler.js55
-rw-r--r--node_modules/vue/src/compiler/directives/bind.js11
-rw-r--r--node_modules/vue/src/compiler/directives/index.js11
-rw-r--r--node_modules/vue/src/compiler/directives/model.js148
-rw-r--r--node_modules/vue/src/compiler/directives/on.js10
-rw-r--r--node_modules/vue/src/compiler/error-detector.js108
-rw-r--r--node_modules/vue/src/compiler/helpers.js164
-rw-r--r--node_modules/vue/src/compiler/index.js25
-rw-r--r--node_modules/vue/src/compiler/optimizer.js128
-rw-r--r--node_modules/vue/src/compiler/parser/entity-decoder.js11
-rw-r--r--node_modules/vue/src/compiler/parser/filter-parser.js97
-rw-r--r--node_modules/vue/src/compiler/parser/html-parser.js310
-rw-r--r--node_modules/vue/src/compiler/parser/index.js675
-rw-r--r--node_modules/vue/src/compiler/parser/text-parser.js53
-rw-r--r--node_modules/vue/src/compiler/to-function.js99
-rw-r--r--node_modules/vue/src/core/components/index.js5
-rw-r--r--node_modules/vue/src/core/components/keep-alive.js124
-rw-r--r--node_modules/vue/src/core/config.js121
-rw-r--r--node_modules/vue/src/core/global-api/assets.js34
-rw-r--r--node_modules/vue/src/core/global-api/extend.js95
-rw-r--r--node_modules/vue/src/core/global-api/index.js62
-rw-r--r--node_modules/vue/src/core/global-api/mixin.js10
-rw-r--r--node_modules/vue/src/core/global-api/use.js23
-rw-r--r--node_modules/vue/src/core/index.js26
-rw-r--r--node_modules/vue/src/core/instance/events.js142
-rw-r--r--node_modules/vue/src/core/instance/index.js23
-rw-r--r--node_modules/vue/src/core/instance/init.js150
-rw-r--r--node_modules/vue/src/core/instance/inject.js74
-rw-r--r--node_modules/vue/src/core/instance/lifecycle.js336
-rw-r--r--node_modules/vue/src/core/instance/proxy.js79
-rw-r--r--node_modules/vue/src/core/instance/render-helpers/bind-object-listeners.js22
-rw-r--r--node_modules/vue/src/core/instance/render-helpers/bind-object-props.js60
-rw-r--r--node_modules/vue/src/core/instance/render-helpers/check-keycodes.js34
-rw-r--r--node_modules/vue/src/core/instance/render-helpers/index.js30
-rw-r--r--node_modules/vue/src/core/instance/render-helpers/render-list.js39
-rw-r--r--node_modules/vue/src/core/instance/render-helpers/render-slot.js50
-rw-r--r--node_modules/vue/src/core/instance/render-helpers/render-static.js60
-rw-r--r--node_modules/vue/src/core/instance/render-helpers/resolve-filter.js10
-rw-r--r--node_modules/vue/src/core/instance/render-helpers/resolve-slots.js65
-rw-r--r--node_modules/vue/src/core/instance/render.js119
-rw-r--r--node_modules/vue/src/core/instance/state.js360
-rw-r--r--node_modules/vue/src/core/observer/array.js45
-rw-r--r--node_modules/vue/src/core/observer/dep.js58
-rw-r--r--node_modules/vue/src/core/observer/index.js273
-rw-r--r--node_modules/vue/src/core/observer/scheduler.js148
-rw-r--r--node_modules/vue/src/core/observer/traverse.js40
-rw-r--r--node_modules/vue/src/core/observer/watcher.js240
-rw-r--r--node_modules/vue/src/core/util/debug.js100
-rw-r--r--node_modules/vue/src/core/util/env.js95
-rw-r--r--node_modules/vue/src/core/util/error.js48
-rw-r--r--node_modules/vue/src/core/util/index.js11
-rw-r--r--node_modules/vue/src/core/util/lang.js39
-rw-r--r--node_modules/vue/src/core/util/next-tick.js117
-rw-r--r--node_modules/vue/src/core/util/options.js438
-rw-r--r--node_modules/vue/src/core/util/perf.js24
-rw-r--r--node_modules/vue/src/core/util/props.js202
-rw-r--r--node_modules/vue/src/core/vdom/create-component.js257
-rw-r--r--node_modules/vue/src/core/vdom/create-element.js160
-rw-r--r--node_modules/vue/src/core/vdom/create-functional-component.js136
-rw-r--r--node_modules/vue/src/core/vdom/helpers/extract-props.js75
-rw-r--r--node_modules/vue/src/core/vdom/helpers/get-first-component-child.js15
-rw-r--r--node_modules/vue/src/core/vdom/helpers/index.js9
-rw-r--r--node_modules/vue/src/core/vdom/helpers/is-async-placeholder.js5
-rw-r--r--node_modules/vue/src/core/vdom/helpers/merge-hook.js38
-rw-r--r--node_modules/vue/src/core/vdom/helpers/normalize-children.js89
-rw-r--r--node_modules/vue/src/core/vdom/helpers/resolve-async-component.js140
-rw-r--r--node_modules/vue/src/core/vdom/helpers/update-listeners.js83
-rw-r--r--node_modules/vue/src/core/vdom/modules/directives.js119
-rw-r--r--node_modules/vue/src/core/vdom/modules/index.js7
-rw-r--r--node_modules/vue/src/core/vdom/modules/ref.js45
-rw-r--r--node_modules/vue/src/core/vdom/patch.js787
-rw-r--r--node_modules/vue/src/core/vdom/vnode.js108
-rw-r--r--node_modules/vue/src/platforms/web/compiler/directives/html.js9
-rw-r--r--node_modules/vue/src/platforms/web/compiler/directives/index.js9
-rw-r--r--node_modules/vue/src/platforms/web/compiler/directives/model.js172
-rw-r--r--node_modules/vue/src/platforms/web/compiler/directives/text.js9
-rw-r--r--node_modules/vue/src/platforms/web/compiler/index.js8
-rw-r--r--node_modules/vue/src/platforms/web/compiler/modules/class.js48
-rw-r--r--node_modules/vue/src/platforms/web/compiler/modules/index.js9
-rw-r--r--node_modules/vue/src/platforms/web/compiler/modules/model.js94
-rw-r--r--node_modules/vue/src/platforms/web/compiler/modules/style.js51
-rw-r--r--node_modules/vue/src/platforms/web/compiler/options.js26
-rw-r--r--node_modules/vue/src/platforms/web/compiler/util.js24
-rw-r--r--node_modules/vue/src/platforms/web/entry-compiler.js5
-rw-r--r--node_modules/vue/src/platforms/web/entry-runtime-with-compiler.js100
-rw-r--r--node_modules/vue/src/platforms/web/entry-runtime.js5
-rw-r--r--node_modules/vue/src/platforms/web/entry-server-basic-renderer.js13
-rw-r--r--node_modules/vue/src/platforms/web/entry-server-renderer.js27
-rw-r--r--node_modules/vue/src/platforms/web/runtime/class-util.js61
-rw-r--r--node_modules/vue/src/platforms/web/runtime/components/index.js7
-rw-r--r--node_modules/vue/src/platforms/web/runtime/components/transition-group.js180
-rw-r--r--node_modules/vue/src/platforms/web/runtime/components/transition.js194
-rw-r--r--node_modules/vue/src/platforms/web/runtime/directives/index.js7
-rw-r--r--node_modules/vue/src/platforms/web/runtime/directives/model.js147
-rw-r--r--node_modules/vue/src/platforms/web/runtime/directives/show.js60
-rw-r--r--node_modules/vue/src/platforms/web/runtime/index.js77
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/attrs.js118
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/class.js48
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/dom-props.js95
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/events.js87
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/index.js15
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/style.js93
-rw-r--r--node_modules/vue/src/platforms/web/runtime/modules/transition.js343
-rw-r--r--node_modules/vue/src/platforms/web/runtime/node-ops.js59
-rw-r--r--node_modules/vue/src/platforms/web/runtime/patch.js12
-rw-r--r--node_modules/vue/src/platforms/web/runtime/transition-util.js185
-rw-r--r--node_modules/vue/src/platforms/web/server/compiler.js11
-rw-r--r--node_modules/vue/src/platforms/web/server/directives/index.js7
-rw-r--r--node_modules/vue/src/platforms/web/server/directives/model.js44
-rw-r--r--node_modules/vue/src/platforms/web/server/directives/show.js12
-rw-r--r--node_modules/vue/src/platforms/web/server/modules/attrs.js62
-rw-r--r--node_modules/vue/src/platforms/web/server/modules/class.js11
-rw-r--r--node_modules/vue/src/platforms/web/server/modules/dom-props.js50
-rw-r--r--node_modules/vue/src/platforms/web/server/modules/index.js11
-rw-r--r--node_modules/vue/src/platforms/web/server/modules/style.js28
-rw-r--r--node_modules/vue/src/platforms/web/server/util.js56
-rw-r--r--node_modules/vue/src/platforms/web/util/attrs.js43
-rw-r--r--node_modules/vue/src/platforms/web/util/class.js85
-rw-r--r--node_modules/vue/src/platforms/web/util/compat.js16
-rw-r--r--node_modules/vue/src/platforms/web/util/element.js77
-rw-r--r--node_modules/vue/src/platforms/web/util/index.js25
-rw-r--r--node_modules/vue/src/platforms/web/util/style.js72
-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
-rw-r--r--node_modules/vue/src/server/bundle-renderer/create-bundle-renderer.js151
-rw-r--r--node_modules/vue/src/server/bundle-renderer/create-bundle-runner.js150
-rw-r--r--node_modules/vue/src/server/bundle-renderer/source-map-support.js45
-rw-r--r--node_modules/vue/src/server/create-basic-renderer.js37
-rw-r--r--node_modules/vue/src/server/create-renderer.js120
-rw-r--r--node_modules/vue/src/server/optimizing-compiler/codegen.js260
-rw-r--r--node_modules/vue/src/server/optimizing-compiler/index.js20
-rw-r--r--node_modules/vue/src/server/optimizing-compiler/modules.js126
-rw-r--r--node_modules/vue/src/server/optimizing-compiler/optimizer.js140
-rw-r--r--node_modules/vue/src/server/optimizing-compiler/runtime-helpers.js150
-rw-r--r--node_modules/vue/src/server/render-context.js130
-rw-r--r--node_modules/vue/src/server/render-stream.js94
-rw-r--r--node_modules/vue/src/server/render.js396
-rw-r--r--node_modules/vue/src/server/template-renderer/create-async-file-mapper.js53
-rw-r--r--node_modules/vue/src/server/template-renderer/index.js257
-rw-r--r--node_modules/vue/src/server/template-renderer/parse-template.js42
-rw-r--r--node_modules/vue/src/server/template-renderer/template-stream.js82
-rw-r--r--node_modules/vue/src/server/util.js18
-rw-r--r--node_modules/vue/src/server/webpack-plugin/client.js70
-rw-r--r--node_modules/vue/src/server/webpack-plugin/server.js66
-rw-r--r--node_modules/vue/src/server/webpack-plugin/util.js24
-rw-r--r--node_modules/vue/src/server/write.js50
-rw-r--r--node_modules/vue/src/sfc/parser.js116
-rw-r--r--node_modules/vue/src/shared/constants.js21
-rw-r--r--node_modules/vue/src/shared/util.js324
190 files changed, 16753 insertions, 0 deletions
diff --git a/node_modules/vue/src/compiler/codegen/events.js b/node_modules/vue/src/compiler/codegen/events.js
new file mode 100644
index 00000000..4f922246
--- /dev/null
+++ b/node_modules/vue/src/compiler/codegen/events.js
@@ -0,0 +1,167 @@
+/* @flow */
+
+const fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/
+const simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/
+
+// KeyboardEvent.keyCode aliases
+const keyCodes: { [key: string]: number | Array<number> } = {
+ esc: 27,
+ tab: 9,
+ enter: 13,
+ space: 32,
+ up: 38,
+ left: 37,
+ right: 39,
+ down: 40,
+ 'delete': [8, 46]
+}
+
+// KeyboardEvent.key aliases
+const keyNames: { [key: string]: string | Array<string> } = {
+ esc: 'Escape',
+ tab: 'Tab',
+ enter: 'Enter',
+ space: ' ',
+ // #7806: IE11 uses key names without `Arrow` prefix for arrow keys.
+ up: ['Up', 'ArrowUp'],
+ left: ['Left', 'ArrowLeft'],
+ right: ['Right', 'ArrowRight'],
+ down: ['Down', 'ArrowDown'],
+ 'delete': ['Backspace', 'Delete']
+}
+
+// #4868: modifiers that prevent the execution of the listener
+// need to explicitly return null so that we can determine whether to remove
+// the listener for .once
+const genGuard = condition => `if(${condition})return null;`
+
+const modifierCode: { [key: string]: string } = {
+ stop: '$event.stopPropagation();',
+ prevent: '$event.preventDefault();',
+ self: genGuard(`$event.target !== $event.currentTarget`),
+ ctrl: genGuard(`!$event.ctrlKey`),
+ shift: genGuard(`!$event.shiftKey`),
+ alt: genGuard(`!$event.altKey`),
+ meta: genGuard(`!$event.metaKey`),
+ left: genGuard(`'button' in $event && $event.button !== 0`),
+ middle: genGuard(`'button' in $event && $event.button !== 1`),
+ right: genGuard(`'button' in $event && $event.button !== 2`)
+}
+
+export function genHandlers (
+ events: ASTElementHandlers,
+ isNative: boolean,
+ warn: Function
+): string {
+ let res = isNative ? 'nativeOn:{' : 'on:{'
+ for (const name in events) {
+ res += `"${name}":${genHandler(name, events[name])},`
+ }
+ return res.slice(0, -1) + '}'
+}
+
+// Generate handler code with binding params on Weex
+/* istanbul ignore next */
+function genWeexHandler (params: Array<any>, handlerCode: string) {
+ let innerHandlerCode = handlerCode
+ const exps = params.filter(exp => simplePathRE.test(exp) && exp !== '$event')
+ const bindings = exps.map(exp => ({ '@binding': exp }))
+ const args = exps.map((exp, i) => {
+ const key = `$_${i + 1}`
+ innerHandlerCode = innerHandlerCode.replace(exp, key)
+ return key
+ })
+ args.push('$event')
+ return '{\n' +
+ `handler:function(${args.join(',')}){${innerHandlerCode}},\n` +
+ `params:${JSON.stringify(bindings)}\n` +
+ '}'
+}
+
+function genHandler (
+ name: string,
+ handler: ASTElementHandler | Array<ASTElementHandler>
+): string {
+ if (!handler) {
+ return 'function(){}'
+ }
+
+ if (Array.isArray(handler)) {
+ return `[${handler.map(handler => genHandler(name, handler)).join(',')}]`
+ }
+
+ const isMethodPath = simplePathRE.test(handler.value)
+ const isFunctionExpression = fnExpRE.test(handler.value)
+
+ if (!handler.modifiers) {
+ if (isMethodPath || isFunctionExpression) {
+ return handler.value
+ }
+ /* istanbul ignore if */
+ if (__WEEX__ && handler.params) {
+ return genWeexHandler(handler.params, handler.value)
+ }
+ return `function($event){${handler.value}}` // inline statement
+ } else {
+ let code = ''
+ let genModifierCode = ''
+ const keys = []
+ for (const key in handler.modifiers) {
+ if (modifierCode[key]) {
+ genModifierCode += modifierCode[key]
+ // left/right
+ if (keyCodes[key]) {
+ keys.push(key)
+ }
+ } else if (key === 'exact') {
+ const modifiers: ASTModifiers = (handler.modifiers: any)
+ genModifierCode += genGuard(
+ ['ctrl', 'shift', 'alt', 'meta']
+ .filter(keyModifier => !modifiers[keyModifier])
+ .map(keyModifier => `$event.${keyModifier}Key`)
+ .join('||')
+ )
+ } else {
+ keys.push(key)
+ }
+ }
+ if (keys.length) {
+ code += genKeyFilter(keys)
+ }
+ // Make sure modifiers like prevent and stop get executed after key filtering
+ if (genModifierCode) {
+ code += genModifierCode
+ }
+ const handlerCode = isMethodPath
+ ? `return ${handler.value}($event)`
+ : isFunctionExpression
+ ? `return (${handler.value})($event)`
+ : handler.value
+ /* istanbul ignore if */
+ if (__WEEX__ && handler.params) {
+ return genWeexHandler(handler.params, code + handlerCode)
+ }
+ return `function($event){${code}${handlerCode}}`
+ }
+}
+
+function genKeyFilter (keys: Array<string>): string {
+ return `if(!('button' in $event)&&${keys.map(genFilterCode).join('&&')})return null;`
+}
+
+function genFilterCode (key: string): string {
+ const keyVal = parseInt(key, 10)
+ if (keyVal) {
+ return `$event.keyCode!==${keyVal}`
+ }
+ const keyCode = keyCodes[key]
+ const keyName = keyNames[key]
+ return (
+ `_k($event.keyCode,` +
+ `${JSON.stringify(key)},` +
+ `${JSON.stringify(keyCode)},` +
+ `$event.key,` +
+ `${JSON.stringify(keyName)}` +
+ `)`
+ )
+}
diff --git a/node_modules/vue/src/compiler/codegen/index.js b/node_modules/vue/src/compiler/codegen/index.js
new file mode 100644
index 00000000..1c912c4d
--- /dev/null
+++ b/node_modules/vue/src/compiler/codegen/index.js
@@ -0,0 +1,513 @@
+/* @flow */
+
+import { genHandlers } from './events'
+import baseDirectives from '../directives/index'
+import { camelize, no, extend } from 'shared/util'
+import { baseWarn, pluckModuleFunction } from '../helpers'
+
+type TransformFunction = (el: ASTElement, code: string) => string;
+type DataGenFunction = (el: ASTElement) => string;
+type DirectiveFunction = (el: ASTElement, dir: ASTDirective, warn: Function) => boolean;
+
+export class CodegenState {
+ options: CompilerOptions;
+ warn: Function;
+ transforms: Array<TransformFunction>;
+ dataGenFns: Array<DataGenFunction>;
+ directives: { [key: string]: DirectiveFunction };
+ maybeComponent: (el: ASTElement) => boolean;
+ onceId: number;
+ staticRenderFns: Array<string>;
+
+ constructor (options: CompilerOptions) {
+ this.options = options
+ this.warn = options.warn || baseWarn
+ this.transforms = pluckModuleFunction(options.modules, 'transformCode')
+ this.dataGenFns = pluckModuleFunction(options.modules, 'genData')
+ this.directives = extend(extend({}, baseDirectives), options.directives)
+ const isReservedTag = options.isReservedTag || no
+ this.maybeComponent = (el: ASTElement) => !isReservedTag(el.tag)
+ this.onceId = 0
+ this.staticRenderFns = []
+ }
+}
+
+export type CodegenResult = {
+ render: string,
+ staticRenderFns: Array<string>
+};
+
+export function generate (
+ ast: ASTElement | void,
+ options: CompilerOptions
+): CodegenResult {
+ const state = new CodegenState(options)
+ const code = ast ? genElement(ast, state) : '_c("div")'
+ return {
+ render: `with(this){return ${code}}`,
+ staticRenderFns: state.staticRenderFns
+ }
+}
+
+export function genElement (el: ASTElement, state: CodegenState): string {
+ if (el.staticRoot && !el.staticProcessed) {
+ return genStatic(el, state)
+ } else if (el.once && !el.onceProcessed) {
+ return genOnce(el, state)
+ } else if (el.for && !el.forProcessed) {
+ return genFor(el, state)
+ } else if (el.if && !el.ifProcessed) {
+ return genIf(el, state)
+ } else if (el.tag === 'template' && !el.slotTarget) {
+ return genChildren(el, state) || 'void 0'
+ } else if (el.tag === 'slot') {
+ return genSlot(el, state)
+ } else {
+ // component or element
+ let code
+ if (el.component) {
+ code = genComponent(el.component, el, state)
+ } else {
+ const data = el.plain ? undefined : genData(el, state)
+
+ const children = el.inlineTemplate ? null : genChildren(el, state, true)
+ code = `_c('${el.tag}'${
+ data ? `,${data}` : '' // data
+ }${
+ children ? `,${children}` : '' // children
+ })`
+ }
+ // module transforms
+ for (let i = 0; i < state.transforms.length; i++) {
+ code = state.transforms[i](el, code)
+ }
+ return code
+ }
+}
+
+// hoist static sub-trees out
+function genStatic (el: ASTElement, state: CodegenState): string {
+ el.staticProcessed = true
+ state.staticRenderFns.push(`with(this){return ${genElement(el, state)}}`)
+ return `_m(${
+ state.staticRenderFns.length - 1
+ }${
+ el.staticInFor ? ',true' : ''
+ })`
+}
+
+// v-once
+function genOnce (el: ASTElement, state: CodegenState): string {
+ el.onceProcessed = true
+ if (el.if && !el.ifProcessed) {
+ return genIf(el, state)
+ } else if (el.staticInFor) {
+ let key = ''
+ let parent = el.parent
+ while (parent) {
+ if (parent.for) {
+ key = parent.key
+ break
+ }
+ parent = parent.parent
+ }
+ if (!key) {
+ process.env.NODE_ENV !== 'production' && state.warn(
+ `v-once can only be used inside v-for that is keyed. `
+ )
+ return genElement(el, state)
+ }
+ return `_o(${genElement(el, state)},${state.onceId++},${key})`
+ } else {
+ return genStatic(el, state)
+ }
+}
+
+export function genIf (
+ el: any,
+ state: CodegenState,
+ altGen?: Function,
+ altEmpty?: string
+): string {
+ el.ifProcessed = true // avoid recursion
+ return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)
+}
+
+function genIfConditions (
+ conditions: ASTIfConditions,
+ state: CodegenState,
+ altGen?: Function,
+ altEmpty?: string
+): string {
+ if (!conditions.length) {
+ return altEmpty || '_e()'
+ }
+
+ const condition = conditions.shift()
+ if (condition.exp) {
+ return `(${condition.exp})?${
+ genTernaryExp(condition.block)
+ }:${
+ genIfConditions(conditions, state, altGen, altEmpty)
+ }`
+ } else {
+ return `${genTernaryExp(condition.block)}`
+ }
+
+ // v-if with v-once should generate code like (a)?_m(0):_m(1)
+ function genTernaryExp (el) {
+ return altGen
+ ? altGen(el, state)
+ : el.once
+ ? genOnce(el, state)
+ : genElement(el, state)
+ }
+}
+
+export function genFor (
+ el: any,
+ state: CodegenState,
+ altGen?: Function,
+ altHelper?: string
+): string {
+ const exp = el.for
+ const alias = el.alias
+ const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''
+ const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''
+
+ if (process.env.NODE_ENV !== 'production' &&
+ state.maybeComponent(el) &&
+ el.tag !== 'slot' &&
+ el.tag !== 'template' &&
+ !el.key
+ ) {
+ state.warn(
+ `<${el.tag} v-for="${alias} in ${exp}">: component lists rendered with ` +
+ `v-for should have explicit keys. ` +
+ `See https://vuejs.org/guide/list.html#key for more info.`,
+ true /* tip */
+ )
+ }
+
+ el.forProcessed = true // avoid recursion
+ return `${altHelper || '_l'}((${exp}),` +
+ `function(${alias}${iterator1}${iterator2}){` +
+ `return ${(altGen || genElement)(el, state)}` +
+ '})'
+}
+
+export function genData (el: ASTElement, state: CodegenState): string {
+ let data = '{'
+
+ // directives first.
+ // directives may mutate the el's other properties before they are generated.
+ const dirs = genDirectives(el, state)
+ if (dirs) data += dirs + ','
+
+ // key
+ if (el.key) {
+ data += `key:${el.key},`
+ }
+ // ref
+ if (el.ref) {
+ data += `ref:${el.ref},`
+ }
+ if (el.refInFor) {
+ data += `refInFor:true,`
+ }
+ // pre
+ if (el.pre) {
+ data += `pre:true,`
+ }
+ // record original tag name for components using "is" attribute
+ if (el.component) {
+ data += `tag:"${el.tag}",`
+ }
+ // module data generation functions
+ for (let i = 0; i < state.dataGenFns.length; i++) {
+ data += state.dataGenFns[i](el)
+ }
+ // attributes
+ if (el.attrs) {
+ data += `attrs:{${genProps(el.attrs)}},`
+ }
+ // DOM props
+ if (el.props) {
+ data += `domProps:{${genProps(el.props)}},`
+ }
+ // event handlers
+ if (el.events) {
+ data += `${genHandlers(el.events, false, state.warn)},`
+ }
+ if (el.nativeEvents) {
+ data += `${genHandlers(el.nativeEvents, true, state.warn)},`
+ }
+ // slot target
+ // only for non-scoped slots
+ if (el.slotTarget && !el.slotScope) {
+ data += `slot:${el.slotTarget},`
+ }
+ // scoped slots
+ if (el.scopedSlots) {
+ data += `${genScopedSlots(el.scopedSlots, state)},`
+ }
+ // component v-model
+ if (el.model) {
+ data += `model:{value:${
+ el.model.value
+ },callback:${
+ el.model.callback
+ },expression:${
+ el.model.expression
+ }},`
+ }
+ // inline-template
+ if (el.inlineTemplate) {
+ const inlineTemplate = genInlineTemplate(el, state)
+ if (inlineTemplate) {
+ data += `${inlineTemplate},`
+ }
+ }
+ data = data.replace(/,$/, '') + '}'
+ // v-bind data wrap
+ if (el.wrapData) {
+ data = el.wrapData(data)
+ }
+ // v-on data wrap
+ if (el.wrapListeners) {
+ data = el.wrapListeners(data)
+ }
+ return data
+}
+
+function genDirectives (el: ASTElement, state: CodegenState): string | void {
+ const dirs = el.directives
+ if (!dirs) return
+ let res = 'directives:['
+ let hasRuntime = false
+ let i, l, dir, needRuntime
+ for (i = 0, l = dirs.length; i < l; i++) {
+ dir = dirs[i]
+ needRuntime = true
+ const gen: DirectiveFunction = state.directives[dir.name]
+ if (gen) {
+ // compile-time directive that manipulates AST.
+ // returns true if it also needs a runtime counterpart.
+ needRuntime = !!gen(el, dir, state.warn)
+ }
+ if (needRuntime) {
+ hasRuntime = true
+ res += `{name:"${dir.name}",rawName:"${dir.rawName}"${
+ dir.value ? `,value:(${dir.value}),expression:${JSON.stringify(dir.value)}` : ''
+ }${
+ dir.arg ? `,arg:"${dir.arg}"` : ''
+ }${
+ dir.modifiers ? `,modifiers:${JSON.stringify(dir.modifiers)}` : ''
+ }},`
+ }
+ }
+ if (hasRuntime) {
+ return res.slice(0, -1) + ']'
+ }
+}
+
+function genInlineTemplate (el: ASTElement, state: CodegenState): ?string {
+ const ast = el.children[0]
+ if (process.env.NODE_ENV !== 'production' && (
+ el.children.length !== 1 || ast.type !== 1
+ )) {
+ state.warn('Inline-template components must have exactly one child element.')
+ }
+ if (ast.type === 1) {
+ const inlineRenderFns = generate(ast, state.options)
+ return `inlineTemplate:{render:function(){${
+ inlineRenderFns.render
+ }},staticRenderFns:[${
+ inlineRenderFns.staticRenderFns.map(code => `function(){${code}}`).join(',')
+ }]}`
+ }
+}
+
+function genScopedSlots (
+ slots: { [key: string]: ASTElement },
+ state: CodegenState
+): string {
+ return `scopedSlots:_u([${
+ Object.keys(slots).map(key => {
+ return genScopedSlot(key, slots[key], state)
+ }).join(',')
+ }])`
+}
+
+function genScopedSlot (
+ key: string,
+ el: ASTElement,
+ state: CodegenState
+): string {
+ if (el.for && !el.forProcessed) {
+ return genForScopedSlot(key, el, state)
+ }
+ const fn = `function(${String(el.slotScope)}){` +
+ `return ${el.tag === 'template'
+ ? el.if
+ ? `${el.if}?${genChildren(el, state) || 'undefined'}:undefined`
+ : genChildren(el, state) || 'undefined'
+ : genElement(el, state)
+ }}`
+ return `{key:${key},fn:${fn}}`
+}
+
+function genForScopedSlot (
+ key: string,
+ el: any,
+ state: CodegenState
+): string {
+ const exp = el.for
+ const alias = el.alias
+ const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''
+ const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''
+ el.forProcessed = true // avoid recursion
+ return `_l((${exp}),` +
+ `function(${alias}${iterator1}${iterator2}){` +
+ `return ${genScopedSlot(key, el, state)}` +
+ '})'
+}
+
+export function genChildren (
+ el: ASTElement,
+ state: CodegenState,
+ checkSkip?: boolean,
+ altGenElement?: Function,
+ altGenNode?: Function
+): string | void {
+ const children = el.children
+ if (children.length) {
+ const el: any = children[0]
+ // optimize single v-for
+ if (children.length === 1 &&
+ el.for &&
+ el.tag !== 'template' &&
+ el.tag !== 'slot'
+ ) {
+ return (altGenElement || genElement)(el, state)
+ }
+ const normalizationType = checkSkip
+ ? getNormalizationType(children, state.maybeComponent)
+ : 0
+ const gen = altGenNode || genNode
+ return `[${children.map(c => gen(c, state)).join(',')}]${
+ normalizationType ? `,${normalizationType}` : ''
+ }`
+ }
+}
+
+// determine the normalization needed for the children array.
+// 0: no normalization needed
+// 1: simple normalization needed (possible 1-level deep nested array)
+// 2: full normalization needed
+function getNormalizationType (
+ children: Array<ASTNode>,
+ maybeComponent: (el: ASTElement) => boolean
+): number {
+ let res = 0
+ for (let i = 0; i < children.length; i++) {
+ const el: ASTNode = children[i]
+ if (el.type !== 1) {
+ continue
+ }
+ if (needsNormalization(el) ||
+ (el.ifConditions && el.ifConditions.some(c => needsNormalization(c.block)))) {
+ res = 2
+ break
+ }
+ if (maybeComponent(el) ||
+ (el.ifConditions && el.ifConditions.some(c => maybeComponent(c.block)))) {
+ res = 1
+ }
+ }
+ return res
+}
+
+function needsNormalization (el: ASTElement): boolean {
+ return el.for !== undefined || el.tag === 'template' || el.tag === 'slot'
+}
+
+function genNode (node: ASTNode, state: CodegenState): string {
+ if (node.type === 1) {
+ return genElement(node, state)
+ } if (node.type === 3 && node.isComment) {
+ return genComment(node)
+ } else {
+ return genText(node)
+ }
+}
+
+export function genText (text: ASTText | ASTExpression): string {
+ return `_v(${text.type === 2
+ ? text.expression // no need for () because already wrapped in _s()
+ : transformSpecialNewlines(JSON.stringify(text.text))
+ })`
+}
+
+export function genComment (comment: ASTText): string {
+ return `_e(${JSON.stringify(comment.text)})`
+}
+
+function genSlot (el: ASTElement, state: CodegenState): string {
+ const slotName = el.slotName || '"default"'
+ const children = genChildren(el, state)
+ let res = `_t(${slotName}${children ? `,${children}` : ''}`
+ const attrs = el.attrs && `{${el.attrs.map(a => `${camelize(a.name)}:${a.value}`).join(',')}}`
+ const bind = el.attrsMap['v-bind']
+ if ((attrs || bind) && !children) {
+ res += `,null`
+ }
+ if (attrs) {
+ res += `,${attrs}`
+ }
+ if (bind) {
+ res += `${attrs ? '' : ',null'},${bind}`
+ }
+ return res + ')'
+}
+
+// componentName is el.component, take it as argument to shun flow's pessimistic refinement
+function genComponent (
+ componentName: string,
+ el: ASTElement,
+ state: CodegenState
+): string {
+ const children = el.inlineTemplate ? null : genChildren(el, state, true)
+ return `_c(${componentName},${genData(el, state)}${
+ children ? `,${children}` : ''
+ })`
+}
+
+function genProps (props: Array<{ name: string, value: any }>): string {
+ let res = ''
+ for (let i = 0; i < props.length; i++) {
+ const prop = props[i]
+ /* istanbul ignore if */
+ if (__WEEX__) {
+ res += `"${prop.name}":${generateValue(prop.value)},`
+ } else {
+ res += `"${prop.name}":${transformSpecialNewlines(prop.value)},`
+ }
+ }
+ return res.slice(0, -1)
+}
+
+/* istanbul ignore next */
+function generateValue (value) {
+ if (typeof value === 'string') {
+ return transformSpecialNewlines(value)
+ }
+ return JSON.stringify(value)
+}
+
+// #3895, #4268
+function transformSpecialNewlines (text: string): string {
+ return text
+ .replace(/\u2028/g, '\\u2028')
+ .replace(/\u2029/g, '\\u2029')
+}
diff --git a/node_modules/vue/src/compiler/create-compiler.js b/node_modules/vue/src/compiler/create-compiler.js
new file mode 100644
index 00000000..6671dcfe
--- /dev/null
+++ b/node_modules/vue/src/compiler/create-compiler.js
@@ -0,0 +1,55 @@
+/* @flow */
+
+import { extend } from 'shared/util'
+import { detectErrors } from './error-detector'
+import { createCompileToFunctionFn } from './to-function'
+
+export function createCompilerCreator (baseCompile: Function): Function {
+ return function createCompiler (baseOptions: CompilerOptions) {
+ function compile (
+ template: string,
+ options?: CompilerOptions
+ ): CompiledResult {
+ const finalOptions = Object.create(baseOptions)
+ const errors = []
+ const tips = []
+ finalOptions.warn = (msg, tip) => {
+ (tip ? tips : errors).push(msg)
+ }
+
+ if (options) {
+ // merge custom modules
+ if (options.modules) {
+ finalOptions.modules =
+ (baseOptions.modules || []).concat(options.modules)
+ }
+ // merge custom directives
+ if (options.directives) {
+ finalOptions.directives = extend(
+ Object.create(baseOptions.directives || null),
+ options.directives
+ )
+ }
+ // copy other options
+ for (const key in options) {
+ if (key !== 'modules' && key !== 'directives') {
+ finalOptions[key] = options[key]
+ }
+ }
+ }
+
+ const compiled = baseCompile(template, finalOptions)
+ if (process.env.NODE_ENV !== 'production') {
+ errors.push.apply(errors, detectErrors(compiled.ast))
+ }
+ compiled.errors = errors
+ compiled.tips = tips
+ return compiled
+ }
+
+ return {
+ compile,
+ compileToFunctions: createCompileToFunctionFn(compile)
+ }
+ }
+}
diff --git a/node_modules/vue/src/compiler/directives/bind.js b/node_modules/vue/src/compiler/directives/bind.js
new file mode 100644
index 00000000..e1035727
--- /dev/null
+++ b/node_modules/vue/src/compiler/directives/bind.js
@@ -0,0 +1,11 @@
+/* @flow */
+
+export default function bind (el: ASTElement, dir: ASTDirective) {
+ el.wrapData = (code: string) => {
+ return `_b(${code},'${el.tag}',${dir.value},${
+ dir.modifiers && dir.modifiers.prop ? 'true' : 'false'
+ }${
+ dir.modifiers && dir.modifiers.sync ? ',true' : ''
+ })`
+ }
+}
diff --git a/node_modules/vue/src/compiler/directives/index.js b/node_modules/vue/src/compiler/directives/index.js
new file mode 100644
index 00000000..8f4342c0
--- /dev/null
+++ b/node_modules/vue/src/compiler/directives/index.js
@@ -0,0 +1,11 @@
+/* @flow */
+
+import on from './on'
+import bind from './bind'
+import { noop } from 'shared/util'
+
+export default {
+ on,
+ bind,
+ cloak: noop
+}
diff --git a/node_modules/vue/src/compiler/directives/model.js b/node_modules/vue/src/compiler/directives/model.js
new file mode 100644
index 00000000..39bdbfda
--- /dev/null
+++ b/node_modules/vue/src/compiler/directives/model.js
@@ -0,0 +1,148 @@
+/* @flow */
+
+/**
+ * Cross-platform code generation for component v-model
+ */
+export function genComponentModel (
+ el: ASTElement,
+ value: string,
+ modifiers: ?ASTModifiers
+): ?boolean {
+ const { number, trim } = modifiers || {}
+
+ const baseValueExpression = '$$v'
+ let valueExpression = baseValueExpression
+ if (trim) {
+ valueExpression =
+ `(typeof ${baseValueExpression} === 'string'` +
+ `? ${baseValueExpression}.trim()` +
+ `: ${baseValueExpression})`
+ }
+ if (number) {
+ valueExpression = `_n(${valueExpression})`
+ }
+ const assignment = genAssignmentCode(value, valueExpression)
+
+ el.model = {
+ value: `(${value})`,
+ expression: `"${value}"`,
+ callback: `function (${baseValueExpression}) {${assignment}}`
+ }
+}
+
+/**
+ * Cross-platform codegen helper for generating v-model value assignment code.
+ */
+export function genAssignmentCode (
+ value: string,
+ assignment: string
+): string {
+ const res = parseModel(value)
+ if (res.key === null) {
+ return `${value}=${assignment}`
+ } else {
+ return `$set(${res.exp}, ${res.key}, ${assignment})`
+ }
+}
+
+/**
+ * Parse a v-model expression into a base path and a final key segment.
+ * Handles both dot-path and possible square brackets.
+ *
+ * Possible cases:
+ *
+ * - test
+ * - test[key]
+ * - test[test1[key]]
+ * - test["a"][key]
+ * - xxx.test[a[a].test1[key]]
+ * - test.xxx.a["asa"][test1[key]]
+ *
+ */
+
+let len, str, chr, index, expressionPos, expressionEndPos
+
+type ModelParseResult = {
+ exp: string,
+ key: string | null
+}
+
+export function parseModel (val: string): ModelParseResult {
+ // Fix https://github.com/vuejs/vue/pull/7730
+ // allow v-model="obj.val " (trailing whitespace)
+ val = val.trim()
+ len = val.length
+
+ if (val.indexOf('[') < 0 || val.lastIndexOf(']') < len - 1) {
+ index = val.lastIndexOf('.')
+ if (index > -1) {
+ return {
+ exp: val.slice(0, index),
+ key: '"' + val.slice(index + 1) + '"'
+ }
+ } else {
+ return {
+ exp: val,
+ key: null
+ }
+ }
+ }
+
+ str = val
+ index = expressionPos = expressionEndPos = 0
+
+ while (!eof()) {
+ chr = next()
+ /* istanbul ignore if */
+ if (isStringStart(chr)) {
+ parseString(chr)
+ } else if (chr === 0x5B) {
+ parseBracket(chr)
+ }
+ }
+
+ return {
+ exp: val.slice(0, expressionPos),
+ key: val.slice(expressionPos + 1, expressionEndPos)
+ }
+}
+
+function next (): number {
+ return str.charCodeAt(++index)
+}
+
+function eof (): boolean {
+ return index >= len
+}
+
+function isStringStart (chr: number): boolean {
+ return chr === 0x22 || chr === 0x27
+}
+
+function parseBracket (chr: number): void {
+ let inBracket = 1
+ expressionPos = index
+ while (!eof()) {
+ chr = next()
+ if (isStringStart(chr)) {
+ parseString(chr)
+ continue
+ }
+ if (chr === 0x5B) inBracket++
+ if (chr === 0x5D) inBracket--
+ if (inBracket === 0) {
+ expressionEndPos = index
+ break
+ }
+ }
+}
+
+function parseString (chr: number): void {
+ const stringQuote = chr
+ while (!eof()) {
+ chr = next()
+ if (chr === stringQuote) {
+ break
+ }
+ }
+}
diff --git a/node_modules/vue/src/compiler/directives/on.js b/node_modules/vue/src/compiler/directives/on.js
new file mode 100644
index 00000000..893a678e
--- /dev/null
+++ b/node_modules/vue/src/compiler/directives/on.js
@@ -0,0 +1,10 @@
+/* @flow */
+
+import { warn } from 'core/util/index'
+
+export default function on (el: ASTElement, dir: ASTDirective) {
+ if (process.env.NODE_ENV !== 'production' && dir.modifiers) {
+ warn(`v-on without argument does not support modifiers.`)
+ }
+ el.wrapListeners = (code: string) => `_g(${code},${dir.value})`
+}
diff --git a/node_modules/vue/src/compiler/error-detector.js b/node_modules/vue/src/compiler/error-detector.js
new file mode 100644
index 00000000..e729c499
--- /dev/null
+++ b/node_modules/vue/src/compiler/error-detector.js
@@ -0,0 +1,108 @@
+/* @flow */
+
+import { dirRE, onRE } from './parser/index'
+
+// these keywords should not appear inside expressions, but operators like
+// typeof, instanceof and in are allowed
+const prohibitedKeywordRE = new RegExp('\\b' + (
+ 'do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +
+ 'super,throw,while,yield,delete,export,import,return,switch,default,' +
+ 'extends,finally,continue,debugger,function,arguments'
+).split(',').join('\\b|\\b') + '\\b')
+
+// these unary operators should not be used as property/method names
+const unaryOperatorsRE = new RegExp('\\b' + (
+ 'delete,typeof,void'
+).split(',').join('\\s*\\([^\\)]*\\)|\\b') + '\\s*\\([^\\)]*\\)')
+
+// strip strings in expressions
+const stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g
+
+// detect problematic expressions in a template
+export function detectErrors (ast: ?ASTNode): Array<string> {
+ const errors: Array<string> = []
+ if (ast) {
+ checkNode(ast, errors)
+ }
+ return errors
+}
+
+function checkNode (node: ASTNode, errors: Array<string>) {
+ if (node.type === 1) {
+ for (const name in node.attrsMap) {
+ if (dirRE.test(name)) {
+ const value = node.attrsMap[name]
+ if (value) {
+ if (name === 'v-for') {
+ checkFor(node, `v-for="${value}"`, errors)
+ } else if (onRE.test(name)) {
+ checkEvent(value, `${name}="${value}"`, errors)
+ } else {
+ checkExpression(value, `${name}="${value}"`, errors)
+ }
+ }
+ }
+ }
+ if (node.children) {
+ for (let i = 0; i < node.children.length; i++) {
+ checkNode(node.children[i], errors)
+ }
+ }
+ } else if (node.type === 2) {
+ checkExpression(node.expression, node.text, errors)
+ }
+}
+
+function checkEvent (exp: string, text: string, errors: Array<string>) {
+ const stipped = exp.replace(stripStringRE, '')
+ const keywordMatch: any = stipped.match(unaryOperatorsRE)
+ if (keywordMatch && stipped.charAt(keywordMatch.index - 1) !== '$') {
+ errors.push(
+ `avoid using JavaScript unary operator as property name: ` +
+ `"${keywordMatch[0]}" in expression ${text.trim()}`
+ )
+ }
+ checkExpression(exp, text, errors)
+}
+
+function checkFor (node: ASTElement, text: string, errors: Array<string>) {
+ checkExpression(node.for || '', text, errors)
+ checkIdentifier(node.alias, 'v-for alias', text, errors)
+ checkIdentifier(node.iterator1, 'v-for iterator', text, errors)
+ checkIdentifier(node.iterator2, 'v-for iterator', text, errors)
+}
+
+function checkIdentifier (
+ ident: ?string,
+ type: string,
+ text: string,
+ errors: Array<string>
+) {
+ if (typeof ident === 'string') {
+ try {
+ new Function(`var ${ident}=_`)
+ } catch (e) {
+ errors.push(`invalid ${type} "${ident}" in expression: ${text.trim()}`)
+ }
+ }
+}
+
+function checkExpression (exp: string, text: string, errors: Array<string>) {
+ try {
+ new Function(`return ${exp}`)
+ } catch (e) {
+ const keywordMatch = exp.replace(stripStringRE, '').match(prohibitedKeywordRE)
+ if (keywordMatch) {
+ errors.push(
+ `avoid using JavaScript keyword as property name: ` +
+ `"${keywordMatch[0]}"\n Raw expression: ${text.trim()}`
+ )
+ } else {
+ errors.push(
+ `invalid expression: ${e.message} in\n\n` +
+ ` ${exp}\n\n` +
+ ` Raw expression: ${text.trim()}\n`
+ )
+ }
+ }
+}
diff --git a/node_modules/vue/src/compiler/helpers.js b/node_modules/vue/src/compiler/helpers.js
new file mode 100644
index 00000000..6a7375a3
--- /dev/null
+++ b/node_modules/vue/src/compiler/helpers.js
@@ -0,0 +1,164 @@
+/* @flow */
+
+import { emptyObject } from 'shared/util'
+import { parseFilters } from './parser/filter-parser'
+
+export function baseWarn (msg: string) {
+ console.error(`[Vue compiler]: ${msg}`)
+}
+
+export function pluckModuleFunction<F: Function> (
+ modules: ?Array<Object>,
+ key: string
+): Array<F> {
+ return modules
+ ? modules.map(m => m[key]).filter(_ => _)
+ : []
+}
+
+export function addProp (el: ASTElement, name: string, value: string) {
+ (el.props || (el.props = [])).push({ name, value })
+ el.plain = false
+}
+
+export function addAttr (el: ASTElement, name: string, value: any) {
+ (el.attrs || (el.attrs = [])).push({ name, value })
+ el.plain = false
+}
+
+// add a raw attr (use this in preTransforms)
+export function addRawAttr (el: ASTElement, name: string, value: any) {
+ el.attrsMap[name] = value
+ el.attrsList.push({ name, value })
+}
+
+export function addDirective (
+ el: ASTElement,
+ name: string,
+ rawName: string,
+ value: string,
+ arg: ?string,
+ modifiers: ?ASTModifiers
+) {
+ (el.directives || (el.directives = [])).push({ name, rawName, value, arg, modifiers })
+ el.plain = false
+}
+
+export function addHandler (
+ el: ASTElement,
+ name: string,
+ value: string,
+ modifiers: ?ASTModifiers,
+ important?: boolean,
+ warn?: Function
+) {
+ modifiers = modifiers || emptyObject
+ // warn prevent and passive modifier
+ /* istanbul ignore if */
+ if (
+ process.env.NODE_ENV !== 'production' && warn &&
+ modifiers.prevent && modifiers.passive
+ ) {
+ warn(
+ 'passive and prevent can\'t be used together. ' +
+ 'Passive handler can\'t prevent default event.'
+ )
+ }
+
+ // check capture modifier
+ if (modifiers.capture) {
+ delete modifiers.capture
+ name = '!' + name // mark the event as captured
+ }
+ if (modifiers.once) {
+ delete modifiers.once
+ name = '~' + name // mark the event as once
+ }
+ /* istanbul ignore if */
+ if (modifiers.passive) {
+ delete modifiers.passive
+ name = '&' + name // mark the event as passive
+ }
+
+ // normalize click.right and click.middle since they don't actually fire
+ // this is technically browser-specific, but at least for now browsers are
+ // the only target envs that have right/middle clicks.
+ if (name === 'click') {
+ if (modifiers.right) {
+ name = 'contextmenu'
+ delete modifiers.right
+ } else if (modifiers.middle) {
+ name = 'mouseup'
+ }
+ }
+
+ let events
+ if (modifiers.native) {
+ delete modifiers.native
+ events = el.nativeEvents || (el.nativeEvents = {})
+ } else {
+ events = el.events || (el.events = {})
+ }
+
+ const newHandler: any = {
+ value: value.trim()
+ }
+ if (modifiers !== emptyObject) {
+ newHandler.modifiers = modifiers
+ }
+
+ const handlers = events[name]
+ /* istanbul ignore if */
+ if (Array.isArray(handlers)) {
+ important ? handlers.unshift(newHandler) : handlers.push(newHandler)
+ } else if (handlers) {
+ events[name] = important ? [newHandler, handlers] : [handlers, newHandler]
+ } else {
+ events[name] = newHandler
+ }
+
+ el.plain = false
+}
+
+export function getBindingAttr (
+ el: ASTElement,
+ name: string,
+ getStatic?: boolean
+): ?string {
+ const dynamicValue =
+ getAndRemoveAttr(el, ':' + name) ||
+ getAndRemoveAttr(el, 'v-bind:' + name)
+ if (dynamicValue != null) {
+ return parseFilters(dynamicValue)
+ } else if (getStatic !== false) {
+ const staticValue = getAndRemoveAttr(el, name)
+ if (staticValue != null) {
+ return JSON.stringify(staticValue)
+ }
+ }
+}
+
+// note: this only removes the attr from the Array (attrsList) so that it
+// doesn't get processed by processAttrs.
+// By default it does NOT remove it from the map (attrsMap) because the map is
+// needed during codegen.
+export function getAndRemoveAttr (
+ el: ASTElement,
+ name: string,
+ removeFromMap?: boolean
+): ?string {
+ let val
+ if ((val = el.attrsMap[name]) != null) {
+ const list = el.attrsList
+ for (let i = 0, l = list.length; i < l; i++) {
+ if (list[i].name === name) {
+ list.splice(i, 1)
+ break
+ }
+ }
+ }
+ if (removeFromMap) {
+ delete el.attrsMap[name]
+ }
+ return val
+}
diff --git a/node_modules/vue/src/compiler/index.js b/node_modules/vue/src/compiler/index.js
new file mode 100644
index 00000000..56b54fd3
--- /dev/null
+++ b/node_modules/vue/src/compiler/index.js
@@ -0,0 +1,25 @@
+/* @flow */
+
+import { parse } from './parser/index'
+import { optimize } from './optimizer'
+import { generate } from './codegen/index'
+import { createCompilerCreator } from './create-compiler'
+
+// `createCompilerCreator` allows creating compilers that use alternative
+// parser/optimizer/codegen, e.g the SSR optimizing compiler.
+// Here we just export a default compiler using the default parts.
+export const createCompiler = createCompilerCreator(function baseCompile (
+ template: string,
+ options: CompilerOptions
+): CompiledResult {
+ const ast = parse(template.trim(), options)
+ if (options.optimize !== false) {
+ optimize(ast, options)
+ }
+ const code = generate(ast, options)
+ return {
+ ast,
+ render: code.render,
+ staticRenderFns: code.staticRenderFns
+ }
+})
diff --git a/node_modules/vue/src/compiler/optimizer.js b/node_modules/vue/src/compiler/optimizer.js
new file mode 100644
index 00000000..ce432035
--- /dev/null
+++ b/node_modules/vue/src/compiler/optimizer.js
@@ -0,0 +1,128 @@
+/* @flow */
+
+import { makeMap, isBuiltInTag, cached, no } from 'shared/util'
+
+let isStaticKey
+let isPlatformReservedTag
+
+const genStaticKeysCached = cached(genStaticKeys)
+
+/**
+ * Goal of the optimizer: walk the generated template AST tree
+ * and detect sub-trees that are purely static, i.e. parts of
+ * the DOM that never needs to change.
+ *
+ * Once we detect these sub-trees, we can:
+ *
+ * 1. Hoist them into constants, so that we no longer need to
+ * create fresh nodes for them on each re-render;
+ * 2. Completely skip them in the patching process.
+ */
+export function optimize (root: ?ASTElement, options: CompilerOptions) {
+ if (!root) return
+ isStaticKey = genStaticKeysCached(options.staticKeys || '')
+ isPlatformReservedTag = options.isReservedTag || no
+ // first pass: mark all non-static nodes.
+ markStatic(root)
+ // second pass: mark static roots.
+ markStaticRoots(root, false)
+}
+
+function genStaticKeys (keys: string): Function {
+ return makeMap(
+ 'type,tag,attrsList,attrsMap,plain,parent,children,attrs' +
+ (keys ? ',' + keys : '')
+ )
+}
+
+function markStatic (node: ASTNode) {
+ node.static = isStatic(node)
+ if (node.type === 1) {
+ // do not make component slot content static. this avoids
+ // 1. components not able to mutate slot nodes
+ // 2. static slot content fails for hot-reloading
+ if (
+ !isPlatformReservedTag(node.tag) &&
+ node.tag !== 'slot' &&
+ node.attrsMap['inline-template'] == null
+ ) {
+ return
+ }
+ for (let i = 0, l = node.children.length; i < l; i++) {
+ const child = node.children[i]
+ markStatic(child)
+ if (!child.static) {
+ node.static = false
+ }
+ }
+ if (node.ifConditions) {
+ for (let i = 1, l = node.ifConditions.length; i < l; i++) {
+ const block = node.ifConditions[i].block
+ markStatic(block)
+ if (!block.static) {
+ node.static = false
+ }
+ }
+ }
+ }
+}
+
+function markStaticRoots (node: ASTNode, isInFor: boolean) {
+ if (node.type === 1) {
+ if (node.static || node.once) {
+ node.staticInFor = isInFor
+ }
+ // For a node to qualify as a static root, it should have children that
+ // are not just static text. Otherwise the cost of hoisting out will
+ // outweigh the benefits and it's better off to just always render it fresh.
+ if (node.static && node.children.length && !(
+ node.children.length === 1 &&
+ node.children[0].type === 3
+ )) {
+ node.staticRoot = true
+ return
+ } else {
+ node.staticRoot = false
+ }
+ if (node.children) {
+ for (let i = 0, l = node.children.length; i < l; i++) {
+ markStaticRoots(node.children[i], isInFor || !!node.for)
+ }
+ }
+ if (node.ifConditions) {
+ for (let i = 1, l = node.ifConditions.length; i < l; i++) {
+ markStaticRoots(node.ifConditions[i].block, isInFor)
+ }
+ }
+ }
+}
+
+function isStatic (node: ASTNode): boolean {
+ if (node.type === 2) { // expression
+ return false
+ }
+ if (node.type === 3) { // text
+ return true
+ }
+ return !!(node.pre || (
+ !node.hasBindings && // no dynamic bindings
+ !node.if && !node.for && // not v-if or v-for or v-else
+ !isBuiltInTag(node.tag) && // not a built-in
+ isPlatformReservedTag(node.tag) && // not a component
+ !isDirectChildOfTemplateFor(node) &&
+ Object.keys(node).every(isStaticKey)
+ ))
+}
+
+function isDirectChildOfTemplateFor (node: ASTElement): boolean {
+ while (node.parent) {
+ node = node.parent
+ if (node.tag !== 'template') {
+ return false
+ }
+ if (node.for) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/node_modules/vue/src/compiler/parser/entity-decoder.js b/node_modules/vue/src/compiler/parser/entity-decoder.js
new file mode 100644
index 00000000..2836294f
--- /dev/null
+++ b/node_modules/vue/src/compiler/parser/entity-decoder.js
@@ -0,0 +1,11 @@
+/* @flow */
+
+let decoder
+
+export default {
+ decode (html: string): string {
+ decoder = decoder || document.createElement('div')
+ decoder.innerHTML = html
+ return decoder.textContent
+ }
+}
diff --git a/node_modules/vue/src/compiler/parser/filter-parser.js b/node_modules/vue/src/compiler/parser/filter-parser.js
new file mode 100644
index 00000000..10939d3f
--- /dev/null
+++ b/node_modules/vue/src/compiler/parser/filter-parser.js
@@ -0,0 +1,97 @@
+/* @flow */
+
+const validDivisionCharRE = /[\w).+\-_$\]]/
+
+export function parseFilters (exp: string): string {
+ let inSingle = false
+ let inDouble = false
+ let inTemplateString = false
+ let inRegex = false
+ let curly = 0
+ let square = 0
+ let paren = 0
+ let lastFilterIndex = 0
+ let c, prev, i, expression, filters
+
+ for (i = 0; i < exp.length; i++) {
+ prev = c
+ c = exp.charCodeAt(i)
+ if (inSingle) {
+ if (c === 0x27 && prev !== 0x5C) inSingle = false
+ } else if (inDouble) {
+ if (c === 0x22 && prev !== 0x5C) inDouble = false
+ } else if (inTemplateString) {
+ if (c === 0x60 && prev !== 0x5C) inTemplateString = false
+ } else if (inRegex) {
+ if (c === 0x2f && prev !== 0x5C) inRegex = false
+ } else if (
+ c === 0x7C && // pipe
+ exp.charCodeAt(i + 1) !== 0x7C &&
+ exp.charCodeAt(i - 1) !== 0x7C &&
+ !curly && !square && !paren
+ ) {
+ if (expression === undefined) {
+ // first filter, end of expression
+ lastFilterIndex = i + 1
+ expression = exp.slice(0, i).trim()
+ } else {
+ pushFilter()
+ }
+ } else {
+ switch (c) {
+ case 0x22: inDouble = true; break // "
+ case 0x27: inSingle = true; break // '
+ case 0x60: inTemplateString = true; break // `
+ case 0x28: paren++; break // (
+ case 0x29: paren--; break // )
+ case 0x5B: square++; break // [
+ case 0x5D: square--; break // ]
+ case 0x7B: curly++; break // {
+ case 0x7D: curly--; break // }
+ }
+ if (c === 0x2f) { // /
+ let j = i - 1
+ let p
+ // find first non-whitespace prev char
+ for (; j >= 0; j--) {
+ p = exp.charAt(j)
+ if (p !== ' ') break
+ }
+ if (!p || !validDivisionCharRE.test(p)) {
+ inRegex = true
+ }
+ }
+ }
+ }
+
+ if (expression === undefined) {
+ expression = exp.slice(0, i).trim()
+ } else if (lastFilterIndex !== 0) {
+ pushFilter()
+ }
+
+ function pushFilter () {
+ (filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim())
+ lastFilterIndex = i + 1
+ }
+
+ if (filters) {
+ for (i = 0; i < filters.length; i++) {
+ expression = wrapFilter(expression, filters[i])
+ }
+ }
+
+ return expression
+}
+
+function wrapFilter (exp: string, filter: string): string {
+ const i = filter.indexOf('(')
+ if (i < 0) {
+ // _f: resolveFilter
+ return `_f("${filter}")(${exp})`
+ } else {
+ const name = filter.slice(0, i)
+ const args = filter.slice(i + 1)
+ return `_f("${name}")(${exp}${args !== ')' ? ',' + args : args}`
+ }
+}
diff --git a/node_modules/vue/src/compiler/parser/html-parser.js b/node_modules/vue/src/compiler/parser/html-parser.js
new file mode 100644
index 00000000..e2203613
--- /dev/null
+++ b/node_modules/vue/src/compiler/parser/html-parser.js
@@ -0,0 +1,310 @@
+/**
+ * Not type-checking this file because it's mostly vendor code.
+ */
+
+/*!
+ * HTML Parser By John Resig (ejohn.org)
+ * Modified by Juriy "kangax" Zaytsev
+ * Original code by Erik Arvidsson, Mozilla Public License
+ * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
+ */
+
+import { makeMap, no } from 'shared/util'
+import { isNonPhrasingTag } from 'web/compiler/util'
+
+// Regular Expressions for parsing tags and attributes
+const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
+// could use https://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-QName
+// but for Vue templates we can enforce a simple charset
+const ncname = '[a-zA-Z_][\\w\\-\\.]*'
+const qnameCapture = `((?:${ncname}\\:)?${ncname})`
+const startTagOpen = new RegExp(`^<${qnameCapture}`)
+const startTagClose = /^\s*(\/?)>/
+const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)
+const doctype = /^<!DOCTYPE [^>]+>/i
+// #7298: escape - to avoid being pased as HTML comment when inlined in page
+const comment = /^<!\--/
+const conditionalComment = /^<!\[/
+
+let IS_REGEX_CAPTURING_BROKEN = false
+'x'.replace(/x(.)?/g, function (m, g) {
+ IS_REGEX_CAPTURING_BROKEN = g === ''
+})
+
+// Special Elements (can contain anything)
+export const isPlainTextElement = makeMap('script,style,textarea', true)
+const reCache = {}
+
+const decodingMap = {
+ '&lt;': '<',
+ '&gt;': '>',
+ '&quot;': '"',
+ '&amp;': '&',
+ '&#10;': '\n',
+ '&#9;': '\t'
+}
+const encodedAttr = /&(?:lt|gt|quot|amp);/g
+const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10|#9);/g
+
+// #5992
+const isIgnoreNewlineTag = makeMap('pre,textarea', true)
+const shouldIgnoreFirstNewline = (tag, html) => tag && isIgnoreNewlineTag(tag) && html[0] === '\n'
+
+function decodeAttr (value, shouldDecodeNewlines) {
+ const re = shouldDecodeNewlines ? encodedAttrWithNewLines : encodedAttr
+ return value.replace(re, match => decodingMap[match])
+}
+
+export function parseHTML (html, options) {
+ const stack = []
+ const expectHTML = options.expectHTML
+ const isUnaryTag = options.isUnaryTag || no
+ const canBeLeftOpenTag = options.canBeLeftOpenTag || no
+ let index = 0
+ let last, lastTag
+ while (html) {
+ last = html
+ // Make sure we're not in a plaintext content element like script/style
+ if (!lastTag || !isPlainTextElement(lastTag)) {
+ let textEnd = html.indexOf('<')
+ if (textEnd === 0) {
+ // Comment:
+ if (comment.test(html)) {
+ const commentEnd = html.indexOf('-->')
+
+ if (commentEnd >= 0) {
+ if (options.shouldKeepComment) {
+ options.comment(html.substring(4, commentEnd))
+ }
+ advance(commentEnd + 3)
+ continue
+ }
+ }
+
+ // http://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment
+ if (conditionalComment.test(html)) {
+ const conditionalEnd = html.indexOf(']>')
+
+ if (conditionalEnd >= 0) {
+ advance(conditionalEnd + 2)
+ continue
+ }
+ }
+
+ // Doctype:
+ const doctypeMatch = html.match(doctype)
+ if (doctypeMatch) {
+ advance(doctypeMatch[0].length)
+ continue
+ }
+
+ // End tag:
+ const endTagMatch = html.match(endTag)
+ if (endTagMatch) {
+ const curIndex = index
+ advance(endTagMatch[0].length)
+ parseEndTag(endTagMatch[1], curIndex, index)
+ continue
+ }
+
+ // Start tag:
+ const startTagMatch = parseStartTag()
+ if (startTagMatch) {
+ handleStartTag(startTagMatch)
+ if (shouldIgnoreFirstNewline(lastTag, html)) {
+ advance(1)
+ }
+ continue
+ }
+ }
+
+ let text, rest, next
+ if (textEnd >= 0) {
+ rest = html.slice(textEnd)
+ while (
+ !endTag.test(rest) &&
+ !startTagOpen.test(rest) &&
+ !comment.test(rest) &&
+ !conditionalComment.test(rest)
+ ) {
+ // < in plain text, be forgiving and treat it as text
+ next = rest.indexOf('<', 1)
+ if (next < 0) break
+ textEnd += next
+ rest = html.slice(textEnd)
+ }
+ text = html.substring(0, textEnd)
+ advance(textEnd)
+ }
+
+ if (textEnd < 0) {
+ text = html
+ html = ''
+ }
+
+ if (options.chars && text) {
+ options.chars(text)
+ }
+ } else {
+ let endTagLength = 0
+ const stackedTag = lastTag.toLowerCase()
+ const reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\s\\S]*?)(</' + stackedTag + '[^>]*>)', 'i'))
+ const rest = html.replace(reStackedTag, function (all, text, endTag) {
+ endTagLength = endTag.length
+ if (!isPlainTextElement(stackedTag) && stackedTag !== 'noscript') {
+ text = text
+ .replace(/<!\--([\s\S]*?)-->/g, '$1') // #7298
+ .replace(/<!\[CDATA\[([\s\S]*?)]]>/g, '$1')
+ }
+ if (shouldIgnoreFirstNewline(stackedTag, text)) {
+ text = text.slice(1)
+ }
+ if (options.chars) {
+ options.chars(text)
+ }
+ return ''
+ })
+ index += html.length - rest.length
+ html = rest
+ parseEndTag(stackedTag, index - endTagLength, index)
+ }
+
+ if (html === last) {
+ options.chars && options.chars(html)
+ if (process.env.NODE_ENV !== 'production' && !stack.length && options.warn) {
+ options.warn(`Mal-formatted tag at end of template: "${html}"`)
+ }
+ break
+ }
+ }
+
+ // Clean up any remaining tags
+ parseEndTag()
+
+ function advance (n) {
+ index += n
+ html = html.substring(n)
+ }
+
+ function parseStartTag () {
+ const start = html.match(startTagOpen)
+ if (start) {
+ const match = {
+ tagName: start[1],
+ attrs: [],
+ start: index
+ }
+ advance(start[0].length)
+ let end, attr
+ while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
+ advance(attr[0].length)
+ match.attrs.push(attr)
+ }
+ if (end) {
+ match.unarySlash = end[1]
+ advance(end[0].length)
+ match.end = index
+ return match
+ }
+ }
+ }
+
+ function handleStartTag (match) {
+ const tagName = match.tagName
+ const unarySlash = match.unarySlash
+
+ if (expectHTML) {
+ if (lastTag === 'p' && isNonPhrasingTag(tagName)) {
+ parseEndTag(lastTag)
+ }
+ if (canBeLeftOpenTag(tagName) && lastTag === tagName) {
+ parseEndTag(tagName)
+ }
+ }
+
+ const unary = isUnaryTag(tagName) || !!unarySlash
+
+ const l = match.attrs.length
+ const attrs = new Array(l)
+ for (let i = 0; i < l; i++) {
+ const args = match.attrs[i]
+ // hackish work around FF bug https://bugzilla.mozilla.org/show_bug.cgi?id=369778
+ if (IS_REGEX_CAPTURING_BROKEN && args[0].indexOf('""') === -1) {
+ if (args[3] === '') { delete args[3] }
+ if (args[4] === '') { delete args[4] }
+ if (args[5] === '') { delete args[5] }
+ }
+ const value = args[3] || args[4] || args[5] || ''
+ const shouldDecodeNewlines = tagName === 'a' && args[1] === 'href'
+ ? options.shouldDecodeNewlinesForHref
+ : options.shouldDecodeNewlines
+ attrs[i] = {
+ name: args[1],
+ value: decodeAttr(value, shouldDecodeNewlines)
+ }
+ }
+
+ if (!unary) {
+ stack.push({ tag: tagName, lowerCasedTag: tagName.toLowerCase(), attrs: attrs })
+ lastTag = tagName
+ }
+
+ if (options.start) {
+ options.start(tagName, attrs, unary, match.start, match.end)
+ }
+ }
+
+ function parseEndTag (tagName, start, end) {
+ let pos, lowerCasedTagName
+ if (start == null) start = index
+ if (end == null) end = index
+
+ if (tagName) {
+ lowerCasedTagName = tagName.toLowerCase()
+ }
+
+ // Find the closest opened tag of the same type
+ if (tagName) {
+ for (pos = stack.length - 1; pos >= 0; pos--) {
+ if (stack[pos].lowerCasedTag === lowerCasedTagName) {
+ break
+ }
+ }
+ } else {
+ // If no tag name is provided, clean shop
+ pos = 0
+ }
+
+ if (pos >= 0) {
+ // Close all the open elements, up the stack
+ for (let i = stack.length - 1; i >= pos; i--) {
+ if (process.env.NODE_ENV !== 'production' &&
+ (i > pos || !tagName) &&
+ options.warn
+ ) {
+ options.warn(
+ `tag <${stack[i].tag}> has no matching end tag.`
+ )
+ }
+ if (options.end) {
+ options.end(stack[i].tag, start, end)
+ }
+ }
+
+ // Remove the open elements from the stack
+ stack.length = pos
+ lastTag = pos && stack[pos - 1].tag
+ } else if (lowerCasedTagName === 'br') {
+ if (options.start) {
+ options.start(tagName, [], true, start, end)
+ }
+ } else if (lowerCasedTagName === 'p') {
+ if (options.start) {
+ options.start(tagName, [], false, start, end)
+ }
+ if (options.end) {
+ options.end(tagName, start, end)
+ }
+ }
+ }
+}
diff --git a/node_modules/vue/src/compiler/parser/index.js b/node_modules/vue/src/compiler/parser/index.js
new file mode 100644
index 00000000..a603b36b
--- /dev/null
+++ b/node_modules/vue/src/compiler/parser/index.js
@@ -0,0 +1,675 @@
+/* @flow */
+
+import he from 'he'
+import { parseHTML } from './html-parser'
+import { parseText } from './text-parser'
+import { parseFilters } from './filter-parser'
+import { genAssignmentCode } from '../directives/model'
+import { extend, cached, no, camelize } from 'shared/util'
+import { isIE, isEdge, isServerRendering } from 'core/util/env'
+
+import {
+ addProp,
+ addAttr,
+ baseWarn,
+ addHandler,
+ addDirective,
+ getBindingAttr,
+ getAndRemoveAttr,
+ pluckModuleFunction
+} from '../helpers'
+
+export const onRE = /^@|^v-on:/
+export const dirRE = /^v-|^@|^:/
+export const forAliasRE = /([^]*?)\s+(?:in|of)\s+([^]*)/
+export const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
+const stripParensRE = /^\(|\)$/g
+
+const argRE = /:(.*)$/
+export const bindRE = /^:|^v-bind:/
+const modifierRE = /\.[^.]+/g
+
+const decodeHTMLCached = cached(he.decode)
+
+// configurable state
+export let warn: any
+let delimiters
+let transforms
+let preTransforms
+let postTransforms
+let platformIsPreTag
+let platformMustUseProp
+let platformGetTagNamespace
+
+type Attr = { name: string; value: string };
+
+export function createASTElement (
+ tag: string,
+ attrs: Array<Attr>,
+ parent: ASTElement | void
+): ASTElement {
+ return {
+ type: 1,
+ tag,
+ attrsList: attrs,
+ attrsMap: makeAttrsMap(attrs),
+ parent,
+ children: []
+ }
+}
+
+/**
+ * Convert HTML string to AST.
+ */
+export function parse (
+ template: string,
+ options: CompilerOptions
+): ASTElement | void {
+ warn = options.warn || baseWarn
+
+ platformIsPreTag = options.isPreTag || no
+ platformMustUseProp = options.mustUseProp || no
+ platformGetTagNamespace = options.getTagNamespace || no
+
+ transforms = pluckModuleFunction(options.modules, 'transformNode')
+ preTransforms = pluckModuleFunction(options.modules, 'preTransformNode')
+ postTransforms = pluckModuleFunction(options.modules, 'postTransformNode')
+
+ delimiters = options.delimiters
+
+ const stack = []
+ const preserveWhitespace = options.preserveWhitespace !== false
+ let root
+ let currentParent
+ let inVPre = false
+ let inPre = false
+ let warned = false
+
+ function warnOnce (msg) {
+ if (!warned) {
+ warned = true
+ warn(msg)
+ }
+ }
+
+ function closeElement (element) {
+ // check pre state
+ if (element.pre) {
+ inVPre = false
+ }
+ if (platformIsPreTag(element.tag)) {
+ inPre = false
+ }
+ // apply post-transforms
+ for (let i = 0; i < postTransforms.length; i++) {
+ postTransforms[i](element, options)
+ }
+ }
+
+ parseHTML(template, {
+ warn,
+ expectHTML: options.expectHTML,
+ isUnaryTag: options.isUnaryTag,
+ canBeLeftOpenTag: options.canBeLeftOpenTag,
+ shouldDecodeNewlines: options.shouldDecodeNewlines,
+ shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
+ shouldKeepComment: options.comments,
+ start (tag, attrs, unary) {
+ // check namespace.
+ // inherit parent ns if there is one
+ const ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag)
+
+ // handle IE svg bug
+ /* istanbul ignore if */
+ if (isIE && ns === 'svg') {
+ attrs = guardIESVGBug(attrs)
+ }
+
+ let element: ASTElement = createASTElement(tag, attrs, currentParent)
+ if (ns) {
+ element.ns = ns
+ }
+
+ if (isForbiddenTag(element) && !isServerRendering()) {
+ element.forbidden = true
+ process.env.NODE_ENV !== 'production' && warn(
+ 'Templates should only be responsible for mapping the state to the ' +
+ 'UI. Avoid placing tags with side-effects in your templates, such as ' +
+ `<${tag}>` + ', as they will not be parsed.'
+ )
+ }
+
+ // apply pre-transforms
+ for (let i = 0; i < preTransforms.length; i++) {
+ element = preTransforms[i](element, options) || element
+ }
+
+ if (!inVPre) {
+ processPre(element)
+ if (element.pre) {
+ inVPre = true
+ }
+ }
+ if (platformIsPreTag(element.tag)) {
+ inPre = true
+ }
+ if (inVPre) {
+ processRawAttrs(element)
+ } else if (!element.processed) {
+ // structural directives
+ processFor(element)
+ processIf(element)
+ processOnce(element)
+ // element-scope stuff
+ processElement(element, options)
+ }
+
+ function checkRootConstraints (el) {
+ if (process.env.NODE_ENV !== 'production') {
+ if (el.tag === 'slot' || el.tag === 'template') {
+ warnOnce(
+ `Cannot use <${el.tag}> as component root element because it may ` +
+ 'contain multiple nodes.'
+ )
+ }
+ if (el.attrsMap.hasOwnProperty('v-for')) {
+ warnOnce(
+ 'Cannot use v-for on stateful component root element because ' +
+ 'it renders multiple elements.'
+ )
+ }
+ }
+ }
+
+ // tree management
+ if (!root) {
+ root = element
+ checkRootConstraints(root)
+ } else if (!stack.length) {
+ // allow root elements with v-if, v-else-if and v-else
+ if (root.if && (element.elseif || element.else)) {
+ checkRootConstraints(element)
+ addIfCondition(root, {
+ exp: element.elseif,
+ block: element
+ })
+ } else if (process.env.NODE_ENV !== 'production') {
+ warnOnce(
+ `Component template should contain exactly one root element. ` +
+ `If you are using v-if on multiple elements, ` +
+ `use v-else-if to chain them instead.`
+ )
+ }
+ }
+ if (currentParent && !element.forbidden) {
+ if (element.elseif || element.else) {
+ processIfConditions(element, currentParent)
+ } else if (element.slotScope) { // scoped slot
+ currentParent.plain = false
+ const name = element.slotTarget || '"default"'
+ ;(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element
+ } else {
+ currentParent.children.push(element)
+ element.parent = currentParent
+ }
+ }
+ if (!unary) {
+ currentParent = element
+ stack.push(element)
+ } else {
+ closeElement(element)
+ }
+ },
+
+ end () {
+ // remove trailing whitespace
+ const element = stack[stack.length - 1]
+ const lastNode = element.children[element.children.length - 1]
+ if (lastNode && lastNode.type === 3 && lastNode.text === ' ' && !inPre) {
+ element.children.pop()
+ }
+ // pop stack
+ stack.length -= 1
+ currentParent = stack[stack.length - 1]
+ closeElement(element)
+ },
+
+ chars (text: string) {
+ if (!currentParent) {
+ if (process.env.NODE_ENV !== 'production') {
+ if (text === template) {
+ warnOnce(
+ 'Component template requires a root element, rather than just text.'
+ )
+ } else if ((text = text.trim())) {
+ warnOnce(
+ `text "${text}" outside root element will be ignored.`
+ )
+ }
+ }
+ return
+ }
+ // IE textarea placeholder bug
+ /* istanbul ignore if */
+ if (isIE &&
+ currentParent.tag === 'textarea' &&
+ currentParent.attrsMap.placeholder === text
+ ) {
+ return
+ }
+ const children = currentParent.children
+ text = inPre || text.trim()
+ ? isTextTag(currentParent) ? text : decodeHTMLCached(text)
+ // only preserve whitespace if its not right after a starting tag
+ : preserveWhitespace && children.length ? ' ' : ''
+ if (text) {
+ let res
+ if (!inVPre && text !== ' ' && (res = parseText(text, delimiters))) {
+ children.push({
+ type: 2,
+ expression: res.expression,
+ tokens: res.tokens,
+ text
+ })
+ } else if (text !== ' ' || !children.length || children[children.length - 1].text !== ' ') {
+ children.push({
+ type: 3,
+ text
+ })
+ }
+ }
+ },
+ comment (text: string) {
+ currentParent.children.push({
+ type: 3,
+ text,
+ isComment: true
+ })
+ }
+ })
+ return root
+}
+
+function processPre (el) {
+ if (getAndRemoveAttr(el, 'v-pre') != null) {
+ el.pre = true
+ }
+}
+
+function processRawAttrs (el) {
+ const l = el.attrsList.length
+ if (l) {
+ const attrs = el.attrs = new Array(l)
+ for (let i = 0; i < l; i++) {
+ attrs[i] = {
+ name: el.attrsList[i].name,
+ value: JSON.stringify(el.attrsList[i].value)
+ }
+ }
+ } else if (!el.pre) {
+ // non root node in pre blocks with no attributes
+ el.plain = true
+ }
+}
+
+export function processElement (element: ASTElement, options: CompilerOptions) {
+ processKey(element)
+
+ // determine whether this is a plain element after
+ // removing structural attributes
+ element.plain = !element.key && !element.attrsList.length
+
+ processRef(element)
+ processSlot(element)
+ processComponent(element)
+ for (let i = 0; i < transforms.length; i++) {
+ element = transforms[i](element, options) || element
+ }
+ processAttrs(element)
+}
+
+function processKey (el) {
+ const exp = getBindingAttr(el, 'key')
+ if (exp) {
+ if (process.env.NODE_ENV !== 'production' && el.tag === 'template') {
+ warn(`<template> cannot be keyed. Place the key on real elements instead.`)
+ }
+ el.key = exp
+ }
+}
+
+function processRef (el) {
+ const ref = getBindingAttr(el, 'ref')
+ if (ref) {
+ el.ref = ref
+ el.refInFor = checkInFor(el)
+ }
+}
+
+export function processFor (el: ASTElement) {
+ let exp
+ if ((exp = getAndRemoveAttr(el, 'v-for'))) {
+ const res = parseFor(exp)
+ if (res) {
+ extend(el, res)
+ } else if (process.env.NODE_ENV !== 'production') {
+ warn(
+ `Invalid v-for expression: ${exp}`
+ )
+ }
+ }
+}
+
+type ForParseResult = {
+ for: string;
+ alias: string;
+ iterator1?: string;
+ iterator2?: string;
+};
+
+export function parseFor (exp: string): ?ForParseResult {
+ const inMatch = exp.match(forAliasRE)
+ if (!inMatch) return
+ const res = {}
+ res.for = inMatch[2].trim()
+ const alias = inMatch[1].trim().replace(stripParensRE, '')
+ const iteratorMatch = alias.match(forIteratorRE)
+ if (iteratorMatch) {
+ res.alias = alias.replace(forIteratorRE, '')
+ res.iterator1 = iteratorMatch[1].trim()
+ if (iteratorMatch[2]) {
+ res.iterator2 = iteratorMatch[2].trim()
+ }
+ } else {
+ res.alias = alias
+ }
+ return res
+}
+
+function processIf (el) {
+ const exp = getAndRemoveAttr(el, 'v-if')
+ if (exp) {
+ el.if = exp
+ addIfCondition(el, {
+ exp: exp,
+ block: el
+ })
+ } else {
+ if (getAndRemoveAttr(el, 'v-else') != null) {
+ el.else = true
+ }
+ const elseif = getAndRemoveAttr(el, 'v-else-if')
+ if (elseif) {
+ el.elseif = elseif
+ }
+ }
+}
+
+function processIfConditions (el, parent) {
+ const prev = findPrevElement(parent.children)
+ if (prev && prev.if) {
+ addIfCondition(prev, {
+ exp: el.elseif,
+ block: el
+ })
+ } else if (process.env.NODE_ENV !== 'production') {
+ warn(
+ `v-${el.elseif ? ('else-if="' + el.elseif + '"') : 'else'} ` +
+ `used on element <${el.tag}> without corresponding v-if.`
+ )
+ }
+}
+
+function findPrevElement (children: Array<any>): ASTElement | void {
+ let i = children.length
+ while (i--) {
+ if (children[i].type === 1) {
+ return children[i]
+ } else {
+ if (process.env.NODE_ENV !== 'production' && children[i].text !== ' ') {
+ warn(
+ `text "${children[i].text.trim()}" between v-if and v-else(-if) ` +
+ `will be ignored.`
+ )
+ }
+ children.pop()
+ }
+ }
+}
+
+export function addIfCondition (el: ASTElement, condition: ASTIfCondition) {
+ if (!el.ifConditions) {
+ el.ifConditions = []
+ }
+ el.ifConditions.push(condition)
+}
+
+function processOnce (el) {
+ const once = getAndRemoveAttr(el, 'v-once')
+ if (once != null) {
+ el.once = true
+ }
+}
+
+function processSlot (el) {
+ if (el.tag === 'slot') {
+ el.slotName = getBindingAttr(el, 'name')
+ if (process.env.NODE_ENV !== 'production' && el.key) {
+ warn(
+ `\`key\` does not work on <slot> because slots are abstract outlets ` +
+ `and can possibly expand into multiple elements. ` +
+ `Use the key on a wrapping element instead.`
+ )
+ }
+ } else {
+ let slotScope
+ if (el.tag === 'template') {
+ slotScope = getAndRemoveAttr(el, 'scope')
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production' && slotScope) {
+ warn(
+ `the "scope" attribute for scoped slots have been deprecated and ` +
+ `replaced by "slot-scope" since 2.5. The new "slot-scope" attribute ` +
+ `can also be used on plain elements in addition to <template> to ` +
+ `denote scoped slots.`,
+ true
+ )
+ }
+ el.slotScope = slotScope || getAndRemoveAttr(el, 'slot-scope')
+ } else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production' && el.attrsMap['v-for']) {
+ warn(
+ `Ambiguous combined usage of slot-scope and v-for on <${el.tag}> ` +
+ `(v-for takes higher priority). Use a wrapper <template> for the ` +
+ `scoped slot to make it clearer.`,
+ true
+ )
+ }
+ el.slotScope = slotScope
+ }
+ const slotTarget = getBindingAttr(el, 'slot')
+ if (slotTarget) {
+ el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget
+ // preserve slot as an attribute for native shadow DOM compat
+ // only for non-scoped slots.
+ if (el.tag !== 'template' && !el.slotScope) {
+ addAttr(el, 'slot', slotTarget)
+ }
+ }
+ }
+}
+
+function processComponent (el) {
+ let binding
+ if ((binding = getBindingAttr(el, 'is'))) {
+ el.component = binding
+ }
+ if (getAndRemoveAttr(el, 'inline-template') != null) {
+ el.inlineTemplate = true
+ }
+}
+
+function processAttrs (el) {
+ const list = el.attrsList
+ let i, l, name, rawName, value, modifiers, isProp
+ for (i = 0, l = list.length; i < l; i++) {
+ name = rawName = list[i].name
+ value = list[i].value
+ if (dirRE.test(name)) {
+ // mark element as dynamic
+ el.hasBindings = true
+ // modifiers
+ modifiers = parseModifiers(name)
+ if (modifiers) {
+ name = name.replace(modifierRE, '')
+ }
+ if (bindRE.test(name)) { // v-bind
+ name = name.replace(bindRE, '')
+ value = parseFilters(value)
+ isProp = false
+ if (modifiers) {
+ if (modifiers.prop) {
+ isProp = true
+ name = camelize(name)
+ if (name === 'innerHtml') name = 'innerHTML'
+ }
+ if (modifiers.camel) {
+ name = camelize(name)
+ }
+ if (modifiers.sync) {
+ addHandler(
+ el,
+ `update:${camelize(name)}`,
+ genAssignmentCode(value, `$event`)
+ )
+ }
+ }
+ if (isProp || (
+ !el.component && platformMustUseProp(el.tag, el.attrsMap.type, name)
+ )) {
+ addProp(el, name, value)
+ } else {
+ addAttr(el, name, value)
+ }
+ } else if (onRE.test(name)) { // v-on
+ name = name.replace(onRE, '')
+ addHandler(el, name, value, modifiers, false, warn)
+ } else { // normal directives
+ name = name.replace(dirRE, '')
+ // parse arg
+ const argMatch = name.match(argRE)
+ const arg = argMatch && argMatch[1]
+ if (arg) {
+ name = name.slice(0, -(arg.length + 1))
+ }
+ addDirective(el, name, rawName, value, arg, modifiers)
+ if (process.env.NODE_ENV !== 'production' && name === 'model') {
+ checkForAliasModel(el, value)
+ }
+ }
+ } else {
+ // literal attribute
+ if (process.env.NODE_ENV !== 'production') {
+ const res = parseText(value, delimiters)
+ if (res) {
+ warn(
+ `${name}="${value}": ` +
+ 'Interpolation inside attributes has been removed. ' +
+ 'Use v-bind or the colon shorthand instead. For example, ' +
+ 'instead of <div id="{{ val }}">, use <div :id="val">.'
+ )
+ }
+ }
+ addAttr(el, name, JSON.stringify(value))
+ // #6887 firefox doesn't update muted state if set via attribute
+ // even immediately after element creation
+ if (!el.component &&
+ name === 'muted' &&
+ platformMustUseProp(el.tag, el.attrsMap.type, name)) {
+ addProp(el, name, 'true')
+ }
+ }
+ }
+}
+
+function checkInFor (el: ASTElement): boolean {
+ let parent = el
+ while (parent) {
+ if (parent.for !== undefined) {
+ return true
+ }
+ parent = parent.parent
+ }
+ return false
+}
+
+function parseModifiers (name: string): Object | void {
+ const match = name.match(modifierRE)
+ if (match) {
+ const ret = {}
+ match.forEach(m => { ret[m.slice(1)] = true })
+ return ret
+ }
+}
+
+function makeAttrsMap (attrs: Array<Object>): Object {
+ const map = {}
+ for (let i = 0, l = attrs.length; i < l; i++) {
+ if (
+ process.env.NODE_ENV !== 'production' &&
+ map[attrs[i].name] && !isIE && !isEdge
+ ) {
+ warn('duplicate attribute: ' + attrs[i].name)
+ }
+ map[attrs[i].name] = attrs[i].value
+ }
+ return map
+}
+
+// for script (e.g. type="x/template") or style, do not decode content
+function isTextTag (el): boolean {
+ return el.tag === 'script' || el.tag === 'style'
+}
+
+function isForbiddenTag (el): boolean {
+ return (
+ el.tag === 'style' ||
+ (el.tag === 'script' && (
+ !el.attrsMap.type ||
+ el.attrsMap.type === 'text/javascript'
+ ))
+ )
+}
+
+const ieNSBug = /^xmlns:NS\d+/
+const ieNSPrefix = /^NS\d+:/
+
+/* istanbul ignore next */
+function guardIESVGBug (attrs) {
+ const res = []
+ for (let i = 0; i < attrs.length; i++) {
+ const attr = attrs[i]
+ if (!ieNSBug.test(attr.name)) {
+ attr.name = attr.name.replace(ieNSPrefix, '')
+ res.push(attr)
+ }
+ }
+ return res
+}
+
+function checkForAliasModel (el, value) {
+ let _el = el
+ while (_el) {
+ if (_el.for && _el.alias === value) {
+ warn(
+ `<${el.tag} v-model="${value}">: ` +
+ `You are binding v-model directly to a v-for iteration alias. ` +
+ `This will not be able to modify the v-for source array because ` +
+ `writing to the alias is like modifying a function local variable. ` +
+ `Consider using an array of objects and use v-model on an object property instead.`
+ )
+ }
+ _el = _el.parent
+ }
+}
diff --git a/node_modules/vue/src/compiler/parser/text-parser.js b/node_modules/vue/src/compiler/parser/text-parser.js
new file mode 100644
index 00000000..284fca33
--- /dev/null
+++ b/node_modules/vue/src/compiler/parser/text-parser.js
@@ -0,0 +1,53 @@
+/* @flow */
+
+import { cached } from 'shared/util'
+import { parseFilters } from './filter-parser'
+
+const defaultTagRE = /\{\{((?:.|\n)+?)\}\}/g
+const regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g
+
+const buildRegex = cached(delimiters => {
+ const open = delimiters[0].replace(regexEscapeRE, '\\$&')
+ const close = delimiters[1].replace(regexEscapeRE, '\\$&')
+ return new RegExp(open + '((?:.|\\n)+?)' + close, 'g')
+})
+
+type TextParseResult = {
+ expression: string,
+ tokens: Array<string | { '@binding': string }>
+}
+
+export function parseText (
+ text: string,
+ delimiters?: [string, string]
+): TextParseResult | void {
+ const tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE
+ if (!tagRE.test(text)) {
+ return
+ }
+ const tokens = []
+ const rawTokens = []
+ let lastIndex = tagRE.lastIndex = 0
+ let match, index, tokenValue
+ while ((match = tagRE.exec(text))) {
+ index = match.index
+ // push text token
+ if (index > lastIndex) {
+ rawTokens.push(tokenValue = text.slice(lastIndex, index))
+ tokens.push(JSON.stringify(tokenValue))
+ }
+ // tag token
+ const exp = parseFilters(match[1].trim())
+ tokens.push(`_s(${exp})`)
+ rawTokens.push({ '@binding': exp })
+ lastIndex = index + match[0].length
+ }
+ if (lastIndex < text.length) {
+ rawTokens.push(tokenValue = text.slice(lastIndex))
+ tokens.push(JSON.stringify(tokenValue))
+ }
+ return {
+ expression: tokens.join('+'),
+ tokens: rawTokens
+ }
+}
diff --git a/node_modules/vue/src/compiler/to-function.js b/node_modules/vue/src/compiler/to-function.js
new file mode 100644
index 00000000..7fe0f13f
--- /dev/null
+++ b/node_modules/vue/src/compiler/to-function.js
@@ -0,0 +1,99 @@
+/* @flow */
+
+import { noop, extend } from 'shared/util'
+import { warn as baseWarn, tip } from 'core/util/debug'
+
+type CompiledFunctionResult = {
+ render: Function;
+ staticRenderFns: Array<Function>;
+};
+
+function createFunction (code, errors) {
+ try {
+ return new Function(code)
+ } catch (err) {
+ errors.push({ err, code })
+ return noop
+ }
+}
+
+export function createCompileToFunctionFn (compile: Function): Function {
+ const cache = Object.create(null)
+
+ return function compileToFunctions (
+ template: string,
+ options?: CompilerOptions,
+ vm?: Component
+ ): CompiledFunctionResult {
+ options = extend({}, options)
+ const warn = options.warn || baseWarn
+ delete options.warn
+
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production') {
+ // detect possible CSP restriction
+ try {
+ new Function('return 1')
+ } catch (e) {
+ if (e.toString().match(/unsafe-eval|CSP/)) {
+ warn(
+ 'It seems you are using the standalone build of Vue.js in an ' +
+ 'environment with Content Security Policy that prohibits unsafe-eval. ' +
+ 'The template compiler cannot work in this environment. Consider ' +
+ 'relaxing the policy to allow unsafe-eval or pre-compiling your ' +
+ 'templates into render functions.'
+ )
+ }
+ }
+ }
+
+ // check cache
+ const key = options.delimiters
+ ? String(options.delimiters) + template
+ : template
+ if (cache[key]) {
+ return cache[key]
+ }
+
+ // compile
+ const compiled = compile(template, options)
+
+ // check compilation errors/tips
+ if (process.env.NODE_ENV !== 'production') {
+ if (compiled.errors && compiled.errors.length) {
+ warn(
+ `Error compiling template:\n\n${template}\n\n` +
+ compiled.errors.map(e => `- ${e}`).join('\n') + '\n',
+ vm
+ )
+ }
+ if (compiled.tips && compiled.tips.length) {
+ compiled.tips.forEach(msg => tip(msg, vm))
+ }
+ }
+
+ // turn code into functions
+ const res = {}
+ const fnGenErrors = []
+ res.render = createFunction(compiled.render, fnGenErrors)
+ res.staticRenderFns = compiled.staticRenderFns.map(code => {
+ return createFunction(code, fnGenErrors)
+ })
+
+ // check function generation errors.
+ // this should only happen if there is a bug in the compiler itself.
+ // mostly for codegen development use
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production') {
+ if ((!compiled.errors || !compiled.errors.length) && fnGenErrors.length) {
+ warn(
+ `Failed to generate render function:\n\n` +
+ fnGenErrors.map(({ err, code }) => `${err.toString()} in\n\n${code}\n`).join('\n'),
+ vm
+ )
+ }
+ }
+
+ return (cache[key] = res)
+ }
+}
diff --git a/node_modules/vue/src/core/components/index.js b/node_modules/vue/src/core/components/index.js
new file mode 100644
index 00000000..5461c763
--- /dev/null
+++ b/node_modules/vue/src/core/components/index.js
@@ -0,0 +1,5 @@
+import KeepAlive from './keep-alive'
+
+export default {
+ KeepAlive
+}
diff --git a/node_modules/vue/src/core/components/keep-alive.js b/node_modules/vue/src/core/components/keep-alive.js
new file mode 100644
index 00000000..fb4cf1e8
--- /dev/null
+++ b/node_modules/vue/src/core/components/keep-alive.js
@@ -0,0 +1,124 @@
+/* @flow */
+
+import { isRegExp, remove } from 'shared/util'
+import { getFirstComponentChild } from 'core/vdom/helpers/index'
+
+type VNodeCache = { [key: string]: ?VNode };
+
+function getComponentName (opts: ?VNodeComponentOptions): ?string {
+ return opts && (opts.Ctor.options.name || opts.tag)
+}
+
+function matches (pattern: string | RegExp | Array<string>, name: string): boolean {
+ if (Array.isArray(pattern)) {
+ return pattern.indexOf(name) > -1
+ } else if (typeof pattern === 'string') {
+ return pattern.split(',').indexOf(name) > -1
+ } else if (isRegExp(pattern)) {
+ return pattern.test(name)
+ }
+ /* istanbul ignore next */
+ return false
+}
+
+function pruneCache (keepAliveInstance: any, filter: Function) {
+ const { cache, keys, _vnode } = keepAliveInstance
+ for (const key in cache) {
+ const cachedNode: ?VNode = cache[key]
+ if (cachedNode) {
+ const name: ?string = getComponentName(cachedNode.componentOptions)
+ if (name && !filter(name)) {
+ pruneCacheEntry(cache, key, keys, _vnode)
+ }
+ }
+ }
+}
+
+function pruneCacheEntry (
+ cache: VNodeCache,
+ key: string,
+ keys: Array<string>,
+ current?: VNode
+) {
+ const cached = cache[key]
+ if (cached && (!current || cached.tag !== current.tag)) {
+ cached.componentInstance.$destroy()
+ }
+ cache[key] = null
+ remove(keys, key)
+}
+
+const patternTypes: Array<Function> = [String, RegExp, Array]
+
+export default {
+ name: 'keep-alive',
+ abstract: true,
+
+ props: {
+ include: patternTypes,
+ exclude: patternTypes,
+ max: [String, Number]
+ },
+
+ created () {
+ this.cache = Object.create(null)
+ this.keys = []
+ },
+
+ destroyed () {
+ for (const key in this.cache) {
+ pruneCacheEntry(this.cache, key, this.keys)
+ }
+ },
+
+ mounted () {
+ this.$watch('include', val => {
+ pruneCache(this, name => matches(val, name))
+ })
+ this.$watch('exclude', val => {
+ pruneCache(this, name => !matches(val, name))
+ })
+ },
+
+ render () {
+ const slot = this.$slots.default
+ const vnode: VNode = getFirstComponentChild(slot)
+ const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
+ if (componentOptions) {
+ // check pattern
+ const name: ?string = getComponentName(componentOptions)
+ const { include, exclude } = this
+ if (
+ // not included
+ (include && (!name || !matches(include, name))) ||
+ // excluded
+ (exclude && name && matches(exclude, name))
+ ) {
+ return vnode
+ }
+
+ const { cache, keys } = this
+ const key: ?string = vnode.key == null
+ // same constructor may get registered as different local components
+ // so cid alone is not enough (#3269)
+ ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
+ : vnode.key
+ if (cache[key]) {
+ vnode.componentInstance = cache[key].componentInstance
+ // make current key freshest
+ remove(keys, key)
+ keys.push(key)
+ } else {
+ cache[key] = vnode
+ keys.push(key)
+ // prune oldest entry
+ if (this.max && keys.length > parseInt(this.max)) {
+ pruneCacheEntry(cache, keys[0], keys, this._vnode)
+ }
+ }
+
+ vnode.data.keepAlive = true
+ }
+ return vnode || (slot && slot[0])
+ }
+}
diff --git a/node_modules/vue/src/core/config.js b/node_modules/vue/src/core/config.js
new file mode 100644
index 00000000..f25f09d1
--- /dev/null
+++ b/node_modules/vue/src/core/config.js
@@ -0,0 +1,121 @@
+/* @flow */
+
+import {
+ no,
+ noop,
+ identity
+} from 'shared/util'
+
+import { LIFECYCLE_HOOKS } from 'shared/constants'
+
+export type Config = {
+ // user
+ optionMergeStrategies: { [key: string]: Function };
+ silent: boolean;
+ productionTip: boolean;
+ performance: boolean;
+ devtools: boolean;
+ errorHandler: ?(err: Error, vm: Component, info: string) => void;
+ warnHandler: ?(msg: string, vm: Component, trace: string) => void;
+ ignoredElements: Array<string | RegExp>;
+ keyCodes: { [key: string]: number | Array<number> };
+
+ // platform
+ isReservedTag: (x?: string) => boolean;
+ isReservedAttr: (x?: string) => boolean;
+ parsePlatformTagName: (x: string) => string;
+ isUnknownElement: (x?: string) => boolean;
+ getTagNamespace: (x?: string) => string | void;
+ mustUseProp: (tag: string, type: ?string, name: string) => boolean;
+
+ // legacy
+ _lifecycleHooks: Array<string>;
+};
+
+export default ({
+ /**
+ * Option merge strategies (used in core/util/options)
+ */
+ // $flow-disable-line
+ optionMergeStrategies: Object.create(null),
+
+ /**
+ * Whether to suppress warnings.
+ */
+ silent: false,
+
+ /**
+ * Show production mode tip message on boot?
+ */
+ productionTip: process.env.NODE_ENV !== 'production',
+
+ /**
+ * Whether to enable devtools
+ */
+ devtools: process.env.NODE_ENV !== 'production',
+
+ /**
+ * Whether to record perf
+ */
+ performance: false,
+
+ /**
+ * Error handler for watcher errors
+ */
+ errorHandler: null,
+
+ /**
+ * Warn handler for watcher warns
+ */
+ warnHandler: null,
+
+ /**
+ * Ignore certain custom elements
+ */
+ ignoredElements: [],
+
+ /**
+ * Custom user key aliases for v-on
+ */
+ // $flow-disable-line
+ keyCodes: Object.create(null),
+
+ /**
+ * Check if a tag is reserved so that it cannot be registered as a
+ * component. This is platform-dependent and may be overwritten.
+ */
+ isReservedTag: no,
+
+ /**
+ * Check if an attribute is reserved so that it cannot be used as a component
+ * prop. This is platform-dependent and may be overwritten.
+ */
+ isReservedAttr: no,
+
+ /**
+ * Check if a tag is an unknown element.
+ * Platform-dependent.
+ */
+ isUnknownElement: no,
+
+ /**
+ * Get the namespace of an element
+ */
+ getTagNamespace: noop,
+
+ /**
+ * Parse the real tag name for the specific platform.
+ */
+ parsePlatformTagName: identity,
+
+ /**
+ * Check if an attribute must be bound using property, e.g. value
+ * Platform-dependent.
+ */
+ mustUseProp: no,
+
+ /**
+ * Exposed for legacy reasons
+ */
+ _lifecycleHooks: LIFECYCLE_HOOKS
+}: Config)
diff --git a/node_modules/vue/src/core/global-api/assets.js b/node_modules/vue/src/core/global-api/assets.js
new file mode 100644
index 00000000..d975a6a5
--- /dev/null
+++ b/node_modules/vue/src/core/global-api/assets.js
@@ -0,0 +1,34 @@
+/* @flow */
+
+import { ASSET_TYPES } from 'shared/constants'
+import { isPlainObject, validateComponentName } from '../util/index'
+
+export function initAssetRegisters (Vue: GlobalAPI) {
+ /**
+ * Create asset registration methods.
+ */
+ ASSET_TYPES.forEach(type => {
+ Vue[type] = function (
+ id: string,
+ definition: Function | Object
+ ): Function | Object | void {
+ if (!definition) {
+ return this.options[type + 's'][id]
+ } else {
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production' && type === 'component') {
+ validateComponentName(id)
+ }
+ if (type === 'component' && isPlainObject(definition)) {
+ definition.name = definition.name || id
+ definition = this.options._base.extend(definition)
+ }
+ if (type === 'directive' && typeof definition === 'function') {
+ definition = { bind: definition, update: definition }
+ }
+ this.options[type + 's'][id] = definition
+ return definition
+ }
+ }
+ })
+}
diff --git a/node_modules/vue/src/core/global-api/extend.js b/node_modules/vue/src/core/global-api/extend.js
new file mode 100644
index 00000000..c1bbda3f
--- /dev/null
+++ b/node_modules/vue/src/core/global-api/extend.js
@@ -0,0 +1,95 @@
+/* @flow */
+
+import { ASSET_TYPES } from 'shared/constants'
+import { defineComputed, proxy } from '../instance/state'
+import { extend, mergeOptions, validateComponentName } from '../util/index'
+
+export function initExtend (Vue: GlobalAPI) {
+ /**
+ * Each instance constructor, including Vue, has a unique
+ * cid. This enables us to create wrapped "child
+ * constructors" for prototypal inheritance and cache them.
+ */
+ Vue.cid = 0
+ let cid = 1
+
+ /**
+ * Class inheritance
+ */
+ Vue.extend = function (extendOptions: Object): Function {
+ extendOptions = extendOptions || {}
+ const Super = this
+ const SuperId = Super.cid
+ const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})
+ if (cachedCtors[SuperId]) {
+ return cachedCtors[SuperId]
+ }
+
+ const name = extendOptions.name || Super.options.name
+ if (process.env.NODE_ENV !== 'production' && name) {
+ validateComponentName(name)
+ }
+
+ const Sub = function VueComponent (options) {
+ this._init(options)
+ }
+ Sub.prototype = Object.create(Super.prototype)
+ Sub.prototype.constructor = Sub
+ Sub.cid = cid++
+ Sub.options = mergeOptions(
+ Super.options,
+ extendOptions
+ )
+ Sub['super'] = Super
+
+ // For props and computed properties, we define the proxy getters on
+ // the Vue instances at extension time, on the extended prototype. This
+ // avoids Object.defineProperty calls for each instance created.
+ if (Sub.options.props) {
+ initProps(Sub)
+ }
+ if (Sub.options.computed) {
+ initComputed(Sub)
+ }
+
+ // allow further extension/mixin/plugin usage
+ Sub.extend = Super.extend
+ Sub.mixin = Super.mixin
+ Sub.use = Super.use
+
+ // create asset registers, so extended classes
+ // can have their private assets too.
+ ASSET_TYPES.forEach(function (type) {
+ Sub[type] = Super[type]
+ })
+ // enable recursive self-lookup
+ if (name) {
+ Sub.options.components[name] = Sub
+ }
+
+ // keep a reference to the super options at extension time.
+ // later at instantiation we can check if Super's options have
+ // been updated.
+ Sub.superOptions = Super.options
+ Sub.extendOptions = extendOptions
+ Sub.sealedOptions = extend({}, Sub.options)
+
+ // cache constructor
+ cachedCtors[SuperId] = Sub
+ return Sub
+ }
+}
+
+function initProps (Comp) {
+ const props = Comp.options.props
+ for (const key in props) {
+ proxy(Comp.prototype, `_props`, key)
+ }
+}
+
+function initComputed (Comp) {
+ const computed = Comp.options.computed
+ for (const key in computed) {
+ defineComputed(Comp.prototype, key, computed[key])
+ }
+}
diff --git a/node_modules/vue/src/core/global-api/index.js b/node_modules/vue/src/core/global-api/index.js
new file mode 100644
index 00000000..03ffa0fb
--- /dev/null
+++ b/node_modules/vue/src/core/global-api/index.js
@@ -0,0 +1,62 @@
+/* @flow */
+
+import config from '../config'
+import { initUse } from './use'
+import { initMixin } from './mixin'
+import { initExtend } from './extend'
+import { initAssetRegisters } from './assets'
+import { set, del } from '../observer/index'
+import { ASSET_TYPES } from 'shared/constants'
+import builtInComponents from '../components/index'
+
+import {
+ warn,
+ extend,
+ nextTick,
+ mergeOptions,
+ defineReactive
+} from '../util/index'
+
+export function initGlobalAPI (Vue: GlobalAPI) {
+ // config
+ const configDef = {}
+ configDef.get = () => config
+ if (process.env.NODE_ENV !== 'production') {
+ configDef.set = () => {
+ warn(
+ 'Do not replace the Vue.config object, set individual fields instead.'
+ )
+ }
+ }
+ Object.defineProperty(Vue, 'config', configDef)
+
+ // exposed util methods.
+ // NOTE: these are not considered part of the public API - avoid relying on
+ // them unless you are aware of the risk.
+ Vue.util = {
+ warn,
+ extend,
+ mergeOptions,
+ defineReactive
+ }
+
+ Vue.set = set
+ Vue.delete = del
+ Vue.nextTick = nextTick
+
+ Vue.options = Object.create(null)
+ ASSET_TYPES.forEach(type => {
+ Vue.options[type + 's'] = Object.create(null)
+ })
+
+ // this is used to identify the "base" constructor to extend all plain-object
+ // components with in Weex's multi-instance scenarios.
+ Vue.options._base = Vue
+
+ extend(Vue.options.components, builtInComponents)
+
+ initUse(Vue)
+ initMixin(Vue)
+ initExtend(Vue)
+ initAssetRegisters(Vue)
+}
diff --git a/node_modules/vue/src/core/global-api/mixin.js b/node_modules/vue/src/core/global-api/mixin.js
new file mode 100644
index 00000000..36017a32
--- /dev/null
+++ b/node_modules/vue/src/core/global-api/mixin.js
@@ -0,0 +1,10 @@
+/* @flow */
+
+import { mergeOptions } from '../util/index'
+
+export function initMixin (Vue: GlobalAPI) {
+ Vue.mixin = function (mixin: Object) {
+ this.options = mergeOptions(this.options, mixin)
+ return this
+ }
+}
diff --git a/node_modules/vue/src/core/global-api/use.js b/node_modules/vue/src/core/global-api/use.js
new file mode 100644
index 00000000..a5b69988
--- /dev/null
+++ b/node_modules/vue/src/core/global-api/use.js
@@ -0,0 +1,23 @@
+/* @flow */
+
+import { toArray } from '../util/index'
+
+export function initUse (Vue: GlobalAPI) {
+ Vue.use = function (plugin: Function | Object) {
+ const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
+ if (installedPlugins.indexOf(plugin) > -1) {
+ return this
+ }
+
+ // additional parameters
+ const args = toArray(arguments, 1)
+ args.unshift(this)
+ if (typeof plugin.install === 'function') {
+ plugin.install.apply(plugin, args)
+ } else if (typeof plugin === 'function') {
+ plugin.apply(null, args)
+ }
+ installedPlugins.push(plugin)
+ return this
+ }
+}
diff --git a/node_modules/vue/src/core/index.js b/node_modules/vue/src/core/index.js
new file mode 100644
index 00000000..daf6203b
--- /dev/null
+++ b/node_modules/vue/src/core/index.js
@@ -0,0 +1,26 @@
+import Vue from './instance/index'
+import { initGlobalAPI } from './global-api/index'
+import { isServerRendering } from 'core/util/env'
+import { FunctionalRenderContext } from 'core/vdom/create-functional-component'
+
+initGlobalAPI(Vue)
+
+Object.defineProperty(Vue.prototype, '$isServer', {
+ get: isServerRendering
+})
+
+Object.defineProperty(Vue.prototype, '$ssrContext', {
+ get () {
+ /* istanbul ignore next */
+ return this.$vnode && this.$vnode.ssrContext
+ }
+})
+
+// expose FunctionalRenderContext for ssr runtime helper installation
+Object.defineProperty(Vue, 'FunctionalRenderContext', {
+ value: FunctionalRenderContext
+})
+
+Vue.version = '__VERSION__'
+
+export default Vue
diff --git a/node_modules/vue/src/core/instance/events.js b/node_modules/vue/src/core/instance/events.js
new file mode 100644
index 00000000..58779996
--- /dev/null
+++ b/node_modules/vue/src/core/instance/events.js
@@ -0,0 +1,142 @@
+/* @flow */
+
+import {
+ tip,
+ toArray,
+ hyphenate,
+ handleError,
+ formatComponentName
+} from '../util/index'
+import { updateListeners } from '../vdom/helpers/index'
+
+export function initEvents (vm: Component) {
+ vm._events = Object.create(null)
+ vm._hasHookEvent = false
+ // init parent attached events
+ const listeners = vm.$options._parentListeners
+ if (listeners) {
+ updateComponentListeners(vm, listeners)
+ }
+}
+
+let target: any
+
+function add (event, fn, once) {
+ if (once) {
+ target.$once(event, fn)
+ } else {
+ target.$on(event, fn)
+ }
+}
+
+function remove (event, fn) {
+ target.$off(event, fn)
+}
+
+export function updateComponentListeners (
+ vm: Component,
+ listeners: Object,
+ oldListeners: ?Object
+) {
+ target = vm
+ updateListeners(listeners, oldListeners || {}, add, remove, vm)
+ target = undefined
+}
+
+export function eventsMixin (Vue: Class<Component>) {
+ const hookRE = /^hook:/
+ Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {
+ const vm: Component = this
+ if (Array.isArray(event)) {
+ for (let i = 0, l = event.length; i < l; i++) {
+ this.$on(event[i], fn)
+ }
+ } else {
+ (vm._events[event] || (vm._events[event] = [])).push(fn)
+ // optimize hook:event cost by using a boolean flag marked at registration
+ // instead of a hash lookup
+ if (hookRE.test(event)) {
+ vm._hasHookEvent = true
+ }
+ }
+ return vm
+ }
+
+ Vue.prototype.$once = function (event: string, fn: Function): Component {
+ const vm: Component = this
+ function on () {
+ vm.$off(event, on)
+ fn.apply(vm, arguments)
+ }
+ on.fn = fn
+ vm.$on(event, on)
+ return vm
+ }
+
+ Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component {
+ const vm: Component = this
+ // all
+ if (!arguments.length) {
+ vm._events = Object.create(null)
+ return vm
+ }
+ // array of events
+ if (Array.isArray(event)) {
+ for (let i = 0, l = event.length; i < l; i++) {
+ this.$off(event[i], fn)
+ }
+ return vm
+ }
+ // specific event
+ const cbs = vm._events[event]
+ if (!cbs) {
+ return vm
+ }
+ if (!fn) {
+ vm._events[event] = null
+ return vm
+ }
+ if (fn) {
+ // specific handler
+ let cb
+ let i = cbs.length
+ while (i--) {
+ cb = cbs[i]
+ if (cb === fn || cb.fn === fn) {
+ cbs.splice(i, 1)
+ break
+ }
+ }
+ }
+ return vm
+ }
+
+ Vue.prototype.$emit = function (event: string): Component {
+ const vm: Component = this
+ if (process.env.NODE_ENV !== 'production') {
+ const lowerCaseEvent = event.toLowerCase()
+ if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
+ tip(
+ `Event "${lowerCaseEvent}" is emitted in component ` +
+ `${formatComponentName(vm)} but the handler is registered for "${event}". ` +
+ `Note that HTML attributes are case-insensitive and you cannot use ` +
+ `v-on to listen to camelCase events when using in-DOM templates. ` +
+ `You should probably use "${hyphenate(event)}" instead of "${event}".`
+ )
+ }
+ }
+ let cbs = vm._events[event]
+ if (cbs) {
+ cbs = cbs.length > 1 ? toArray(cbs) : cbs
+ const args = toArray(arguments, 1)
+ for (let i = 0, l = cbs.length; i < l; i++) {
+ try {
+ cbs[i].apply(vm, args)
+ } catch (e) {
+ handleError(e, vm, `event handler for "${event}"`)
+ }
+ }
+ }
+ return vm
+ }
+}
diff --git a/node_modules/vue/src/core/instance/index.js b/node_modules/vue/src/core/instance/index.js
new file mode 100644
index 00000000..8a440231
--- /dev/null
+++ b/node_modules/vue/src/core/instance/index.js
@@ -0,0 +1,23 @@
+import { initMixin } from './init'
+import { stateMixin } from './state'
+import { renderMixin } from './render'
+import { eventsMixin } from './events'
+import { lifecycleMixin } from './lifecycle'
+import { warn } from '../util/index'
+
+function Vue (options) {
+ if (process.env.NODE_ENV !== 'production' &&
+ !(this instanceof Vue)
+ ) {
+ warn('Vue is a constructor and should be called with the `new` keyword')
+ }
+ this._init(options)
+}
+
+initMixin(Vue)
+stateMixin(Vue)
+eventsMixin(Vue)
+lifecycleMixin(Vue)
+renderMixin(Vue)
+
+export default Vue
diff --git a/node_modules/vue/src/core/instance/init.js b/node_modules/vue/src/core/instance/init.js
new file mode 100644
index 00000000..ed2550d0
--- /dev/null
+++ b/node_modules/vue/src/core/instance/init.js
@@ -0,0 +1,150 @@
+/* @flow */
+
+import config from '../config'
+import { initProxy } from './proxy'
+import { initState } from './state'
+import { initRender } from './render'
+import { initEvents } from './events'
+import { mark, measure } from '../util/perf'
+import { initLifecycle, callHook } from './lifecycle'
+import { initProvide, initInjections } from './inject'
+import { extend, mergeOptions, formatComponentName } from '../util/index'
+
+let uid = 0
+
+export function initMixin (Vue: Class<Component>) {
+ Vue.prototype._init = function (options?: Object) {
+ const vm: Component = this
+ // a uid
+ vm._uid = uid++
+
+ let startTag, endTag
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
+ startTag = `vue-perf-start:${vm._uid}`
+ endTag = `vue-perf-end:${vm._uid}`
+ mark(startTag)
+ }
+
+ // 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
+ }
+ // expose real self
+ 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')
+
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
+ vm._name = formatComponentName(vm, false)
+ mark(endTag)
+ measure(`vue ${vm._name} init`, startTag, endTag)
+ }
+
+ if (vm.$options.el) {
+ vm.$mount(vm.$options.el)
+ }
+ }
+}
+
+export function initInternalComponent (vm: Component, options: InternalComponentOptions) {
+ const opts = vm.$options = Object.create(vm.constructor.options)
+ // doing this because it's faster than dynamic enumeration.
+ const parentVnode = options._parentVnode
+ opts.parent = options.parent
+ opts._parentVnode = parentVnode
+ opts._parentElm = options._parentElm
+ opts._refElm = options._refElm
+
+ const vnodeComponentOptions = parentVnode.componentOptions
+ opts.propsData = vnodeComponentOptions.propsData
+ opts._parentListeners = vnodeComponentOptions.listeners
+ opts._renderChildren = vnodeComponentOptions.children
+ opts._componentTag = vnodeComponentOptions.tag
+
+ if (options.render) {
+ opts.render = options.render
+ opts.staticRenderFns = options.staticRenderFns
+ }
+}
+
+export function resolveConstructorOptions (Ctor: Class<Component>) {
+ let options = Ctor.options
+ if (Ctor.super) {
+ const superOptions = resolveConstructorOptions(Ctor.super)
+ const cachedSuperOptions = Ctor.superOptions
+ if (superOptions !== cachedSuperOptions) {
+ // super option changed,
+ // need to resolve new options.
+ Ctor.superOptions = superOptions
+ // check if there are any late-modified/attached options (#4976)
+ const modifiedOptions = resolveModifiedOptions(Ctor)
+ // update base extend options
+ if (modifiedOptions) {
+ extend(Ctor.extendOptions, modifiedOptions)
+ }
+ options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions)
+ if (options.name) {
+ options.components[options.name] = Ctor
+ }
+ }
+ }
+ return options
+}
+
+function resolveModifiedOptions (Ctor: Class<Component>): ?Object {
+ let modified
+ const latest = Ctor.options
+ const extended = Ctor.extendOptions
+ const sealed = Ctor.sealedOptions
+ for (const key in latest) {
+ if (latest[key] !== sealed[key]) {
+ if (!modified) modified = {}
+ modified[key] = dedupe(latest[key], extended[key], sealed[key])
+ }
+ }
+ return modified
+}
+
+function dedupe (latest, extended, sealed) {
+ // compare latest and sealed to ensure lifecycle hooks won't be duplicated
+ // between merges
+ if (Array.isArray(latest)) {
+ const res = []
+ sealed = Array.isArray(sealed) ? sealed : [sealed]
+ extended = Array.isArray(extended) ? extended : [extended]
+ for (let i = 0; i < latest.length; i++) {
+ // push original options and not sealed options to exclude duplicated options
+ if (extended.indexOf(latest[i]) >= 0 || sealed.indexOf(latest[i]) < 0) {
+ res.push(latest[i])
+ }
+ }
+ return res
+ } else {
+ return latest
+ }
+}
diff --git a/node_modules/vue/src/core/instance/inject.js b/node_modules/vue/src/core/instance/inject.js
new file mode 100644
index 00000000..e464e12a
--- /dev/null
+++ b/node_modules/vue/src/core/instance/inject.js
@@ -0,0 +1,74 @@
+/* @flow */
+
+import { hasOwn } from 'shared/util'
+import { warn, hasSymbol } from '../util/index'
+import { defineReactive, toggleObserving } from '../observer/index'
+
+export function initProvide (vm: Component) {
+ const provide = vm.$options.provide
+ if (provide) {
+ vm._provided = typeof provide === 'function'
+ ? provide.call(vm)
+ : provide
+ }
+}
+
+export function initInjections (vm: Component) {
+ const result = resolveInject(vm.$options.inject, vm)
+ if (result) {
+ toggleObserving(false)
+ Object.keys(result).forEach(key => {
+ /* istanbul ignore else */
+ if (process.env.NODE_ENV !== 'production') {
+ defineReactive(vm, key, result[key], () => {
+ warn(
+ `Avoid mutating an injected value directly since the changes will be ` +
+ `overwritten whenever the provided component re-renders. ` +
+ `injection being mutated: "${key}"`,
+ vm
+ )
+ })
+ } else {
+ defineReactive(vm, key, result[key])
+ }
+ })
+ toggleObserving(true)
+ }
+}
+
+export function resolveInject (inject: any, vm: Component): ?Object {
+ if (inject) {
+ // inject is :any because flow is not smart enough to figure out cached
+ const result = Object.create(null)
+ const keys = hasSymbol
+ ? Reflect.ownKeys(inject).filter(key => {
+ /* istanbul ignore next */
+ return Object.getOwnPropertyDescriptor(inject, key).enumerable
+ })
+ : Object.keys(inject)
+
+ for (let i = 0; i < keys.length; i++) {
+ const key = keys[i]
+ const provideKey = inject[key].from
+ let source = vm
+ while (source) {
+ if (source._provided && hasOwn(source._provided, provideKey)) {
+ result[key] = source._provided[provideKey]
+ break
+ }
+ source = source.$parent
+ }
+ if (!source) {
+ if ('default' in inject[key]) {
+ const provideDefault = inject[key].default
+ result[key] = typeof provideDefault === 'function'
+ ? provideDefault.call(vm)
+ : provideDefault
+ } else if (process.env.NODE_ENV !== 'production') {
+ warn(`Injection "${key}" not found`, vm)
+ }
+ }
+ }
+ return result
+ }
+}
diff --git a/node_modules/vue/src/core/instance/lifecycle.js b/node_modules/vue/src/core/instance/lifecycle.js
new file mode 100644
index 00000000..169a54a6
--- /dev/null
+++ b/node_modules/vue/src/core/instance/lifecycle.js
@@ -0,0 +1,336 @@
+/* @flow */
+
+import config from '../config'
+import Watcher from '../observer/watcher'
+import { mark, measure } from '../util/perf'
+import { createEmptyVNode } from '../vdom/vnode'
+import { updateComponentListeners } from './events'
+import { resolveSlots } from './render-helpers/resolve-slots'
+import { toggleObserving } from '../observer/index'
+import { pushTarget, popTarget } from '../observer/dep'
+
+import {
+ warn,
+ noop,
+ remove,
+ handleError,
+ emptyObject,
+ validateProp
+} from '../util/index'
+
+export let activeInstance: any = null
+export let isUpdatingChildComponent: boolean = false
+
+export function initLifecycle (vm: Component) {
+ const options = vm.$options
+
+ // locate first non-abstract parent
+ let parent = options.parent
+ if (parent && !options.abstract) {
+ while (parent.$options.abstract && parent.$parent) {
+ parent = parent.$parent
+ }
+ parent.$children.push(vm)
+ }
+
+ vm.$parent = parent
+ vm.$root = parent ? parent.$root : vm
+
+ vm.$children = []
+ vm.$refs = {}
+
+ vm._watcher = null
+ vm._inactive = null
+ vm._directInactive = false
+ vm._isMounted = false
+ vm._isDestroyed = false
+ vm._isBeingDestroyed = false
+}
+
+export function lifecycleMixin (Vue: Class<Component>) {
+ Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
+ const vm: Component = this
+ if (vm._isMounted) {
+ callHook(vm, 'beforeUpdate')
+ }
+ const prevEl = vm.$el
+ const prevVnode = vm._vnode
+ const prevActiveInstance = activeInstance
+ activeInstance = vm
+ vm._vnode = vnode
+ // Vue.prototype.__patch__ is injected in entry points
+ // based on the rendering backend used.
+ if (!prevVnode) {
+ // initial render
+ vm.$el = vm.__patch__(
+ vm.$el, vnode, hydrating, false /* removeOnly */,
+ vm.$options._parentElm,
+ vm.$options._refElm
+ )
+ // no need for the ref nodes after initial patch
+ // this prevents keeping a detached DOM tree in memory (#5851)
+ vm.$options._parentElm = vm.$options._refElm = null
+ } else {
+ // updates
+ vm.$el = vm.__patch__(prevVnode, vnode)
+ }
+ activeInstance = prevActiveInstance
+ // update __vue__ reference
+ if (prevEl) {
+ prevEl.__vue__ = null
+ }
+ if (vm.$el) {
+ vm.$el.__vue__ = vm
+ }
+ // if parent is an HOC, update its $el as well
+ if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
+ vm.$parent.$el = vm.$el
+ }
+ // updated hook is called by the scheduler to ensure that children are
+ // updated in a parent's updated hook.
+ }
+
+ Vue.prototype.$forceUpdate = function () {
+ const vm: Component = this
+ if (vm._watcher) {
+ vm._watcher.update()
+ }
+ }
+
+ Vue.prototype.$destroy = function () {
+ const vm: Component = this
+ if (vm._isBeingDestroyed) {
+ return
+ }
+ callHook(vm, 'beforeDestroy')
+ vm._isBeingDestroyed = true
+ // remove self from parent
+ const parent = vm.$parent
+ if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
+ remove(parent.$children, vm)
+ }
+ // teardown watchers
+ if (vm._watcher) {
+ vm._watcher.teardown()
+ }
+ let i = vm._watchers.length
+ while (i--) {
+ vm._watchers[i].teardown()
+ }
+ // remove reference from data ob
+ // frozen object may not have observer.
+ if (vm._data.__ob__) {
+ vm._data.__ob__.vmCount--
+ }
+ // call the last hook...
+ vm._isDestroyed = true
+ // invoke destroy hooks on current rendered tree
+ vm.__patch__(vm._vnode, null)
+ // fire destroyed hook
+ callHook(vm, 'destroyed')
+ // turn off all instance listeners.
+ vm.$off()
+ // remove __vue__ reference
+ if (vm.$el) {
+ vm.$el.__vue__ = null
+ }
+ // release circular reference (#6759)
+ if (vm.$vnode) {
+ vm.$vnode.parent = null
+ }
+ }
+}
+
+export function mountComponent (
+ vm: Component,
+ el: ?Element,
+ hydrating?: boolean
+): Component {
+ vm.$el = el
+ if (!vm.$options.render) {
+ vm.$options.render = createEmptyVNode
+ if (process.env.NODE_ENV !== 'production') {
+ /* istanbul ignore if */
+ if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||
+ vm.$options.el || el) {
+ warn(
+ 'You are using the runtime-only build of Vue where the template ' +
+ 'compiler is not available. Either pre-compile the templates into ' +
+ 'render functions, or use the compiler-included build.',
+ vm
+ )
+ } else {
+ warn(
+ 'Failed to mount component: template or render function not defined.',
+ vm
+ )
+ }
+ }
+ }
+ callHook(vm, 'beforeMount')
+
+ let updateComponent
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
+ updateComponent = () => {
+ const name = vm._name
+ const id = vm._uid
+ const startTag = `vue-perf-start:${id}`
+ const endTag = `vue-perf-end:${id}`
+
+ mark(startTag)
+ const vnode = vm._render()
+ mark(endTag)
+ measure(`vue ${name} render`, startTag, endTag)
+
+ mark(startTag)
+ vm._update(vnode, hydrating)
+ mark(endTag)
+ measure(`vue ${name} patch`, startTag, endTag)
+ }
+ } else {
+ updateComponent = () => {
+ vm._update(vm._render(), hydrating)
+ }
+ }
+
+ // we set this to vm._watcher inside the watcher's constructor
+ // since the watcher's initial patch may call $forceUpdate (e.g. inside child
+ // component's mounted hook), which relies on vm._watcher being already defined
+ new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */)
+ hydrating = false
+
+ // manually mounted instance, call mounted on self
+ // mounted is called for render-created child components in its inserted hook
+ if (vm.$vnode == null) {
+ vm._isMounted = true
+ callHook(vm, 'mounted')
+ }
+ return vm
+}
+
+export function updateChildComponent (
+ vm: Component,
+ propsData: ?Object,
+ listeners: ?Object,
+ parentVnode: MountedComponentVNode,
+ renderChildren: ?Array<VNode>
+) {
+ if (process.env.NODE_ENV !== 'production') {
+ isUpdatingChildComponent = true
+ }
+
+ // determine whether component has slot children
+ // we need to do this before overwriting $options._renderChildren
+ const hasChildren = !!(
+ renderChildren || // has new static slots
+ vm.$options._renderChildren || // has old static slots
+ parentVnode.data.scopedSlots || // has new scoped slots
+ vm.$scopedSlots !== emptyObject // has old scoped slots
+ )
+
+ vm.$options._parentVnode = parentVnode
+ vm.$vnode = parentVnode // update vm's placeholder node without re-render
+
+ if (vm._vnode) { // update child tree's parent
+ vm._vnode.parent = parentVnode
+ }
+ vm.$options._renderChildren = renderChildren
+
+ // update $attrs and $listeners hash
+ // these are also reactive so they may trigger child update if the child
+ // used them during render
+ vm.$attrs = parentVnode.data.attrs || emptyObject
+ vm.$listeners = listeners || emptyObject
+
+ // update props
+ if (propsData && vm.$options.props) {
+ toggleObserving(false)
+ const props = vm._props
+ const propKeys = vm.$options._propKeys || []
+ for (let i = 0; i < propKeys.length; i++) {
+ const key = propKeys[i]
+ const propOptions: any = vm.$options.props // wtf flow?
+ props[key] = validateProp(key, propOptions, propsData, vm)
+ }
+ toggleObserving(true)
+ // keep a copy of raw propsData
+ vm.$options.propsData = propsData
+ }
+
+ // update listeners
+ listeners = listeners || emptyObject
+ const oldListeners = vm.$options._parentListeners
+ vm.$options._parentListeners = listeners
+ updateComponentListeners(vm, listeners, oldListeners)
+
+ // resolve slots + force update if has children
+ if (hasChildren) {
+ vm.$slots = resolveSlots(renderChildren, parentVnode.context)
+ vm.$forceUpdate()
+ }
+
+ if (process.env.NODE_ENV !== 'production') {
+ isUpdatingChildComponent = false
+ }
+}
+
+function isInInactiveTree (vm) {
+ while (vm && (vm = vm.$parent)) {
+ if (vm._inactive) return true
+ }
+ return false
+}
+
+export function activateChildComponent (vm: Component, direct?: boolean) {
+ if (direct) {
+ vm._directInactive = false
+ if (isInInactiveTree(vm)) {
+ return
+ }
+ } else if (vm._directInactive) {
+ return
+ }
+ if (vm._inactive || vm._inactive === null) {
+ vm._inactive = false
+ for (let i = 0; i < vm.$children.length; i++) {
+ activateChildComponent(vm.$children[i])
+ }
+ callHook(vm, 'activated')
+ }
+}
+
+export function deactivateChildComponent (vm: Component, direct?: boolean) {
+ if (direct) {
+ vm._directInactive = true
+ if (isInInactiveTree(vm)) {
+ return
+ }
+ }
+ if (!vm._inactive) {
+ vm._inactive = true
+ for (let i = 0; i < vm.$children.length; i++) {
+ deactivateChildComponent(vm.$children[i])
+ }
+ callHook(vm, 'deactivated')
+ }
+}
+
+export function callHook (vm: Component, hook: string) {
+ // #7573 disable dep collection when invoking lifecycle hooks
+ pushTarget()
+ const handlers = vm.$options[hook]
+ if (handlers) {
+ for (let i = 0, j = handlers.length; i < j; i++) {
+ try {
+ handlers[i].call(vm)
+ } catch (e) {
+ handleError(e, vm, `${hook} hook`)
+ }
+ }
+ }
+ if (vm._hasHookEvent) {
+ vm.$emit('hook:' + hook)
+ }
+ popTarget()
+}
diff --git a/node_modules/vue/src/core/instance/proxy.js b/node_modules/vue/src/core/instance/proxy.js
new file mode 100644
index 00000000..0d6dcf80
--- /dev/null
+++ b/node_modules/vue/src/core/instance/proxy.js
@@ -0,0 +1,79 @@
+/* not type checking this file because flow doesn't play well with Proxy */
+
+import config from 'core/config'
+import { warn, makeMap, isNative } from '../util/index'
+
+let initProxy
+
+if (process.env.NODE_ENV !== 'production') {
+ const allowedGlobals = makeMap(
+ 'Infinity,undefined,NaN,isFinite,isNaN,' +
+ 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
+ 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
+ 'require' // for Webpack/Browserify
+ )
+
+ const warnNonPresent = (target, key) => {
+ warn(
+ `Property or method "${key}" is not defined on the instance but ` +
+ 'referenced during render. Make sure that this property is reactive, ' +
+ 'either in the data option, or for class-based components, by ' +
+ 'initializing the property. ' +
+ 'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.',
+ target
+ )
+ }
+
+ const hasProxy =
+ typeof Proxy !== 'undefined' && isNative(Proxy)
+
+ if (hasProxy) {
+ const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact')
+ config.keyCodes = new Proxy(config.keyCodes, {
+ set (target, key, value) {
+ if (isBuiltInModifier(key)) {
+ warn(`Avoid overwriting built-in modifier in config.keyCodes: .${key}`)
+ return false
+ } else {
+ target[key] = value
+ return true
+ }
+ }
+ })
+ }
+
+ const hasHandler = {
+ has (target, key) {
+ const has = key in target
+ const isAllowed = allowedGlobals(key) || key.charAt(0) === '_'
+ if (!has && !isAllowed) {
+ warnNonPresent(target, key)
+ }
+ return has || !isAllowed
+ }
+ }
+
+ const getHandler = {
+ get (target, key) {
+ if (typeof key === 'string' && !(key in target)) {
+ warnNonPresent(target, key)
+ }
+ return target[key]
+ }
+ }
+
+ initProxy = function initProxy (vm) {
+ if (hasProxy) {
+ // determine which proxy handler to use
+ const options = vm.$options
+ const handlers = options.render && options.render._withStripped
+ ? getHandler
+ : hasHandler
+ vm._renderProxy = new Proxy(vm, handlers)
+ } else {
+ vm._renderProxy = vm
+ }
+ }
+}
+
+export { initProxy }
diff --git a/node_modules/vue/src/core/instance/render-helpers/bind-object-listeners.js b/node_modules/vue/src/core/instance/render-helpers/bind-object-listeners.js
new file mode 100644
index 00000000..5bfc7514
--- /dev/null
+++ b/node_modules/vue/src/core/instance/render-helpers/bind-object-listeners.js
@@ -0,0 +1,22 @@
+/* @flow */
+
+import { warn, extend, isPlainObject } from 'core/util/index'
+
+export function bindObjectListeners (data: any, value: any): VNodeData {
+ if (value) {
+ if (!isPlainObject(value)) {
+ process.env.NODE_ENV !== 'production' && warn(
+ 'v-on without argument expects an Object value',
+ this
+ )
+ } else {
+ const on = data.on = data.on ? extend({}, data.on) : {}
+ for (const key in value) {
+ const existing = on[key]
+ const ours = value[key]
+ on[key] = existing ? [].concat(existing, ours) : ours
+ }
+ }
+ }
+ return data
+}
diff --git a/node_modules/vue/src/core/instance/render-helpers/bind-object-props.js b/node_modules/vue/src/core/instance/render-helpers/bind-object-props.js
new file mode 100644
index 00000000..c71dce5c
--- /dev/null
+++ b/node_modules/vue/src/core/instance/render-helpers/bind-object-props.js
@@ -0,0 +1,60 @@
+/* @flow */
+
+import config from 'core/config'
+
+import {
+ warn,
+ isObject,
+ toObject,
+ isReservedAttribute
+} from 'core/util/index'
+
+/**
+ * Runtime helper for merging v-bind="object" into a VNode's data.
+ */
+export function bindObjectProps (
+ data: any,
+ tag: string,
+ value: any,
+ asProp: boolean,
+ isSync?: boolean
+): VNodeData {
+ if (value) {
+ if (!isObject(value)) {
+ process.env.NODE_ENV !== 'production' && warn(
+ 'v-bind without argument expects an Object or Array value',
+ this
+ )
+ } else {
+ if (Array.isArray(value)) {
+ value = toObject(value)
+ }
+ let hash
+ for (const key in value) {
+ if (
+ key === 'class' ||
+ key === 'style' ||
+ isReservedAttribute(key)
+ ) {
+ hash = data
+ } else {
+ const type = data.attrs && data.attrs.type
+ hash = asProp || config.mustUseProp(tag, type, key)
+ ? data.domProps || (data.domProps = {})
+ : data.attrs || (data.attrs = {})
+ }
+ if (!(key in hash)) {
+ hash[key] = value[key]
+
+ if (isSync) {
+ const on = data.on || (data.on = {})
+ on[`update:${key}`] = function ($event) {
+ value[key] = $event
+ }
+ }
+ }
+ }
+ }
+ }
+ return data
+}
diff --git a/node_modules/vue/src/core/instance/render-helpers/check-keycodes.js b/node_modules/vue/src/core/instance/render-helpers/check-keycodes.js
new file mode 100644
index 00000000..c12402b1
--- /dev/null
+++ b/node_modules/vue/src/core/instance/render-helpers/check-keycodes.js
@@ -0,0 +1,34 @@
+/* @flow */
+
+import config from 'core/config'
+import { hyphenate } from 'shared/util'
+
+function isKeyNotMatch<T> (expect: T | Array<T>, actual: T): boolean {
+ if (Array.isArray(expect)) {
+ return expect.indexOf(actual) === -1
+ } else {
+ return expect !== actual
+ }
+}
+
+/**
+ * Runtime helper for checking keyCodes from config.
+ * exposed as Vue.prototype._k
+ * passing in eventKeyName as last argument separately for backwards compat
+ */
+export function checkKeyCodes (
+ eventKeyCode: number,
+ key: string,
+ builtInKeyCode?: number | Array<number>,
+ eventKeyName?: string,
+ builtInKeyName?: string | Array<string>
+): ?boolean {
+ const mappedKeyCode = config.keyCodes[key] || builtInKeyCode
+ if (builtInKeyName && eventKeyName && !config.keyCodes[key]) {
+ return isKeyNotMatch(builtInKeyName, eventKeyName)
+ } else if (mappedKeyCode) {
+ return isKeyNotMatch(mappedKeyCode, eventKeyCode)
+ } else if (eventKeyName) {
+ return hyphenate(eventKeyName) !== key
+ }
+}
diff --git a/node_modules/vue/src/core/instance/render-helpers/index.js b/node_modules/vue/src/core/instance/render-helpers/index.js
new file mode 100644
index 00000000..38414a9a
--- /dev/null
+++ b/node_modules/vue/src/core/instance/render-helpers/index.js
@@ -0,0 +1,30 @@
+/* @flow */
+
+import { toNumber, toString, looseEqual, looseIndexOf } from 'shared/util'
+import { createTextVNode, createEmptyVNode } from 'core/vdom/vnode'
+import { renderList } from './render-list'
+import { renderSlot } from './render-slot'
+import { resolveFilter } from './resolve-filter'
+import { checkKeyCodes } from './check-keycodes'
+import { bindObjectProps } from './bind-object-props'
+import { renderStatic, markOnce } from './render-static'
+import { bindObjectListeners } from './bind-object-listeners'
+import { resolveScopedSlots } from './resolve-slots'
+
+export function installRenderHelpers (target: any) {
+ target._o = markOnce
+ target._n = toNumber
+ target._s = toString
+ target._l = renderList
+ target._t = renderSlot
+ target._q = looseEqual
+ target._i = looseIndexOf
+ target._m = renderStatic
+ target._f = resolveFilter
+ target._k = checkKeyCodes
+ target._b = bindObjectProps
+ target._v = createTextVNode
+ target._e = createEmptyVNode
+ target._u = resolveScopedSlots
+ target._g = bindObjectListeners
+}
diff --git a/node_modules/vue/src/core/instance/render-helpers/render-list.js b/node_modules/vue/src/core/instance/render-helpers/render-list.js
new file mode 100644
index 00000000..abe99db4
--- /dev/null
+++ b/node_modules/vue/src/core/instance/render-helpers/render-list.js
@@ -0,0 +1,39 @@
+/* @flow */
+
+import { isObject, isDef } from 'core/util/index'
+
+/**
+ * Runtime helper for rendering v-for lists.
+ */
+export function renderList (
+ val: any,
+ render: (
+ val: any,
+ keyOrIndex: string | number,
+ index?: number
+ ) => VNode
+): ?Array<VNode> {
+ let ret: ?Array<VNode>, i, l, keys, key
+ if (Array.isArray(val) || typeof val === 'string') {
+ ret = new Array(val.length)
+ for (i = 0, l = val.length; i < l; i++) {
+ ret[i] = render(val[i], i)
+ }
+ } else if (typeof val === 'number') {
+ ret = new Array(val)
+ for (i = 0; i < val; i++) {
+ ret[i] = render(i + 1, i)
+ }
+ } else if (isObject(val)) {
+ keys = Object.keys(val)
+ ret = new Array(keys.length)
+ for (i = 0, l = keys.length; i < l; i++) {
+ key = keys[i]
+ ret[i] = render(val[key], key, i)
+ }
+ }
+ if (isDef(ret)) {
+ (ret: any)._isVList = true
+ }
+ return ret
+}
diff --git a/node_modules/vue/src/core/instance/render-helpers/render-slot.js b/node_modules/vue/src/core/instance/render-helpers/render-slot.js
new file mode 100644
index 00000000..a58daa74
--- /dev/null
+++ b/node_modules/vue/src/core/instance/render-helpers/render-slot.js
@@ -0,0 +1,50 @@
+/* @flow */
+
+import { extend, warn, isObject } from 'core/util/index'
+
+/**
+ * Runtime helper for rendering <slot>
+ */
+export function renderSlot (
+ name: string,
+ fallback: ?Array<VNode>,
+ props: ?Object,
+ bindObject: ?Object
+): ?Array<VNode> {
+ const scopedSlotFn = this.$scopedSlots[name]
+ let nodes
+ if (scopedSlotFn) { // scoped slot
+ props = props || {}
+ if (bindObject) {
+ if (process.env.NODE_ENV !== 'production' && !isObject(bindObject)) {
+ warn(
+ 'slot v-bind without argument expects an Object',
+ this
+ )
+ }
+ props = extend(extend({}, bindObject), props)
+ }
+ nodes = scopedSlotFn(props) || fallback
+ } else {
+ const slotNodes = this.$slots[name]
+ // warn duplicate slot usage
+ if (slotNodes) {
+ if (process.env.NODE_ENV !== 'production' && slotNodes._rendered) {
+ warn(
+ `Duplicate presence of slot "${name}" found in the same render tree ` +
+ `- this will likely cause render errors.`,
+ this
+ )
+ }
+ slotNodes._rendered = true
+ }
+ nodes = slotNodes || fallback
+ }
+
+ const target = props && props.slot
+ if (target) {
+ return this.$createElement('template', { slot: target }, nodes)
+ } else {
+ return nodes
+ }
+}
diff --git a/node_modules/vue/src/core/instance/render-helpers/render-static.js b/node_modules/vue/src/core/instance/render-helpers/render-static.js
new file mode 100644
index 00000000..f56510b3
--- /dev/null
+++ b/node_modules/vue/src/core/instance/render-helpers/render-static.js
@@ -0,0 +1,60 @@
+/* @flow */
+
+/**
+ * Runtime helper for rendering static trees.
+ */
+export function renderStatic (
+ index: number,
+ isInFor: boolean
+): VNode | Array<VNode> {
+ const cached = this._staticTrees || (this._staticTrees = [])
+ let tree = cached[index]
+ // if has already-rendered static tree and not inside v-for,
+ // we can reuse the same tree.
+ if (tree && !isInFor) {
+ return tree
+ }
+ // otherwise, render a fresh tree.
+ tree = cached[index] = this.$options.staticRenderFns[index].call(
+ this._renderProxy,
+ null,
+ this // for render fns generated for functional component templates
+ )
+ markStatic(tree, `__static__${index}`, false)
+ return tree
+}
+
+/**
+ * Runtime helper for v-once.
+ * Effectively it means marking the node as static with a unique key.
+ */
+export function markOnce (
+ tree: VNode | Array<VNode>,
+ index: number,
+ key: string
+) {
+ markStatic(tree, `__once__${index}${key ? `_${key}` : ``}`, true)
+ return tree
+}
+
+function markStatic (
+ tree: VNode | Array<VNode>,
+ key: string,
+ isOnce: boolean
+) {
+ if (Array.isArray(tree)) {
+ for (let i = 0; i < tree.length; i++) {
+ if (tree[i] && typeof tree[i] !== 'string') {
+ markStaticNode(tree[i], `${key}_${i}`, isOnce)
+ }
+ }
+ } else {
+ markStaticNode(tree, key, isOnce)
+ }
+}
+
+function markStaticNode (node, key, isOnce) {
+ node.isStatic = true
+ node.key = key
+ node.isOnce = isOnce
+}
diff --git a/node_modules/vue/src/core/instance/render-helpers/resolve-filter.js b/node_modules/vue/src/core/instance/render-helpers/resolve-filter.js
new file mode 100644
index 00000000..08a81e14
--- /dev/null
+++ b/node_modules/vue/src/core/instance/render-helpers/resolve-filter.js
@@ -0,0 +1,10 @@
+/* @flow */
+
+import { identity, resolveAsset } from 'core/util/index'
+
+/**
+ * Runtime helper for resolving filters
+ */
+export function resolveFilter (id: string): Function {
+ return resolveAsset(this.$options, 'filters', id, true) || identity
+}
diff --git a/node_modules/vue/src/core/instance/render-helpers/resolve-slots.js b/node_modules/vue/src/core/instance/render-helpers/resolve-slots.js
new file mode 100644
index 00000000..02f007cf
--- /dev/null
+++ b/node_modules/vue/src/core/instance/render-helpers/resolve-slots.js
@@ -0,0 +1,65 @@
+/* @flow */
+
+import type VNode from 'core/vdom/vnode'
+
+/**
+ * Runtime helper for resolving raw children VNodes into a slot object.
+ */
+export function resolveSlots (
+ children: ?Array<VNode>,
+ context: ?Component
+): { [key: string]: Array<VNode> } {
+ const slots = {}
+ if (!children) {
+ return slots
+ }
+ for (let i = 0, l = children.length; i < l; i++) {
+ const child = children[i]
+ const data = child.data
+ // remove slot attribute if the node is resolved as a Vue slot node
+ if (data && data.attrs && data.attrs.slot) {
+ delete data.attrs.slot
+ }
+ // named slots should only be respected if the vnode was rendered in the
+ // same context.
+ if ((child.context === context || child.fnContext === context) &&
+ data && data.slot != null
+ ) {
+ const name = data.slot
+ const slot = (slots[name] || (slots[name] = []))
+ if (child.tag === 'template') {
+ slot.push.apply(slot, child.children || [])
+ } else {
+ slot.push(child)
+ }
+ } else {
+ (slots.default || (slots.default = [])).push(child)
+ }
+ }
+ // ignore slots that contains only whitespace
+ for (const name in slots) {
+ if (slots[name].every(isWhitespace)) {
+ delete slots[name]
+ }
+ }
+ return slots
+}
+
+function isWhitespace (node: VNode): boolean {
+ return (node.isComment && !node.asyncFactory) || node.text === ' '
+}
+
+export function resolveScopedSlots (
+ fns: ScopedSlotsData, // see flow/vnode
+ res?: Object
+): { [key: string]: Function } {
+ res = res || {}
+ for (let i = 0; i < fns.length; i++) {
+ if (Array.isArray(fns[i])) {
+ resolveScopedSlots(fns[i], res)
+ } else {
+ res[fns[i].key] = fns[i].fn
+ }
+ }
+ return res
+}
diff --git a/node_modules/vue/src/core/instance/render.js b/node_modules/vue/src/core/instance/render.js
new file mode 100644
index 00000000..70fb2c0e
--- /dev/null
+++ b/node_modules/vue/src/core/instance/render.js
@@ -0,0 +1,119 @@
+/* @flow */
+
+import {
+ warn,
+ nextTick,
+ emptyObject,
+ handleError,
+ defineReactive
+} from '../util/index'
+
+import { createElement } from '../vdom/create-element'
+import { installRenderHelpers } from './render-helpers/index'
+import { resolveSlots } from './render-helpers/resolve-slots'
+import VNode, { createEmptyVNode } from '../vdom/vnode'
+
+import { isUpdatingChildComponent } from './lifecycle'
+
+export function initRender (vm: Component) {
+ vm._vnode = null // the root of the child tree
+ vm._staticTrees = null // v-once cached trees
+ const options = vm.$options
+ const parentVnode = vm.$vnode = options._parentVnode // the placeholder node in parent tree
+ const renderContext = parentVnode && parentVnode.context
+ vm.$slots = resolveSlots(options._renderChildren, renderContext)
+ vm.$scopedSlots = emptyObject
+ // bind the createElement fn to this instance
+ // so that we get proper render context inside it.
+ // args order: tag, data, children, normalizationType, alwaysNormalize
+ // internal version is used by render functions compiled from templates
+ vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
+ // normalization is always applied for the public version, used in
+ // user-written render functions.
+ vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)
+
+ // $attrs & $listeners are exposed for easier HOC creation.
+ // they need to be reactive so that HOCs using them are always updated
+ const parentData = parentVnode && parentVnode.data
+
+ /* istanbul ignore else */
+ if (process.env.NODE_ENV !== 'production') {
+ defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, () => {
+ !isUpdatingChildComponent && warn(`$attrs is readonly.`, vm)
+ }, true)
+ defineReactive(vm, '$listeners', options._parentListeners || emptyObject, () => {
+ !isUpdatingChildComponent && warn(`$listeners is readonly.`, vm)
+ }, true)
+ } else {
+ defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, null, true)
+ defineReactive(vm, '$listeners', options._parentListeners || emptyObject, null, true)
+ }
+}
+
+export function renderMixin (Vue: Class<Component>) {
+ // install runtime convenience helpers
+ installRenderHelpers(Vue.prototype)
+
+ Vue.prototype.$nextTick = function (fn: Function) {
+ return nextTick(fn, this)
+ }
+
+ Vue.prototype._render = function (): VNode {
+ const vm: Component = this
+ const { render, _parentVnode } = vm.$options
+
+ // reset _rendered flag on slots for duplicate slot check
+ if (process.env.NODE_ENV !== 'production') {
+ for (const key in vm.$slots) {
+ // $flow-disable-line
+ vm.$slots[key]._rendered = false
+ }
+ }
+
+ if (_parentVnode) {
+ vm.$scopedSlots = _parentVnode.data.scopedSlots || emptyObject
+ }
+
+ // set parent vnode. this allows render functions to have access
+ // to the data on the placeholder node.
+ vm.$vnode = _parentVnode
+ // render self
+ let vnode
+ try {
+ vnode = render.call(vm._renderProxy, vm.$createElement)
+ } catch (e) {
+ handleError(e, vm, `render`)
+ // return error render result,
+ // or previous vnode to prevent render error causing blank component
+ /* istanbul ignore else */
+ if (process.env.NODE_ENV !== 'production') {
+ if (vm.$options.renderError) {
+ try {
+ vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e)
+ } catch (e) {
+ handleError(e, vm, `renderError`)
+ vnode = vm._vnode
+ }
+ } else {
+ vnode = vm._vnode
+ }
+ } else {
+ vnode = vm._vnode
+ }
+ }
+ // return empty vnode in case the render function errored out
+ if (!(vnode instanceof VNode)) {
+ if (process.env.NODE_ENV !== 'production' && Array.isArray(vnode)) {
+ warn(
+ 'Multiple root nodes returned from render function. Render function ' +
+ 'should return a single root node.',
+ vm
+ )
+ }
+ vnode = createEmptyVNode()
+ }
+ // set parent
+ vnode.parent = _parentVnode
+ return vnode
+ }
+}
diff --git a/node_modules/vue/src/core/instance/state.js b/node_modules/vue/src/core/instance/state.js
new file mode 100644
index 00000000..b1549b0d
--- /dev/null
+++ b/node_modules/vue/src/core/instance/state.js
@@ -0,0 +1,360 @@
+/* @flow */
+
+import config from '../config'
+import Watcher from '../observer/watcher'
+import Dep, { pushTarget, popTarget } from '../observer/dep'
+import { isUpdatingChildComponent } from './lifecycle'
+
+import {
+ set,
+ del,
+ observe,
+ defineReactive,
+ toggleObserving
+} from '../observer/index'
+
+import {
+ warn,
+ bind,
+ noop,
+ hasOwn,
+ hyphenate,
+ isReserved,
+ handleError,
+ nativeWatch,
+ validateProp,
+ isPlainObject,
+ isServerRendering,
+ isReservedAttribute
+} from '../util/index'
+
+const sharedPropertyDefinition = {
+ enumerable: true,
+ configurable: true,
+ get: noop,
+ set: noop
+}
+
+export function proxy (target: Object, sourceKey: string, key: string) {
+ sharedPropertyDefinition.get = function proxyGetter () {
+ return this[sourceKey][key]
+ }
+ sharedPropertyDefinition.set = function proxySetter (val) {
+ this[sourceKey][key] = val
+ }
+ Object.defineProperty(target, key, sharedPropertyDefinition)
+}
+
+export function initState (vm: Component) {
+ vm._watchers = []
+ const opts = vm.$options
+ if (opts.props) initProps(vm, opts.props)
+ if (opts.methods) initMethods(vm, opts.methods)
+ if (opts.data) {
+ initData(vm)
+ } else {
+ observe(vm._data = {}, true /* asRootData */)
+ }
+ if (opts.computed) initComputed(vm, opts.computed)
+ if (opts.watch && opts.watch !== nativeWatch) {
+ initWatch(vm, opts.watch)
+ }
+}
+
+function initProps (vm: Component, propsOptions: Object) {
+ const propsData = vm.$options.propsData || {}
+ const props = vm._props = {}
+ // cache prop keys so that future props updates can iterate using Array
+ // instead of dynamic object key enumeration.
+ const keys = vm.$options._propKeys = []
+ const isRoot = !vm.$parent
+ // root instance props should be converted
+ if (!isRoot) {
+ toggleObserving(false)
+ }
+ for (const key in propsOptions) {
+ keys.push(key)
+ const value = validateProp(key, propsOptions, propsData, vm)
+ /* istanbul ignore else */
+ if (process.env.NODE_ENV !== 'production') {
+ const hyphenatedKey = hyphenate(key)
+ if (isReservedAttribute(hyphenatedKey) ||
+ config.isReservedAttr(hyphenatedKey)) {
+ warn(
+ `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`,
+ vm
+ )
+ }
+ defineReactive(props, key, value, () => {
+ if (vm.$parent && !isUpdatingChildComponent) {
+ warn(
+ `Avoid mutating a prop directly since the value will be ` +
+ `overwritten whenever the parent component re-renders. ` +
+ `Instead, use a data or computed property based on the prop's ` +
+ `value. Prop being mutated: "${key}"`,
+ vm
+ )
+ }
+ })
+ } else {
+ defineReactive(props, key, value)
+ }
+ // static props are already proxied on the component's prototype
+ // during Vue.extend(). We only need to proxy props defined at
+ // instantiation here.
+ if (!(key in vm)) {
+ proxy(vm, `_props`, key)
+ }
+ }
+ toggleObserving(true)
+}
+
+function initData (vm: Component) {
+ let data = vm.$options.data
+ data = vm._data = typeof data === 'function'
+ ? getData(data, vm)
+ : data || {}
+ if (!isPlainObject(data)) {
+ data = {}
+ process.env.NODE_ENV !== 'production' && warn(
+ 'data functions should return an object:\n' +
+ 'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
+ vm
+ )
+ }
+ // proxy data on instance
+ const keys = Object.keys(data)
+ const props = vm.$options.props
+ const methods = vm.$options.methods
+ let i = keys.length
+ while (i--) {
+ const key = keys[i]
+ if (process.env.NODE_ENV !== 'production') {
+ if (methods && hasOwn(methods, key)) {
+ warn(
+ `Method "${key}" has already been defined as a data property.`,
+ vm
+ )
+ }
+ }
+ if (props && hasOwn(props, key)) {
+ process.env.NODE_ENV !== 'production' && warn(
+ `The data property "${key}" is already declared as a prop. ` +
+ `Use prop default value instead.`,
+ vm
+ )
+ } else if (!isReserved(key)) {
+ proxy(vm, `_data`, key)
+ }
+ }
+ // observe data
+ observe(data, true /* asRootData */)
+}
+
+export function getData (data: Function, vm: Component): any {
+ // #7573 disable dep collection when invoking data getters
+ pushTarget()
+ try {
+ return data.call(vm, vm)
+ } catch (e) {
+ handleError(e, vm, `data()`)
+ return {}
+ } finally {
+ popTarget()
+ }
+}
+
+const computedWatcherOptions = { lazy: true }
+
+function initComputed (vm: Component, computed: Object) {
+ // $flow-disable-line
+ const watchers = vm._computedWatchers = Object.create(null)
+ // computed properties are just getters during SSR
+ const isSSR = isServerRendering()
+
+ for (const key in computed) {
+ const userDef = computed[key]
+ const getter = typeof userDef === 'function' ? userDef : userDef.get
+ if (process.env.NODE_ENV !== 'production' && getter == null) {
+ warn(
+ `Getter is missing for computed property "${key}".`,
+ vm
+ )
+ }
+
+ if (!isSSR) {
+ // create internal watcher for the computed property.
+ watchers[key] = new Watcher(
+ vm,
+ getter || noop,
+ noop,
+ computedWatcherOptions
+ )
+ }
+
+ // component-defined computed properties are already defined on the
+ // component prototype. We only need to define computed properties defined
+ // at instantiation here.
+ if (!(key in vm)) {
+ defineComputed(vm, key, userDef)
+ } else if (process.env.NODE_ENV !== 'production') {
+ if (key in vm.$data) {
+ warn(`The computed property "${key}" is already defined in data.`, vm)
+ } else if (vm.$options.props && key in vm.$options.props) {
+ warn(`The computed property "${key}" is already defined as a prop.`, vm)
+ }
+ }
+ }
+}
+
+export function defineComputed (
+ target: any,
+ key: string,
+ userDef: Object | Function
+) {
+ const shouldCache = !isServerRendering()
+ if (typeof userDef === 'function') {
+ sharedPropertyDefinition.get = shouldCache
+ ? createComputedGetter(key)
+ : userDef
+ sharedPropertyDefinition.set = noop
+ } else {
+ sharedPropertyDefinition.get = userDef.get
+ ? shouldCache && userDef.cache !== false
+ ? createComputedGetter(key)
+ : userDef.get
+ : noop
+ sharedPropertyDefinition.set = userDef.set
+ ? userDef.set
+ : noop
+ }
+ if (process.env.NODE_ENV !== 'production' &&
+ sharedPropertyDefinition.set === noop) {
+ sharedPropertyDefinition.set = function () {
+ warn(
+ `Computed property "${key}" was assigned to but it has no setter.`,
+ this
+ )
+ }
+ }
+ Object.defineProperty(target, key, sharedPropertyDefinition)
+}
+
+function createComputedGetter (key) {
+ return function computedGetter () {
+ const watcher = this._computedWatchers && this._computedWatchers[key]
+ if (watcher) {
+ if (watcher.dirty) {
+ watcher.evaluate()
+ }
+ if (Dep.target) {
+ watcher.depend()
+ }
+ return watcher.value
+ }
+ }
+}
+
+function initMethods (vm: Component, methods: Object) {
+ const props = vm.$options.props
+ for (const key in methods) {
+ if (process.env.NODE_ENV !== 'production') {
+ if (methods[key] == null) {
+ warn(
+ `Method "${key}" has an undefined value in the component definition. ` +
+ `Did you reference the function correctly?`,
+ vm
+ )
+ }
+ if (props && hasOwn(props, key)) {
+ warn(
+ `Method "${key}" has already been defined as a prop.`,
+ vm
+ )
+ }
+ if ((key in vm) && isReserved(key)) {
+ warn(
+ `Method "${key}" conflicts with an existing Vue instance method. ` +
+ `Avoid defining component methods that start with _ or $.`
+ )
+ }
+ }
+ vm[key] = methods[key] == null ? noop : bind(methods[key], vm)
+ }
+}
+
+function initWatch (vm: Component, watch: Object) {
+ for (const key in watch) {
+ const handler = watch[key]
+ if (Array.isArray(handler)) {
+ for (let i = 0; i < handler.length; i++) {
+ createWatcher(vm, key, handler[i])
+ }
+ } else {
+ createWatcher(vm, key, handler)
+ }
+ }
+}
+
+function createWatcher (
+ vm: Component,
+ expOrFn: string | Function,
+ handler: any,
+ options?: Object
+) {
+ if (isPlainObject(handler)) {
+ options = handler
+ handler = handler.handler
+ }
+ if (typeof handler === 'string') {
+ handler = vm[handler]
+ }
+ return vm.$watch(expOrFn, handler, options)
+}
+
+export function stateMixin (Vue: Class<Component>) {
+ // flow somehow has problems with directly declared definition object
+ // when using Object.defineProperty, so we have to procedurally build up
+ // the object here.
+ const dataDef = {}
+ dataDef.get = function () { return this._data }
+ const propsDef = {}
+ propsDef.get = function () { return this._props }
+ if (process.env.NODE_ENV !== 'production') {
+ dataDef.set = function (newData: Object) {
+ warn(
+ 'Avoid replacing instance root $data. ' +
+ 'Use nested data properties instead.',
+ this
+ )
+ }
+ propsDef.set = function () {
+ warn(`$props is readonly.`, this)
+ }
+ }
+ Object.defineProperty(Vue.prototype, '$data', dataDef)
+ Object.defineProperty(Vue.prototype, '$props', propsDef)
+
+ Vue.prototype.$set = set
+ Vue.prototype.$delete = del
+
+ Vue.prototype.$watch = function (
+ expOrFn: string | Function,
+ cb: any,
+ options?: Object
+ ): Function {
+ const vm: Component = this
+ if (isPlainObject(cb)) {
+ return createWatcher(vm, expOrFn, cb, options)
+ }
+ options = options || {}
+ options.user = true
+ const watcher = new Watcher(vm, expOrFn, cb, options)
+ if (options.immediate) {
+ cb.call(vm, watcher.value)
+ }
+ return function unwatchFn () {
+ watcher.teardown()
+ }
+ }
+}
diff --git a/node_modules/vue/src/core/observer/array.js b/node_modules/vue/src/core/observer/array.js
new file mode 100644
index 00000000..684e37ec
--- /dev/null
+++ b/node_modules/vue/src/core/observer/array.js
@@ -0,0 +1,45 @@
+/*
+ * not type checking this file because flow doesn't play well with
+ * dynamically accessing methods on Array prototype
+ */
+
+import { def } from '../util/index'
+
+const arrayProto = Array.prototype
+export const arrayMethods = Object.create(arrayProto)
+
+const methodsToPatch = [
+ 'push',
+ 'pop',
+ 'shift',
+ 'unshift',
+ 'splice',
+ 'sort',
+ 'reverse'
+]
+
+/**
+ * Intercept mutating methods and emit events
+ */
+methodsToPatch.forEach(function (method) {
+ // cache original method
+ const original = arrayProto[method]
+ def(arrayMethods, method, function mutator (...args) {
+ const result = original.apply(this, args)
+ const ob = this.__ob__
+ let inserted
+ switch (method) {
+ case 'push':
+ case 'unshift':
+ inserted = args
+ break
+ case 'splice':
+ inserted = args.slice(2)
+ break
+ }
+ if (inserted) ob.observeArray(inserted)
+ // notify change
+ ob.dep.notify()
+ return result
+ })
+})
diff --git a/node_modules/vue/src/core/observer/dep.js b/node_modules/vue/src/core/observer/dep.js
new file mode 100644
index 00000000..abf3b275
--- /dev/null
+++ b/node_modules/vue/src/core/observer/dep.js
@@ -0,0 +1,58 @@
+/* @flow */
+
+import type Watcher from './watcher'
+import { remove } from '../util/index'
+
+let uid = 0
+
+/**
+ * A dep is an observable that can have multiple
+ * directives subscribing to it.
+ */
+export default class Dep {
+ static target: ?Watcher;
+ id: number;
+ subs: Array<Watcher>;
+
+ constructor () {
+ this.id = uid++
+ this.subs = []
+ }
+
+ addSub (sub: Watcher) {
+ this.subs.push(sub)
+ }
+
+ removeSub (sub: Watcher) {
+ remove(this.subs, sub)
+ }
+
+ depend () {
+ if (Dep.target) {
+ Dep.target.addDep(this)
+ }
+ }
+
+ notify () {
+ // stabilize the subscriber list first
+ const subs = this.subs.slice()
+ for (let i = 0, l = subs.length; i < l; i++) {
+ subs[i].update()
+ }
+ }
+}
+
+// the current target watcher being evaluated.
+// this is globally unique because there could be only one
+// watcher being evaluated at any time.
+Dep.target = null
+const targetStack = []
+
+export function pushTarget (_target: ?Watcher) {
+ if (Dep.target) targetStack.push(Dep.target)
+ Dep.target = _target
+}
+
+export function popTarget () {
+ Dep.target = targetStack.pop()
+}
diff --git a/node_modules/vue/src/core/observer/index.js b/node_modules/vue/src/core/observer/index.js
new file mode 100644
index 00000000..4a030ed7
--- /dev/null
+++ b/node_modules/vue/src/core/observer/index.js
@@ -0,0 +1,273 @@
+/* @flow */
+
+import Dep from './dep'
+import VNode from '../vdom/vnode'
+import { arrayMethods } from './array'
+import {
+ def,
+ warn,
+ hasOwn,
+ hasProto,
+ isObject,
+ isPlainObject,
+ isPrimitive,
+ isUndef,
+ isValidArrayIndex,
+ isServerRendering
+} from '../util/index'
+
+const arrayKeys = Object.getOwnPropertyNames(arrayMethods)
+
+/**
+ * In some cases we may want to disable observation inside a component's
+ * update computation.
+ */
+export let shouldObserve: boolean = true
+
+export function toggleObserving (value: boolean) {
+ shouldObserve = value
+}
+
+/**
+ * Observer class that is attached to each observed
+ * object. Once attached, the observer converts the target
+ * object's property keys into getter/setters that
+ * collect dependencies and dispatch updates.
+ */
+export class Observer {
+ value: any;
+ dep: Dep;
+ vmCount: number; // number of vms that has this object as root $data
+
+ constructor (value: any) {
+ this.value = value
+ this.dep = new Dep()
+ this.vmCount = 0
+ def(value, '__ob__', this)
+ if (Array.isArray(value)) {
+ const augment = hasProto
+ ? protoAugment
+ : copyAugment
+ augment(value, arrayMethods, arrayKeys)
+ this.observeArray(value)
+ } else {
+ this.walk(value)
+ }
+ }
+
+ /**
+ * Walk through each property and convert them into
+ * getter/setters. This method should only be called when
+ * value type is Object.
+ */
+ walk (obj: Object) {
+ const keys = Object.keys(obj)
+ for (let i = 0; i < keys.length; i++) {
+ defineReactive(obj, keys[i])
+ }
+ }
+
+ /**
+ * Observe a list of Array items.
+ */
+ observeArray (items: Array<any>) {
+ for (let i = 0, l = items.length; i < l; i++) {
+ observe(items[i])
+ }
+ }
+}
+
+// helpers
+
+/**
+ * Augment an target Object or Array by intercepting
+ * the prototype chain using __proto__
+ */
+function protoAugment (target, src: Object, keys: any) {
+ /* eslint-disable no-proto */
+ target.__proto__ = src
+ /* eslint-enable no-proto */
+}
+
+/**
+ * Augment an target Object or Array by defining
+ * hidden properties.
+ */
+/* istanbul ignore next */
+function copyAugment (target: Object, src: Object, keys: Array<string>) {
+ for (let i = 0, l = keys.length; i < l; i++) {
+ const key = keys[i]
+ def(target, key, src[key])
+ }
+}
+
+/**
+ * Attempt to create an observer instance for a value,
+ * returns the new observer if successfully observed,
+ * or the existing observer if the value already has one.
+ */
+export function observe (value: any, asRootData: ?boolean): Observer | void {
+ if (!isObject(value) || value instanceof VNode) {
+ return
+ }
+ let ob: Observer | void
+ if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
+ ob = value.__ob__
+ } else if (
+ shouldObserve &&
+ !isServerRendering() &&
+ (Array.isArray(value) || isPlainObject(value)) &&
+ Object.isExtensible(value) &&
+ !value._isVue
+ ) {
+ ob = new Observer(value)
+ }
+ if (asRootData && ob) {
+ ob.vmCount++
+ }
+ return ob
+}
+
+/**
+ * Define a reactive property on an Object.
+ */
+export function defineReactive (
+ obj: Object,
+ key: string,
+ val: any,
+ customSetter?: ?Function,
+ shallow?: boolean
+) {
+ const dep = new Dep()
+
+ const property = Object.getOwnPropertyDescriptor(obj, key)
+ if (property && property.configurable === false) {
+ return
+ }
+
+ // cater for pre-defined getter/setters
+ const getter = property && property.get
+ if (!getter && arguments.length === 2) {
+ val = obj[key]
+ }
+ const setter = property && property.set
+
+ let childOb = !shallow && observe(val)
+ Object.defineProperty(obj, key, {
+ enumerable: true,
+ configurable: true,
+ get: function reactiveGetter () {
+ const value = getter ? getter.call(obj) : val
+ if (Dep.target) {
+ dep.depend()
+ if (childOb) {
+ childOb.dep.depend()
+ if (Array.isArray(value)) {
+ dependArray(value)
+ }
+ }
+ }
+ return value
+ },
+ set: function reactiveSetter (newVal) {
+ const value = getter ? getter.call(obj) : val
+ /* eslint-disable no-self-compare */
+ if (newVal === value || (newVal !== newVal && value !== value)) {
+ return
+ }
+ /* eslint-enable no-self-compare */
+ if (process.env.NODE_ENV !== 'production' && customSetter) {
+ customSetter()
+ }
+ if (setter) {
+ setter.call(obj, newVal)
+ } else {
+ val = newVal
+ }
+ childOb = !shallow && observe(newVal)
+ dep.notify()
+ }
+ })
+}
+
+/**
+ * Set a property on an object. Adds the new property and
+ * triggers change notification if the property doesn't
+ * already exist.
+ */
+export function set (target: Array<any> | Object, key: any, val: any): any {
+ if (process.env.NODE_ENV !== 'production' &&
+ (isUndef(target) || isPrimitive(target))
+ ) {
+ warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
+ }
+ if (Array.isArray(target) && isValidArrayIndex(key)) {
+ target.length = Math.max(target.length, key)
+ target.splice(key, 1, val)
+ return val
+ }
+ if (key in target && !(key in Object.prototype)) {
+ target[key] = val
+ return val
+ }
+ const ob = (target: any).__ob__
+ if (target._isVue || (ob && ob.vmCount)) {
+ process.env.NODE_ENV !== 'production' && warn(
+ 'Avoid adding reactive properties to a Vue instance or its root $data ' +
+ 'at runtime - declare it upfront in the data option.'
+ )
+ return val
+ }
+ if (!ob) {
+ target[key] = val
+ return val
+ }
+ defineReactive(ob.value, key, val)
+ ob.dep.notify()
+ return val
+}
+
+/**
+ * Delete a property and trigger change if necessary.
+ */
+export function del (target: Array<any> | Object, key: any) {
+ if (process.env.NODE_ENV !== 'production' &&
+ (isUndef(target) || isPrimitive(target))
+ ) {
+ warn(`Cannot delete reactive property on undefined, null, or primitive value: ${(target: any)}`)
+ }
+ if (Array.isArray(target) && isValidArrayIndex(key)) {
+ target.splice(key, 1)
+ return
+ }
+ const ob = (target: any).__ob__
+ if (target._isVue || (ob && ob.vmCount)) {
+ process.env.NODE_ENV !== 'production' && warn(
+ 'Avoid deleting properties on a Vue instance or its root $data ' +
+ '- just set it to null.'
+ )
+ return
+ }
+ if (!hasOwn(target, key)) {
+ return
+ }
+ delete target[key]
+ if (!ob) {
+ return
+ }
+ ob.dep.notify()
+}
+
+/**
+ * Collect dependencies on array elements when the array is touched, since
+ * we cannot intercept array element access like property getters.
+ */
+function dependArray (value: Array<any>) {
+ for (let e, i = 0, l = value.length; i < l; i++) {
+ e = value[i]
+ e && e.__ob__ && e.__ob__.dep.depend()
+ if (Array.isArray(e)) {
+ dependArray(e)
+ }
+ }
+}
diff --git a/node_modules/vue/src/core/observer/scheduler.js b/node_modules/vue/src/core/observer/scheduler.js
new file mode 100644
index 00000000..fce86e5f
--- /dev/null
+++ b/node_modules/vue/src/core/observer/scheduler.js
@@ -0,0 +1,148 @@
+/* @flow */
+
+import type Watcher from './watcher'
+import config from '../config'
+import { callHook, activateChildComponent } from '../instance/lifecycle'
+
+import {
+ warn,
+ nextTick,
+ devtools
+} from '../util/index'
+
+export const MAX_UPDATE_COUNT = 100
+
+const queue: Array<Watcher> = []
+const activatedChildren: Array<Component> = []
+let has: { [key: number]: ?true } = {}
+let circular: { [key: number]: number } = {}
+let waiting = false
+let flushing = false
+let index = 0
+
+/**
+ * Reset the scheduler's state.
+ */
+function resetSchedulerState () {
+ index = queue.length = activatedChildren.length = 0
+ has = {}
+ if (process.env.NODE_ENV !== 'production') {
+ circular = {}
+ }
+ waiting = flushing = false
+}
+
+/**
+ * Flush both queues and run the watchers.
+ */
+function flushSchedulerQueue () {
+ flushing = true
+ let watcher, id
+
+ // Sort queue before flush.
+ // This ensures that:
+ // 1. Components are updated from parent to child. (because parent is always
+ // created before the child)
+ // 2. A component's user watchers are run before its render watcher (because
+ // user watchers are created before the render watcher)
+ // 3. If a component is destroyed during a parent component's watcher run,
+ // its watchers can be skipped.
+ queue.sort((a, b) => a.id - b.id)
+
+ // do not cache length because more watchers might be pushed
+ // as we run existing watchers
+ for (index = 0; index < queue.length; index++) {
+ watcher = queue[index]
+ id = watcher.id
+ has[id] = null
+ watcher.run()
+ // in dev build, check and stop circular updates.
+ if (process.env.NODE_ENV !== 'production' && has[id] != null) {
+ circular[id] = (circular[id] || 0) + 1
+ if (circular[id] > MAX_UPDATE_COUNT) {
+ warn(
+ 'You may have an infinite update loop ' + (
+ watcher.user
+ ? `in watcher with expression "${watcher.expression}"`
+ : `in a component render function.`
+ ),
+ watcher.vm
+ )
+ break
+ }
+ }
+ }
+
+ // keep copies of post queues before resetting state
+ const activatedQueue = activatedChildren.slice()
+ const updatedQueue = queue.slice()
+
+ resetSchedulerState()
+
+ // call component updated and activated hooks
+ callActivatedHooks(activatedQueue)
+ callUpdatedHooks(updatedQueue)
+
+ // devtool hook
+ /* istanbul ignore if */
+ if (devtools && config.devtools) {
+ devtools.emit('flush')
+ }
+}
+
+function callUpdatedHooks (queue) {
+ let i = queue.length
+ while (i--) {
+ const watcher = queue[i]
+ const vm = watcher.vm
+ if (vm._watcher === watcher && vm._isMounted) {
+ callHook(vm, 'updated')
+ }
+ }
+}
+
+/**
+ * Queue a kept-alive component that was activated during patch.
+ * The queue will be processed after the entire tree has been patched.
+ */
+export function queueActivatedComponent (vm: Component) {
+ // setting _inactive to false here so that a render function can
+ // rely on checking whether it's in an inactive tree (e.g. router-view)
+ vm._inactive = false
+ activatedChildren.push(vm)
+}
+
+function callActivatedHooks (queue) {
+ for (let i = 0; i < queue.length; i++) {
+ queue[i]._inactive = true
+ activateChildComponent(queue[i], true /* true */)
+ }
+}
+
+/**
+ * Push a watcher into the watcher queue.
+ * Jobs with duplicate IDs will be skipped unless it's
+ * pushed when the queue is being flushed.
+ */
+export function queueWatcher (watcher: Watcher) {
+ const id = watcher.id
+ if (has[id] == null) {
+ has[id] = true
+ if (!flushing) {
+ queue.push(watcher)
+ } else {
+ // if already flushing, splice the watcher based on its id
+ // if already past its id, it will be run next immediately.
+ let i = queue.length - 1
+ while (i > index && queue[i].id > watcher.id) {
+ i--
+ }
+ queue.splice(i + 1, 0, watcher)
+ }
+ // queue the flush
+ if (!waiting) {
+ waiting = true
+ nextTick(flushSchedulerQueue)
+ }
+ }
+}
diff --git a/node_modules/vue/src/core/observer/traverse.js b/node_modules/vue/src/core/observer/traverse.js
new file mode 100644
index 00000000..6b26524a
--- /dev/null
+++ b/node_modules/vue/src/core/observer/traverse.js
@@ -0,0 +1,40 @@
+/* @flow */
+
+import { _Set as Set, isObject } from '../util/index'
+import type { SimpleSet } from '../util/index'
+import VNode from '../vdom/vnode'
+
+const seenObjects = new Set()
+
+/**
+ * Recursively traverse an object to evoke all converted
+ * getters, so that every nested property inside the object
+ * is collected as a "deep" dependency.
+ */
+export function traverse (val: any) {
+ _traverse(val, seenObjects)
+ seenObjects.clear()
+}
+
+function _traverse (val: any, seen: SimpleSet) {
+ let i, keys
+ const isA = Array.isArray(val)
+ if ((!isA && !isObject(val)) || Object.isFrozen(val) || val instanceof VNode) {
+ return
+ }
+ if (val.__ob__) {
+ const depId = val.__ob__.dep.id
+ if (seen.has(depId)) {
+ return
+ }
+ seen.add(depId)
+ }
+ if (isA) {
+ i = val.length
+ while (i--) _traverse(val[i], seen)
+ } else {
+ keys = Object.keys(val)
+ i = keys.length
+ while (i--) _traverse(val[keys[i]], seen)
+ }
+}
diff --git a/node_modules/vue/src/core/observer/watcher.js b/node_modules/vue/src/core/observer/watcher.js
new file mode 100644
index 00000000..48a2e612
--- /dev/null
+++ b/node_modules/vue/src/core/observer/watcher.js
@@ -0,0 +1,240 @@
+/* @flow */
+
+import {
+ warn,
+ remove,
+ isObject,
+ parsePath,
+ _Set as Set,
+ handleError
+} from '../util/index'
+
+import { traverse } from './traverse'
+import { queueWatcher } from './scheduler'
+import Dep, { pushTarget, popTarget } from './dep'
+
+import type { SimpleSet } from '../util/index'
+
+let uid = 0
+
+/**
+ * A watcher parses an expression, collects dependencies,
+ * and fires callback when the expression value changes.
+ * This is used for both the $watch() api and directives.
+ */
+export default class Watcher {
+ vm: Component;
+ expression: string;
+ cb: Function;
+ id: number;
+ deep: boolean;
+ user: boolean;
+ lazy: boolean;
+ sync: boolean;
+ dirty: boolean;
+ active: boolean;
+ deps: Array<Dep>;
+ newDeps: Array<Dep>;
+ depIds: SimpleSet;
+ newDepIds: SimpleSet;
+ getter: Function;
+ value: any;
+
+ constructor (
+ vm: Component,
+ expOrFn: string | Function,
+ cb: Function,
+ options?: ?Object,
+ isRenderWatcher?: boolean
+ ) {
+ this.vm = vm
+ if (isRenderWatcher) {
+ vm._watcher = this
+ }
+ vm._watchers.push(this)
+ // options
+ if (options) {
+ this.deep = !!options.deep
+ this.user = !!options.user
+ this.lazy = !!options.lazy
+ this.sync = !!options.sync
+ } else {
+ this.deep = this.user = this.lazy = this.sync = false
+ }
+ this.cb = cb
+ this.id = ++uid // uid for batching
+ this.active = true
+ this.dirty = this.lazy // for lazy watchers
+ this.deps = []
+ this.newDeps = []
+ this.depIds = new Set()
+ this.newDepIds = new Set()
+ this.expression = process.env.NODE_ENV !== 'production'
+ ? expOrFn.toString()
+ : ''
+ // parse expression for getter
+ if (typeof expOrFn === 'function') {
+ this.getter = expOrFn
+ } else {
+ this.getter = parsePath(expOrFn)
+ if (!this.getter) {
+ this.getter = function () {}
+ process.env.NODE_ENV !== 'production' && warn(
+ `Failed watching path: "${expOrFn}" ` +
+ 'Watcher only accepts simple dot-delimited paths. ' +
+ 'For full control, use a function instead.',
+ vm
+ )
+ }
+ }
+ this.value = this.lazy
+ ? undefined
+ : this.get()
+ }
+
+ /**
+ * Evaluate the getter, and re-collect dependencies.
+ */
+ get () {
+ pushTarget(this)
+ let value
+ const vm = this.vm
+ try {
+ value = this.getter.call(vm, vm)
+ } catch (e) {
+ if (this.user) {
+ handleError(e, vm, `getter for watcher "${this.expression}"`)
+ } else {
+ throw e
+ }
+ } finally {
+ // "touch" every property so they are all tracked as
+ // dependencies for deep watching
+ if (this.deep) {
+ traverse(value)
+ }
+ popTarget()
+ this.cleanupDeps()
+ }
+ return value
+ }
+
+ /**
+ * Add a dependency to this directive.
+ */
+ addDep (dep: Dep) {
+ const id = dep.id
+ if (!this.newDepIds.has(id)) {
+ this.newDepIds.add(id)
+ this.newDeps.push(dep)
+ if (!this.depIds.has(id)) {
+ dep.addSub(this)
+ }
+ }
+ }
+
+ /**
+ * Clean up for dependency collection.
+ */
+ cleanupDeps () {
+ let i = this.deps.length
+ while (i--) {
+ const dep = this.deps[i]
+ if (!this.newDepIds.has(dep.id)) {
+ dep.removeSub(this)
+ }
+ }
+ let tmp = this.depIds
+ this.depIds = this.newDepIds
+ this.newDepIds = tmp
+ this.newDepIds.clear()
+ tmp = this.deps
+ this.deps = this.newDeps
+ this.newDeps = tmp
+ this.newDeps.length = 0
+ }
+
+ /**
+ * Subscriber interface.
+ * Will be called when a dependency changes.
+ */
+ update () {
+ /* istanbul ignore else */
+ if (this.lazy) {
+ this.dirty = true
+ } else if (this.sync) {
+ this.run()
+ } else {
+ queueWatcher(this)
+ }
+ }
+
+ /**
+ * Scheduler job interface.
+ * Will be called by the scheduler.
+ */
+ run () {
+ if (this.active) {
+ const value = this.get()
+ if (
+ value !== this.value ||
+ // Deep watchers and watchers on Object/Arrays should fire even
+ // when the value is the same, because the value may
+ // have mutated.
+ isObject(value) ||
+ this.deep
+ ) {
+ // set new value
+ const oldValue = this.value
+ this.value = value
+ if (this.user) {
+ try {
+ this.cb.call(this.vm, value, oldValue)
+ } catch (e) {
+ handleError(e, this.vm, `callback for watcher "${this.expression}"`)
+ }
+ } else {
+ this.cb.call(this.vm, value, oldValue)
+ }
+ }
+ }
+ }
+
+ /**
+ * Evaluate the value of the watcher.
+ * This only gets called for lazy watchers.
+ */
+ evaluate () {
+ this.value = this.get()
+ this.dirty = false
+ }
+
+ /**
+ * Depend on all deps collected by this watcher.
+ */
+ depend () {
+ let i = this.deps.length
+ while (i--) {
+ this.deps[i].depend()
+ }
+ }
+
+ /**
+ * Remove self from all dependencies' subscriber list.
+ */
+ teardown () {
+ if (this.active) {
+ // remove self from vm's watcher list
+ // this is a somewhat expensive operation so we skip it
+ // if the vm is being destroyed.
+ if (!this.vm._isBeingDestroyed) {
+ remove(this.vm._watchers, this)
+ }
+ let i = this.deps.length
+ while (i--) {
+ this.deps[i].removeSub(this)
+ }
+ this.active = false
+ }
+ }
+}
diff --git a/node_modules/vue/src/core/util/debug.js b/node_modules/vue/src/core/util/debug.js
new file mode 100644
index 00000000..6b7315f4
--- /dev/null
+++ b/node_modules/vue/src/core/util/debug.js
@@ -0,0 +1,100 @@
+/* @flow */
+
+import config from '../config'
+import { noop } from 'shared/util'
+
+export let warn = noop
+export let tip = noop
+export let generateComponentTrace = (noop: any) // work around flow check
+export let formatComponentName = (noop: any)
+
+if (process.env.NODE_ENV !== 'production') {
+ const hasConsole = typeof console !== 'undefined'
+ const classifyRE = /(?:^|[-_])(\w)/g
+ const classify = str => str
+ .replace(classifyRE, c => c.toUpperCase())
+ .replace(/[-_]/g, '')
+
+ warn = (msg, vm) => {
+ const trace = vm ? generateComponentTrace(vm) : ''
+
+ if (config.warnHandler) {
+ config.warnHandler.call(null, msg, vm, trace)
+ } else if (hasConsole && (!config.silent)) {
+ console.error(`[Vue warn]: ${msg}${trace}`)
+ }
+ }
+
+ tip = (msg, vm) => {
+ if (hasConsole && (!config.silent)) {
+ console.warn(`[Vue tip]: ${msg}` + (
+ vm ? generateComponentTrace(vm) : ''
+ ))
+ }
+ }
+
+ formatComponentName = (vm, includeFile) => {
+ if (vm.$root === vm) {
+ return '<Root>'
+ }
+ const options = typeof vm === 'function' && vm.cid != null
+ ? vm.options
+ : vm._isVue
+ ? vm.$options || vm.constructor.options
+ : vm || {}
+ let name = options.name || options._componentTag
+ const file = options.__file
+ if (!name && file) {
+ const match = file.match(/([^/\\]+)\.vue$/)
+ name = match && match[1]
+ }
+
+ return (
+ (name ? `<${classify(name)}>` : `<Anonymous>`) +
+ (file && includeFile !== false ? ` at ${file}` : '')
+ )
+ }
+
+ const repeat = (str, n) => {
+ let res = ''
+ while (n) {
+ if (n % 2 === 1) res += str
+ if (n > 1) str += str
+ n >>= 1
+ }
+ return res
+ }
+
+ generateComponentTrace = vm => {
+ if (vm._isVue && vm.$parent) {
+ const tree = []
+ let currentRecursiveSequence = 0
+ while (vm) {
+ if (tree.length > 0) {
+ const last = tree[tree.length - 1]
+ if (last.constructor === vm.constructor) {
+ currentRecursiveSequence++
+ vm = vm.$parent
+ continue
+ } else if (currentRecursiveSequence > 0) {
+ tree[tree.length - 1] = [last, currentRecursiveSequence]
+ currentRecursiveSequence = 0
+ }
+ }
+ tree.push(vm)
+ vm = vm.$parent
+ }
+ return '\n\nfound in\n\n' + tree
+ .map((vm, i) => `${
+ i === 0 ? '---> ' : repeat(' ', 5 + i * 2)
+ }${
+ Array.isArray(vm)
+ ? `${formatComponentName(vm[0])}... (${vm[1]} recursive calls)`
+ : formatComponentName(vm)
+ }`)
+ .join('\n')
+ } else {
+ return `\n\n(found in ${formatComponentName(vm)})`
+ }
+ }
+}
diff --git a/node_modules/vue/src/core/util/env.js b/node_modules/vue/src/core/util/env.js
new file mode 100644
index 00000000..07cadd9c
--- /dev/null
+++ b/node_modules/vue/src/core/util/env.js
@@ -0,0 +1,95 @@
+/* @flow */
+
+// can we use __proto__?
+export const hasProto = '__proto__' in {}
+
+// Browser environment sniffing
+export const inBrowser = typeof window !== 'undefined'
+export const inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform
+export const weexPlatform = inWeex && WXEnvironment.platform.toLowerCase()
+export const UA = inBrowser && window.navigator.userAgent.toLowerCase()
+export const isIE = UA && /msie|trident/.test(UA)
+export const isIE9 = UA && UA.indexOf('msie 9.0') > 0
+export const isEdge = UA && UA.indexOf('edge/') > 0
+export const isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android')
+export const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios')
+export const isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge
+
+// Firefox has a "watch" function on Object.prototype...
+export const nativeWatch = ({}).watch
+
+export let supportsPassive = false
+if (inBrowser) {
+ try {
+ const opts = {}
+ Object.defineProperty(opts, 'passive', ({
+ get () {
+ /* istanbul ignore next */
+ supportsPassive = true
+ }
+ }: Object)) // https://github.com/facebook/flow/issues/285
+ window.addEventListener('test-passive', null, opts)
+ } catch (e) {}
+}
+
+// this needs to be lazy-evaled because vue may be required before
+// vue-server-renderer can set VUE_ENV
+let _isServer
+export const isServerRendering = () => {
+ if (_isServer === undefined) {
+ /* istanbul ignore if */
+ if (!inBrowser && !inWeex && typeof global !== 'undefined') {
+ // detect presence of vue-server-renderer and avoid
+ // Webpack shimming the process
+ _isServer = global['process'].env.VUE_ENV === 'server'
+ } else {
+ _isServer = false
+ }
+ }
+ return _isServer
+}
+
+// detect devtools
+export const devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__
+
+/* istanbul ignore next */
+export function isNative (Ctor: any): boolean {
+ return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
+}
+
+export const hasSymbol =
+ typeof Symbol !== 'undefined' && isNative(Symbol) &&
+ typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys)
+
+let _Set
+/* istanbul ignore if */ // $flow-disable-line
+if (typeof Set !== 'undefined' && isNative(Set)) {
+ // use native Set when available.
+ _Set = Set
+} else {
+ // a non-standard Set polyfill that only works with primitive keys.
+ _Set = class Set implements SimpleSet {
+ set: Object;
+ constructor () {
+ this.set = Object.create(null)
+ }
+ has (key: string | number) {
+ return this.set[key] === true
+ }
+ add (key: string | number) {
+ this.set[key] = true
+ }
+ clear () {
+ this.set = Object.create(null)
+ }
+ }
+}
+
+interface SimpleSet {
+ has(key: string | number): boolean;
+ add(key: string | number): mixed;
+ clear(): void;
+}
+
+export { _Set }
+export type { SimpleSet }
diff --git a/node_modules/vue/src/core/util/error.js b/node_modules/vue/src/core/util/error.js
new file mode 100644
index 00000000..b7d05a6d
--- /dev/null
+++ b/node_modules/vue/src/core/util/error.js
@@ -0,0 +1,48 @@
+/* @flow */
+
+import config from '../config'
+import { warn } from './debug'
+import { inBrowser, inWeex } from './env'
+
+export function handleError (err: Error, vm: any, info: string) {
+ if (vm) {
+ let cur = vm
+ while ((cur = cur.$parent)) {
+ const hooks = cur.$options.errorCaptured
+ if (hooks) {
+ for (let i = 0; i < hooks.length; i++) {
+ try {
+ const capture = hooks[i].call(cur, err, vm, info) === false
+ if (capture) return
+ } catch (e) {
+ globalHandleError(e, cur, 'errorCaptured hook')
+ }
+ }
+ }
+ }
+ }
+ globalHandleError(err, vm, info)
+}
+
+function globalHandleError (err, vm, info) {
+ if (config.errorHandler) {
+ try {
+ return config.errorHandler.call(null, err, vm, info)
+ } catch (e) {
+ logError(e, null, 'config.errorHandler')
+ }
+ }
+ logError(err, vm, info)
+}
+
+function logError (err, vm, info) {
+ if (process.env.NODE_ENV !== 'production') {
+ warn(`Error in ${info}: "${err.toString()}"`, vm)
+ }
+ /* istanbul ignore else */
+ if ((inBrowser || inWeex) && typeof console !== 'undefined') {
+ console.error(err)
+ } else {
+ throw err
+ }
+}
diff --git a/node_modules/vue/src/core/util/index.js b/node_modules/vue/src/core/util/index.js
new file mode 100644
index 00000000..115d77cd
--- /dev/null
+++ b/node_modules/vue/src/core/util/index.js
@@ -0,0 +1,11 @@
+/* @flow */
+
+export * from 'shared/util'
+export * from './lang'
+export * from './env'
+export * from './options'
+export * from './debug'
+export * from './props'
+export * from './error'
+export * from './next-tick'
+export { defineReactive } from '../observer/index'
diff --git a/node_modules/vue/src/core/util/lang.js b/node_modules/vue/src/core/util/lang.js
new file mode 100644
index 00000000..96b8219a
--- /dev/null
+++ b/node_modules/vue/src/core/util/lang.js
@@ -0,0 +1,39 @@
+/* @flow */
+
+/**
+ * Check if a string starts with $ or _
+ */
+export function isReserved (str: string): boolean {
+ const c = (str + '').charCodeAt(0)
+ return c === 0x24 || c === 0x5F
+}
+
+/**
+ * Define a property.
+ */
+export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
+ Object.defineProperty(obj, key, {
+ value: val,
+ enumerable: !!enumerable,
+ writable: true,
+ configurable: true
+ })
+}
+
+/**
+ * Parse simple path.
+ */
+const bailRE = /[^\w.$]/
+export function parsePath (path: string): any {
+ if (bailRE.test(path)) {
+ return
+ }
+ const segments = path.split('.')
+ return function (obj) {
+ for (let i = 0; i < segments.length; i++) {
+ if (!obj) return
+ obj = obj[segments[i]]
+ }
+ return obj
+ }
+}
diff --git a/node_modules/vue/src/core/util/next-tick.js b/node_modules/vue/src/core/util/next-tick.js
new file mode 100644
index 00000000..07a9e841
--- /dev/null
+++ b/node_modules/vue/src/core/util/next-tick.js
@@ -0,0 +1,117 @@
+/* @flow */
+/* globals MessageChannel */
+
+import { noop } from 'shared/util'
+import { handleError } from './error'
+import { isIOS, isNative } from './env'
+
+const callbacks = []
+let pending = false
+
+function flushCallbacks () {
+ pending = false
+ const copies = callbacks.slice(0)
+ callbacks.length = 0
+ for (let i = 0; i < copies.length; i++) {
+ copies[i]()
+ }
+}
+
+// Here we have async deferring wrappers using both microtasks and (macro) tasks.
+// In < 2.4 we used microtasks everywhere, but there are some scenarios where
+// microtasks have too high a priority and fire in between supposedly
+// sequential events (e.g. #4521, #6690) or even between bubbling of the same
+// event (#6566). However, using (macro) tasks everywhere also has subtle problems
+// when state is changed right before repaint (e.g. #6813, out-in transitions).
+// Here we use microtask by default, but expose a way to force (macro) task when
+// needed (e.g. in event handlers attached by v-on).
+let microTimerFunc
+let macroTimerFunc
+let useMacroTask = false
+
+// Determine (macro) task defer implementation.
+// Technically setImmediate should be the ideal choice, but it's only available
+// in IE. The only polyfill that consistently queues the callback after all DOM
+// events triggered in the same loop is by using MessageChannel.
+/* istanbul ignore if */
+if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
+ macroTimerFunc = () => {
+ setImmediate(flushCallbacks)
+ }
+} else if (typeof MessageChannel !== 'undefined' && (
+ isNative(MessageChannel) ||
+ // PhantomJS
+ MessageChannel.toString() === '[object MessageChannelConstructor]'
+)) {
+ const channel = new MessageChannel()
+ const port = channel.port2
+ channel.port1.onmessage = flushCallbacks
+ macroTimerFunc = () => {
+ port.postMessage(1)
+ }
+} else {
+ /* istanbul ignore next */
+ macroTimerFunc = () => {
+ setTimeout(flushCallbacks, 0)
+ }
+}
+
+// Determine microtask defer implementation.
+/* istanbul ignore next, $flow-disable-line */
+if (typeof Promise !== 'undefined' && isNative(Promise)) {
+ const p = Promise.resolve()
+ microTimerFunc = () => {
+ p.then(flushCallbacks)
+ // in problematic UIWebViews, Promise.then doesn't completely break, but
+ // it can get stuck in a weird state where callbacks are pushed into the
+ // microtask queue but the queue isn't being flushed, until the browser
+ // needs to do some other work, e.g. handle a timer. Therefore we can
+ // "force" the microtask queue to be flushed by adding an empty timer.
+ if (isIOS) setTimeout(noop)
+ }
+} else {
+ // fallback to macro
+ microTimerFunc = macroTimerFunc
+}
+
+/**
+ * Wrap a function so that if any code inside triggers state change,
+ * the changes are queued using a (macro) task instead of a microtask.
+ */
+export function withMacroTask (fn: Function): Function {
+ return fn._withTask || (fn._withTask = function () {
+ useMacroTask = true
+ const res = fn.apply(null, arguments)
+ useMacroTask = false
+ return res
+ })
+}
+
+export function nextTick (cb?: Function, ctx?: Object) {
+ let _resolve
+ callbacks.push(() => {
+ if (cb) {
+ try {
+ cb.call(ctx)
+ } catch (e) {
+ handleError(e, ctx, 'nextTick')
+ }
+ } else if (_resolve) {
+ _resolve(ctx)
+ }
+ })
+ if (!pending) {
+ pending = true
+ if (useMacroTask) {
+ macroTimerFunc()
+ } else {
+ microTimerFunc()
+ }
+ }
+ // $flow-disable-line
+ if (!cb && typeof Promise !== 'undefined') {
+ return new Promise(resolve => {
+ _resolve = resolve
+ })
+ }
+}
diff --git a/node_modules/vue/src/core/util/options.js b/node_modules/vue/src/core/util/options.js
new file mode 100644
index 00000000..5f0d10d3
--- /dev/null
+++ b/node_modules/vue/src/core/util/options.js
@@ -0,0 +1,438 @@
+/* @flow */
+
+import config from '../config'
+import { warn } from './debug'
+import { nativeWatch } from './env'
+import { set } from '../observer/index'
+
+import {
+ ASSET_TYPES,
+ LIFECYCLE_HOOKS
+} from 'shared/constants'
+
+import {
+ extend,
+ hasOwn,
+ camelize,
+ toRawType,
+ capitalize,
+ isBuiltInTag,
+ isPlainObject
+} from 'shared/util'
+
+/**
+ * Option overwriting strategies are functions that handle
+ * how to merge a parent option value and a child option
+ * value into the final value.
+ */
+const strats = config.optionMergeStrategies
+
+/**
+ * Options with restrictions
+ */
+if (process.env.NODE_ENV !== 'production') {
+ strats.el = strats.propsData = function (parent, child, vm, key) {
+ if (!vm) {
+ warn(
+ `option "${key}" can only be used during instance ` +
+ 'creation with the `new` keyword.'
+ )
+ }
+ return defaultStrat(parent, child)
+ }
+}
+
+/**
+ * Helper that recursively merges two data objects together.
+ */
+function mergeData (to: Object, from: ?Object): Object {
+ if (!from) return to
+ let key, toVal, fromVal
+ const keys = Object.keys(from)
+ for (let i = 0; i < keys.length; i++) {
+ key = keys[i]
+ toVal = to[key]
+ fromVal = from[key]
+ if (!hasOwn(to, key)) {
+ set(to, key, fromVal)
+ } else if (isPlainObject(toVal) && isPlainObject(fromVal)) {
+ mergeData(toVal, fromVal)
+ }
+ }
+ return to
+}
+
+/**
+ * Data
+ */
+export function mergeDataOrFn (
+ parentVal: any,
+ childVal: any,
+ vm?: Component
+): ?Function {
+ if (!vm) {
+ // in a Vue.extend merge, both should be functions
+ if (!childVal) {
+ return parentVal
+ }
+ if (!parentVal) {
+ return childVal
+ }
+ // when parentVal & childVal are both present,
+ // we need to return a function that returns the
+ // merged result of both functions... no need to
+ // check if parentVal is a function here because
+ // it has to be a function to pass previous merges.
+ return function mergedDataFn () {
+ return mergeData(
+ typeof childVal === 'function' ? childVal.call(this, this) : childVal,
+ typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal
+ )
+ }
+ } else {
+ return function mergedInstanceDataFn () {
+ // instance merge
+ const instanceData = typeof childVal === 'function'
+ ? childVal.call(vm, vm)
+ : childVal
+ const defaultData = typeof parentVal === 'function'
+ ? parentVal.call(vm, vm)
+ : parentVal
+ if (instanceData) {
+ return mergeData(instanceData, defaultData)
+ } else {
+ return defaultData
+ }
+ }
+ }
+}
+
+strats.data = function (
+ parentVal: any,
+ childVal: any,
+ vm?: Component
+): ?Function {
+ if (!vm) {
+ if (childVal && typeof childVal !== 'function') {
+ process.env.NODE_ENV !== 'production' && warn(
+ 'The "data" option should be a function ' +
+ 'that returns a per-instance value in component ' +
+ 'definitions.',
+ vm
+ )
+
+ return parentVal
+ }
+ return mergeDataOrFn(parentVal, childVal)
+ }
+
+ return mergeDataOrFn(parentVal, childVal, vm)
+}
+
+/**
+ * Hooks and props are merged as arrays.
+ */
+function mergeHook (
+ parentVal: ?Array<Function>,
+ childVal: ?Function | ?Array<Function>
+): ?Array<Function> {
+ return childVal
+ ? parentVal
+ ? parentVal.concat(childVal)
+ : Array.isArray(childVal)
+ ? childVal
+ : [childVal]
+ : parentVal
+}
+
+LIFECYCLE_HOOKS.forEach(hook => {
+ strats[hook] = mergeHook
+})
+
+/**
+ * Assets
+ *
+ * When a vm is present (instance creation), we need to do
+ * a three-way merge between constructor options, instance
+ * options and parent options.
+ */
+function mergeAssets (
+ parentVal: ?Object,
+ childVal: ?Object,
+ vm?: Component,
+ key: string
+): Object {
+ const res = Object.create(parentVal || null)
+ if (childVal) {
+ process.env.NODE_ENV !== 'production' && assertObjectType(key, childVal, vm)
+ return extend(res, childVal)
+ } else {
+ return res
+ }
+}
+
+ASSET_TYPES.forEach(function (type) {
+ strats[type + 's'] = mergeAssets
+})
+
+/**
+ * Watchers.
+ *
+ * Watchers hashes should not overwrite one
+ * another, so we merge them as arrays.
+ */
+strats.watch = function (
+ parentVal: ?Object,
+ childVal: ?Object,
+ vm?: Component,
+ key: string
+): ?Object {
+ // work around Firefox's Object.prototype.watch...
+ if (parentVal === nativeWatch) parentVal = undefined
+ if (childVal === nativeWatch) childVal = undefined
+ /* istanbul ignore if */
+ if (!childVal) return Object.create(parentVal || null)
+ if (process.env.NODE_ENV !== 'production') {
+ assertObjectType(key, childVal, vm)
+ }
+ if (!parentVal) return childVal
+ const ret = {}
+ extend(ret, parentVal)
+ for (const key in childVal) {
+ let parent = ret[key]
+ const child = childVal[key]
+ if (parent && !Array.isArray(parent)) {
+ parent = [parent]
+ }
+ ret[key] = parent
+ ? parent.concat(child)
+ : Array.isArray(child) ? child : [child]
+ }
+ return ret
+}
+
+/**
+ * Other object hashes.
+ */
+strats.props =
+strats.methods =
+strats.inject =
+strats.computed = function (
+ parentVal: ?Object,
+ childVal: ?Object,
+ vm?: Component,
+ key: string
+): ?Object {
+ if (childVal && process.env.NODE_ENV !== 'production') {
+ assertObjectType(key, childVal, vm)
+ }
+ if (!parentVal) return childVal
+ const ret = Object.create(null)
+ extend(ret, parentVal)
+ if (childVal) extend(ret, childVal)
+ return ret
+}
+strats.provide = mergeDataOrFn
+
+/**
+ * Default strategy.
+ */
+const defaultStrat = function (parentVal: any, childVal: any): any {
+ return childVal === undefined
+ ? parentVal
+ : childVal
+}
+
+/**
+ * Validate component names
+ */
+function checkComponents (options: Object) {
+ for (const key in options.components) {
+ validateComponentName(key)
+ }
+}
+
+export function validateComponentName (name: string) {
+ if (!/^[a-zA-Z][\w-]*$/.test(name)) {
+ warn(
+ 'Invalid component name: "' + name + '". Component names ' +
+ 'can only contain alphanumeric characters and the hyphen, ' +
+ 'and must start with a letter.'
+ )
+ }
+ if (isBuiltInTag(name) || config.isReservedTag(name)) {
+ warn(
+ 'Do not use built-in or reserved HTML elements as component ' +
+ 'id: ' + name
+ )
+ }
+}
+
+/**
+ * Ensure all props option syntax are normalized into the
+ * Object-based format.
+ */
+function normalizeProps (options: Object, vm: ?Component) {
+ const props = options.props
+ if (!props) return
+ const res = {}
+ let i, val, name
+ if (Array.isArray(props)) {
+ i = props.length
+ while (i--) {
+ val = props[i]
+ if (typeof val === 'string') {
+ name = camelize(val)
+ res[name] = { type: null }
+ } else if (process.env.NODE_ENV !== 'production') {
+ warn('props must be strings when using array syntax.')
+ }
+ }
+ } else if (isPlainObject(props)) {
+ for (const key in props) {
+ val = props[key]
+ name = camelize(key)
+ res[name] = isPlainObject(val)
+ ? val
+ : { type: val }
+ }
+ } else if (process.env.NODE_ENV !== 'production') {
+ warn(
+ `Invalid value for option "props": expected an Array or an Object, ` +
+ `but got ${toRawType(props)}.`,
+ vm
+ )
+ }
+ options.props = res
+}
+
+/**
+ * Normalize all injections into Object-based format
+ */
+function normalizeInject (options: Object, vm: ?Component) {
+ const inject = options.inject
+ if (!inject) return
+ const normalized = options.inject = {}
+ if (Array.isArray(inject)) {
+ for (let i = 0; i < inject.length; i++) {
+ normalized[inject[i]] = { from: inject[i] }
+ }
+ } else if (isPlainObject(inject)) {
+ for (const key in inject) {
+ const val = inject[key]
+ normalized[key] = isPlainObject(val)
+ ? extend({ from: key }, val)
+ : { from: val }
+ }
+ } else if (process.env.NODE_ENV !== 'production') {
+ warn(
+ `Invalid value for option "inject": expected an Array or an Object, ` +
+ `but got ${toRawType(inject)}.`,
+ vm
+ )
+ }
+}
+
+/**
+ * Normalize raw function directives into object format.
+ */
+function normalizeDirectives (options: Object) {
+ const dirs = options.directives
+ if (dirs) {
+ for (const key in dirs) {
+ const def = dirs[key]
+ if (typeof def === 'function') {
+ dirs[key] = { bind: def, update: def }
+ }
+ }
+ }
+}
+
+function assertObjectType (name: string, value: any, vm: ?Component) {
+ if (!isPlainObject(value)) {
+ warn(
+ `Invalid value for option "${name}": expected an Object, ` +
+ `but got ${toRawType(value)}.`,
+ vm
+ )
+ }
+}
+
+/**
+ * Merge two option objects into a new one.
+ * Core utility used in both instantiation and inheritance.
+ */
+export function mergeOptions (
+ parent: Object,
+ child: Object,
+ vm?: Component
+): Object {
+ if (process.env.NODE_ENV !== 'production') {
+ checkComponents(child)
+ }
+
+ if (typeof child === 'function') {
+ child = child.options
+ }
+
+ normalizeProps(child, vm)
+ normalizeInject(child, vm)
+ normalizeDirectives(child)
+ const extendsFrom = child.extends
+ if (extendsFrom) {
+ parent = mergeOptions(parent, extendsFrom, vm)
+ }
+ if (child.mixins) {
+ for (let i = 0, l = child.mixins.length; i < l; i++) {
+ parent = mergeOptions(parent, child.mixins[i], vm)
+ }
+ }
+ const options = {}
+ let key
+ for (key in parent) {
+ mergeField(key)
+ }
+ for (key in child) {
+ if (!hasOwn(parent, key)) {
+ mergeField(key)
+ }
+ }
+ function mergeField (key) {
+ const strat = strats[key] || defaultStrat
+ options[key] = strat(parent[key], child[key], vm, key)
+ }
+ return options
+}
+
+/**
+ * Resolve an asset.
+ * This function is used because child instances need access
+ * to assets defined in its ancestor chain.
+ */
+export function resolveAsset (
+ options: Object,
+ type: string,
+ id: string,
+ warnMissing?: boolean
+): any {
+ /* istanbul ignore if */
+ if (typeof id !== 'string') {
+ return
+ }
+ const assets = options[type]
+ // check local registration variations first
+ if (hasOwn(assets, id)) return assets[id]
+ const camelizedId = camelize(id)
+ if (hasOwn(assets, camelizedId)) return assets[camelizedId]
+ const PascalCaseId = capitalize(camelizedId)
+ if (hasOwn(assets, PascalCaseId)) return assets[PascalCaseId]
+ // fallback to prototype chain
+ const res = assets[id] || assets[camelizedId] || assets[PascalCaseId]
+ if (process.env.NODE_ENV !== 'production' && warnMissing && !res) {
+ warn(
+ 'Failed to resolve ' + type.slice(0, -1) + ': ' + id,
+ options
+ )
+ }
+ return res
+}
diff --git a/node_modules/vue/src/core/util/perf.js b/node_modules/vue/src/core/util/perf.js
new file mode 100644
index 00000000..4a537b2d
--- /dev/null
+++ b/node_modules/vue/src/core/util/perf.js
@@ -0,0 +1,24 @@
+import { inBrowser } from './env'
+
+export let mark
+export let measure
+
+if (process.env.NODE_ENV !== 'production') {
+ const perf = inBrowser && window.performance
+ /* istanbul ignore if */
+ if (
+ perf &&
+ perf.mark &&
+ perf.measure &&
+ perf.clearMarks &&
+ perf.clearMeasures
+ ) {
+ mark = tag => perf.mark(tag)
+ measure = (name, startTag, endTag) => {
+ perf.measure(name, startTag, endTag)
+ perf.clearMarks(startTag)
+ perf.clearMarks(endTag)
+ perf.clearMeasures(name)
+ }
+ }
+}
diff --git a/node_modules/vue/src/core/util/props.js b/node_modules/vue/src/core/util/props.js
new file mode 100644
index 00000000..a92643f9
--- /dev/null
+++ b/node_modules/vue/src/core/util/props.js
@@ -0,0 +1,202 @@
+/* @flow */
+
+import { warn } from './debug'
+import { observe, toggleObserving, shouldObserve } from '../observer/index'
+import {
+ hasOwn,
+ isObject,
+ toRawType,
+ hyphenate,
+ capitalize,
+ isPlainObject
+} from 'shared/util'
+
+type PropOptions = {
+ type: Function | Array<Function> | null,
+ default: any,
+ required: ?boolean,
+ validator: ?Function
+};
+
+export function validateProp (
+ key: string,
+ propOptions: Object,
+ propsData: Object,
+ vm?: Component
+): any {
+ const prop = propOptions[key]
+ const absent = !hasOwn(propsData, key)
+ let value = propsData[key]
+ // boolean casting
+ const booleanIndex = getTypeIndex(Boolean, prop.type)
+ if (booleanIndex > -1) {
+ if (absent && !hasOwn(prop, 'default')) {
+ value = false
+ } else if (value === '' || value === hyphenate(key)) {
+ // only cast empty string / same name to boolean if
+ // boolean has higher priority
+ const stringIndex = getTypeIndex(String, prop.type)
+ if (stringIndex < 0 || booleanIndex < stringIndex) {
+ value = true
+ }
+ }
+ }
+ // check default value
+ if (value === undefined) {
+ value = getPropDefaultValue(vm, prop, key)
+ // since the default value is a fresh copy,
+ // make sure to observe it.
+ const prevShouldObserve = shouldObserve
+ toggleObserving(true)
+ observe(value)
+ toggleObserving(prevShouldObserve)
+ }
+ if (
+ process.env.NODE_ENV !== 'production' &&
+ // skip validation for weex recycle-list child component props
+ !(__WEEX__ && isObject(value) && ('@binding' in value))
+ ) {
+ assertProp(prop, key, value, vm, absent)
+ }
+ return value
+}
+
+/**
+ * Get the default value of a prop.
+ */
+function getPropDefaultValue (vm: ?Component, prop: PropOptions, key: string): any {
+ // no default, return undefined
+ if (!hasOwn(prop, 'default')) {
+ return undefined
+ }
+ const def = prop.default
+ // warn against non-factory defaults for Object & Array
+ if (process.env.NODE_ENV !== 'production' && isObject(def)) {
+ warn(
+ 'Invalid default value for prop "' + key + '": ' +
+ 'Props with type Object/Array must use a factory function ' +
+ 'to return the default value.',
+ vm
+ )
+ }
+ // the raw prop value was also undefined from previous render,
+ // return previous default value to avoid unnecessary watcher trigger
+ if (vm && vm.$options.propsData &&
+ vm.$options.propsData[key] === undefined &&
+ vm._props[key] !== undefined
+ ) {
+ return vm._props[key]
+ }
+ // call factory function for non-Function types
+ // a value is Function if its prototype is function even across different execution context
+ return typeof def === 'function' && getType(prop.type) !== 'Function'
+ ? def.call(vm)
+ : def
+}
+
+/**
+ * Assert whether a prop is valid.
+ */
+function assertProp (
+ prop: PropOptions,
+ name: string,
+ value: any,
+ vm: ?Component,
+ absent: boolean
+) {
+ if (prop.required && absent) {
+ warn(
+ 'Missing required prop: "' + name + '"',
+ vm
+ )
+ return
+ }
+ if (value == null && !prop.required) {
+ return
+ }
+ let type = prop.type
+ let valid = !type || type === true
+ const expectedTypes = []
+ if (type) {
+ if (!Array.isArray(type)) {
+ type = [type]
+ }
+ for (let i = 0; i < type.length && !valid; i++) {
+ const assertedType = assertType(value, type[i])
+ expectedTypes.push(assertedType.expectedType || '')
+ valid = assertedType.valid
+ }
+ }
+ if (!valid) {
+ warn(
+ `Invalid prop: type check failed for prop "${name}".` +
+ ` Expected ${expectedTypes.map(capitalize).join(', ')}` +
+ `, got ${toRawType(value)}.`,
+ vm
+ )
+ return
+ }
+ const validator = prop.validator
+ if (validator) {
+ if (!validator(value)) {
+ warn(
+ 'Invalid prop: custom validator check failed for prop "' + name + '".',
+ vm
+ )
+ }
+ }
+}
+
+const simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/
+
+function assertType (value: any, type: Function): {
+ valid: boolean;
+ expectedType: string;
+} {
+ let valid
+ const expectedType = getType(type)
+ if (simpleCheckRE.test(expectedType)) {
+ const t = typeof value
+ valid = t === expectedType.toLowerCase()
+ // for primitive wrapper objects
+ if (!valid && t === 'object') {
+ valid = value instanceof type
+ }
+ } else if (expectedType === 'Object') {
+ valid = isPlainObject(value)
+ } else if (expectedType === 'Array') {
+ valid = Array.isArray(value)
+ } else {
+ valid = value instanceof type
+ }
+ return {
+ valid,
+ expectedType
+ }
+}
+
+/**
+ * Use function string name to check built-in types,
+ * because a simple equality check will fail when running
+ * across different vms / iframes.
+ */
+function getType (fn) {
+ const match = fn && fn.toString().match(/^\s*function (\w+)/)
+ return match ? match[1] : ''
+}
+
+function isSameType (a, b) {
+ return getType(a) === getType(b)
+}
+
+function getTypeIndex (type, expectedTypes): number {
+ if (!Array.isArray(expectedTypes)) {
+ return isSameType(expectedTypes, type) ? 0 : -1
+ }
+ for (let i = 0, len = expectedTypes.length; i < len; i++) {
+ if (isSameType(expectedTypes[i], type)) {
+ return i
+ }
+ }
+ return -1
+}
diff --git a/node_modules/vue/src/core/vdom/create-component.js b/node_modules/vue/src/core/vdom/create-component.js
new file mode 100644
index 00000000..89578224
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/create-component.js
@@ -0,0 +1,257 @@
+/* @flow */
+
+import VNode from './vnode'
+import { resolveConstructorOptions } from 'core/instance/init'
+import { queueActivatedComponent } from 'core/observer/scheduler'
+import { createFunctionalComponent } from './create-functional-component'
+
+import {
+ warn,
+ isDef,
+ isUndef,
+ isTrue,
+ isObject
+} from '../util/index'
+
+import {
+ resolveAsyncComponent,
+ createAsyncPlaceholder,
+ extractPropsFromVNodeData
+} from './helpers/index'
+
+import {
+ callHook,
+ activeInstance,
+ updateChildComponent,
+ activateChildComponent,
+ deactivateChildComponent
+} from '../instance/lifecycle'
+
+import {
+ isRecyclableComponent,
+ renderRecyclableComponentTemplate
+} from 'weex/runtime/recycle-list/render-component-template'
+
+// inline hooks to be invoked on component VNodes during patch
+const componentVNodeHooks = {
+ init (
+ vnode: VNodeWithData,
+ hydrating: boolean,
+ parentElm: ?Node,
+ refElm: ?Node
+ ): ?boolean {
+ if (
+ vnode.componentInstance &&
+ !vnode.componentInstance._isDestroyed &&
+ vnode.data.keepAlive
+ ) {
+ // kept-alive components, treat as a patch
+ const mountedNode: any = vnode // work around flow
+ componentVNodeHooks.prepatch(mountedNode, mountedNode)
+ } else {
+ const child = vnode.componentInstance = createComponentInstanceForVnode(
+ vnode,
+ activeInstance,
+ parentElm,
+ refElm
+ )
+ child.$mount(hydrating ? vnode.elm : undefined, hydrating)
+ }
+ },
+
+ prepatch (oldVnode: MountedComponentVNode, vnode: MountedComponentVNode) {
+ const options = vnode.componentOptions
+ const child = vnode.componentInstance = oldVnode.componentInstance
+ updateChildComponent(
+ child,
+ options.propsData, // updated props
+ options.listeners, // updated listeners
+ vnode, // new parent vnode
+ options.children // new children
+ )
+ },
+
+ insert (vnode: MountedComponentVNode) {
+ const { context, componentInstance } = vnode
+ if (!componentInstance._isMounted) {
+ componentInstance._isMounted = true
+ callHook(componentInstance, 'mounted')
+ }
+ if (vnode.data.keepAlive) {
+ if (context._isMounted) {
+ // vue-router#1212
+ // During updates, a kept-alive component's child components may
+ // change, so directly walking the tree here may call activated hooks
+ // on incorrect children. Instead we push them into a queue which will
+ // be processed after the whole patch process ended.
+ queueActivatedComponent(componentInstance)
+ } else {
+ activateChildComponent(componentInstance, true /* direct */)
+ }
+ }
+ },
+
+ destroy (vnode: MountedComponentVNode) {
+ const { componentInstance } = vnode
+ if (!componentInstance._isDestroyed) {
+ if (!vnode.data.keepAlive) {
+ componentInstance.$destroy()
+ } else {
+ deactivateChildComponent(componentInstance, true /* direct */)
+ }
+ }
+ }
+}
+
+const hooksToMerge = Object.keys(componentVNodeHooks)
+
+export function createComponent (
+ Ctor: Class<Component> | Function | Object | void,
+ data: ?VNodeData,
+ context: Component,
+ children: ?Array<VNode>,
+ tag?: string
+): VNode | Array<VNode> | void {
+ if (isUndef(Ctor)) {
+ return
+ }
+
+ const baseCtor = context.$options._base
+
+ // plain options object: turn it into a constructor
+ if (isObject(Ctor)) {
+ Ctor = baseCtor.extend(Ctor)
+ }
+
+ // if at this stage it's not a constructor or an async component factory,
+ // reject.
+ if (typeof Ctor !== 'function') {
+ if (process.env.NODE_ENV !== 'production') {
+ warn(`Invalid Component definition: ${String(Ctor)}`, context)
+ }
+ return
+ }
+
+ // async component
+ let asyncFactory
+ if (isUndef(Ctor.cid)) {
+ asyncFactory = Ctor
+ Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context)
+ if (Ctor === undefined) {
+ // return a placeholder node for async component, which is rendered
+ // as a comment node but preserves all the raw information for the node.
+ // the information will be used for async server-rendering and hydration.
+ return createAsyncPlaceholder(
+ asyncFactory,
+ data,
+ context,
+ children,
+ tag
+ )
+ }
+ }
+
+ data = data || {}
+
+ // resolve constructor options in case global mixins are applied after
+ // component constructor creation
+ resolveConstructorOptions(Ctor)
+
+ // transform component v-model data into props & events
+ if (isDef(data.model)) {
+ transformModel(Ctor.options, data)
+ }
+
+ // extract props
+ const propsData = extractPropsFromVNodeData(data, Ctor, tag)
+
+ // functional component
+ if (isTrue(Ctor.options.functional)) {
+ return createFunctionalComponent(Ctor, propsData, data, context, children)
+ }
+
+ // extract listeners, since these needs to be treated as
+ // child component listeners instead of DOM listeners
+ const listeners = data.on
+ // replace with listeners with .native modifier
+ // so it gets processed during parent component patch.
+ data.on = data.nativeOn
+
+ if (isTrue(Ctor.options.abstract)) {
+ // abstract components do not keep anything
+ // other than props & listeners & slot
+
+ // work around flow
+ const slot = data.slot
+ data = {}
+ if (slot) {
+ data.slot = slot
+ }
+ }
+
+ // install component management hooks onto the placeholder node
+ installComponentHooks(data)
+
+ // return a placeholder vnode
+ const name = Ctor.options.name || tag
+ const vnode = new VNode(
+ `vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
+ data, undefined, undefined, undefined, context,
+ { Ctor, propsData, listeners, tag, children },
+ asyncFactory
+ )
+
+ // Weex specific: invoke recycle-list optimized @render function for
+ // extracting cell-slot template.
+ // https://github.com/Hanks10100/weex-native-directive/tree/master/component
+ /* istanbul ignore if */
+ if (__WEEX__ && isRecyclableComponent(vnode)) {
+ return renderRecyclableComponentTemplate(vnode)
+ }
+
+ return vnode
+}
+
+export function createComponentInstanceForVnode (
+ vnode: any, // we know it's MountedComponentVNode but flow doesn't
+ parent: any, // activeInstance in lifecycle state
+ parentElm?: ?Node,
+ refElm?: ?Node
+): Component {
+ const options: InternalComponentOptions = {
+ _isComponent: true,
+ parent,
+ _parentVnode: vnode,
+ _parentElm: parentElm || null,
+ _refElm: refElm || null
+ }
+ // check inline-template render functions
+ const inlineTemplate = vnode.data.inlineTemplate
+ if (isDef(inlineTemplate)) {
+ options.render = inlineTemplate.render
+ options.staticRenderFns = inlineTemplate.staticRenderFns
+ }
+ return new vnode.componentOptions.Ctor(options)
+}
+
+function installComponentHooks (data: VNodeData) {
+ const hooks = data.hook || (data.hook = {})
+ for (let i = 0; i < hooksToMerge.length; i++) {
+ const key = hooksToMerge[i]
+ hooks[key] = componentVNodeHooks[key]
+ }
+}
+
+// transform component v-model info (value and callback) into
+// prop and event handler respectively.
+function transformModel (options, data: any) {
+ const prop = (options.model && options.model.prop) || 'value'
+ const event = (options.model && options.model.event) || 'input'
+ ;(data.props || (data.props = {}))[prop] = data.model.value
+ const on = data.on || (data.on = {})
+ if (isDef(on[event])) {
+ on[event] = [data.model.callback].concat(on[event])
+ } else {
+ on[event] = data.model.callback
+ }
+}
diff --git a/node_modules/vue/src/core/vdom/create-element.js b/node_modules/vue/src/core/vdom/create-element.js
new file mode 100644
index 00000000..c5cde2c6
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/create-element.js
@@ -0,0 +1,160 @@
+/* @flow */
+
+import config from '../config'
+import VNode, { createEmptyVNode } from './vnode'
+import { createComponent } from './create-component'
+import { traverse } from '../observer/traverse'
+
+import {
+ warn,
+ isDef,
+ isUndef,
+ isTrue,
+ isObject,
+ isPrimitive,
+ resolveAsset
+} from '../util/index'
+
+import {
+ normalizeChildren,
+ simpleNormalizeChildren
+} from './helpers/index'
+
+const SIMPLE_NORMALIZE = 1
+const ALWAYS_NORMALIZE = 2
+
+// wrapper function for providing a more flexible interface
+// without getting yelled at by flow
+export function createElement (
+ context: Component,
+ tag: any,
+ data: any,
+ children: any,
+ normalizationType: any,
+ alwaysNormalize: boolean
+): VNode | Array<VNode> {
+ if (Array.isArray(data) || isPrimitive(data)) {
+ normalizationType = children
+ children = data
+ data = undefined
+ }
+ if (isTrue(alwaysNormalize)) {
+ normalizationType = ALWAYS_NORMALIZE
+ }
+ return _createElement(context, tag, data, children, normalizationType)
+}
+
+export function _createElement (
+ context: Component,
+ tag?: string | Class<Component> | Function | Object,
+ data?: VNodeData,
+ children?: any,
+ normalizationType?: number
+): VNode | Array<VNode> {
+ if (isDef(data) && isDef((data: any).__ob__)) {
+ process.env.NODE_ENV !== 'production' && warn(
+ `Avoid using observed data object as vnode data: ${JSON.stringify(data)}\n` +
+ 'Always create fresh vnode data objects in each render!',
+ context
+ )
+ return createEmptyVNode()
+ }
+ // object syntax in v-bind
+ if (isDef(data) && isDef(data.is)) {
+ tag = data.is
+ }
+ if (!tag) {
+ // in case of component :is set to falsy value
+ return createEmptyVNode()
+ }
+ // warn against non-primitive key
+ if (process.env.NODE_ENV !== 'production' &&
+ isDef(data) && isDef(data.key) && !isPrimitive(data.key)
+ ) {
+ if (!__WEEX__ || !('@binding' in data.key)) {
+ warn(
+ 'Avoid using non-primitive value as key, ' +
+ 'use string/number value instead.',
+ context
+ )
+ }
+ }
+ // support single function children as default scoped slot
+ if (Array.isArray(children) &&
+ typeof children[0] === 'function'
+ ) {
+ data = data || {}
+ data.scopedSlots = { default: children[0] }
+ children.length = 0
+ }
+ if (normalizationType === ALWAYS_NORMALIZE) {
+ children = normalizeChildren(children)
+ } else if (normalizationType === SIMPLE_NORMALIZE) {
+ children = simpleNormalizeChildren(children)
+ }
+ let vnode, ns
+ if (typeof tag === 'string') {
+ let Ctor
+ ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag)
+ if (config.isReservedTag(tag)) {
+ // platform built-in elements
+ vnode = new VNode(
+ config.parsePlatformTagName(tag), data, children,
+ undefined, undefined, context
+ )
+ } else if (isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {
+ // component
+ vnode = createComponent(Ctor, data, context, children, tag)
+ } else {
+ // unknown or unlisted namespaced elements
+ // check at runtime because it may get assigned a namespace when its
+ // parent normalizes children
+ vnode = new VNode(
+ tag, data, children,
+ undefined, undefined, context
+ )
+ }
+ } else {
+ // direct component options / constructor
+ vnode = createComponent(tag, data, context, children)
+ }
+ if (Array.isArray(vnode)) {
+ return vnode
+ } else if (isDef(vnode)) {
+ if (isDef(ns)) applyNS(vnode, ns)
+ if (isDef(data)) registerDeepBindings(data)
+ return vnode
+ } else {
+ return createEmptyVNode()
+ }
+}
+
+function applyNS (vnode, ns, force) {
+ vnode.ns = ns
+ if (vnode.tag === 'foreignObject') {
+ // use default namespace inside foreignObject
+ ns = undefined
+ force = true
+ }
+ if (isDef(vnode.children)) {
+ for (let i = 0, l = vnode.children.length; i < l; i++) {
+ const child = vnode.children[i]
+ if (isDef(child.tag) && (
+ isUndef(child.ns) || (isTrue(force) && child.tag !== 'svg'))) {
+ applyNS(child, ns, force)
+ }
+ }
+ }
+}
+
+// ref #5318
+// necessary to ensure parent re-render when deep bindings like :style and
+// :class are used on slot nodes
+function registerDeepBindings (data) {
+ if (isObject(data.style)) {
+ traverse(data.style)
+ }
+ if (isObject(data.class)) {
+ traverse(data.class)
+ }
+}
diff --git a/node_modules/vue/src/core/vdom/create-functional-component.js b/node_modules/vue/src/core/vdom/create-functional-component.js
new file mode 100644
index 00000000..efed801d
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/create-functional-component.js
@@ -0,0 +1,136 @@
+/* @flow */
+
+import VNode, { cloneVNode } from './vnode'
+import { createElement } from './create-element'
+import { resolveInject } from '../instance/inject'
+import { normalizeChildren } from '../vdom/helpers/normalize-children'
+import { resolveSlots } from '../instance/render-helpers/resolve-slots'
+import { installRenderHelpers } from '../instance/render-helpers/index'
+
+import {
+ isDef,
+ isTrue,
+ hasOwn,
+ camelize,
+ emptyObject,
+ validateProp
+} from '../util/index'
+
+export function FunctionalRenderContext (
+ data: VNodeData,
+ props: Object,
+ children: ?Array<VNode>,
+ parent: Component,
+ Ctor: Class<Component>
+) {
+ const options = Ctor.options
+ // ensure the createElement function in functional components
+ // gets a unique context - this is necessary for correct named slot check
+ let contextVm
+ if (hasOwn(parent, '_uid')) {
+ contextVm = Object.create(parent)
+ // $flow-disable-line
+ contextVm._original = parent
+ } else {
+ // the context vm passed in is a functional context as well.
+ // in this case we want to make sure we are able to get a hold to the
+ // real context instance.
+ contextVm = parent
+ // $flow-disable-line
+ parent = parent._original
+ }
+ const isCompiled = isTrue(options._compiled)
+ const needNormalization = !isCompiled
+
+ this.data = data
+ this.props = props
+ this.children = children
+ this.parent = parent
+ this.listeners = data.on || emptyObject
+ this.injections = resolveInject(options.inject, parent)
+ this.slots = () => resolveSlots(children, parent)
+
+ // support for compiled functional template
+ if (isCompiled) {
+ // exposing $options for renderStatic()
+ this.$options = options
+ // pre-resolve slots for renderSlot()
+ this.$slots = this.slots()
+ this.$scopedSlots = data.scopedSlots || emptyObject
+ }
+
+ if (options._scopeId) {
+ this._c = (a, b, c, d) => {
+ const vnode = createElement(contextVm, a, b, c, d, needNormalization)
+ if (vnode && !Array.isArray(vnode)) {
+ vnode.fnScopeId = options._scopeId
+ vnode.fnContext = parent
+ }
+ return vnode
+ }
+ } else {
+ this._c = (a, b, c, d) => createElement(contextVm, a, b, c, d, needNormalization)
+ }
+}
+
+installRenderHelpers(FunctionalRenderContext.prototype)
+
+export function createFunctionalComponent (
+ Ctor: Class<Component>,
+ propsData: ?Object,
+ data: VNodeData,
+ contextVm: Component,
+ children: ?Array<VNode>
+): VNode | Array<VNode> | void {
+ const options = Ctor.options
+ const props = {}
+ const propOptions = options.props
+ if (isDef(propOptions)) {
+ for (const key in propOptions) {
+ props[key] = validateProp(key, propOptions, propsData || emptyObject)
+ }
+ } else {
+ if (isDef(data.attrs)) mergeProps(props, data.attrs)
+ if (isDef(data.props)) mergeProps(props, data.props)
+ }
+
+ const renderContext = new FunctionalRenderContext(
+ data,
+ props,
+ children,
+ contextVm,
+ Ctor
+ )
+
+ const vnode = options.render.call(null, renderContext._c, renderContext)
+
+ if (vnode instanceof VNode) {
+ return cloneAndMarkFunctionalResult(vnode, data, renderContext.parent, options)
+ } else if (Array.isArray(vnode)) {
+ const vnodes = normalizeChildren(vnode) || []
+ const res = new Array(vnodes.length)
+ for (let i = 0; i < vnodes.length; i++) {
+ res[i] = cloneAndMarkFunctionalResult(vnodes[i], data, renderContext.parent, options)
+ }
+ return res
+ }
+}
+
+function cloneAndMarkFunctionalResult (vnode, data, contextVm, options) {
+ // #7817 clone node before setting fnContext, otherwise if the node is reused
+ // (e.g. it was from a cached normal slot) the fnContext causes named slots
+ // that should not be matched to match.
+ const clone = cloneVNode(vnode)
+ clone.fnContext = contextVm
+ clone.fnOptions = options
+ if (data.slot) {
+ (clone.data || (clone.data = {})).slot = data.slot
+ }
+ return clone
+}
+
+function mergeProps (to, from) {
+ for (const key in from) {
+ to[camelize(key)] = from[key]
+ }
+}
diff --git a/node_modules/vue/src/core/vdom/helpers/extract-props.js b/node_modules/vue/src/core/vdom/helpers/extract-props.js
new file mode 100644
index 00000000..f2a41661
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/helpers/extract-props.js
@@ -0,0 +1,75 @@
+/* @flow */
+
+import {
+ tip,
+ hasOwn,
+ isDef,
+ isUndef,
+ hyphenate,
+ formatComponentName
+} from 'core/util/index'
+
+export function extractPropsFromVNodeData (
+ data: VNodeData,
+ Ctor: Class<Component>,
+ tag?: string
+): ?Object {
+ // we are only extracting raw values here.
+ // validation and default values are handled in the child
+ // component itself.
+ const propOptions = Ctor.options.props
+ if (isUndef(propOptions)) {
+ return
+ }
+ const res = {}
+ const { attrs, props } = data
+ if (isDef(attrs) || isDef(props)) {
+ for (const key in propOptions) {
+ const altKey = hyphenate(key)
+ if (process.env.NODE_ENV !== 'production') {
+ const keyInLowerCase = key.toLowerCase()
+ if (
+ key !== keyInLowerCase &&
+ attrs && hasOwn(attrs, keyInLowerCase)
+ ) {
+ tip(
+ `Prop "${keyInLowerCase}" is passed to component ` +
+ `${formatComponentName(tag || Ctor)}, but the declared prop name is` +
+ ` "${key}". ` +
+ `Note that HTML attributes are case-insensitive and camelCased ` +
+ `props need to use their kebab-case equivalents when using in-DOM ` +
+ `templates. You should probably use "${altKey}" instead of "${key}".`
+ )
+ }
+ }
+ checkProp(res, props, key, altKey, true) ||
+ checkProp(res, attrs, key, altKey, false)
+ }
+ }
+ return res
+}
+
+function checkProp (
+ res: Object,
+ hash: ?Object,
+ key: string,
+ altKey: string,
+ preserve: boolean
+): boolean {
+ if (isDef(hash)) {
+ if (hasOwn(hash, key)) {
+ res[key] = hash[key]
+ if (!preserve) {
+ delete hash[key]
+ }
+ return true
+ } else if (hasOwn(hash, altKey)) {
+ res[key] = hash[altKey]
+ if (!preserve) {
+ delete hash[altKey]
+ }
+ return true
+ }
+ }
+ return false
+}
diff --git a/node_modules/vue/src/core/vdom/helpers/get-first-component-child.js b/node_modules/vue/src/core/vdom/helpers/get-first-component-child.js
new file mode 100644
index 00000000..f8649dd8
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/helpers/get-first-component-child.js
@@ -0,0 +1,15 @@
+/* @flow */
+
+import { isDef } from 'shared/util'
+import { isAsyncPlaceholder } from './is-async-placeholder'
+
+export function getFirstComponentChild (children: ?Array<VNode>): ?VNode {
+ if (Array.isArray(children)) {
+ for (let i = 0; i < children.length; i++) {
+ const c = children[i]
+ if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
+ return c
+ }
+ }
+ }
+}
diff --git a/node_modules/vue/src/core/vdom/helpers/index.js b/node_modules/vue/src/core/vdom/helpers/index.js
new file mode 100644
index 00000000..320cf4c4
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/helpers/index.js
@@ -0,0 +1,9 @@
+/* @flow */
+
+export * from './merge-hook'
+export * from './extract-props'
+export * from './update-listeners'
+export * from './normalize-children'
+export * from './resolve-async-component'
+export * from './get-first-component-child'
+export * from './is-async-placeholder'
diff --git a/node_modules/vue/src/core/vdom/helpers/is-async-placeholder.js b/node_modules/vue/src/core/vdom/helpers/is-async-placeholder.js
new file mode 100644
index 00000000..6c4a6596
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/helpers/is-async-placeholder.js
@@ -0,0 +1,5 @@
+/* @flow */
+
+export function isAsyncPlaceholder (node: VNode): boolean {
+ return node.isComment && node.asyncFactory
+}
diff --git a/node_modules/vue/src/core/vdom/helpers/merge-hook.js b/node_modules/vue/src/core/vdom/helpers/merge-hook.js
new file mode 100644
index 00000000..0bb96e8b
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/helpers/merge-hook.js
@@ -0,0 +1,38 @@
+/* @flow */
+
+import VNode from '../vnode'
+import { createFnInvoker } from './update-listeners'
+import { remove, isDef, isUndef, isTrue } from 'shared/util'
+
+export function mergeVNodeHook (def: Object, hookKey: string, hook: Function) {
+ if (def instanceof VNode) {
+ def = def.data.hook || (def.data.hook = {})
+ }
+ let invoker
+ const oldHook = def[hookKey]
+
+ function wrappedHook () {
+ hook.apply(this, arguments)
+ // important: remove merged hook to ensure it's called only once
+ // and prevent memory leak
+ remove(invoker.fns, wrappedHook)
+ }
+
+ if (isUndef(oldHook)) {
+ // no existing hook
+ invoker = createFnInvoker([wrappedHook])
+ } else {
+ /* istanbul ignore if */
+ if (isDef(oldHook.fns) && isTrue(oldHook.merged)) {
+ // already a merged invoker
+ invoker = oldHook
+ invoker.fns.push(wrappedHook)
+ } else {
+ // existing plain hook
+ invoker = createFnInvoker([oldHook, wrappedHook])
+ }
+ }
+
+ invoker.merged = true
+ def[hookKey] = invoker
+}
diff --git a/node_modules/vue/src/core/vdom/helpers/normalize-children.js b/node_modules/vue/src/core/vdom/helpers/normalize-children.js
new file mode 100644
index 00000000..a4622ef4
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/helpers/normalize-children.js
@@ -0,0 +1,89 @@
+/* @flow */
+
+import VNode, { createTextVNode } from 'core/vdom/vnode'
+import { isFalse, isTrue, isDef, isUndef, isPrimitive } from 'shared/util'
+
+// The template compiler attempts to minimize the need for normalization by
+// statically analyzing the template at compile time.
+//
+// For plain HTML markup, normalization can be completely skipped because the
+// generated render function is guaranteed to return Array<VNode>. There are
+// two cases where extra normalization is needed:
+
+// 1. When the children contains components - because a functional component
+// may return an Array instead of a single root. In this case, just a simple
+// normalization is needed - if any child is an Array, we flatten the whole
+// thing with Array.prototype.concat. It is guaranteed to be only 1-level deep
+// because functional components already normalize their own children.
+export function simpleNormalizeChildren (children: any) {
+ for (let i = 0; i < children.length; i++) {
+ if (Array.isArray(children[i])) {
+ return Array.prototype.concat.apply([], children)
+ }
+ }
+ return children
+}
+
+// 2. When the children contains constructs that always generated nested Arrays,
+// e.g. <template>, <slot>, v-for, or when the children is provided by user
+// with hand-written render functions / JSX. In such cases a full normalization
+// is needed to cater to all possible types of children values.
+export function normalizeChildren (children: any): ?Array<VNode> {
+ return isPrimitive(children)
+ ? [createTextVNode(children)]
+ : Array.isArray(children)
+ ? normalizeArrayChildren(children)
+ : undefined
+}
+
+function isTextNode (node): boolean {
+ return isDef(node) && isDef(node.text) && isFalse(node.isComment)
+}
+
+function normalizeArrayChildren (children: any, nestedIndex?: string): Array<VNode> {
+ const res = []
+ let i, c, lastIndex, last
+ for (i = 0; i < children.length; i++) {
+ c = children[i]
+ if (isUndef(c) || typeof c === 'boolean') continue
+ lastIndex = res.length - 1
+ last = res[lastIndex]
+ // nested
+ if (Array.isArray(c)) {
+ if (c.length > 0) {
+ c = normalizeArrayChildren(c, `${nestedIndex || ''}_${i}`)
+ // merge adjacent text nodes
+ if (isTextNode(c[0]) && isTextNode(last)) {
+ res[lastIndex] = createTextVNode(last.text + (c[0]: any).text)
+ c.shift()
+ }
+ res.push.apply(res, c)
+ }
+ } else if (isPrimitive(c)) {
+ if (isTextNode(last)) {
+ // merge adjacent text nodes
+ // this is necessary for SSR hydration because text nodes are
+ // essentially merged when rendered to HTML strings
+ res[lastIndex] = createTextVNode(last.text + c)
+ } else if (c !== '') {
+ // convert primitive to vnode
+ res.push(createTextVNode(c))
+ }
+ } else {
+ if (isTextNode(c) && isTextNode(last)) {
+ // merge adjacent text nodes
+ res[lastIndex] = createTextVNode(last.text + c.text)
+ } else {
+ // default key for nested array children (likely generated by v-for)
+ if (isTrue(children._isVList) &&
+ isDef(c.tag) &&
+ isUndef(c.key) &&
+ isDef(nestedIndex)) {
+ c.key = `__vlist${nestedIndex}_${i}__`
+ }
+ res.push(c)
+ }
+ }
+ }
+ return res
+}
diff --git a/node_modules/vue/src/core/vdom/helpers/resolve-async-component.js b/node_modules/vue/src/core/vdom/helpers/resolve-async-component.js
new file mode 100644
index 00000000..99ce5ce4
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/helpers/resolve-async-component.js
@@ -0,0 +1,140 @@
+/* @flow */
+
+import {
+ warn,
+ once,
+ isDef,
+ isUndef,
+ isTrue,
+ isObject,
+ hasSymbol
+} from 'core/util/index'
+
+import { createEmptyVNode } from 'core/vdom/vnode'
+
+function ensureCtor (comp: any, base) {
+ if (
+ comp.__esModule ||
+ (hasSymbol && comp[Symbol.toStringTag] === 'Module')
+ ) {
+ comp = comp.default
+ }
+ return isObject(comp)
+ ? base.extend(comp)
+ : comp
+}
+
+export function createAsyncPlaceholder (
+ factory: Function,
+ data: ?VNodeData,
+ context: Component,
+ children: ?Array<VNode>,
+ tag: ?string
+): VNode {
+ const node = createEmptyVNode()
+ node.asyncFactory = factory
+ node.asyncMeta = { data, context, children, tag }
+ return node
+}
+
+export function resolveAsyncComponent (
+ factory: Function,
+ baseCtor: Class<Component>,
+ context: Component
+): Class<Component> | void {
+ if (isTrue(factory.error) && isDef(factory.errorComp)) {
+ return factory.errorComp
+ }
+
+ if (isDef(factory.resolved)) {
+ return factory.resolved
+ }
+
+ if (isTrue(factory.loading) && isDef(factory.loadingComp)) {
+ return factory.loadingComp
+ }
+
+ if (isDef(factory.contexts)) {
+ // already pending
+ factory.contexts.push(context)
+ } else {
+ const contexts = factory.contexts = [context]
+ let sync = true
+
+ const forceRender = () => {
+ for (let i = 0, l = contexts.length; i < l; i++) {
+ contexts[i].$forceUpdate()
+ }
+ }
+
+ const resolve = once((res: Object | Class<Component>) => {
+ // cache resolved
+ factory.resolved = ensureCtor(res, baseCtor)
+ // invoke callbacks only if this is not a synchronous resolve
+ // (async resolves are shimmed as synchronous during SSR)
+ if (!sync) {
+ forceRender()
+ }
+ })
+
+ const reject = once(reason => {
+ process.env.NODE_ENV !== 'production' && warn(
+ `Failed to resolve async component: ${String(factory)}` +
+ (reason ? `\nReason: ${reason}` : '')
+ )
+ if (isDef(factory.errorComp)) {
+ factory.error = true
+ forceRender()
+ }
+ })
+
+ const res = factory(resolve, reject)
+
+ if (isObject(res)) {
+ if (typeof res.then === 'function') {
+ // () => Promise
+ if (isUndef(factory.resolved)) {
+ res.then(resolve, reject)
+ }
+ } else if (isDef(res.component) && typeof res.component.then === 'function') {
+ res.component.then(resolve, reject)
+
+ if (isDef(res.error)) {
+ factory.errorComp = ensureCtor(res.error, baseCtor)
+ }
+
+ if (isDef(res.loading)) {
+ factory.loadingComp = ensureCtor(res.loading, baseCtor)
+ if (res.delay === 0) {
+ factory.loading = true
+ } else {
+ setTimeout(() => {
+ if (isUndef(factory.resolved) && isUndef(factory.error)) {
+ factory.loading = true
+ forceRender()
+ }
+ }, res.delay || 200)
+ }
+ }
+
+ if (isDef(res.timeout)) {
+ setTimeout(() => {
+ if (isUndef(factory.resolved)) {
+ reject(
+ process.env.NODE_ENV !== 'production'
+ ? `timeout (${res.timeout}ms)`
+ : null
+ )
+ }
+ }, res.timeout)
+ }
+ }
+ }
+
+ sync = false
+ // return in case resolved synchronously
+ return factory.loading
+ ? factory.loadingComp
+ : factory.resolved
+ }
+}
diff --git a/node_modules/vue/src/core/vdom/helpers/update-listeners.js b/node_modules/vue/src/core/vdom/helpers/update-listeners.js
new file mode 100644
index 00000000..11c5a2cd
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/helpers/update-listeners.js
@@ -0,0 +1,83 @@
+/* @flow */
+
+import { warn } from 'core/util/index'
+import { cached, isUndef, isPlainObject } from 'shared/util'
+
+const normalizeEvent = cached((name: string): {
+ name: string,
+ once: boolean,
+ capture: boolean,
+ passive: boolean,
+ handler?: Function,
+ params?: Array<any>
+} => {
+ const passive = name.charAt(0) === '&'
+ name = passive ? name.slice(1) : name
+ const once = name.charAt(0) === '~' // Prefixed last, checked first
+ name = once ? name.slice(1) : name
+ const capture = name.charAt(0) === '!'
+ name = capture ? name.slice(1) : name
+ return {
+ name,
+ once,
+ capture,
+ passive
+ }
+})
+
+export function createFnInvoker (fns: Function | Array<Function>): Function {
+ function invoker () {
+ const fns = invoker.fns
+ if (Array.isArray(fns)) {
+ const cloned = fns.slice()
+ for (let i = 0; i < cloned.length; i++) {
+ cloned[i].apply(null, arguments)
+ }
+ } else {
+ // return handler return value for single handlers
+ return fns.apply(null, arguments)
+ }
+ }
+ invoker.fns = fns
+ return invoker
+}
+
+export function updateListeners (
+ on: Object,
+ oldOn: Object,
+ add: Function,
+ remove: Function,
+ vm: Component
+) {
+ let name, def, cur, old, event
+ for (name in on) {
+ def = cur = on[name]
+ old = oldOn[name]
+ event = normalizeEvent(name)
+ /* istanbul ignore if */
+ if (__WEEX__ && isPlainObject(def)) {
+ cur = def.handler
+ event.params = def.params
+ }
+ if (isUndef(cur)) {
+ process.env.NODE_ENV !== 'production' && warn(
+ `Invalid handler for event "${event.name}": got ` + String(cur),
+ vm
+ )
+ } else if (isUndef(old)) {
+ if (isUndef(cur.fns)) {
+ cur = on[name] = createFnInvoker(cur)
+ }
+ add(event.name, cur, event.once, event.capture, event.passive, event.params)
+ } else if (cur !== old) {
+ old.fns = cur
+ on[name] = old
+ }
+ }
+ for (name in oldOn) {
+ if (isUndef(on[name])) {
+ event = normalizeEvent(name)
+ remove(event.name, oldOn[name], event.capture)
+ }
+ }
+}
diff --git a/node_modules/vue/src/core/vdom/modules/directives.js b/node_modules/vue/src/core/vdom/modules/directives.js
new file mode 100644
index 00000000..639982fa
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/modules/directives.js
@@ -0,0 +1,119 @@
+/* @flow */
+
+import { emptyNode } from 'core/vdom/patch'
+import { resolveAsset, handleError } from 'core/util/index'
+import { mergeVNodeHook } from 'core/vdom/helpers/index'
+
+export default {
+ create: updateDirectives,
+ update: updateDirectives,
+ destroy: function unbindDirectives (vnode: VNodeWithData) {
+ updateDirectives(vnode, emptyNode)
+ }
+}
+
+function updateDirectives (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (oldVnode.data.directives || vnode.data.directives) {
+ _update(oldVnode, vnode)
+ }
+}
+
+function _update (oldVnode, vnode) {
+ const isCreate = oldVnode === emptyNode
+ const isDestroy = vnode === emptyNode
+ const oldDirs = normalizeDirectives(oldVnode.data.directives, oldVnode.context)
+ const newDirs = normalizeDirectives(vnode.data.directives, vnode.context)
+
+ const dirsWithInsert = []
+ const dirsWithPostpatch = []
+
+ let key, oldDir, dir
+ for (key in newDirs) {
+ oldDir = oldDirs[key]
+ dir = newDirs[key]
+ if (!oldDir) {
+ // new directive, bind
+ callHook(dir, 'bind', vnode, oldVnode)
+ if (dir.def && dir.def.inserted) {
+ dirsWithInsert.push(dir)
+ }
+ } else {
+ // existing directive, update
+ dir.oldValue = oldDir.value
+ callHook(dir, 'update', vnode, oldVnode)
+ if (dir.def && dir.def.componentUpdated) {
+ dirsWithPostpatch.push(dir)
+ }
+ }
+ }
+
+ if (dirsWithInsert.length) {
+ const callInsert = () => {
+ for (let i = 0; i < dirsWithInsert.length; i++) {
+ callHook(dirsWithInsert[i], 'inserted', vnode, oldVnode)
+ }
+ }
+ if (isCreate) {
+ mergeVNodeHook(vnode, 'insert', callInsert)
+ } else {
+ callInsert()
+ }
+ }
+
+ if (dirsWithPostpatch.length) {
+ mergeVNodeHook(vnode, 'postpatch', () => {
+ for (let i = 0; i < dirsWithPostpatch.length; i++) {
+ callHook(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode)
+ }
+ })
+ }
+
+ if (!isCreate) {
+ for (key in oldDirs) {
+ if (!newDirs[key]) {
+ // no longer present, unbind
+ callHook(oldDirs[key], 'unbind', oldVnode, oldVnode, isDestroy)
+ }
+ }
+ }
+}
+
+const emptyModifiers = Object.create(null)
+
+function normalizeDirectives (
+ dirs: ?Array<VNodeDirective>,
+ vm: Component
+): { [key: string]: VNodeDirective } {
+ const res = Object.create(null)
+ if (!dirs) {
+ // $flow-disable-line
+ return res
+ }
+ let i, dir
+ for (i = 0; i < dirs.length; i++) {
+ dir = dirs[i]
+ if (!dir.modifiers) {
+ // $flow-disable-line
+ dir.modifiers = emptyModifiers
+ }
+ res[getRawDirName(dir)] = dir
+ dir.def = resolveAsset(vm.$options, 'directives', dir.name, true)
+ }
+ // $flow-disable-line
+ return res
+}
+
+function getRawDirName (dir: VNodeDirective): string {
+ return dir.rawName || `${dir.name}.${Object.keys(dir.modifiers || {}).join('.')}`
+}
+
+function callHook (dir, hook, vnode, oldVnode, isDestroy) {
+ const fn = dir.def && dir.def[hook]
+ if (fn) {
+ try {
+ fn(vnode.elm, dir, vnode, oldVnode, isDestroy)
+ } catch (e) {
+ handleError(e, vnode.context, `directive ${dir.name} ${hook} hook`)
+ }
+ }
+}
diff --git a/node_modules/vue/src/core/vdom/modules/index.js b/node_modules/vue/src/core/vdom/modules/index.js
new file mode 100644
index 00000000..727c8646
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/modules/index.js
@@ -0,0 +1,7 @@
+import directives from './directives'
+import ref from './ref'
+
+export default [
+ ref,
+ directives
+]
diff --git a/node_modules/vue/src/core/vdom/modules/ref.js b/node_modules/vue/src/core/vdom/modules/ref.js
new file mode 100644
index 00000000..aa9bdcfc
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/modules/ref.js
@@ -0,0 +1,45 @@
+/* @flow */
+
+import { remove, isDef } from 'shared/util'
+
+export default {
+ create (_: any, vnode: VNodeWithData) {
+ registerRef(vnode)
+ },
+ update (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (oldVnode.data.ref !== vnode.data.ref) {
+ registerRef(oldVnode, true)
+ registerRef(vnode)
+ }
+ },
+ destroy (vnode: VNodeWithData) {
+ registerRef(vnode, true)
+ }
+}
+
+export function registerRef (vnode: VNodeWithData, isRemoval: ?boolean) {
+ const key = vnode.data.ref
+ if (!isDef(key)) return
+
+ const vm = vnode.context
+ const ref = vnode.componentInstance || vnode.elm
+ const refs = vm.$refs
+ if (isRemoval) {
+ if (Array.isArray(refs[key])) {
+ remove(refs[key], ref)
+ } else if (refs[key] === ref) {
+ refs[key] = undefined
+ }
+ } else {
+ if (vnode.data.refInFor) {
+ if (!Array.isArray(refs[key])) {
+ refs[key] = [ref]
+ } else if (refs[key].indexOf(ref) < 0) {
+ // $flow-disable-line
+ refs[key].push(ref)
+ }
+ } else {
+ refs[key] = ref
+ }
+ }
+}
diff --git a/node_modules/vue/src/core/vdom/patch.js b/node_modules/vue/src/core/vdom/patch.js
new file mode 100644
index 00000000..9f3bcc65
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/patch.js
@@ -0,0 +1,787 @@
+/**
+ * Virtual DOM patching algorithm based on Snabbdom by
+ * Simon Friis Vindum (@paldepind)
+ * Licensed under the MIT License
+ * https://github.com/paldepind/snabbdom/blob/master/LICENSE
+ *
+ * modified by Evan You (@yyx990803)
+ *
+ * Not type-checking this because this file is perf-critical and the cost
+ * of making flow understand it is not worth it.
+ */
+
+import VNode, { cloneVNode } from './vnode'
+import config from '../config'
+import { SSR_ATTR } from 'shared/constants'
+import { registerRef } from './modules/ref'
+import { traverse } from '../observer/traverse'
+import { activeInstance } from '../instance/lifecycle'
+import { isTextInputType } from 'web/util/element'
+
+import {
+ warn,
+ isDef,
+ isUndef,
+ isTrue,
+ makeMap,
+ isRegExp,
+ isPrimitive
+} from '../util/index'
+
+export const emptyNode = new VNode('', {}, [])
+
+const hooks = ['create', 'activate', 'update', 'remove', 'destroy']
+
+function sameVnode (a, b) {
+ return (
+ a.key === b.key && (
+ (
+ a.tag === b.tag &&
+ a.isComment === b.isComment &&
+ isDef(a.data) === isDef(b.data) &&
+ sameInputType(a, b)
+ ) || (
+ isTrue(a.isAsyncPlaceholder) &&
+ a.asyncFactory === b.asyncFactory &&
+ isUndef(b.asyncFactory.error)
+ )
+ )
+ )
+}
+
+function sameInputType (a, b) {
+ if (a.tag !== 'input') return true
+ let i
+ const typeA = isDef(i = a.data) && isDef(i = i.attrs) && i.type
+ const typeB = isDef(i = b.data) && isDef(i = i.attrs) && i.type
+ return typeA === typeB || isTextInputType(typeA) && isTextInputType(typeB)
+}
+
+function createKeyToOldIdx (children, beginIdx, endIdx) {
+ let i, key
+ const map = {}
+ for (i = beginIdx; i <= endIdx; ++i) {
+ key = children[i].key
+ if (isDef(key)) map[key] = i
+ }
+ return map
+}
+
+export function createPatchFunction (backend) {
+ let i, j
+ const cbs = {}
+
+ const { modules, nodeOps } = backend
+
+ for (i = 0; i < hooks.length; ++i) {
+ cbs[hooks[i]] = []
+ for (j = 0; j < modules.length; ++j) {
+ if (isDef(modules[j][hooks[i]])) {
+ cbs[hooks[i]].push(modules[j][hooks[i]])
+ }
+ }
+ }
+
+ function emptyNodeAt (elm) {
+ return new VNode(nodeOps.tagName(elm).toLowerCase(), {}, [], undefined, elm)
+ }
+
+ function createRmCb (childElm, listeners) {
+ function remove () {
+ if (--remove.listeners === 0) {
+ removeNode(childElm)
+ }
+ }
+ remove.listeners = listeners
+ return remove
+ }
+
+ function removeNode (el) {
+ const parent = nodeOps.parentNode(el)
+ // element may have already been removed due to v-html / v-text
+ if (isDef(parent)) {
+ nodeOps.removeChild(parent, el)
+ }
+ }
+
+ function isUnknownElement (vnode, inVPre) {
+ return (
+ !inVPre &&
+ !vnode.ns &&
+ !(
+ config.ignoredElements.length &&
+ config.ignoredElements.some(ignore => {
+ return isRegExp(ignore)
+ ? ignore.test(vnode.tag)
+ : ignore === vnode.tag
+ })
+ ) &&
+ config.isUnknownElement(vnode.tag)
+ )
+ }
+
+ let creatingElmInVPre = 0
+
+ function createElm (
+ vnode,
+ insertedVnodeQueue,
+ parentElm,
+ refElm,
+ nested,
+ ownerArray,
+ index
+ ) {
+ if (isDef(vnode.elm) && isDef(ownerArray)) {
+ // This vnode was used in a previous render!
+ // now it's used as a new node, overwriting its elm would cause
+ // potential patch errors down the road when it's used as an insertion
+ // reference node. Instead, we clone the node on-demand before creating
+ // associated DOM element for it.
+ vnode = ownerArray[index] = cloneVNode(vnode)
+ }
+
+ vnode.isRootInsert = !nested // for transition enter check
+ if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {
+ return
+ }
+
+ const data = vnode.data
+ const children = vnode.children
+ const tag = vnode.tag
+ if (isDef(tag)) {
+ if (process.env.NODE_ENV !== 'production') {
+ if (data && data.pre) {
+ creatingElmInVPre++
+ }
+ if (isUnknownElement(vnode, creatingElmInVPre)) {
+ warn(
+ 'Unknown custom element: <' + tag + '> - did you ' +
+ 'register the component correctly? For recursive components, ' +
+ 'make sure to provide the "name" option.',
+ vnode.context
+ )
+ }
+ }
+
+ vnode.elm = vnode.ns
+ ? nodeOps.createElementNS(vnode.ns, tag)
+ : nodeOps.createElement(tag, vnode)
+ setScope(vnode)
+
+ /* istanbul ignore if */
+ if (__WEEX__) {
+ // in Weex, the default insertion order is parent-first.
+ // List items can be optimized to use children-first insertion
+ // with append="tree".
+ const appendAsTree = isDef(data) && isTrue(data.appendAsTree)
+ if (!appendAsTree) {
+ if (isDef(data)) {
+ invokeCreateHooks(vnode, insertedVnodeQueue)
+ }
+ insert(parentElm, vnode.elm, refElm)
+ }
+ createChildren(vnode, children, insertedVnodeQueue)
+ if (appendAsTree) {
+ if (isDef(data)) {
+ invokeCreateHooks(vnode, insertedVnodeQueue)
+ }
+ insert(parentElm, vnode.elm, refElm)
+ }
+ } else {
+ createChildren(vnode, children, insertedVnodeQueue)
+ if (isDef(data)) {
+ invokeCreateHooks(vnode, insertedVnodeQueue)
+ }
+ insert(parentElm, vnode.elm, refElm)
+ }
+
+ if (process.env.NODE_ENV !== 'production' && data && data.pre) {
+ creatingElmInVPre--
+ }
+ } else if (isTrue(vnode.isComment)) {
+ vnode.elm = nodeOps.createComment(vnode.text)
+ insert(parentElm, vnode.elm, refElm)
+ } else {
+ vnode.elm = nodeOps.createTextNode(vnode.text)
+ insert(parentElm, vnode.elm, refElm)
+ }
+ }
+
+ function createComponent (vnode, insertedVnodeQueue, parentElm, refElm) {
+ let i = vnode.data
+ if (isDef(i)) {
+ const isReactivated = isDef(vnode.componentInstance) && i.keepAlive
+ if (isDef(i = i.hook) && isDef(i = i.init)) {
+ i(vnode, false /* hydrating */, parentElm, refElm)
+ }
+ // after calling the init hook, if the vnode is a child component
+ // it should've created a child instance and mounted it. the child
+ // component also has set the placeholder vnode's elm.
+ // in that case we can just return the element and be done.
+ if (isDef(vnode.componentInstance)) {
+ initComponent(vnode, insertedVnodeQueue)
+ if (isTrue(isReactivated)) {
+ reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm)
+ }
+ return true
+ }
+ }
+ }
+
+ function initComponent (vnode, insertedVnodeQueue) {
+ if (isDef(vnode.data.pendingInsert)) {
+ insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert)
+ vnode.data.pendingInsert = null
+ }
+ vnode.elm = vnode.componentInstance.$el
+ if (isPatchable(vnode)) {
+ invokeCreateHooks(vnode, insertedVnodeQueue)
+ setScope(vnode)
+ } else {
+ // empty component root.
+ // skip all element-related modules except for ref (#3455)
+ registerRef(vnode)
+ // make sure to invoke the insert hook
+ insertedVnodeQueue.push(vnode)
+ }
+ }
+
+ function reactivateComponent (vnode, insertedVnodeQueue, parentElm, refElm) {
+ let i
+ // hack for #4339: a reactivated component with inner transition
+ // does not trigger because the inner node's created hooks are not called
+ // again. It's not ideal to involve module-specific logic in here but
+ // there doesn't seem to be a better way to do it.
+ let innerNode = vnode
+ while (innerNode.componentInstance) {
+ innerNode = innerNode.componentInstance._vnode
+ if (isDef(i = innerNode.data) && isDef(i = i.transition)) {
+ for (i = 0; i < cbs.activate.length; ++i) {
+ cbs.activate[i](emptyNode, innerNode)
+ }
+ insertedVnodeQueue.push(innerNode)
+ break
+ }
+ }
+ // unlike a newly created component,
+ // a reactivated keep-alive component doesn't insert itself
+ insert(parentElm, vnode.elm, refElm)
+ }
+
+ function insert (parent, elm, ref) {
+ if (isDef(parent)) {
+ if (isDef(ref)) {
+ if (ref.parentNode === parent) {
+ nodeOps.insertBefore(parent, elm, ref)
+ }
+ } else {
+ nodeOps.appendChild(parent, elm)
+ }
+ }
+ }
+
+ function createChildren (vnode, children, insertedVnodeQueue) {
+ if (Array.isArray(children)) {
+ if (process.env.NODE_ENV !== 'production') {
+ checkDuplicateKeys(children)
+ }
+ for (let i = 0; i < children.length; ++i) {
+ createElm(children[i], insertedVnodeQueue, vnode.elm, null, true, children, i)
+ }
+ } else if (isPrimitive(vnode.text)) {
+ nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(String(vnode.text)))
+ }
+ }
+
+ function isPatchable (vnode) {
+ while (vnode.componentInstance) {
+ vnode = vnode.componentInstance._vnode
+ }
+ return isDef(vnode.tag)
+ }
+
+ function invokeCreateHooks (vnode, insertedVnodeQueue) {
+ for (let i = 0; i < cbs.create.length; ++i) {
+ cbs.create[i](emptyNode, vnode)
+ }
+ i = vnode.data.hook // Reuse variable
+ if (isDef(i)) {
+ if (isDef(i.create)) i.create(emptyNode, vnode)
+ if (isDef(i.insert)) insertedVnodeQueue.push(vnode)
+ }
+ }
+
+ // set scope id attribute for scoped CSS.
+ // this is implemented as a special case to avoid the overhead
+ // of going through the normal attribute patching process.
+ function setScope (vnode) {
+ let i
+ if (isDef(i = vnode.fnScopeId)) {
+ nodeOps.setStyleScope(vnode.elm, i)
+ } else {
+ let ancestor = vnode
+ while (ancestor) {
+ if (isDef(i = ancestor.context) && isDef(i = i.$options._scopeId)) {
+ nodeOps.setStyleScope(vnode.elm, i)
+ }
+ ancestor = ancestor.parent
+ }
+ }
+ // for slot content they should also get the scopeId from the host instance.
+ if (isDef(i = activeInstance) &&
+ i !== vnode.context &&
+ i !== vnode.fnContext &&
+ isDef(i = i.$options._scopeId)
+ ) {
+ nodeOps.setStyleScope(vnode.elm, i)
+ }
+ }
+
+ function addVnodes (parentElm, refElm, vnodes, startIdx, endIdx, insertedVnodeQueue) {
+ for (; startIdx <= endIdx; ++startIdx) {
+ createElm(vnodes[startIdx], insertedVnodeQueue, parentElm, refElm, false, vnodes, startIdx)
+ }
+ }
+
+ function invokeDestroyHook (vnode) {
+ let i, j
+ const data = vnode.data
+ if (isDef(data)) {
+ if (isDef(i = data.hook) && isDef(i = i.destroy)) i(vnode)
+ for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode)
+ }
+ if (isDef(i = vnode.children)) {
+ for (j = 0; j < vnode.children.length; ++j) {
+ invokeDestroyHook(vnode.children[j])
+ }
+ }
+ }
+
+ function removeVnodes (parentElm, vnodes, startIdx, endIdx) {
+ for (; startIdx <= endIdx; ++startIdx) {
+ const ch = vnodes[startIdx]
+ if (isDef(ch)) {
+ if (isDef(ch.tag)) {
+ removeAndInvokeRemoveHook(ch)
+ invokeDestroyHook(ch)
+ } else { // Text node
+ removeNode(ch.elm)
+ }
+ }
+ }
+ }
+
+ function removeAndInvokeRemoveHook (vnode, rm) {
+ if (isDef(rm) || isDef(vnode.data)) {
+ let i
+ const listeners = cbs.remove.length + 1
+ if (isDef(rm)) {
+ // we have a recursively passed down rm callback
+ // increase the listeners count
+ rm.listeners += listeners
+ } else {
+ // directly removing
+ rm = createRmCb(vnode.elm, listeners)
+ }
+ // recursively invoke hooks on child component root node
+ if (isDef(i = vnode.componentInstance) && isDef(i = i._vnode) && isDef(i.data)) {
+ removeAndInvokeRemoveHook(i, rm)
+ }
+ for (i = 0; i < cbs.remove.length; ++i) {
+ cbs.remove[i](vnode, rm)
+ }
+ if (isDef(i = vnode.data.hook) && isDef(i = i.remove)) {
+ i(vnode, rm)
+ } else {
+ rm()
+ }
+ } else {
+ removeNode(vnode.elm)
+ }
+ }
+
+ function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {
+ let oldStartIdx = 0
+ let newStartIdx = 0
+ let oldEndIdx = oldCh.length - 1
+ let oldStartVnode = oldCh[0]
+ let oldEndVnode = oldCh[oldEndIdx]
+ let newEndIdx = newCh.length - 1
+ let newStartVnode = newCh[0]
+ let newEndVnode = newCh[newEndIdx]
+ let oldKeyToIdx, idxInOld, vnodeToMove, refElm
+
+ // removeOnly is a special flag used only by <transition-group>
+ // to ensure removed elements stay in correct relative positions
+ // during leaving transitions
+ const canMove = !removeOnly
+
+ if (process.env.NODE_ENV !== 'production') {
+ checkDuplicateKeys(newCh)
+ }
+
+ while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
+ if (isUndef(oldStartVnode)) {
+ oldStartVnode = oldCh[++oldStartIdx] // Vnode has been moved left
+ } else if (isUndef(oldEndVnode)) {
+ oldEndVnode = oldCh[--oldEndIdx]
+ } else if (sameVnode(oldStartVnode, newStartVnode)) {
+ patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue)
+ oldStartVnode = oldCh[++oldStartIdx]
+ newStartVnode = newCh[++newStartIdx]
+ } else if (sameVnode(oldEndVnode, newEndVnode)) {
+ patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue)
+ oldEndVnode = oldCh[--oldEndIdx]
+ newEndVnode = newCh[--newEndIdx]
+ } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
+ patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue)
+ canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm))
+ oldStartVnode = oldCh[++oldStartIdx]
+ newEndVnode = newCh[--newEndIdx]
+ } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
+ patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue)
+ canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm)
+ oldEndVnode = oldCh[--oldEndIdx]
+ newStartVnode = newCh[++newStartIdx]
+ } else {
+ if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
+ idxInOld = isDef(newStartVnode.key)
+ ? oldKeyToIdx[newStartVnode.key]
+ : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
+ if (isUndef(idxInOld)) { // New element
+ createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
+ } else {
+ vnodeToMove = oldCh[idxInOld]
+ if (sameVnode(vnodeToMove, newStartVnode)) {
+ patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue)
+ oldCh[idxInOld] = undefined
+ canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm)
+ } else {
+ // same key but different element. treat as new element
+ createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
+ }
+ }
+ newStartVnode = newCh[++newStartIdx]
+ }
+ }
+ if (oldStartIdx > oldEndIdx) {
+ refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm
+ addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)
+ } else if (newStartIdx > newEndIdx) {
+ removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)
+ }
+ }
+
+ function checkDuplicateKeys (children) {
+ const seenKeys = {}
+ for (let i = 0; i < children.length; i++) {
+ const vnode = children[i]
+ const key = vnode.key
+ if (isDef(key)) {
+ if (seenKeys[key]) {
+ warn(
+ `Duplicate keys detected: '${key}'. This may cause an update error.`,
+ vnode.context
+ )
+ } else {
+ seenKeys[key] = true
+ }
+ }
+ }
+ }
+
+ function findIdxInOld (node, oldCh, start, end) {
+ for (let i = start; i < end; i++) {
+ const c = oldCh[i]
+ if (isDef(c) && sameVnode(node, c)) return i
+ }
+ }
+
+ function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {
+ if (oldVnode === vnode) {
+ return
+ }
+
+ const elm = vnode.elm = oldVnode.elm
+
+ if (isTrue(oldVnode.isAsyncPlaceholder)) {
+ if (isDef(vnode.asyncFactory.resolved)) {
+ hydrate(oldVnode.elm, vnode, insertedVnodeQueue)
+ } else {
+ vnode.isAsyncPlaceholder = true
+ }
+ return
+ }
+
+ // reuse element for static trees.
+ // note we only do this if the vnode is cloned -
+ // if the new node is not cloned it means the render functions have been
+ // reset by the hot-reload-api and we need to do a proper re-render.
+ if (isTrue(vnode.isStatic) &&
+ isTrue(oldVnode.isStatic) &&
+ vnode.key === oldVnode.key &&
+ (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))
+ ) {
+ vnode.componentInstance = oldVnode.componentInstance
+ return
+ }
+
+ let i
+ const data = vnode.data
+ if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {
+ i(oldVnode, vnode)
+ }
+
+ const oldCh = oldVnode.children
+ const ch = vnode.children
+ if (isDef(data) && isPatchable(vnode)) {
+ for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)
+ if (isDef(i = data.hook) && isDef(i = i.update)) i(oldVnode, vnode)
+ }
+ if (isUndef(vnode.text)) {
+ if (isDef(oldCh) && isDef(ch)) {
+ if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
+ } else if (isDef(ch)) {
+ if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, '')
+ addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
+ } else if (isDef(oldCh)) {
+ removeVnodes(elm, oldCh, 0, oldCh.length - 1)
+ } else if (isDef(oldVnode.text)) {
+ nodeOps.setTextContent(elm, '')
+ }
+ } else if (oldVnode.text !== vnode.text) {
+ nodeOps.setTextContent(elm, vnode.text)
+ }
+ if (isDef(data)) {
+ if (isDef(i = data.hook) && isDef(i = i.postpatch)) i(oldVnode, vnode)
+ }
+ }
+
+ function invokeInsertHook (vnode, queue, initial) {
+ // delay insert hooks for component root nodes, invoke them after the
+ // element is really inserted
+ if (isTrue(initial) && isDef(vnode.parent)) {
+ vnode.parent.data.pendingInsert = queue
+ } else {
+ for (let i = 0; i < queue.length; ++i) {
+ queue[i].data.hook.insert(queue[i])
+ }
+ }
+ }
+
+ let hydrationBailed = false
+ // list of modules that can skip create hook during hydration because they
+ // are already rendered on the client or has no need for initialization
+ // Note: style is excluded because it relies on initial clone for future
+ // deep updates (#7063).
+ const isRenderedModule = makeMap('attrs,class,staticClass,staticStyle,key')
+
+ // Note: this is a browser-only function so we can assume elms are DOM nodes.
+ function hydrate (elm, vnode, insertedVnodeQueue, inVPre) {
+ let i
+ const { tag, data, children } = vnode
+ inVPre = inVPre || (data && data.pre)
+ vnode.elm = elm
+
+ if (isTrue(vnode.isComment) && isDef(vnode.asyncFactory)) {
+ vnode.isAsyncPlaceholder = true
+ return true
+ }
+ // assert node match
+ if (process.env.NODE_ENV !== 'production') {
+ if (!assertNodeMatch(elm, vnode, inVPre)) {
+ return false
+ }
+ }
+ if (isDef(data)) {
+ if (isDef(i = data.hook) && isDef(i = i.init)) i(vnode, true /* hydrating */)
+ if (isDef(i = vnode.componentInstance)) {
+ // child component. it should have hydrated its own tree.
+ initComponent(vnode, insertedVnodeQueue)
+ return true
+ }
+ }
+ if (isDef(tag)) {
+ if (isDef(children)) {
+ // empty element, allow client to pick up and populate children
+ if (!elm.hasChildNodes()) {
+ createChildren(vnode, children, insertedVnodeQueue)
+ } else {
+ // v-html and domProps: innerHTML
+ if (isDef(i = data) && isDef(i = i.domProps) && isDef(i = i.innerHTML)) {
+ if (i !== elm.innerHTML) {
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production' &&
+ typeof console !== 'undefined' &&
+ !hydrationBailed
+ ) {
+ hydrationBailed = true
+ console.warn('Parent: ', elm)
+ console.warn('server innerHTML: ', i)
+ console.warn('client innerHTML: ', elm.innerHTML)
+ }
+ return false
+ }
+ } else {
+ // iterate and compare children lists
+ let childrenMatch = true
+ let childNode = elm.firstChild
+ for (let i = 0; i < children.length; i++) {
+ if (!childNode || !hydrate(childNode, children[i], insertedVnodeQueue, inVPre)) {
+ childrenMatch = false
+ break
+ }
+ childNode = childNode.nextSibling
+ }
+ // if childNode is not null, it means the actual childNodes list is
+ // longer than the virtual children list.
+ if (!childrenMatch || childNode) {
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production' &&
+ typeof console !== 'undefined' &&
+ !hydrationBailed
+ ) {
+ hydrationBailed = true
+ console.warn('Parent: ', elm)
+ console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children)
+ }
+ return false
+ }
+ }
+ }
+ }
+ if (isDef(data)) {
+ let fullInvoke = false
+ for (const key in data) {
+ if (!isRenderedModule(key)) {
+ fullInvoke = true
+ invokeCreateHooks(vnode, insertedVnodeQueue)
+ break
+ }
+ }
+ if (!fullInvoke && data['class']) {
+ // ensure collecting deps for deep class bindings for future updates
+ traverse(data['class'])
+ }
+ }
+ } else if (elm.data !== vnode.text) {
+ elm.data = vnode.text
+ }
+ return true
+ }
+
+ function assertNodeMatch (node, vnode, inVPre) {
+ if (isDef(vnode.tag)) {
+ return vnode.tag.indexOf('vue-component') === 0 || (
+ !isUnknownElement(vnode, inVPre) &&
+ vnode.tag.toLowerCase() === (node.tagName && node.tagName.toLowerCase())
+ )
+ } else {
+ return node.nodeType === (vnode.isComment ? 8 : 3)
+ }
+ }
+
+ return function patch (oldVnode, vnode, hydrating, removeOnly, parentElm, refElm) {
+ if (isUndef(vnode)) {
+ if (isDef(oldVnode)) invokeDestroyHook(oldVnode)
+ return
+ }
+
+ let isInitialPatch = false
+ const insertedVnodeQueue = []
+
+ if (isUndef(oldVnode)) {
+ // empty mount (likely as component), create new root element
+ isInitialPatch = true
+ createElm(vnode, insertedVnodeQueue, parentElm, refElm)
+ } else {
+ const isRealElement = isDef(oldVnode.nodeType)
+ if (!isRealElement && sameVnode(oldVnode, vnode)) {
+ // patch existing root node
+ patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly)
+ } else {
+ if (isRealElement) {
+ // mounting to a real element
+ // check if this is server-rendered content and if we can perform
+ // a successful hydration.
+ if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {
+ oldVnode.removeAttribute(SSR_ATTR)
+ hydrating = true
+ }
+ if (isTrue(hydrating)) {
+ if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {
+ invokeInsertHook(vnode, insertedVnodeQueue, true)
+ return oldVnode
+ } else if (process.env.NODE_ENV !== 'production') {
+ warn(
+ 'The client-side rendered virtual DOM tree is not matching ' +
+ 'server-rendered content. This is likely caused by incorrect ' +
+ 'HTML markup, for example nesting block-level elements inside ' +
+ '<p>, or missing <tbody>. Bailing hydration and performing ' +
+ 'full client-side render.'
+ )
+ }
+ }
+ // either not server-rendered, or hydration failed.
+ // create an empty node and replace it
+ oldVnode = emptyNodeAt(oldVnode)
+ }
+
+ // replacing existing element
+ const oldElm = oldVnode.elm
+ const parentElm = nodeOps.parentNode(oldElm)
+
+ // create new node
+ createElm(
+ vnode,
+ insertedVnodeQueue,
+ // extremely rare edge case: do not insert if old element is in a
+ // leaving transition. Only happens when combining transition +
+ // keep-alive + HOCs. (#4590)
+ oldElm._leaveCb ? null : parentElm,
+ nodeOps.nextSibling(oldElm)
+ )
+
+ // update parent placeholder node element, recursively
+ if (isDef(vnode.parent)) {
+ let ancestor = vnode.parent
+ const patchable = isPatchable(vnode)
+ while (ancestor) {
+ for (let i = 0; i < cbs.destroy.length; ++i) {
+ cbs.destroy[i](ancestor)
+ }
+ ancestor.elm = vnode.elm
+ if (patchable) {
+ for (let i = 0; i < cbs.create.length; ++i) {
+ cbs.create[i](emptyNode, ancestor)
+ }
+ // #6513
+ // invoke insert hooks that may have been merged by create hooks.
+ // e.g. for directives that uses the "inserted" hook.
+ const insert = ancestor.data.hook.insert
+ if (insert.merged) {
+ // start at index 1 to avoid re-invoking component mounted hook
+ for (let i = 1; i < insert.fns.length; i++) {
+ insert.fns[i]()
+ }
+ }
+ } else {
+ registerRef(ancestor)
+ }
+ ancestor = ancestor.parent
+ }
+ }
+
+ // destroy old node
+ if (isDef(parentElm)) {
+ removeVnodes(parentElm, [oldVnode], 0, 0)
+ } else if (isDef(oldVnode.tag)) {
+ invokeDestroyHook(oldVnode)
+ }
+ }
+ }
+
+ invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch)
+ return vnode.elm
+ }
+}
diff --git a/node_modules/vue/src/core/vdom/vnode.js b/node_modules/vue/src/core/vdom/vnode.js
new file mode 100644
index 00000000..88e80cec
--- /dev/null
+++ b/node_modules/vue/src/core/vdom/vnode.js
@@ -0,0 +1,108 @@
+/* @flow */
+
+export default class VNode {
+ tag: string | void;
+ data: VNodeData | void;
+ children: ?Array<VNode>;
+ text: string | void;
+ elm: Node | void;
+ ns: string | void;
+ context: Component | void; // rendered in this component's scope
+ key: string | number | void;
+ componentOptions: VNodeComponentOptions | void;
+ componentInstance: Component | void; // component instance
+ parent: VNode | void; // component placeholder node
+
+ // strictly internal
+ raw: boolean; // contains raw HTML? (server only)
+ isStatic: boolean; // hoisted static node
+ isRootInsert: boolean; // necessary for enter transition check
+ isComment: boolean; // empty comment placeholder?
+ isCloned: boolean; // is a cloned node?
+ isOnce: boolean; // is a v-once node?
+ asyncFactory: Function | void; // async component factory function
+ asyncMeta: Object | void;
+ isAsyncPlaceholder: boolean;
+ ssrContext: Object | void;
+ fnContext: Component | void; // real context vm for functional nodes
+ fnOptions: ?ComponentOptions; // for SSR caching
+ fnScopeId: ?string; // functional scope id support
+
+ constructor (
+ tag?: string,
+ data?: VNodeData,
+ children?: ?Array<VNode>,
+ text?: string,
+ elm?: Node,
+ context?: Component,
+ componentOptions?: VNodeComponentOptions,
+ asyncFactory?: Function
+ ) {
+ this.tag = tag
+ this.data = data
+ this.children = children
+ this.text = text
+ this.elm = elm
+ this.ns = undefined
+ this.context = context
+ this.fnContext = undefined
+ this.fnOptions = undefined
+ this.fnScopeId = undefined
+ this.key = data && data.key
+ this.componentOptions = componentOptions
+ this.componentInstance = undefined
+ this.parent = undefined
+ this.raw = false
+ this.isStatic = false
+ this.isRootInsert = true
+ this.isComment = false
+ this.isCloned = false
+ this.isOnce = false
+ this.asyncFactory = asyncFactory
+ this.asyncMeta = undefined
+ this.isAsyncPlaceholder = false
+ }
+
+ // DEPRECATED: alias for componentInstance for backwards compat.
+ /* istanbul ignore next */
+ get child (): Component | void {
+ return this.componentInstance
+ }
+}
+
+export const createEmptyVNode = (text: string = '') => {
+ const node = new VNode()
+ node.text = text
+ node.isComment = true
+ return node
+}
+
+export function createTextVNode (val: string | number) {
+ return new VNode(undefined, undefined, undefined, String(val))
+}
+
+// optimized shallow clone
+// used for static nodes and slot nodes because they may be reused across
+// multiple renders, cloning them avoids errors when DOM manipulations rely
+// on their elm reference.
+export function cloneVNode (vnode: VNode): VNode {
+ const cloned = new VNode(
+ vnode.tag,
+ vnode.data,
+ vnode.children,
+ vnode.text,
+ vnode.elm,
+ vnode.context,
+ vnode.componentOptions,
+ vnode.asyncFactory
+ )
+ cloned.ns = vnode.ns
+ cloned.isStatic = vnode.isStatic
+ cloned.key = vnode.key
+ cloned.isComment = vnode.isComment
+ cloned.fnContext = vnode.fnContext
+ cloned.fnOptions = vnode.fnOptions
+ cloned.fnScopeId = vnode.fnScopeId
+ cloned.isCloned = true
+ return cloned
+}
diff --git a/node_modules/vue/src/platforms/web/compiler/directives/html.js b/node_modules/vue/src/platforms/web/compiler/directives/html.js
new file mode 100644
index 00000000..58569d8e
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/compiler/directives/html.js
@@ -0,0 +1,9 @@
+/* @flow */
+
+import { addProp } from 'compiler/helpers'
+
+export default function html (el: ASTElement, dir: ASTDirective) {
+ if (dir.value) {
+ addProp(el, 'innerHTML', `_s(${dir.value})`)
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/compiler/directives/index.js b/node_modules/vue/src/platforms/web/compiler/directives/index.js
new file mode 100644
index 00000000..0955b51e
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/compiler/directives/index.js
@@ -0,0 +1,9 @@
+import model from './model'
+import text from './text'
+import html from './html'
+
+export default {
+ model,
+ text,
+ html
+}
diff --git a/node_modules/vue/src/platforms/web/compiler/directives/model.js b/node_modules/vue/src/platforms/web/compiler/directives/model.js
new file mode 100644
index 00000000..126f0c7d
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/compiler/directives/model.js
@@ -0,0 +1,172 @@
+/* @flow */
+
+import config from 'core/config'
+import { addHandler, addProp, getBindingAttr } from 'compiler/helpers'
+import { genComponentModel, genAssignmentCode } from 'compiler/directives/model'
+
+let warn
+
+// in some cases, the event used has to be determined at runtime
+// so we used some reserved tokens during compile.
+export const RANGE_TOKEN = '__r'
+export const CHECKBOX_RADIO_TOKEN = '__c'
+
+export default function model (
+ el: ASTElement,
+ dir: ASTDirective,
+ _warn: Function
+): ?boolean {
+ warn = _warn
+ const value = dir.value
+ const modifiers = dir.modifiers
+ const tag = el.tag
+ const type = el.attrsMap.type
+
+ if (process.env.NODE_ENV !== 'production') {
+ // inputs with type="file" are read only and setting the input's
+ // value will throw an error.
+ if (tag === 'input' && type === 'file') {
+ warn(
+ `<${el.tag} v-model="${value}" type="file">:\n` +
+ `File inputs are read only. Use a v-on:change listener instead.`
+ )
+ }
+ }
+
+ if (el.component) {
+ genComponentModel(el, value, modifiers)
+ // component v-model doesn't need extra runtime
+ return false
+ } else if (tag === 'select') {
+ genSelect(el, value, modifiers)
+ } else if (tag === 'input' && type === 'checkbox') {
+ genCheckboxModel(el, value, modifiers)
+ } else if (tag === 'input' && type === 'radio') {
+ genRadioModel(el, value, modifiers)
+ } else if (tag === 'input' || tag === 'textarea') {
+ genDefaultModel(el, value, modifiers)
+ } else if (!config.isReservedTag(tag)) {
+ genComponentModel(el, value, modifiers)
+ // component v-model doesn't need extra runtime
+ return false
+ } else if (process.env.NODE_ENV !== 'production') {
+ warn(
+ `<${el.tag} v-model="${value}">: ` +
+ `v-model is not supported on this element type. ` +
+ 'If you are working with contenteditable, it\'s recommended to ' +
+ 'wrap a library dedicated for that purpose inside a custom component.'
+ )
+ }
+
+ // ensure runtime directive metadata
+ return true
+}
+
+function genCheckboxModel (
+ el: ASTElement,
+ value: string,
+ modifiers: ?ASTModifiers
+) {
+ const number = modifiers && modifiers.number
+ const valueBinding = getBindingAttr(el, 'value') || 'null'
+ const trueValueBinding = getBindingAttr(el, 'true-value') || 'true'
+ const falseValueBinding = getBindingAttr(el, 'false-value') || 'false'
+ addProp(el, 'checked',
+ `Array.isArray(${value})` +
+ `?_i(${value},${valueBinding})>-1` + (
+ trueValueBinding === 'true'
+ ? `:(${value})`
+ : `:_q(${value},${trueValueBinding})`
+ )
+ )
+ addHandler(el, 'change',
+ `var $$a=${value},` +
+ '$$el=$event.target,' +
+ `$$c=$$el.checked?(${trueValueBinding}):(${falseValueBinding});` +
+ 'if(Array.isArray($$a)){' +
+ `var $$v=${number ? '_n(' + valueBinding + ')' : valueBinding},` +
+ '$$i=_i($$a,$$v);' +
+ `if($$el.checked){$$i<0&&(${genAssignmentCode(value, '$$a.concat([$$v])')})}` +
+ `else{$$i>-1&&(${genAssignmentCode(value, '$$a.slice(0,$$i).concat($$a.slice($$i+1))')})}` +
+ `}else{${genAssignmentCode(value, '$$c')}}`,
+ null, true
+ )
+}
+
+function genRadioModel (
+ el: ASTElement,
+ value: string,
+ modifiers: ?ASTModifiers
+) {
+ const number = modifiers && modifiers.number
+ let valueBinding = getBindingAttr(el, 'value') || 'null'
+ valueBinding = number ? `_n(${valueBinding})` : valueBinding
+ addProp(el, 'checked', `_q(${value},${valueBinding})`)
+ addHandler(el, 'change', genAssignmentCode(value, valueBinding), null, true)
+}
+
+function genSelect (
+ el: ASTElement,
+ value: string,
+ modifiers: ?ASTModifiers
+) {
+ const number = modifiers && modifiers.number
+ const selectedVal = `Array.prototype.filter` +
+ `.call($event.target.options,function(o){return o.selected})` +
+ `.map(function(o){var val = "_value" in o ? o._value : o.value;` +
+ `return ${number ? '_n(val)' : 'val'}})`
+
+ const assignment = '$event.target.multiple ? $$selectedVal : $$selectedVal[0]'
+ let code = `var $$selectedVal = ${selectedVal};`
+ code = `${code} ${genAssignmentCode(value, assignment)}`
+ addHandler(el, 'change', code, null, true)
+}
+
+function genDefaultModel (
+ el: ASTElement,
+ value: string,
+ modifiers: ?ASTModifiers
+): ?boolean {
+ const type = el.attrsMap.type
+
+ // warn if v-bind:value conflicts with v-model
+ // except for inputs with v-bind:type
+ if (process.env.NODE_ENV !== 'production') {
+ const value = el.attrsMap['v-bind:value'] || el.attrsMap[':value']
+ const typeBinding = el.attrsMap['v-bind:type'] || el.attrsMap[':type']
+ if (value && !typeBinding) {
+ const binding = el.attrsMap['v-bind:value'] ? 'v-bind:value' : ':value'
+ warn(
+ `${binding}="${value}" conflicts with v-model on the same element ` +
+ 'because the latter already expands to a value binding internally'
+ )
+ }
+ }
+
+ const { lazy, number, trim } = modifiers || {}
+ const needCompositionGuard = !lazy && type !== 'range'
+ const event = lazy
+ ? 'change'
+ : type === 'range'
+ ? RANGE_TOKEN
+ : 'input'
+
+ let valueExpression = '$event.target.value'
+ if (trim) {
+ valueExpression = `$event.target.value.trim()`
+ }
+ if (number) {
+ valueExpression = `_n(${valueExpression})`
+ }
+
+ let code = genAssignmentCode(value, valueExpression)
+ if (needCompositionGuard) {
+ code = `if($event.target.composing)return;${code}`
+ }
+
+ addProp(el, 'value', `(${value})`)
+ addHandler(el, event, code, null, true)
+ if (trim || number) {
+ addHandler(el, 'blur', '$forceUpdate()')
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/compiler/directives/text.js b/node_modules/vue/src/platforms/web/compiler/directives/text.js
new file mode 100644
index 00000000..1af914f8
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/compiler/directives/text.js
@@ -0,0 +1,9 @@
+/* @flow */
+
+import { addProp } from 'compiler/helpers'
+
+export default function text (el: ASTElement, dir: ASTDirective) {
+ if (dir.value) {
+ addProp(el, 'textContent', `_s(${dir.value})`)
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/compiler/index.js b/node_modules/vue/src/platforms/web/compiler/index.js
new file mode 100644
index 00000000..7ace0936
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/compiler/index.js
@@ -0,0 +1,8 @@
+/* @flow */
+
+import { baseOptions } from './options'
+import { createCompiler } from 'compiler/index'
+
+const { compile, compileToFunctions } = createCompiler(baseOptions)
+
+export { compile, compileToFunctions }
diff --git a/node_modules/vue/src/platforms/web/compiler/modules/class.js b/node_modules/vue/src/platforms/web/compiler/modules/class.js
new file mode 100644
index 00000000..ffdca250
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/compiler/modules/class.js
@@ -0,0 +1,48 @@
+/* @flow */
+
+import { parseText } from 'compiler/parser/text-parser'
+import {
+ getAndRemoveAttr,
+ getBindingAttr,
+ baseWarn
+} from 'compiler/helpers'
+
+function transformNode (el: ASTElement, options: CompilerOptions) {
+ const warn = options.warn || baseWarn
+ const staticClass = getAndRemoveAttr(el, 'class')
+ if (process.env.NODE_ENV !== 'production' && staticClass) {
+ const res = parseText(staticClass, options.delimiters)
+ if (res) {
+ warn(
+ `class="${staticClass}": ` +
+ 'Interpolation inside attributes has been removed. ' +
+ 'Use v-bind or the colon shorthand instead. For example, ' +
+ 'instead of <div class="{{ val }}">, use <div :class="val">.'
+ )
+ }
+ }
+ if (staticClass) {
+ el.staticClass = JSON.stringify(staticClass)
+ }
+ const classBinding = getBindingAttr(el, 'class', false /* getStatic */)
+ if (classBinding) {
+ el.classBinding = classBinding
+ }
+}
+
+function genData (el: ASTElement): string {
+ let data = ''
+ if (el.staticClass) {
+ data += `staticClass:${el.staticClass},`
+ }
+ if (el.classBinding) {
+ data += `class:${el.classBinding},`
+ }
+ return data
+}
+
+export default {
+ staticKeys: ['staticClass'],
+ transformNode,
+ genData
+}
diff --git a/node_modules/vue/src/platforms/web/compiler/modules/index.js b/node_modules/vue/src/platforms/web/compiler/modules/index.js
new file mode 100644
index 00000000..29114a53
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/compiler/modules/index.js
@@ -0,0 +1,9 @@
+import klass from './class'
+import style from './style'
+import model from './model'
+
+export default [
+ klass,
+ style,
+ model
+]
diff --git a/node_modules/vue/src/platforms/web/compiler/modules/model.js b/node_modules/vue/src/platforms/web/compiler/modules/model.js
new file mode 100644
index 00000000..8d784fe4
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/compiler/modules/model.js
@@ -0,0 +1,94 @@
+/* @flow */
+
+/**
+ * Expand input[v-model] with dyanmic type bindings into v-if-else chains
+ * Turn this:
+ * <input v-model="data[type]" :type="type">
+ * into this:
+ * <input v-if="type === 'checkbox'" type="checkbox" v-model="data[type]">
+ * <input v-else-if="type === 'radio'" type="radio" v-model="data[type]">
+ * <input v-else :type="type" v-model="data[type]">
+ */
+
+import {
+ addRawAttr,
+ getBindingAttr,
+ getAndRemoveAttr
+} from 'compiler/helpers'
+
+import {
+ processFor,
+ processElement,
+ addIfCondition,
+ createASTElement
+} from 'compiler/parser/index'
+
+function preTransformNode (el: ASTElement, options: CompilerOptions) {
+ if (el.tag === 'input') {
+ const map = el.attrsMap
+ if (!map['v-model']) {
+ return
+ }
+
+ let typeBinding
+ if (map[':type'] || map['v-bind:type']) {
+ typeBinding = getBindingAttr(el, 'type')
+ }
+ if (!map.type && !typeBinding && map['v-bind']) {
+ typeBinding = `(${map['v-bind']}).type`
+ }
+
+ if (typeBinding) {
+ const ifCondition = getAndRemoveAttr(el, 'v-if', true)
+ const ifConditionExtra = ifCondition ? `&&(${ifCondition})` : ``
+ const hasElse = getAndRemoveAttr(el, 'v-else', true) != null
+ const elseIfCondition = getAndRemoveAttr(el, 'v-else-if', true)
+ // 1. checkbox
+ const branch0 = cloneASTElement(el)
+ // process for on the main node
+ processFor(branch0)
+ addRawAttr(branch0, 'type', 'checkbox')
+ processElement(branch0, options)
+ branch0.processed = true // prevent it from double-processed
+ branch0.if = `(${typeBinding})==='checkbox'` + ifConditionExtra
+ addIfCondition(branch0, {
+ exp: branch0.if,
+ block: branch0
+ })
+ // 2. add radio else-if condition
+ const branch1 = cloneASTElement(el)
+ getAndRemoveAttr(branch1, 'v-for', true)
+ addRawAttr(branch1, 'type', 'radio')
+ processElement(branch1, options)
+ addIfCondition(branch0, {
+ exp: `(${typeBinding})==='radio'` + ifConditionExtra,
+ block: branch1
+ })
+ // 3. other
+ const branch2 = cloneASTElement(el)
+ getAndRemoveAttr(branch2, 'v-for', true)
+ addRawAttr(branch2, ':type', typeBinding)
+ processElement(branch2, options)
+ addIfCondition(branch0, {
+ exp: ifCondition,
+ block: branch2
+ })
+
+ if (hasElse) {
+ branch0.else = true
+ } else if (elseIfCondition) {
+ branch0.elseif = elseIfCondition
+ }
+
+ return branch0
+ }
+ }
+}
+
+function cloneASTElement (el) {
+ return createASTElement(el.tag, el.attrsList.slice(), el.parent)
+}
+
+export default {
+ preTransformNode
+}
diff --git a/node_modules/vue/src/platforms/web/compiler/modules/style.js b/node_modules/vue/src/platforms/web/compiler/modules/style.js
new file mode 100644
index 00000000..2722b92b
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/compiler/modules/style.js
@@ -0,0 +1,51 @@
+/* @flow */
+
+import { parseText } from 'compiler/parser/text-parser'
+import { parseStyleText } from 'web/util/style'
+import {
+ getAndRemoveAttr,
+ getBindingAttr,
+ baseWarn
+} from 'compiler/helpers'
+
+function transformNode (el: ASTElement, options: CompilerOptions) {
+ const warn = options.warn || baseWarn
+ const staticStyle = getAndRemoveAttr(el, 'style')
+ if (staticStyle) {
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production') {
+ const res = parseText(staticStyle, options.delimiters)
+ if (res) {
+ warn(
+ `style="${staticStyle}": ` +
+ 'Interpolation inside attributes has been removed. ' +
+ 'Use v-bind or the colon shorthand instead. For example, ' +
+ 'instead of <div style="{{ val }}">, use <div :style="val">.'
+ )
+ }
+ }
+ el.staticStyle = JSON.stringify(parseStyleText(staticStyle))
+ }
+
+ const styleBinding = getBindingAttr(el, 'style', false /* getStatic */)
+ if (styleBinding) {
+ el.styleBinding = styleBinding
+ }
+}
+
+function genData (el: ASTElement): string {
+ let data = ''
+ if (el.staticStyle) {
+ data += `staticStyle:${el.staticStyle},`
+ }
+ if (el.styleBinding) {
+ data += `style:(${el.styleBinding}),`
+ }
+ return data
+}
+
+export default {
+ staticKeys: ['staticStyle'],
+ transformNode,
+ genData
+}
diff --git a/node_modules/vue/src/platforms/web/compiler/options.js b/node_modules/vue/src/platforms/web/compiler/options.js
new file mode 100644
index 00000000..70c0c488
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/compiler/options.js
@@ -0,0 +1,26 @@
+/* @flow */
+
+import {
+ isPreTag,
+ mustUseProp,
+ isReservedTag,
+ getTagNamespace
+} from '../util/index'
+
+import modules from './modules/index'
+import directives from './directives/index'
+import { genStaticKeys } from 'shared/util'
+import { isUnaryTag, canBeLeftOpenTag } from './util'
+
+export const baseOptions: CompilerOptions = {
+ expectHTML: true,
+ modules,
+ directives,
+ isPreTag,
+ isUnaryTag,
+ mustUseProp,
+ canBeLeftOpenTag,
+ isReservedTag,
+ getTagNamespace,
+ staticKeys: genStaticKeys(modules)
+}
diff --git a/node_modules/vue/src/platforms/web/compiler/util.js b/node_modules/vue/src/platforms/web/compiler/util.js
new file mode 100644
index 00000000..7d9394d3
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/compiler/util.js
@@ -0,0 +1,24 @@
+/* @flow */
+
+import { makeMap } from 'shared/util'
+
+export const isUnaryTag = makeMap(
+ 'area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' +
+ 'link,meta,param,source,track,wbr'
+)
+
+// Elements that you can, intentionally, leave open
+// (and which close themselves)
+export const canBeLeftOpenTag = makeMap(
+ 'colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source'
+)
+
+// HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3
+// Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content
+export const isNonPhrasingTag = makeMap(
+ 'address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' +
+ 'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' +
+ 'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' +
+ 'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' +
+ 'title,tr,track'
+)
diff --git a/node_modules/vue/src/platforms/web/entry-compiler.js b/node_modules/vue/src/platforms/web/entry-compiler.js
new file mode 100644
index 00000000..ee63476e
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/entry-compiler.js
@@ -0,0 +1,5 @@
+/* @flow */
+
+export { parseComponent } from 'sfc/parser'
+export { compile, compileToFunctions } from './compiler/index'
+export { ssrCompile, ssrCompileToFunctions } from './server/compiler'
diff --git a/node_modules/vue/src/platforms/web/entry-runtime-with-compiler.js b/node_modules/vue/src/platforms/web/entry-runtime-with-compiler.js
new file mode 100644
index 00000000..1ebc102d
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/entry-runtime-with-compiler.js
@@ -0,0 +1,100 @@
+/* @flow */
+
+import config from 'core/config'
+import { warn, cached } from 'core/util/index'
+import { mark, measure } from 'core/util/perf'
+
+import Vue from './runtime/index'
+import { query } from './util/index'
+import { compileToFunctions } from './compiler/index'
+import { shouldDecodeNewlines, shouldDecodeNewlinesForHref } from './util/compat'
+
+const idToTemplate = cached(id => {
+ const el = query(id)
+ return el && el.innerHTML
+})
+
+const mount = Vue.prototype.$mount
+Vue.prototype.$mount = function (
+ el?: string | Element,
+ hydrating?: boolean
+): Component {
+ el = el && query(el)
+
+ /* istanbul ignore if */
+ if (el === document.body || el === document.documentElement) {
+ process.env.NODE_ENV !== 'production' && warn(
+ `Do not mount Vue to <html> or <body> - mount to normal elements instead.`
+ )
+ return this
+ }
+
+ const options = this.$options
+ // resolve template/el and convert to render function
+ if (!options.render) {
+ let template = options.template
+ if (template) {
+ if (typeof template === 'string') {
+ if (template.charAt(0) === '#') {
+ template = idToTemplate(template)
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production' && !template) {
+ warn(
+ `Template element not found or is empty: ${options.template}`,
+ this
+ )
+ }
+ }
+ } else if (template.nodeType) {
+ template = template.innerHTML
+ } else {
+ if (process.env.NODE_ENV !== 'production') {
+ warn('invalid template option:' + template, this)
+ }
+ return this
+ }
+ } else if (el) {
+ template = getOuterHTML(el)
+ }
+ if (template) {
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
+ mark('compile')
+ }
+
+ const { render, staticRenderFns } = compileToFunctions(template, {
+ shouldDecodeNewlines,
+ shouldDecodeNewlinesForHref,
+ delimiters: options.delimiters,
+ comments: options.comments
+ }, this)
+ options.render = render
+ options.staticRenderFns = staticRenderFns
+
+ /* istanbul ignore if */
+ if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
+ mark('compile end')
+ measure(`vue ${this._name} compile`, 'compile', 'compile end')
+ }
+ }
+ }
+ return mount.call(this, el, hydrating)
+}
+
+/**
+ * Get outerHTML of elements, taking care
+ * of SVG elements in IE as well.
+ */
+function getOuterHTML (el: Element): string {
+ if (el.outerHTML) {
+ return el.outerHTML
+ } else {
+ const container = document.createElement('div')
+ container.appendChild(el.cloneNode(true))
+ return container.innerHTML
+ }
+}
+
+Vue.compile = compileToFunctions
+
+export default Vue
diff --git a/node_modules/vue/src/platforms/web/entry-runtime.js b/node_modules/vue/src/platforms/web/entry-runtime.js
new file mode 100644
index 00000000..27c97ff0
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/entry-runtime.js
@@ -0,0 +1,5 @@
+/* @flow */
+
+import Vue from './runtime/index'
+
+export default Vue
diff --git a/node_modules/vue/src/platforms/web/entry-server-basic-renderer.js b/node_modules/vue/src/platforms/web/entry-server-basic-renderer.js
new file mode 100644
index 00000000..c4b973bd
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/entry-server-basic-renderer.js
@@ -0,0 +1,13 @@
+/* @flow */
+
+import modules from './server/modules/index'
+import directives from './server/directives/index'
+import { isUnaryTag, canBeLeftOpenTag } from './compiler/util'
+import { createBasicRenderer } from 'server/create-basic-renderer'
+
+export default createBasicRenderer({
+ modules,
+ directives,
+ isUnaryTag,
+ canBeLeftOpenTag
+})
diff --git a/node_modules/vue/src/platforms/web/entry-server-renderer.js b/node_modules/vue/src/platforms/web/entry-server-renderer.js
new file mode 100644
index 00000000..f61f601b
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/entry-server-renderer.js
@@ -0,0 +1,27 @@
+/* @flow */
+
+process.env.VUE_ENV = 'server'
+
+import { extend } from 'shared/util'
+import modules from './server/modules/index'
+import baseDirectives from './server/directives/index'
+import { isUnaryTag, canBeLeftOpenTag } from './compiler/util'
+
+import { createRenderer as _createRenderer } from 'server/create-renderer'
+import { createBundleRendererCreator } from 'server/bundle-renderer/create-bundle-renderer'
+
+export function createRenderer (options?: Object = {}): {
+ renderToString: Function,
+ renderToStream: Function
+} {
+ return _createRenderer(extend(extend({}, options), {
+ isUnaryTag,
+ canBeLeftOpenTag,
+ modules,
+ // user can provide server-side implementations for custom directives
+ // when creating the renderer.
+ directives: extend(baseDirectives, options.directives)
+ }))
+}
+
+export const createBundleRenderer = createBundleRendererCreator(createRenderer)
diff --git a/node_modules/vue/src/platforms/web/runtime/class-util.js b/node_modules/vue/src/platforms/web/runtime/class-util.js
new file mode 100644
index 00000000..709526c2
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/class-util.js
@@ -0,0 +1,61 @@
+/* @flow */
+
+/**
+ * Add class with compatibility for SVG since classList is not supported on
+ * SVG elements in IE
+ */
+export function addClass (el: HTMLElement, cls: ?string) {
+ /* istanbul ignore if */
+ if (!cls || !(cls = cls.trim())) {
+ return
+ }
+
+ /* istanbul ignore else */
+ if (el.classList) {
+ if (cls.indexOf(' ') > -1) {
+ cls.split(/\s+/).forEach(c => el.classList.add(c))
+ } else {
+ el.classList.add(cls)
+ }
+ } else {
+ const cur = ` ${el.getAttribute('class') || ''} `
+ if (cur.indexOf(' ' + cls + ' ') < 0) {
+ el.setAttribute('class', (cur + cls).trim())
+ }
+ }
+}
+
+/**
+ * Remove class with compatibility for SVG since classList is not supported on
+ * SVG elements in IE
+ */
+export function removeClass (el: HTMLElement, cls: ?string) {
+ /* istanbul ignore if */
+ if (!cls || !(cls = cls.trim())) {
+ return
+ }
+
+ /* istanbul ignore else */
+ if (el.classList) {
+ if (cls.indexOf(' ') > -1) {
+ cls.split(/\s+/).forEach(c => el.classList.remove(c))
+ } else {
+ el.classList.remove(cls)
+ }
+ if (!el.classList.length) {
+ el.removeAttribute('class')
+ }
+ } else {
+ let cur = ` ${el.getAttribute('class') || ''} `
+ const tar = ' ' + cls + ' '
+ while (cur.indexOf(tar) >= 0) {
+ cur = cur.replace(tar, ' ')
+ }
+ cur = cur.trim()
+ if (cur) {
+ el.setAttribute('class', cur)
+ } else {
+ el.removeAttribute('class')
+ }
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/components/index.js b/node_modules/vue/src/platforms/web/runtime/components/index.js
new file mode 100644
index 00000000..6bfe5780
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/components/index.js
@@ -0,0 +1,7 @@
+import Transition from './transition'
+import TransitionGroup from './transition-group'
+
+export default {
+ Transition,
+ TransitionGroup
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/components/transition-group.js b/node_modules/vue/src/platforms/web/runtime/components/transition-group.js
new file mode 100644
index 00000000..219ff01c
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/components/transition-group.js
@@ -0,0 +1,180 @@
+/* @flow */
+
+// Provides transition support for list items.
+// supports move transitions using the FLIP technique.
+
+// Because the vdom's children update algorithm is "unstable" - i.e.
+// it doesn't guarantee the relative positioning of removed elements,
+// we force transition-group to update its children into two passes:
+// in the first pass, we remove all nodes that need to be removed,
+// triggering their leaving transition; in the second pass, we insert/move
+// into the final desired state. This way in the second pass removed
+// nodes will remain where they should be.
+
+import { warn, extend } from 'core/util/index'
+import { addClass, removeClass } from '../class-util'
+import { transitionProps, extractTransitionData } from './transition'
+
+import {
+ hasTransition,
+ getTransitionInfo,
+ transitionEndEvent,
+ addTransitionClass,
+ removeTransitionClass
+} from '../transition-util'
+
+const props = extend({
+ tag: String,
+ moveClass: String
+}, transitionProps)
+
+delete props.mode
+
+export default {
+ props,
+
+ render (h: Function) {
+ const tag: string = this.tag || this.$vnode.data.tag || 'span'
+ const map: Object = Object.create(null)
+ const prevChildren: Array<VNode> = this.prevChildren = this.children
+ const rawChildren: Array<VNode> = this.$slots.default || []
+ const children: Array<VNode> = this.children = []
+ const transitionData: Object = extractTransitionData(this)
+
+ for (let i = 0; i < rawChildren.length; i++) {
+ const c: VNode = 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: ?VNodeComponentOptions = c.componentOptions
+ const name: string = opts ? (opts.Ctor.options.name || opts.tag || '') : c.tag
+ warn(`<transition-group> children must be keyed: <${name}>`)
+ }
+ }
+ }
+
+ if (prevChildren) {
+ const kept: Array<VNode> = []
+ const removed: Array<VNode> = []
+ for (let i = 0; i < prevChildren.length; i++) {
+ const c: VNode = prevChildren[i]
+ c.data.transition = transitionData
+ c.data.pos = c.elm.getBoundingClientRect()
+ 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: Array<VNode> = this.prevChildren
+ const moveClass: string = this.moveClass || ((this.name || 'v') + '-move')
+ if (!children.length || !this.hasMove(children[0].elm, moveClass)) {
+ return
+ }
+
+ // we divide the work into three loops to avoid mixing DOM reads and writes
+ // in each iteration - which helps prevent layout thrashing.
+ children.forEach(callPendingCbs)
+ children.forEach(recordPosition)
+ children.forEach(applyTranslation)
+
+ // force reflow to put everything in position
+ // assign to this to avoid being removed in tree-shaking
+ // $flow-disable-line
+ this._reflow = document.body.offsetHeight
+
+ children.forEach((c: VNode) => {
+ if (c.data.moved) {
+ var el: any = c.elm
+ var s: any = el.style
+ addTransitionClass(el, moveClass)
+ s.transform = s.WebkitTransform = s.transitionDuration = ''
+ el.addEventListener(transitionEndEvent, el._moveCb = function cb (e) {
+ if (!e || /transform$/.test(e.propertyName)) {
+ el.removeEventListener(transitionEndEvent, cb)
+ el._moveCb = null
+ removeTransitionClass(el, moveClass)
+ }
+ })
+ }
+ })
+ },
+
+ methods: {
+ hasMove (el: any, moveClass: string): boolean {
+ /* istanbul ignore if */
+ if (!hasTransition) {
+ return false
+ }
+ /* istanbul ignore if */
+ if (this._hasMove) {
+ return this._hasMove
+ }
+ // Detect whether an element with the move class applied has
+ // CSS transitions. Since the element may be inside an entering
+ // transition at this very moment, we make a clone of it and remove
+ // all other transition classes applied to ensure only the move class
+ // is applied.
+ const clone: HTMLElement = el.cloneNode()
+ if (el._transitionClasses) {
+ el._transitionClasses.forEach((cls: string) => { removeClass(clone, cls) })
+ }
+ addClass(clone, moveClass)
+ clone.style.display = 'none'
+ this.$el.appendChild(clone)
+ const info: Object = getTransitionInfo(clone)
+ this.$el.removeChild(clone)
+ return (this._hasMove = info.hasTransform)
+ }
+ }
+}
+
+function callPendingCbs (c: VNode) {
+ /* istanbul ignore if */
+ if (c.elm._moveCb) {
+ c.elm._moveCb()
+ }
+ /* istanbul ignore if */
+ if (c.elm._enterCb) {
+ c.elm._enterCb()
+ }
+}
+
+function recordPosition (c: VNode) {
+ c.data.newPos = c.elm.getBoundingClientRect()
+}
+
+function applyTranslation (c: VNode) {
+ 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
+ const s = c.elm.style
+ s.transform = s.WebkitTransform = `translate(${dx}px,${dy}px)`
+ s.transitionDuration = '0s'
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/components/transition.js b/node_modules/vue/src/platforms/web/runtime/components/transition.js
new file mode 100644
index 00000000..6111d8cb
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/components/transition.js
@@ -0,0 +1,194 @@
+/* @flow */
+
+// Provides transition support for a single element/component.
+// supports transition mode (out-in / in-out)
+
+import { warn } from 'core/util/index'
+import { camelize, extend, isPrimitive } from 'shared/util'
+import {
+ mergeVNodeHook,
+ isAsyncPlaceholder,
+ getFirstComponentChild
+} from 'core/vdom/helpers/index'
+
+export const transitionProps = {
+ name: String,
+ appear: Boolean,
+ css: Boolean,
+ mode: String,
+ type: String,
+ enterClass: String,
+ leaveClass: String,
+ enterToClass: String,
+ leaveToClass: String,
+ enterActiveClass: String,
+ leaveActiveClass: String,
+ appearClass: String,
+ appearActiveClass: String,
+ appearToClass: String,
+ duration: [Number, String, Object]
+}
+
+// in case the child is also an abstract component, e.g. <keep-alive>
+// we want to recursively retrieve the real component to be rendered
+function getRealChild (vnode: ?VNode): ?VNode {
+ const compOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
+ if (compOptions && compOptions.Ctor.options.abstract) {
+ return getRealChild(getFirstComponentChild(compOptions.children))
+ } else {
+ return vnode
+ }
+}
+
+export function extractTransitionData (comp: Component): Object {
+ const data = {}
+ const options: ComponentOptions = comp.$options
+ // props
+ for (const key in options.propsData) {
+ data[key] = comp[key]
+ }
+ // events.
+ // extract listeners and pass them directly to the transition methods
+ const listeners: ?Object = options._parentListeners
+ for (const key in listeners) {
+ data[camelize(key)] = listeners[key]
+ }
+ return data
+}
+
+function placeholder (h: Function, rawChild: VNode): ?VNode {
+ if (/\d-keep-alive$/.test(rawChild.tag)) {
+ return h('keep-alive', {
+ props: rawChild.componentOptions.propsData
+ })
+ }
+}
+
+function hasParentTransition (vnode: VNode): ?boolean {
+ while ((vnode = vnode.parent)) {
+ if (vnode.data.transition) {
+ return true
+ }
+ }
+}
+
+function isSameChild (child: VNode, oldChild: VNode): boolean {
+ return oldChild.key === child.key && oldChild.tag === child.tag
+}
+
+export default {
+ name: 'transition',
+ props: transitionProps,
+ abstract: true,
+
+ render (h: Function) {
+ let children: any = this.$slots.default
+ if (!children) {
+ return
+ }
+
+ // filter out text nodes (possible whitespaces)
+ children = children.filter((c: VNode) => c.tag || isAsyncPlaceholder(c))
+ /* istanbul ignore if */
+ if (!children.length) {
+ return
+ }
+
+ // warn multiple elements
+ if (process.env.NODE_ENV !== 'production' && children.length > 1) {
+ warn(
+ '<transition> can only be used on a single element. Use ' +
+ '<transition-group> for lists.',
+ this.$parent
+ )
+ }
+
+ const mode: string = this.mode
+
+ // warn invalid mode
+ if (process.env.NODE_ENV !== 'production' &&
+ mode && mode !== 'in-out' && mode !== 'out-in'
+ ) {
+ warn(
+ 'invalid <transition> mode: ' + mode,
+ this.$parent
+ )
+ }
+
+ const rawChild: VNode = children[0]
+
+ // if this is a component root node and the component's
+ // parent container node also has transition, skip.
+ if (hasParentTransition(this.$vnode)) {
+ return rawChild
+ }
+
+ // apply transition data to child
+ // use getRealChild() to ignore abstract components e.g. keep-alive
+ const child: ?VNode = getRealChild(rawChild)
+ /* istanbul ignore if */
+ if (!child) {
+ return rawChild
+ }
+
+ if (this._leaving) {
+ return placeholder(h, rawChild)
+ }
+
+ // ensure a key that is unique to the vnode type and to this transition
+ // component instance. This key will be used to remove pending leaving nodes
+ // during entering.
+ const id: string = `__transition-${this._uid}-`
+ child.key = child.key == null
+ ? child.isComment
+ ? id + 'comment'
+ : id + child.tag
+ : isPrimitive(child.key)
+ ? (String(child.key).indexOf(id) === 0 ? child.key : id + child.key)
+ : child.key
+
+ const data: Object = (child.data || (child.data = {})).transition = extractTransitionData(this)
+ const oldRawChild: VNode = this._vnode
+ const oldChild: VNode = getRealChild(oldRawChild)
+
+ // mark v-show
+ // so that the transition module can hand over the control to the directive
+ if (child.data.directives && child.data.directives.some(d => d.name === 'show')) {
+ child.data.show = true
+ }
+
+ if (
+ oldChild &&
+ oldChild.data &&
+ !isSameChild(child, oldChild) &&
+ !isAsyncPlaceholder(oldChild) &&
+ // #6687 component root is a comment node
+ !(oldChild.componentInstance && oldChild.componentInstance._vnode.isComment)
+ ) {
+ // replace old child transition data with fresh one
+ // important for dynamic transitions!
+ const oldData: Object = oldChild.data.transition = extend({}, data)
+ // handle transition mode
+ if (mode === 'out-in') {
+ // return placeholder node and queue update when leave finishes
+ this._leaving = true
+ mergeVNodeHook(oldData, 'afterLeave', () => {
+ this._leaving = false
+ this.$forceUpdate()
+ })
+ return placeholder(h, rawChild)
+ } else if (mode === 'in-out') {
+ if (isAsyncPlaceholder(child)) {
+ return oldRawChild
+ }
+ let delayedLeave
+ const performLeave = () => { delayedLeave() }
+ mergeVNodeHook(data, 'afterEnter', performLeave)
+ mergeVNodeHook(data, 'enterCancelled', performLeave)
+ mergeVNodeHook(oldData, 'delayLeave', leave => { delayedLeave = leave })
+ }
+ }
+
+ return rawChild
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/directives/index.js b/node_modules/vue/src/platforms/web/runtime/directives/index.js
new file mode 100644
index 00000000..b673f11a
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/directives/index.js
@@ -0,0 +1,7 @@
+import model from './model'
+import show from './show'
+
+export default {
+ model,
+ show
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/directives/model.js b/node_modules/vue/src/platforms/web/runtime/directives/model.js
new file mode 100644
index 00000000..cba8ded0
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/directives/model.js
@@ -0,0 +1,147 @@
+/**
+ * Not type checking this file because flow doesn't like attaching
+ * properties to Elements.
+ */
+
+import { isTextInputType } from 'web/util/element'
+import { looseEqual, looseIndexOf } from 'shared/util'
+import { mergeVNodeHook } from 'core/vdom/helpers/index'
+import { warn, isIE9, isIE, isEdge } from 'core/util/index'
+
+/* istanbul ignore if */
+if (isIE9) {
+ // http://www.matts411.com/post/internet-explorer-9-oninput/
+ document.addEventListener('selectionchange', () => {
+ const el = document.activeElement
+ if (el && el.vmodel) {
+ trigger(el, 'input')
+ }
+ })
+}
+
+const directive = {
+ inserted (el, binding, vnode, oldVnode) {
+ if (vnode.tag === 'select') {
+ // #6903
+ if (oldVnode.elm && !oldVnode.elm._vOptions) {
+ mergeVNodeHook(vnode, 'postpatch', () => {
+ directive.componentUpdated(el, binding, vnode)
+ })
+ } else {
+ setSelected(el, binding, vnode.context)
+ }
+ el._vOptions = [].map.call(el.options, getValue)
+ } else if (vnode.tag === 'textarea' || isTextInputType(el.type)) {
+ el._vModifiers = binding.modifiers
+ if (!binding.modifiers.lazy) {
+ el.addEventListener('compositionstart', onCompositionStart)
+ el.addEventListener('compositionend', onCompositionEnd)
+ // Safari < 10.2 & UIWebView doesn't fire compositionend when
+ // switching focus before confirming composition choice
+ // this also fixes the issue where some browsers e.g. iOS Chrome
+ // fires "change" instead of "input" on autocomplete.
+ el.addEventListener('change', onCompositionEnd)
+ /* istanbul ignore if */
+ if (isIE9) {
+ el.vmodel = true
+ }
+ }
+ }
+ },
+
+ componentUpdated (el, binding, vnode) {
+ if (vnode.tag === 'select') {
+ setSelected(el, binding, vnode.context)
+ // in case the options rendered by v-for have changed,
+ // it's possible that the value is out-of-sync with the rendered options.
+ // detect such cases and filter out values that no longer has a matching
+ // option in the DOM.
+ const prevOptions = el._vOptions
+ const curOptions = el._vOptions = [].map.call(el.options, getValue)
+ if (curOptions.some((o, i) => !looseEqual(o, prevOptions[i]))) {
+ // trigger change event if
+ // no matching option found for at least one value
+ const needReset = el.multiple
+ ? binding.value.some(v => hasNoMatchingOption(v, curOptions))
+ : binding.value !== binding.oldValue && hasNoMatchingOption(binding.value, curOptions)
+ if (needReset) {
+ trigger(el, 'change')
+ }
+ }
+ }
+ }
+}
+
+function setSelected (el, binding, vm) {
+ actuallySetSelected(el, binding, vm)
+ /* istanbul ignore if */
+ if (isIE || isEdge) {
+ setTimeout(() => {
+ actuallySetSelected(el, binding, vm)
+ }, 0)
+ }
+}
+
+function actuallySetSelected (el, binding, vm) {
+ const value = binding.value
+ const isMultiple = el.multiple
+ if (isMultiple && !Array.isArray(value)) {
+ process.env.NODE_ENV !== 'production' && warn(
+ `<select multiple v-model="${binding.expression}"> ` +
+ `expects an Array value for its binding, but got ${
+ Object.prototype.toString.call(value).slice(8, -1)
+ }`,
+ vm
+ )
+ return
+ }
+ let selected, option
+ for (let i = 0, l = el.options.length; i < l; i++) {
+ option = el.options[i]
+ if (isMultiple) {
+ selected = looseIndexOf(value, getValue(option)) > -1
+ if (option.selected !== selected) {
+ option.selected = selected
+ }
+ } else {
+ if (looseEqual(getValue(option), value)) {
+ if (el.selectedIndex !== i) {
+ el.selectedIndex = i
+ }
+ return
+ }
+ }
+ }
+ if (!isMultiple) {
+ el.selectedIndex = -1
+ }
+}
+
+function hasNoMatchingOption (value, options) {
+ return options.every(o => !looseEqual(o, value))
+}
+
+function getValue (option) {
+ return '_value' in option
+ ? option._value
+ : option.value
+}
+
+function onCompositionStart (e) {
+ e.target.composing = true
+}
+
+function onCompositionEnd (e) {
+ // prevent triggering an input event for no reason
+ if (!e.target.composing) return
+ e.target.composing = false
+ trigger(e.target, 'input')
+}
+
+function trigger (el, type) {
+ const e = document.createEvent('HTMLEvents')
+ e.initEvent(type, true, true)
+ el.dispatchEvent(e)
+}
+
+export default directive
diff --git a/node_modules/vue/src/platforms/web/runtime/directives/show.js b/node_modules/vue/src/platforms/web/runtime/directives/show.js
new file mode 100644
index 00000000..17fb5dec
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/directives/show.js
@@ -0,0 +1,60 @@
+/* @flow */
+
+import { enter, leave } from '../modules/transition'
+
+// recursively search for possible transition defined inside the component root
+function locateNode (vnode: VNode): VNodeWithData {
+ return vnode.componentInstance && (!vnode.data || !vnode.data.transition)
+ ? locateNode(vnode.componentInstance._vnode)
+ : vnode
+}
+
+export default {
+ bind (el: any, { value }: VNodeDirective, vnode: VNodeWithData) {
+ vnode = locateNode(vnode)
+ const transition = vnode.data && vnode.data.transition
+ const originalDisplay = el.__vOriginalDisplay =
+ el.style.display === 'none' ? '' : el.style.display
+ if (value && transition) {
+ vnode.data.show = true
+ enter(vnode, () => {
+ el.style.display = originalDisplay
+ })
+ } else {
+ el.style.display = value ? originalDisplay : 'none'
+ }
+ },
+
+ update (el: any, { value, oldValue }: VNodeDirective, vnode: VNodeWithData) {
+ /* istanbul ignore if */
+ if (!value === !oldValue) return
+ vnode = locateNode(vnode)
+ const transition = vnode.data && vnode.data.transition
+ if (transition) {
+ vnode.data.show = true
+ if (value) {
+ enter(vnode, () => {
+ el.style.display = el.__vOriginalDisplay
+ })
+ } else {
+ leave(vnode, () => {
+ el.style.display = 'none'
+ })
+ }
+ } else {
+ el.style.display = value ? el.__vOriginalDisplay : 'none'
+ }
+ },
+
+ unbind (
+ el: any,
+ binding: VNodeDirective,
+ vnode: VNodeWithData,
+ oldVnode: VNodeWithData,
+ isDestroy: boolean
+ ) {
+ if (!isDestroy) {
+ el.style.display = el.__vOriginalDisplay
+ }
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/index.js b/node_modules/vue/src/platforms/web/runtime/index.js
new file mode 100644
index 00000000..1283f521
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/index.js
@@ -0,0 +1,77 @@
+/* @flow */
+
+import Vue from 'core/index'
+import config from 'core/config'
+import { extend, noop } from 'shared/util'
+import { mountComponent } from 'core/instance/lifecycle'
+import { devtools, inBrowser, isChrome } from 'core/util/index'
+
+import {
+ query,
+ mustUseProp,
+ isReservedTag,
+ isReservedAttr,
+ getTagNamespace,
+ isUnknownElement
+} from 'web/util/index'
+
+import { patch } from './patch'
+import platformDirectives from './directives/index'
+import platformComponents from './components/index'
+
+// install platform specific utils
+Vue.config.mustUseProp = mustUseProp
+Vue.config.isReservedTag = isReservedTag
+Vue.config.isReservedAttr = isReservedAttr
+Vue.config.getTagNamespace = getTagNamespace
+Vue.config.isUnknownElement = isUnknownElement
+
+// install platform runtime directives & components
+extend(Vue.options.directives, platformDirectives)
+extend(Vue.options.components, platformComponents)
+
+// install platform patch function
+Vue.prototype.__patch__ = inBrowser ? patch : noop
+
+// public mount method
+Vue.prototype.$mount = function (
+ el?: string | Element,
+ hydrating?: boolean
+): Component {
+ el = el && inBrowser ? query(el) : undefined
+ return mountComponent(this, el, hydrating)
+}
+
+// devtools global hook
+/* istanbul ignore next */
+if (inBrowser) {
+ setTimeout(() => {
+ if (config.devtools) {
+ if (devtools) {
+ devtools.emit('init', Vue)
+ } else if (
+ process.env.NODE_ENV !== 'production' &&
+ process.env.NODE_ENV !== 'test' &&
+ isChrome
+ ) {
+ console[console.info ? 'info' : 'log'](
+ 'Download the Vue Devtools extension for a better development experience:\n' +
+ 'https://github.com/vuejs/vue-devtools'
+ )
+ }
+ }
+ if (process.env.NODE_ENV !== 'production' &&
+ process.env.NODE_ENV !== 'test' &&
+ config.productionTip !== false &&
+ typeof console !== 'undefined'
+ ) {
+ console[console.info ? 'info' : 'log'](
+ `You are running Vue in development mode.\n` +
+ `Make sure to turn on production mode when deploying for production.\n` +
+ `See more tips at https://vuejs.org/guide/deployment.html`
+ )
+ }
+ }, 0)
+}
+
+export default Vue
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/attrs.js b/node_modules/vue/src/platforms/web/runtime/modules/attrs.js
new file mode 100644
index 00000000..78ef28a1
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/attrs.js
@@ -0,0 +1,118 @@
+/* @flow */
+
+import { isIE, isIE9, isEdge } from 'core/util/env'
+
+import {
+ extend,
+ isDef,
+ isUndef
+} from 'shared/util'
+
+import {
+ isXlink,
+ xlinkNS,
+ getXlinkProp,
+ isBooleanAttr,
+ isEnumeratedAttr,
+ isFalsyAttrValue
+} from 'web/util/index'
+
+function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ const opts = vnode.componentOptions
+ if (isDef(opts) && opts.Ctor.options.inheritAttrs === false) {
+ return
+ }
+ if (isUndef(oldVnode.data.attrs) && isUndef(vnode.data.attrs)) {
+ return
+ }
+ let key, cur, old
+ const elm = vnode.elm
+ const oldAttrs = oldVnode.data.attrs || {}
+ let attrs: any = vnode.data.attrs || {}
+ // clone observed objects, as the user probably wants to mutate it
+ if (isDef(attrs.__ob__)) {
+ attrs = vnode.data.attrs = extend({}, attrs)
+ }
+
+ for (key in attrs) {
+ cur = attrs[key]
+ old = oldAttrs[key]
+ if (old !== cur) {
+ setAttr(elm, key, cur)
+ }
+ }
+ // #4391: in IE9, setting type can reset value for input[type=radio]
+ // #6666: IE/Edge forces progress value down to 1 before setting a max
+ /* istanbul ignore if */
+ if ((isIE || isEdge) && attrs.value !== oldAttrs.value) {
+ setAttr(elm, 'value', attrs.value)
+ }
+ for (key in oldAttrs) {
+ if (isUndef(attrs[key])) {
+ if (isXlink(key)) {
+ elm.removeAttributeNS(xlinkNS, getXlinkProp(key))
+ } else if (!isEnumeratedAttr(key)) {
+ elm.removeAttribute(key)
+ }
+ }
+ }
+}
+
+function setAttr (el: Element, key: string, value: any) {
+ if (el.tagName.indexOf('-') > -1) {
+ baseSetAttr(el, key, value)
+ } else if (isBooleanAttr(key)) {
+ // set attribute for blank value
+ // e.g. <option disabled>Select one</option>
+ if (isFalsyAttrValue(value)) {
+ el.removeAttribute(key)
+ } else {
+ // technically allowfullscreen is a boolean attribute for <iframe>,
+ // but Flash expects a value of "true" when used on <embed> tag
+ value = key === 'allowfullscreen' && el.tagName === 'EMBED'
+ ? 'true'
+ : key
+ el.setAttribute(key, value)
+ }
+ } else if (isEnumeratedAttr(key)) {
+ el.setAttribute(key, isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true')
+ } else if (isXlink(key)) {
+ if (isFalsyAttrValue(value)) {
+ el.removeAttributeNS(xlinkNS, getXlinkProp(key))
+ } else {
+ el.setAttributeNS(xlinkNS, key, value)
+ }
+ } else {
+ baseSetAttr(el, key, value)
+ }
+}
+
+function baseSetAttr (el, key, value) {
+ if (isFalsyAttrValue(value)) {
+ el.removeAttribute(key)
+ } else {
+ // #7138: IE10 & 11 fires input event when setting placeholder on
+ // <textarea>... block the first input event and remove the blocker
+ // immediately.
+ /* istanbul ignore if */
+ if (
+ isIE && !isIE9 &&
+ el.tagName === 'TEXTAREA' &&
+ key === 'placeholder' && !el.__ieph
+ ) {
+ const blocker = e => {
+ e.stopImmediatePropagation()
+ el.removeEventListener('input', blocker)
+ }
+ el.addEventListener('input', blocker)
+ // $flow-disable-line
+ el.__ieph = true /* IE placeholder patched */
+ }
+ el.setAttribute(key, value)
+ }
+}
+
+export default {
+ create: updateAttrs,
+ update: updateAttrs
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/class.js b/node_modules/vue/src/platforms/web/runtime/modules/class.js
new file mode 100644
index 00000000..29fd2c11
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/class.js
@@ -0,0 +1,48 @@
+/* @flow */
+
+import {
+ isDef,
+ isUndef
+} from 'shared/util'
+
+import {
+ concat,
+ stringifyClass,
+ genClassForVnode
+} from 'web/util/index'
+
+function updateClass (oldVnode: any, vnode: any) {
+ const el = vnode.elm
+ const data: VNodeData = vnode.data
+ const oldData: VNodeData = oldVnode.data
+ if (
+ isUndef(data.staticClass) &&
+ isUndef(data.class) && (
+ isUndef(oldData) || (
+ isUndef(oldData.staticClass) &&
+ isUndef(oldData.class)
+ )
+ )
+ ) {
+ return
+ }
+
+ let cls = genClassForVnode(vnode)
+
+ // handle transition classes
+ const transitionClass = el._transitionClasses
+ if (isDef(transitionClass)) {
+ cls = concat(cls, stringifyClass(transitionClass))
+ }
+
+ // set the class
+ if (cls !== el._prevClass) {
+ el.setAttribute('class', cls)
+ el._prevClass = cls
+ }
+}
+
+export default {
+ create: updateClass,
+ update: updateClass
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/dom-props.js b/node_modules/vue/src/platforms/web/runtime/modules/dom-props.js
new file mode 100644
index 00000000..f3888aed
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/dom-props.js
@@ -0,0 +1,95 @@
+/* @flow */
+
+import { isDef, isUndef, extend, toNumber } from 'shared/util'
+
+function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (isUndef(oldVnode.data.domProps) && isUndef(vnode.data.domProps)) {
+ return
+ }
+ let key, cur
+ const elm: any = vnode.elm
+ const oldProps = oldVnode.data.domProps || {}
+ let props = vnode.data.domProps || {}
+ // clone observed objects, as the user probably wants to mutate it
+ if (isDef(props.__ob__)) {
+ props = vnode.data.domProps = extend({}, props)
+ }
+
+ for (key in oldProps) {
+ if (isUndef(props[key])) {
+ elm[key] = ''
+ }
+ }
+ for (key in props) {
+ cur = props[key]
+ // ignore children if the node has textContent or innerHTML,
+ // as these will throw away existing DOM nodes and cause removal errors
+ // on subsequent patches (#3360)
+ if (key === 'textContent' || key === 'innerHTML') {
+ if (vnode.children) vnode.children.length = 0
+ if (cur === oldProps[key]) continue
+ // #6601 work around Chrome version <= 55 bug where single textNode
+ // replaced by innerHTML/textContent retains its parentNode property
+ if (elm.childNodes.length === 1) {
+ elm.removeChild(elm.childNodes[0])
+ }
+ }
+
+ if (key === 'value') {
+ // store value as _value as well since
+ // non-string values will be stringified
+ elm._value = cur
+ // avoid resetting cursor position when value is the same
+ const strCur = isUndef(cur) ? '' : String(cur)
+ if (shouldUpdateValue(elm, strCur)) {
+ elm.value = strCur
+ }
+ } else {
+ elm[key] = cur
+ }
+ }
+}
+
+// check platforms/web/util/attrs.js acceptValue
+type acceptValueElm = HTMLInputElement | HTMLSelectElement | HTMLOptionElement;
+
+function shouldUpdateValue (elm: acceptValueElm, checkVal: string): boolean {
+ return (!elm.composing && (
+ elm.tagName === 'OPTION' ||
+ isNotInFocusAndDirty(elm, checkVal) ||
+ isDirtyWithModifiers(elm, checkVal)
+ ))
+}
+
+function isNotInFocusAndDirty (elm: acceptValueElm, checkVal: string): boolean {
+ // return true when textbox (.number and .trim) loses focus and its value is
+ // not equal to the updated value
+ let notInFocus = true
+ // #6157
+ // work around IE bug when accessing document.activeElement in an iframe
+ try { notInFocus = document.activeElement !== elm } catch (e) {}
+ return notInFocus && elm.value !== checkVal
+}
+
+function isDirtyWithModifiers (elm: any, newVal: string): boolean {
+ const value = elm.value
+ const modifiers = elm._vModifiers // injected by v-model runtime
+ if (isDef(modifiers)) {
+ if (modifiers.lazy) {
+ // inputs with lazy should only be updated when not in focus
+ return false
+ }
+ if (modifiers.number) {
+ return toNumber(value) !== toNumber(newVal)
+ }
+ if (modifiers.trim) {
+ return value.trim() !== newVal.trim()
+ }
+ }
+ return value !== newVal
+}
+
+export default {
+ create: updateDOMProps,
+ update: updateDOMProps
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/events.js b/node_modules/vue/src/platforms/web/runtime/modules/events.js
new file mode 100644
index 00000000..1e71b667
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/events.js
@@ -0,0 +1,87 @@
+/* @flow */
+
+import { isDef, isUndef } from 'shared/util'
+import { updateListeners } from 'core/vdom/helpers/index'
+import { withMacroTask, isIE, supportsPassive } from 'core/util/index'
+import { RANGE_TOKEN, CHECKBOX_RADIO_TOKEN } from 'web/compiler/directives/model'
+
+// normalize v-model event tokens that can only be determined at runtime.
+// it's important to place the event as the first in the array because
+// the whole point is ensuring the v-model callback gets called before
+// user-attached handlers.
+function normalizeEvents (on) {
+ /* istanbul ignore if */
+ if (isDef(on[RANGE_TOKEN])) {
+ // IE input[type=range] only supports `change` event
+ const event = isIE ? 'change' : 'input'
+ on[event] = [].concat(on[RANGE_TOKEN], on[event] || [])
+ delete on[RANGE_TOKEN]
+ }
+ // This was originally intended to fix #4521 but no longer necessary
+ // after 2.5. Keeping it for backwards compat with generated code from < 2.4
+ /* istanbul ignore if */
+ if (isDef(on[CHECKBOX_RADIO_TOKEN])) {
+ on.change = [].concat(on[CHECKBOX_RADIO_TOKEN], on.change || [])
+ delete on[CHECKBOX_RADIO_TOKEN]
+ }
+}
+
+let target: any
+
+function createOnceHandler (handler, event, capture) {
+ const _target = target // save current target element in closure
+ return function onceHandler () {
+ const res = handler.apply(null, arguments)
+ if (res !== null) {
+ remove(event, onceHandler, capture, _target)
+ }
+ }
+}
+
+function add (
+ event: string,
+ handler: Function,
+ once: boolean,
+ capture: boolean,
+ passive: boolean
+) {
+ handler = withMacroTask(handler)
+ if (once) handler = createOnceHandler(handler, event, capture)
+ target.addEventListener(
+ event,
+ handler,
+ supportsPassive
+ ? { capture, passive }
+ : capture
+ )
+}
+
+function remove (
+ event: string,
+ handler: Function,
+ capture: boolean,
+ _target?: HTMLElement
+) {
+ (_target || target).removeEventListener(
+ event,
+ handler._withTask || handler,
+ capture
+ )
+}
+
+function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ if (isUndef(oldVnode.data.on) && isUndef(vnode.data.on)) {
+ return
+ }
+ const on = vnode.data.on || {}
+ const oldOn = oldVnode.data.on || {}
+ target = vnode.elm
+ normalizeEvents(on)
+ updateListeners(on, oldOn, add, remove, vnode.context)
+ target = undefined
+}
+
+export default {
+ create: updateDOMListeners,
+ update: updateDOMListeners
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/index.js b/node_modules/vue/src/platforms/web/runtime/modules/index.js
new file mode 100644
index 00000000..9f6ad8f9
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/index.js
@@ -0,0 +1,15 @@
+import attrs from './attrs'
+import klass from './class'
+import events from './events'
+import domProps from './dom-props'
+import style from './style'
+import transition from './transition'
+
+export default [
+ attrs,
+ klass,
+ events,
+ domProps,
+ style,
+ transition
+]
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/style.js b/node_modules/vue/src/platforms/web/runtime/modules/style.js
new file mode 100644
index 00000000..29e1c3c1
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/style.js
@@ -0,0 +1,93 @@
+/* @flow */
+
+import { getStyle, normalizeStyleBinding } from 'web/util/style'
+import { cached, camelize, extend, isDef, isUndef } from 'shared/util'
+
+const cssVarRE = /^--/
+const importantRE = /\s*!important$/
+const setProp = (el, name, val) => {
+ /* istanbul ignore if */
+ if (cssVarRE.test(name)) {
+ el.style.setProperty(name, val)
+ } else if (importantRE.test(val)) {
+ el.style.setProperty(name, val.replace(importantRE, ''), 'important')
+ } else {
+ const normalizedName = normalize(name)
+ if (Array.isArray(val)) {
+ // Support values array created by autoprefixer, e.g.
+ // {display: ["-webkit-box", "-ms-flexbox", "flex"]}
+ // Set them one by one, and the browser will only set those it can recognize
+ for (let i = 0, len = val.length; i < len; i++) {
+ el.style[normalizedName] = val[i]
+ }
+ } else {
+ el.style[normalizedName] = val
+ }
+ }
+}
+
+const vendorNames = ['Webkit', 'Moz', 'ms']
+
+let emptyStyle
+const normalize = cached(function (prop) {
+ emptyStyle = emptyStyle || document.createElement('div').style
+ prop = camelize(prop)
+ if (prop !== 'filter' && (prop in emptyStyle)) {
+ return prop
+ }
+ const capName = prop.charAt(0).toUpperCase() + prop.slice(1)
+ for (let i = 0; i < vendorNames.length; i++) {
+ const name = vendorNames[i] + capName
+ if (name in emptyStyle) {
+ return name
+ }
+ }
+})
+
+function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
+ const data = vnode.data
+ const oldData = oldVnode.data
+
+ if (isUndef(data.staticStyle) && isUndef(data.style) &&
+ isUndef(oldData.staticStyle) && isUndef(oldData.style)
+ ) {
+ return
+ }
+
+ let cur, name
+ const el: any = vnode.elm
+ const oldStaticStyle: any = oldData.staticStyle
+ const oldStyleBinding: any = oldData.normalizedStyle || oldData.style || {}
+
+ // if static style exists, stylebinding already merged into it when doing normalizeStyleData
+ const oldStyle = oldStaticStyle || oldStyleBinding
+
+ const style = normalizeStyleBinding(vnode.data.style) || {}
+
+ // store normalized style under a different key for next diff
+ // make sure to clone it if it's reactive, since the user likely wants
+ // to mutate it.
+ vnode.data.normalizedStyle = isDef(style.__ob__)
+ ? extend({}, style)
+ : style
+
+ const newStyle = getStyle(vnode, true)
+
+ for (name in oldStyle) {
+ if (isUndef(newStyle[name])) {
+ setProp(el, name, '')
+ }
+ }
+ for (name in newStyle) {
+ cur = newStyle[name]
+ if (cur !== oldStyle[name]) {
+ // ie9 setting to null has no effect, must use empty string
+ setProp(el, name, cur == null ? '' : cur)
+ }
+ }
+}
+
+export default {
+ create: updateStyle,
+ update: updateStyle
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/modules/transition.js b/node_modules/vue/src/platforms/web/runtime/modules/transition.js
new file mode 100644
index 00000000..0796b5da
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/modules/transition.js
@@ -0,0 +1,343 @@
+/* @flow */
+
+import { inBrowser, isIE9, warn } from 'core/util/index'
+import { mergeVNodeHook } from 'core/vdom/helpers/index'
+import { activeInstance } from 'core/instance/lifecycle'
+
+import {
+ once,
+ isDef,
+ isUndef,
+ isObject,
+ toNumber
+} from 'shared/util'
+
+import {
+ nextFrame,
+ resolveTransition,
+ whenTransitionEnds,
+ addTransitionClass,
+ removeTransitionClass
+} from '../transition-util'
+
+export function enter (vnode: VNodeWithData, toggleDisplay: ?() => void) {
+ const el: any = vnode.elm
+
+ // call leave callback now
+ if (isDef(el._leaveCb)) {
+ el._leaveCb.cancelled = true
+ el._leaveCb()
+ }
+
+ const data = resolveTransition(vnode.data.transition)
+ if (isUndef(data)) {
+ return
+ }
+
+ /* istanbul ignore if */
+ if (isDef(el._enterCb) || el.nodeType !== 1) {
+ return
+ }
+
+ const {
+ css,
+ type,
+ enterClass,
+ enterToClass,
+ enterActiveClass,
+ appearClass,
+ appearToClass,
+ appearActiveClass,
+ beforeEnter,
+ enter,
+ afterEnter,
+ enterCancelled,
+ beforeAppear,
+ appear,
+ afterAppear,
+ appearCancelled,
+ duration
+ } = data
+
+ // activeInstance will always be the <transition> component managing this
+ // transition. One edge case to check is when the <transition> is placed
+ // as the root node of a child component. In that case we need to check
+ // <transition>'s parent for appear check.
+ let context = activeInstance
+ let transitionNode = activeInstance.$vnode
+ while (transitionNode && transitionNode.parent) {
+ transitionNode = transitionNode.parent
+ context = transitionNode.context
+ }
+
+ const isAppear = !context._isMounted || !vnode.isRootInsert
+
+ if (isAppear && !appear && appear !== '') {
+ return
+ }
+
+ const startClass = isAppear && appearClass
+ ? appearClass
+ : enterClass
+ const activeClass = isAppear && appearActiveClass
+ ? appearActiveClass
+ : enterActiveClass
+ const toClass = isAppear && appearToClass
+ ? appearToClass
+ : enterToClass
+
+ const beforeEnterHook = isAppear
+ ? (beforeAppear || beforeEnter)
+ : beforeEnter
+ const enterHook = isAppear
+ ? (typeof appear === 'function' ? appear : enter)
+ : enter
+ const afterEnterHook = isAppear
+ ? (afterAppear || afterEnter)
+ : afterEnter
+ const enterCancelledHook = isAppear
+ ? (appearCancelled || enterCancelled)
+ : enterCancelled
+
+ const explicitEnterDuration: any = toNumber(
+ isObject(duration)
+ ? duration.enter
+ : duration
+ )
+
+ if (process.env.NODE_ENV !== 'production' && explicitEnterDuration != null) {
+ checkDuration(explicitEnterDuration, 'enter', vnode)
+ }
+
+ const expectsCSS = css !== false && !isIE9
+ const userWantsControl = getHookArgumentsLength(enterHook)
+
+ const cb = el._enterCb = once(() => {
+ if (expectsCSS) {
+ removeTransitionClass(el, toClass)
+ removeTransitionClass(el, activeClass)
+ }
+ if (cb.cancelled) {
+ if (expectsCSS) {
+ removeTransitionClass(el, startClass)
+ }
+ enterCancelledHook && enterCancelledHook(el)
+ } else {
+ afterEnterHook && afterEnterHook(el)
+ }
+ el._enterCb = null
+ })
+
+ if (!vnode.data.show) {
+ // remove pending leave element on enter by injecting an insert hook
+ mergeVNodeHook(vnode, 'insert', () => {
+ const parent = el.parentNode
+ const pendingNode = parent && parent._pending && parent._pending[vnode.key]
+ if (pendingNode &&
+ pendingNode.tag === vnode.tag &&
+ pendingNode.elm._leaveCb
+ ) {
+ pendingNode.elm._leaveCb()
+ }
+ enterHook && enterHook(el, cb)
+ })
+ }
+
+ // start enter transition
+ beforeEnterHook && beforeEnterHook(el)
+ if (expectsCSS) {
+ addTransitionClass(el, startClass)
+ addTransitionClass(el, activeClass)
+ nextFrame(() => {
+ removeTransitionClass(el, startClass)
+ if (!cb.cancelled) {
+ addTransitionClass(el, toClass)
+ if (!userWantsControl) {
+ if (isValidDuration(explicitEnterDuration)) {
+ setTimeout(cb, explicitEnterDuration)
+ } else {
+ whenTransitionEnds(el, type, cb)
+ }
+ }
+ }
+ })
+ }
+
+ if (vnode.data.show) {
+ toggleDisplay && toggleDisplay()
+ enterHook && enterHook(el, cb)
+ }
+
+ if (!expectsCSS && !userWantsControl) {
+ cb()
+ }
+}
+
+export function leave (vnode: VNodeWithData, rm: Function) {
+ const el: any = vnode.elm
+
+ // call enter callback now
+ if (isDef(el._enterCb)) {
+ el._enterCb.cancelled = true
+ el._enterCb()
+ }
+
+ const data = resolveTransition(vnode.data.transition)
+ if (isUndef(data) || el.nodeType !== 1) {
+ return rm()
+ }
+
+ /* istanbul ignore if */
+ if (isDef(el._leaveCb)) {
+ return
+ }
+
+ const {
+ css,
+ type,
+ leaveClass,
+ leaveToClass,
+ leaveActiveClass,
+ beforeLeave,
+ leave,
+ afterLeave,
+ leaveCancelled,
+ delayLeave,
+ duration
+ } = data
+
+ const expectsCSS = css !== false && !isIE9
+ const userWantsControl = getHookArgumentsLength(leave)
+
+ const explicitLeaveDuration: any = toNumber(
+ isObject(duration)
+ ? duration.leave
+ : duration
+ )
+
+ if (process.env.NODE_ENV !== 'production' && isDef(explicitLeaveDuration)) {
+ checkDuration(explicitLeaveDuration, 'leave', vnode)
+ }
+
+ const cb = el._leaveCb = once(() => {
+ if (el.parentNode && el.parentNode._pending) {
+ el.parentNode._pending[vnode.key] = null
+ }
+ if (expectsCSS) {
+ removeTransitionClass(el, leaveToClass)
+ removeTransitionClass(el, leaveActiveClass)
+ }
+ if (cb.cancelled) {
+ if (expectsCSS) {
+ removeTransitionClass(el, leaveClass)
+ }
+ leaveCancelled && leaveCancelled(el)
+ } else {
+ rm()
+ afterLeave && afterLeave(el)
+ }
+ el._leaveCb = null
+ })
+
+ if (delayLeave) {
+ delayLeave(performLeave)
+ } else {
+ performLeave()
+ }
+
+ function performLeave () {
+ // the delayed leave may have already been cancelled
+ if (cb.cancelled) {
+ return
+ }
+ // record leaving element
+ if (!vnode.data.show) {
+ (el.parentNode._pending || (el.parentNode._pending = {}))[(vnode.key: any)] = vnode
+ }
+ beforeLeave && beforeLeave(el)
+ if (expectsCSS) {
+ addTransitionClass(el, leaveClass)
+ addTransitionClass(el, leaveActiveClass)
+ nextFrame(() => {
+ removeTransitionClass(el, leaveClass)
+ if (!cb.cancelled) {
+ addTransitionClass(el, leaveToClass)
+ if (!userWantsControl) {
+ if (isValidDuration(explicitLeaveDuration)) {
+ setTimeout(cb, explicitLeaveDuration)
+ } else {
+ whenTransitionEnds(el, type, cb)
+ }
+ }
+ }
+ })
+ }
+ leave && leave(el, cb)
+ if (!expectsCSS && !userWantsControl) {
+ cb()
+ }
+ }
+}
+
+// only used in dev mode
+function checkDuration (val, name, vnode) {
+ if (typeof val !== 'number') {
+ warn(
+ `<transition> explicit ${name} duration is not a valid number - ` +
+ `got ${JSON.stringify(val)}.`,
+ vnode.context
+ )
+ } else if (isNaN(val)) {
+ warn(
+ `<transition> explicit ${name} duration is NaN - ` +
+ 'the duration expression might be incorrect.',
+ vnode.context
+ )
+ }
+}
+
+function isValidDuration (val) {
+ return typeof val === 'number' && !isNaN(val)
+}
+
+/**
+ * Normalize a transition hook's argument length. The hook may be:
+ * - a merged hook (invoker) with the original in .fns
+ * - a wrapped component method (check ._length)
+ * - a plain function (.length)
+ */
+function getHookArgumentsLength (fn: Function): boolean {
+ if (isUndef(fn)) {
+ return false
+ }
+ const invokerFns = fn.fns
+ if (isDef(invokerFns)) {
+ // invoker
+ return getHookArgumentsLength(
+ Array.isArray(invokerFns)
+ ? invokerFns[0]
+ : invokerFns
+ )
+ } else {
+ return (fn._length || fn.length) > 1
+ }
+}
+
+function _enter (_: any, vnode: VNodeWithData) {
+ if (vnode.data.show !== true) {
+ enter(vnode)
+ }
+}
+
+export default inBrowser ? {
+ create: _enter,
+ activate: _enter,
+ remove (vnode: VNode, rm: Function) {
+ /* istanbul ignore else */
+ if (vnode.data.show !== true) {
+ leave(vnode, rm)
+ } else {
+ rm()
+ }
+ }
+} : {}
diff --git a/node_modules/vue/src/platforms/web/runtime/node-ops.js b/node_modules/vue/src/platforms/web/runtime/node-ops.js
new file mode 100644
index 00000000..3a2978a7
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/node-ops.js
@@ -0,0 +1,59 @@
+/* @flow */
+
+import { namespaceMap } from 'web/util/index'
+
+export function createElement (tagName: string, vnode: VNode): Element {
+ const elm = document.createElement(tagName)
+ if (tagName !== 'select') {
+ return elm
+ }
+ // false or null will remove the attribute but undefined will not
+ if (vnode.data && vnode.data.attrs && vnode.data.attrs.multiple !== undefined) {
+ elm.setAttribute('multiple', 'multiple')
+ }
+ return elm
+}
+
+export function createElementNS (namespace: string, tagName: string): Element {
+ return document.createElementNS(namespaceMap[namespace], tagName)
+}
+
+export function createTextNode (text: string): Text {
+ return document.createTextNode(text)
+}
+
+export function createComment (text: string): Comment {
+ return document.createComment(text)
+}
+
+export function insertBefore (parentNode: Node, newNode: Node, referenceNode: Node) {
+ parentNode.insertBefore(newNode, referenceNode)
+}
+
+export function removeChild (node: Node, child: Node) {
+ node.removeChild(child)
+}
+
+export function appendChild (node: Node, child: Node) {
+ node.appendChild(child)
+}
+
+export function parentNode (node: Node): ?Node {
+ return node.parentNode
+}
+
+export function nextSibling (node: Node): ?Node {
+ return node.nextSibling
+}
+
+export function tagName (node: Element): string {
+ return node.tagName
+}
+
+export function setTextContent (node: Node, text: string) {
+ node.textContent = text
+}
+
+export function setStyleScope (node: Element, scopeId: string) {
+ node.setAttribute(scopeId, '')
+}
diff --git a/node_modules/vue/src/platforms/web/runtime/patch.js b/node_modules/vue/src/platforms/web/runtime/patch.js
new file mode 100644
index 00000000..d982afe9
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/patch.js
@@ -0,0 +1,12 @@
+/* @flow */
+
+import * as nodeOps from 'web/runtime/node-ops'
+import { createPatchFunction } from 'core/vdom/patch'
+import baseModules from 'core/vdom/modules/index'
+import platformModules from 'web/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 })
diff --git a/node_modules/vue/src/platforms/web/runtime/transition-util.js b/node_modules/vue/src/platforms/web/runtime/transition-util.js
new file mode 100644
index 00000000..47668f0c
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/runtime/transition-util.js
@@ -0,0 +1,185 @@
+/* @flow */
+
+import { inBrowser, isIE9 } from 'core/util/index'
+import { addClass, removeClass } from './class-util'
+import { remove, extend, cached } from 'shared/util'
+
+export function resolveTransition (def?: string | Object): ?Object {
+ if (!def) {
+ return
+ }
+ /* istanbul ignore else */
+ if (typeof def === 'object') {
+ const res = {}
+ if (def.css !== false) {
+ extend(res, autoCssTransition(def.name || 'v'))
+ }
+ extend(res, def)
+ return res
+ } else if (typeof def === 'string') {
+ return autoCssTransition(def)
+ }
+}
+
+const autoCssTransition: (name: string) => Object = cached(name => {
+ return {
+ enterClass: `${name}-enter`,
+ enterToClass: `${name}-enter-to`,
+ enterActiveClass: `${name}-enter-active`,
+ leaveClass: `${name}-leave`,
+ leaveToClass: `${name}-leave-to`,
+ leaveActiveClass: `${name}-leave-active`
+ }
+})
+
+export const hasTransition = inBrowser && !isIE9
+const TRANSITION = 'transition'
+const ANIMATION = 'animation'
+
+// Transition property/event sniffing
+export let transitionProp = 'transition'
+export let transitionEndEvent = 'transitionend'
+export let animationProp = 'animation'
+export let animationEndEvent = 'animationend'
+if (hasTransition) {
+ /* istanbul ignore if */
+ if (window.ontransitionend === undefined &&
+ window.onwebkittransitionend !== undefined
+ ) {
+ transitionProp = 'WebkitTransition'
+ transitionEndEvent = 'webkitTransitionEnd'
+ }
+ if (window.onanimationend === undefined &&
+ window.onwebkitanimationend !== undefined
+ ) {
+ animationProp = 'WebkitAnimation'
+ animationEndEvent = 'webkitAnimationEnd'
+ }
+}
+
+// binding to window is necessary to make hot reload work in IE in strict mode
+const raf = inBrowser
+ ? window.requestAnimationFrame
+ ? window.requestAnimationFrame.bind(window)
+ : setTimeout
+ : /* istanbul ignore next */ fn => fn()
+
+export function nextFrame (fn: Function) {
+ raf(() => {
+ raf(fn)
+ })
+}
+
+export function addTransitionClass (el: any, cls: string) {
+ const transitionClasses = el._transitionClasses || (el._transitionClasses = [])
+ if (transitionClasses.indexOf(cls) < 0) {
+ transitionClasses.push(cls)
+ addClass(el, cls)
+ }
+}
+
+export function removeTransitionClass (el: any, cls: string) {
+ if (el._transitionClasses) {
+ remove(el._transitionClasses, cls)
+ }
+ removeClass(el, cls)
+}
+
+export function whenTransitionEnds (
+ el: Element,
+ expectedType: ?string,
+ cb: Function
+) {
+ const { type, timeout, propCount } = getTransitionInfo(el, expectedType)
+ if (!type) return cb()
+ const event: string = type === TRANSITION ? transitionEndEvent : animationEndEvent
+ let ended = 0
+ const end = () => {
+ el.removeEventListener(event, onEnd)
+ cb()
+ }
+ const onEnd = e => {
+ if (e.target === el) {
+ if (++ended >= propCount) {
+ end()
+ }
+ }
+ }
+ setTimeout(() => {
+ if (ended < propCount) {
+ end()
+ }
+ }, timeout + 1)
+ el.addEventListener(event, onEnd)
+}
+
+const transformRE = /\b(transform|all)(,|$)/
+
+export function getTransitionInfo (el: Element, expectedType?: ?string): {
+ type: ?string;
+ propCount: number;
+ timeout: number;
+ hasTransform: boolean;
+} {
+ const styles: any = window.getComputedStyle(el)
+ const transitionDelays: Array<string> = styles[transitionProp + 'Delay'].split(', ')
+ const transitionDurations: Array<string> = styles[transitionProp + 'Duration'].split(', ')
+ const transitionTimeout: number = getTimeout(transitionDelays, transitionDurations)
+ const animationDelays: Array<string> = styles[animationProp + 'Delay'].split(', ')
+ const animationDurations: Array<string> = styles[animationProp + 'Duration'].split(', ')
+ const animationTimeout: number = getTimeout(animationDelays, animationDurations)
+
+ let type: ?string
+ let timeout = 0
+ let propCount = 0
+ /* istanbul ignore if */
+ if (expectedType === TRANSITION) {
+ if (transitionTimeout > 0) {
+ type = TRANSITION
+ timeout = transitionTimeout
+ propCount = transitionDurations.length
+ }
+ } else if (expectedType === ANIMATION) {
+ if (animationTimeout > 0) {
+ type = ANIMATION
+ timeout = animationTimeout
+ propCount = animationDurations.length
+ }
+ } else {
+ timeout = Math.max(transitionTimeout, animationTimeout)
+ type = timeout > 0
+ ? transitionTimeout > animationTimeout
+ ? TRANSITION
+ : ANIMATION
+ : null
+ propCount = type
+ ? type === TRANSITION
+ ? transitionDurations.length
+ : animationDurations.length
+ : 0
+ }
+ const hasTransform: boolean =
+ type === TRANSITION &&
+ transformRE.test(styles[transitionProp + 'Property'])
+ return {
+ type,
+ timeout,
+ propCount,
+ hasTransform
+ }
+}
+
+function getTimeout (delays: Array<string>, durations: Array<string>): number {
+ /* istanbul ignore next */
+ while (delays.length < durations.length) {
+ delays = delays.concat(delays)
+ }
+
+ return Math.max.apply(null, durations.map((d, i) => {
+ return toMs(d) + toMs(delays[i])
+ }))
+}
+
+function toMs (s: string): number {
+ return Number(s.slice(0, -1)) * 1000
+}
diff --git a/node_modules/vue/src/platforms/web/server/compiler.js b/node_modules/vue/src/platforms/web/server/compiler.js
new file mode 100644
index 00000000..20e57367
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/server/compiler.js
@@ -0,0 +1,11 @@
+/* @flow */
+
+import { baseOptions } from '../compiler/options'
+import { createCompiler } from 'server/optimizing-compiler/index'
+
+const { compile, compileToFunctions } = createCompiler(baseOptions)
+
+export {
+ compile as ssrCompile,
+ compileToFunctions as ssrCompileToFunctions
+}
diff --git a/node_modules/vue/src/platforms/web/server/directives/index.js b/node_modules/vue/src/platforms/web/server/directives/index.js
new file mode 100644
index 00000000..fd7fce0a
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/server/directives/index.js
@@ -0,0 +1,7 @@
+import show from './show'
+import model from './model'
+
+export default {
+ show,
+ model
+}
diff --git a/node_modules/vue/src/platforms/web/server/directives/model.js b/node_modules/vue/src/platforms/web/server/directives/model.js
new file mode 100644
index 00000000..7962d6c8
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/server/directives/model.js
@@ -0,0 +1,44 @@
+/* @flow */
+
+import { looseEqual, looseIndexOf } from 'shared/util'
+
+// this is only applied for <select v-model> because it is the only edge case
+// that must be done at runtime instead of compile time.
+export default function model (node: VNodeWithData, dir: VNodeDirective) {
+ if (!node.children) return
+ const value = dir.value
+ const isMultiple = node.data.attrs && node.data.attrs.multiple
+ for (let i = 0, l = node.children.length; i < l; i++) {
+ const option = node.children[i]
+ if (option.tag === 'option') {
+ if (isMultiple) {
+ const selected =
+ Array.isArray(value) &&
+ (looseIndexOf(value, getValue(option)) > -1)
+ if (selected) {
+ setSelected(option)
+ }
+ } else {
+ if (looseEqual(value, getValue(option))) {
+ setSelected(option)
+ return
+ }
+ }
+ }
+ }
+}
+
+function getValue (option) {
+ const data = option.data || {}
+ return (
+ (data.attrs && data.attrs.value) ||
+ (data.domProps && data.domProps.value) ||
+ (option.children && option.children[0] && option.children[0].text)
+ )
+}
+
+function setSelected (option) {
+ const data = option.data || (option.data = {})
+ const attrs = data.attrs || (data.attrs = {})
+ attrs.selected = ''
+}
diff --git a/node_modules/vue/src/platforms/web/server/directives/show.js b/node_modules/vue/src/platforms/web/server/directives/show.js
new file mode 100644
index 00000000..7493b27e
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/server/directives/show.js
@@ -0,0 +1,12 @@
+/* @flow */
+
+export default function show (node: VNodeWithData, dir: VNodeDirective) {
+ if (!dir.value) {
+ const style: any = node.data.style || (node.data.style = {})
+ if (Array.isArray(style)) {
+ style.push({ display: 'none' })
+ } else {
+ style.display = 'none'
+ }
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/server/modules/attrs.js b/node_modules/vue/src/platforms/web/server/modules/attrs.js
new file mode 100644
index 00000000..c3f73013
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/server/modules/attrs.js
@@ -0,0 +1,62 @@
+/* @flow */
+
+import { escape } from '../util'
+
+import {
+ isDef,
+ isUndef,
+ extend
+} from 'shared/util'
+
+import {
+ isBooleanAttr,
+ isEnumeratedAttr,
+ isFalsyAttrValue
+} from 'web/util/attrs'
+
+import { isSSRUnsafeAttr } from 'web/server/util'
+
+export default function renderAttrs (node: VNodeWithData): string {
+ let attrs = node.data.attrs
+ let res = ''
+
+ const opts = node.parent && node.parent.componentOptions
+ if (isUndef(opts) || opts.Ctor.options.inheritAttrs !== false) {
+ let parent = node.parent
+ while (isDef(parent)) {
+ if (isDef(parent.data) && isDef(parent.data.attrs)) {
+ attrs = extend(extend({}, attrs), parent.data.attrs)
+ }
+ parent = parent.parent
+ }
+ }
+
+ if (isUndef(attrs)) {
+ return res
+ }
+
+ for (const key in attrs) {
+ if (isSSRUnsafeAttr(key)) {
+ continue
+ }
+ if (key === 'style') {
+ // leave it to the style module
+ continue
+ }
+ res += renderAttr(key, attrs[key])
+ }
+ return res
+}
+
+export function renderAttr (key: string, value: string): string {
+ if (isBooleanAttr(key)) {
+ if (!isFalsyAttrValue(value)) {
+ return ` ${key}="${key}"`
+ }
+ } else if (isEnumeratedAttr(key)) {
+ return ` ${key}="${isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true'}"`
+ } else if (!isFalsyAttrValue(value)) {
+ return ` ${key}="${escape(String(value))}"`
+ }
+ return ''
+}
diff --git a/node_modules/vue/src/platforms/web/server/modules/class.js b/node_modules/vue/src/platforms/web/server/modules/class.js
new file mode 100644
index 00000000..c19040ed
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/server/modules/class.js
@@ -0,0 +1,11 @@
+/* @flow */
+
+import { escape } from '../util'
+import { genClassForVnode } from 'web/util/index'
+
+export default function renderClass (node: VNodeWithData): ?string {
+ const classList = genClassForVnode(node)
+ if (classList !== '') {
+ return ` class="${escape(classList)}"`
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/server/modules/dom-props.js b/node_modules/vue/src/platforms/web/server/modules/dom-props.js
new file mode 100644
index 00000000..57c18eef
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/server/modules/dom-props.js
@@ -0,0 +1,50 @@
+/* @flow */
+
+import VNode from 'core/vdom/vnode'
+import { renderAttr } from './attrs'
+import { isDef, isUndef, extend } from 'shared/util'
+import { propsToAttrMap, isRenderableAttr } from '../util'
+
+export default function renderDOMProps (node: VNodeWithData): string {
+ let props = node.data.domProps
+ let res = ''
+
+ let parent = node.parent
+ while (isDef(parent)) {
+ if (parent.data && parent.data.domProps) {
+ props = extend(extend({}, props), parent.data.domProps)
+ }
+ parent = parent.parent
+ }
+
+ if (isUndef(props)) {
+ return res
+ }
+
+ const attrs = node.data.attrs
+ for (const key in props) {
+ if (key === 'innerHTML') {
+ setText(node, props[key], true)
+ } else if (key === 'textContent') {
+ setText(node, props[key], false)
+ } else if (key === 'value' && node.tag === 'textarea') {
+ setText(node, props[key], false)
+ } else {
+ // $flow-disable-line (WTF?)
+ const attr = propsToAttrMap[key] || key.toLowerCase()
+ if (isRenderableAttr(attr) &&
+ // avoid rendering double-bound props/attrs twice
+ !(isDef(attrs) && isDef(attrs[attr]))
+ ) {
+ res += renderAttr(attr, props[key])
+ }
+ }
+ }
+ return res
+}
+
+function setText (node, text, raw) {
+ const child = new VNode(undefined, undefined, undefined, text)
+ child.raw = raw
+ node.children = [child]
+}
diff --git a/node_modules/vue/src/platforms/web/server/modules/index.js b/node_modules/vue/src/platforms/web/server/modules/index.js
new file mode 100644
index 00000000..3d15bc50
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/server/modules/index.js
@@ -0,0 +1,11 @@
+import attrs from './attrs'
+import domProps from './dom-props'
+import klass from './class'
+import style from './style'
+
+export default [
+ attrs,
+ domProps,
+ klass,
+ style
+]
diff --git a/node_modules/vue/src/platforms/web/server/modules/style.js b/node_modules/vue/src/platforms/web/server/modules/style.js
new file mode 100644
index 00000000..fc043ef3
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/server/modules/style.js
@@ -0,0 +1,28 @@
+/* @flow */
+
+import { escape } from '../util'
+import { hyphenate } from 'shared/util'
+import { getStyle } from 'web/util/style'
+
+export function genStyle (style: Object): string {
+ let styleText = ''
+ for (const key in style) {
+ const value = style[key]
+ const hyphenatedKey = hyphenate(key)
+ if (Array.isArray(value)) {
+ for (let i = 0, len = value.length; i < len; i++) {
+ styleText += `${hyphenatedKey}:${value[i]};`
+ }
+ } else {
+ styleText += `${hyphenatedKey}:${value};`
+ }
+ }
+ return styleText
+}
+
+export default function renderStyle (vnode: VNodeWithData): ?string {
+ const styleText = genStyle(getStyle(vnode, false))
+ if (styleText !== '') {
+ return ` style=${JSON.stringify(escape(styleText))}`
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/server/util.js b/node_modules/vue/src/platforms/web/server/util.js
new file mode 100644
index 00000000..27489705
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/server/util.js
@@ -0,0 +1,56 @@
+/* @flow */
+
+import { makeMap } from 'shared/util'
+
+const isAttr = makeMap(
+ 'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,' +
+ 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,' +
+ 'checked,cite,class,code,codebase,color,cols,colspan,content,http-equiv,' +
+ 'name,contenteditable,contextmenu,controls,coords,data,datetime,default,' +
+ 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,method,for,' +
+ 'form,formaction,headers,height,hidden,high,href,hreflang,http-equiv,' +
+ 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,' +
+ 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,' +
+ 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,' +
+ 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,' +
+ 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,' +
+ 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,' +
+ 'target,title,type,usemap,value,width,wrap'
+)
+
+const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/
+export const isSSRUnsafeAttr = (name: string): boolean => {
+ return unsafeAttrCharRE.test(name)
+}
+
+/* istanbul ignore next */
+const isRenderableAttr = (name: string): boolean => {
+ return (
+ isAttr(name) ||
+ name.indexOf('data-') === 0 ||
+ name.indexOf('aria-') === 0
+ )
+}
+export { isRenderableAttr }
+
+export const propsToAttrMap = {
+ acceptCharset: 'accept-charset',
+ className: 'class',
+ htmlFor: 'for',
+ httpEquiv: 'http-equiv'
+}
+
+const ESC = {
+ '<': '&lt;',
+ '>': '&gt;',
+ '"': '&quot;',
+ '&': '&amp;'
+}
+
+export function escape (s: string) {
+ return s.replace(/[<>"&]/g, escapeChar)
+}
+
+function escapeChar (a) {
+ return ESC[a] || a
+}
diff --git a/node_modules/vue/src/platforms/web/util/attrs.js b/node_modules/vue/src/platforms/web/util/attrs.js
new file mode 100644
index 00000000..59517da9
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/util/attrs.js
@@ -0,0 +1,43 @@
+/* @flow */
+
+import { makeMap } from 'shared/util'
+
+// these are reserved for web because they are directly compiled away
+// during template compilation
+export const isReservedAttr = makeMap('style,class')
+
+// attributes that should be using props for binding
+const acceptValue = makeMap('input,textarea,option,select,progress')
+export const mustUseProp = (tag: string, type: ?string, attr: string): boolean => {
+ return (
+ (attr === 'value' && acceptValue(tag)) && type !== 'button' ||
+ (attr === 'selected' && tag === 'option') ||
+ (attr === 'checked' && tag === 'input') ||
+ (attr === 'muted' && tag === 'video')
+ )
+}
+
+export const isEnumeratedAttr = makeMap('contenteditable,draggable,spellcheck')
+
+export const isBooleanAttr = makeMap(
+ 'allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,' +
+ 'default,defaultchecked,defaultmuted,defaultselected,defer,disabled,' +
+ 'enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,' +
+ 'muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,' +
+ 'required,reversed,scoped,seamless,selected,sortable,translate,' +
+ 'truespeed,typemustmatch,visible'
+)
+
+export const xlinkNS = 'http://www.w3.org/1999/xlink'
+
+export const isXlink = (name: string): boolean => {
+ return name.charAt(5) === ':' && name.slice(0, 5) === 'xlink'
+}
+
+export const getXlinkProp = (name: string): string => {
+ return isXlink(name) ? name.slice(6, name.length) : ''
+}
+
+export const isFalsyAttrValue = (val: any): boolean => {
+ return val == null || val === false
+}
diff --git a/node_modules/vue/src/platforms/web/util/class.js b/node_modules/vue/src/platforms/web/util/class.js
new file mode 100644
index 00000000..542dcbc4
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/util/class.js
@@ -0,0 +1,85 @@
+/* @flow */
+
+import { isDef, isObject } from 'shared/util'
+
+export function genClassForVnode (vnode: VNodeWithData): string {
+ let data = vnode.data
+ let parentNode = vnode
+ let childNode = vnode
+ while (isDef(childNode.componentInstance)) {
+ childNode = childNode.componentInstance._vnode
+ if (childNode && childNode.data) {
+ data = mergeClassData(childNode.data, data)
+ }
+ }
+ while (isDef(parentNode = parentNode.parent)) {
+ if (parentNode && parentNode.data) {
+ data = mergeClassData(data, parentNode.data)
+ }
+ }
+ return renderClass(data.staticClass, data.class)
+}
+
+function mergeClassData (child: VNodeData, parent: VNodeData): {
+ staticClass: string,
+ class: any
+} {
+ return {
+ staticClass: concat(child.staticClass, parent.staticClass),
+ class: isDef(child.class)
+ ? [child.class, parent.class]
+ : parent.class
+ }
+}
+
+export function renderClass (
+ staticClass: ?string,
+ dynamicClass: any
+): string {
+ if (isDef(staticClass) || isDef(dynamicClass)) {
+ return concat(staticClass, stringifyClass(dynamicClass))
+ }
+ /* istanbul ignore next */
+ return ''
+}
+
+export function concat (a: ?string, b: ?string): string {
+ return a ? b ? (a + ' ' + b) : a : (b || '')
+}
+
+export function stringifyClass (value: any): string {
+ if (Array.isArray(value)) {
+ return stringifyArray(value)
+ }
+ if (isObject(value)) {
+ return stringifyObject(value)
+ }
+ if (typeof value === 'string') {
+ return value
+ }
+ /* istanbul ignore next */
+ return ''
+}
+
+function stringifyArray (value: Array<any>): string {
+ let res = ''
+ let stringified
+ for (let i = 0, l = value.length; i < l; i++) {
+ if (isDef(stringified = stringifyClass(value[i])) && stringified !== '') {
+ if (res) res += ' '
+ res += stringified
+ }
+ }
+ return res
+}
+
+function stringifyObject (value: Object): string {
+ let res = ''
+ for (const key in value) {
+ if (value[key]) {
+ if (res) res += ' '
+ res += key
+ }
+ }
+ return res
+}
diff --git a/node_modules/vue/src/platforms/web/util/compat.js b/node_modules/vue/src/platforms/web/util/compat.js
new file mode 100644
index 00000000..d95759cc
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/util/compat.js
@@ -0,0 +1,16 @@
+/* @flow */
+
+import { inBrowser } from 'core/util/index'
+
+// check whether current browser encodes a char inside attribute values
+let div
+function getShouldDecode (href: boolean): boolean {
+ div = div || document.createElement('div')
+ div.innerHTML = href ? `<a href="\n"/>` : `<div a="\n"/>`
+ return div.innerHTML.indexOf('&#10;') > 0
+}
+
+// #3663: IE encodes newlines inside attribute values while other browsers don't
+export const shouldDecodeNewlines = inBrowser ? getShouldDecode(false) : false
+// #6828: chrome encodes content in a[href]
+export const shouldDecodeNewlinesForHref = inBrowser ? getShouldDecode(true) : false
diff --git a/node_modules/vue/src/platforms/web/util/element.js b/node_modules/vue/src/platforms/web/util/element.js
new file mode 100644
index 00000000..65f1aafb
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/util/element.js
@@ -0,0 +1,77 @@
+/* @flow */
+
+import { inBrowser } from 'core/util/env'
+import { makeMap } from 'shared/util'
+
+export const namespaceMap = {
+ svg: 'http://www.w3.org/2000/svg',
+ math: 'http://www.w3.org/1998/Math/MathML'
+}
+
+export const isHTMLTag = makeMap(
+ 'html,body,base,head,link,meta,style,title,' +
+ 'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' +
+ 'div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,' +
+ 'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' +
+ 's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' +
+ 'embed,object,param,source,canvas,script,noscript,del,ins,' +
+ 'caption,col,colgroup,table,thead,tbody,td,th,tr,' +
+ 'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' +
+ 'output,progress,select,textarea,' +
+ 'details,dialog,menu,menuitem,summary,' +
+ 'content,element,shadow,template,blockquote,iframe,tfoot'
+)
+
+// this map is intentionally selective, only covering SVG elements that may
+// contain child elements.
+export const isSVG = makeMap(
+ 'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,' +
+ 'foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' +
+ 'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view',
+ true
+)
+
+export const isPreTag = (tag: ?string): boolean => tag === 'pre'
+
+export const isReservedTag = (tag: string): ?boolean => {
+ return isHTMLTag(tag) || isSVG(tag)
+}
+
+export function getTagNamespace (tag: string): ?string {
+ if (isSVG(tag)) {
+ return 'svg'
+ }
+ // basic support for MathML
+ // note it doesn't support other MathML elements being component roots
+ if (tag === 'math') {
+ return 'math'
+ }
+}
+
+const unknownElementCache = Object.create(null)
+export function isUnknownElement (tag: string): boolean {
+ /* istanbul ignore if */
+ if (!inBrowser) {
+ return true
+ }
+ if (isReservedTag(tag)) {
+ return false
+ }
+ tag = tag.toLowerCase()
+ /* istanbul ignore if */
+ if (unknownElementCache[tag] != null) {
+ return unknownElementCache[tag]
+ }
+ const el = document.createElement(tag)
+ if (tag.indexOf('-') > -1) {
+ // http://stackoverflow.com/a/28210364/1070244
+ return (unknownElementCache[tag] = (
+ el.constructor === window.HTMLUnknownElement ||
+ el.constructor === window.HTMLElement
+ ))
+ } else {
+ return (unknownElementCache[tag] = /HTMLUnknownElement/.test(el.toString()))
+ }
+}
+
+export const isTextInputType = makeMap('text,number,password,search,email,tel,url')
diff --git a/node_modules/vue/src/platforms/web/util/index.js b/node_modules/vue/src/platforms/web/util/index.js
new file mode 100644
index 00000000..da5e46ed
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/util/index.js
@@ -0,0 +1,25 @@
+/* @flow */
+
+import { warn } from 'core/util/index'
+
+export * from './attrs'
+export * from './class'
+export * from './element'
+
+/**
+ * Query an element selector if it's not an element already.
+ */
+export function query (el: string | Element): Element {
+ if (typeof el === 'string') {
+ const selected = document.querySelector(el)
+ if (!selected) {
+ process.env.NODE_ENV !== 'production' && warn(
+ 'Cannot find element: ' + el
+ )
+ return document.createElement('div')
+ }
+ return selected
+ } else {
+ return el
+ }
+}
diff --git a/node_modules/vue/src/platforms/web/util/style.js b/node_modules/vue/src/platforms/web/util/style.js
new file mode 100644
index 00000000..fc119043
--- /dev/null
+++ b/node_modules/vue/src/platforms/web/util/style.js
@@ -0,0 +1,72 @@
+/* @flow */
+
+import { cached, extend, toObject } from 'shared/util'
+
+export const parseStyleText = cached(function (cssText) {
+ const res = {}
+ const listDelimiter = /;(?![^(]*\))/g
+ const propertyDelimiter = /:(.+)/
+ cssText.split(listDelimiter).forEach(function (item) {
+ if (item) {
+ var tmp = item.split(propertyDelimiter)
+ tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim())
+ }
+ })
+ return res
+})
+
+// merge static and dynamic style data on the same vnode
+function normalizeStyleData (data: VNodeData): ?Object {
+ const style = normalizeStyleBinding(data.style)
+ // static style is pre-processed into an object during compilation
+ // and is always a fresh object, so it's safe to merge into it
+ return data.staticStyle
+ ? extend(data.staticStyle, style)
+ : style
+}
+
+// normalize possible array / string values into Object
+export function normalizeStyleBinding (bindingStyle: any): ?Object {
+ if (Array.isArray(bindingStyle)) {
+ return toObject(bindingStyle)
+ }
+ if (typeof bindingStyle === 'string') {
+ return parseStyleText(bindingStyle)
+ }
+ return bindingStyle
+}
+
+/**
+ * parent component style should be after child's
+ * so that parent component's style could override it
+ */
+export function getStyle (vnode: VNodeWithData, checkChild: boolean): Object {
+ const res = {}
+ let styleData
+
+ if (checkChild) {
+ let childNode = vnode
+ while (childNode.componentInstance) {
+ childNode = childNode.componentInstance._vnode
+ if (
+ childNode && childNode.data &&
+ (styleData = normalizeStyleData(childNode.data))
+ ) {
+ extend(res, styleData)
+ }
+ }
+ }
+
+ if ((styleData = normalizeStyleData(vnode.data))) {
+ extend(res, styleData)
+ }
+
+ let parentNode = vnode
+ while ((parentNode = parentNode.parent)) {
+ if (parentNode.data && (styleData = normalizeStyleData(parentNode.data))) {
+ extend(res, styleData)
+ }
+ }
+ return res
+}
+
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
+ }
+}
diff --git a/node_modules/vue/src/server/bundle-renderer/create-bundle-renderer.js b/node_modules/vue/src/server/bundle-renderer/create-bundle-renderer.js
new file mode 100644
index 00000000..05c60c35
--- /dev/null
+++ b/node_modules/vue/src/server/bundle-renderer/create-bundle-renderer.js
@@ -0,0 +1,151 @@
+/* @flow */
+
+import { createPromiseCallback } from '../util'
+import { createBundleRunner } from './create-bundle-runner'
+import type { Renderer, RenderOptions } from '../create-renderer'
+import { createSourceMapConsumers, rewriteErrorTrace } from './source-map-support'
+
+const fs = require('fs')
+const path = require('path')
+const PassThrough = require('stream').PassThrough
+
+const INVALID_MSG =
+ 'Invalid server-rendering bundle format. Should be a string ' +
+ 'or a bundle Object of type:\n\n' +
+`{
+ entry: string;
+ files: { [filename: string]: string; };
+ maps: { [filename: string]: string; };
+}\n`
+
+// The render bundle can either be a string (single bundled file)
+// or a bundle manifest object generated by vue-ssr-webpack-plugin.
+type RenderBundle = {
+ basedir?: string;
+ entry: string;
+ files: { [filename: string]: string; };
+ maps: { [filename: string]: string; };
+ modules?: { [filename: string]: Array<string> };
+};
+
+export function createBundleRendererCreator (
+ createRenderer: (options?: RenderOptions) => Renderer
+) {
+ return function createBundleRenderer (
+ bundle: string | RenderBundle,
+ rendererOptions?: RenderOptions = {}
+ ) {
+ let files, entry, maps
+ let basedir = rendererOptions.basedir
+
+ // load bundle if given filepath
+ if (
+ typeof bundle === 'string' &&
+ /\.js(on)?$/.test(bundle) &&
+ path.isAbsolute(bundle)
+ ) {
+ if (fs.existsSync(bundle)) {
+ const isJSON = /\.json$/.test(bundle)
+ basedir = basedir || path.dirname(bundle)
+ bundle = fs.readFileSync(bundle, 'utf-8')
+ if (isJSON) {
+ try {
+ bundle = JSON.parse(bundle)
+ } catch (e) {
+ throw new Error(`Invalid JSON bundle file: ${bundle}`)
+ }
+ }
+ } else {
+ throw new Error(`Cannot locate bundle file: ${bundle}`)
+ }
+ }
+
+ if (typeof bundle === 'object') {
+ entry = bundle.entry
+ files = bundle.files
+ basedir = basedir || bundle.basedir
+ maps = createSourceMapConsumers(bundle.maps)
+ if (typeof entry !== 'string' || typeof files !== 'object') {
+ throw new Error(INVALID_MSG)
+ }
+ } else if (typeof bundle === 'string') {
+ entry = '__vue_ssr_bundle__'
+ files = { '__vue_ssr_bundle__': bundle }
+ maps = {}
+ } else {
+ throw new Error(INVALID_MSG)
+ }
+
+ const renderer = createRenderer(rendererOptions)
+
+ const run = createBundleRunner(
+ entry,
+ files,
+ basedir,
+ rendererOptions.runInNewContext
+ )
+
+ return {
+ renderToString: (context?: Object, cb: any) => {
+ if (typeof context === 'function') {
+ cb = context
+ context = {}
+ }
+
+ let promise
+ if (!cb) {
+ ({ promise, cb } = createPromiseCallback())
+ }
+
+ run(context).catch(err => {
+ rewriteErrorTrace(err, maps)
+ cb(err)
+ }).then(app => {
+ if (app) {
+ renderer.renderToString(app, context, (err, res) => {
+ rewriteErrorTrace(err, maps)
+ cb(err, res)
+ })
+ }
+ })
+
+ return promise
+ },
+
+ renderToStream: (context?: Object) => {
+ const res = new PassThrough()
+ run(context).catch(err => {
+ rewriteErrorTrace(err, maps)
+ // avoid emitting synchronously before user can
+ // attach error listener
+ process.nextTick(() => {
+ res.emit('error', err)
+ })
+ }).then(app => {
+ if (app) {
+ const renderStream = renderer.renderToStream(app, context)
+
+ renderStream.on('error', err => {
+ rewriteErrorTrace(err, maps)
+ res.emit('error', err)
+ })
+
+ // relay HTMLStream special events
+ if (rendererOptions && rendererOptions.template) {
+ renderStream.on('beforeStart', () => {
+ res.emit('beforeStart')
+ })
+ renderStream.on('beforeEnd', () => {
+ res.emit('beforeEnd')
+ })
+ }
+
+ renderStream.pipe(res)
+ }
+ })
+
+ return res
+ }
+ }
+ }
+}
diff --git a/node_modules/vue/src/server/bundle-renderer/create-bundle-runner.js b/node_modules/vue/src/server/bundle-renderer/create-bundle-runner.js
new file mode 100644
index 00000000..16c33c41
--- /dev/null
+++ b/node_modules/vue/src/server/bundle-renderer/create-bundle-runner.js
@@ -0,0 +1,150 @@
+import { isPlainObject } from 'shared/util'
+
+const vm = require('vm')
+const path = require('path')
+const resolve = require('resolve')
+const NativeModule = require('module')
+
+function createSandbox (context) {
+ const sandbox = {
+ Buffer,
+ console,
+ process,
+ setTimeout,
+ setInterval,
+ setImmediate,
+ clearTimeout,
+ clearInterval,
+ clearImmediate,
+ __VUE_SSR_CONTEXT__: context
+ }
+ sandbox.global = sandbox
+ return sandbox
+}
+
+function compileModule (files, basedir, runInNewContext) {
+ const compiledScripts = {}
+ const resolvedModules = {}
+
+ function getCompiledScript (filename) {
+ if (compiledScripts[filename]) {
+ return compiledScripts[filename]
+ }
+ const code = files[filename]
+ const wrapper = NativeModule.wrap(code)
+ const script = new vm.Script(wrapper, {
+ filename,
+ displayErrors: true
+ })
+ compiledScripts[filename] = script
+ return script
+ }
+
+ function evaluateModule (filename, sandbox, evaluatedFiles = {}) {
+ if (evaluatedFiles[filename]) {
+ return evaluatedFiles[filename]
+ }
+
+ const script = getCompiledScript(filename)
+ const compiledWrapper = runInNewContext === false
+ ? script.runInThisContext()
+ : script.runInNewContext(sandbox)
+ const m = { exports: {}}
+ const r = file => {
+ file = path.posix.join('.', file)
+ if (files[file]) {
+ return evaluateModule(file, sandbox, evaluatedFiles)
+ } else if (basedir) {
+ return require(
+ resolvedModules[file] ||
+ (resolvedModules[file] = resolve.sync(file, { basedir }))
+ )
+ } else {
+ return require(file)
+ }
+ }
+ compiledWrapper.call(m.exports, m.exports, r, m)
+
+ const res = Object.prototype.hasOwnProperty.call(m.exports, 'default')
+ ? m.exports.default
+ : m.exports
+ evaluatedFiles[filename] = res
+ return res
+ }
+ return evaluateModule
+}
+
+function deepClone (val) {
+ if (isPlainObject(val)) {
+ const res = {}
+ for (const key in val) {
+ res[key] = deepClone(val[key])
+ }
+ return res
+ } else if (Array.isArray(val)) {
+ return val.slice()
+ } else {
+ return val
+ }
+}
+
+export function createBundleRunner (entry, files, basedir, runInNewContext) {
+ const evaluate = compileModule(files, basedir, runInNewContext)
+ if (runInNewContext !== false && runInNewContext !== 'once') {
+ // new context mode: creates a fresh context and re-evaluate the bundle
+ // on each render. Ensures entire application state is fresh for each
+ // render, but incurs extra evaluation cost.
+ return (userContext = {}) => new Promise(resolve => {
+ userContext._registeredComponents = new Set()
+ const res = evaluate(entry, createSandbox(userContext))
+ resolve(typeof res === 'function' ? res(userContext) : res)
+ })
+ } else {
+ // direct mode: instead of re-evaluating the whole bundle on
+ // each render, it simply calls the exported function. This avoids the
+ // module evaluation costs but requires the source code to be structured
+ // slightly differently.
+ let runner // lazy creation so that errors can be caught by user
+ let initialContext
+ return (userContext = {}) => new Promise(resolve => {
+ if (!runner) {
+ const sandbox = runInNewContext === 'once'
+ ? createSandbox()
+ : global
+ // the initial context is only used for collecting possible non-component
+ // styles injected by vue-style-loader.
+ initialContext = sandbox.__VUE_SSR_CONTEXT__ = {}
+ runner = evaluate(entry, sandbox)
+ // On subsequent renders, __VUE_SSR_CONTEXT__ will not be available
+ // to prevent cross-request pollution.
+ delete sandbox.__VUE_SSR_CONTEXT__
+ if (typeof runner !== 'function') {
+ throw new Error(
+ 'bundle export should be a function when using ' +
+ '{ runInNewContext: false }.'
+ )
+ }
+ }
+ userContext._registeredComponents = new Set()
+
+ // vue-style-loader styles imported outside of component lifecycle hooks
+ if (initialContext._styles) {
+ userContext._styles = deepClone(initialContext._styles)
+ // #6353 ensure "styles" is exposed even if no styles are injected
+ // in component lifecycles.
+ // the renderStyles fn is exposed by vue-style-loader >= 3.0.3
+ const renderStyles = initialContext._renderStyles
+ if (renderStyles) {
+ Object.defineProperty(userContext, 'styles', {
+ enumerable: true,
+ get () {
+ return renderStyles(userContext._styles)
+ }
+ })
+ }
+ }
+
+ resolve(runner(userContext))
+ })
+ }
+}
diff --git a/node_modules/vue/src/server/bundle-renderer/source-map-support.js b/node_modules/vue/src/server/bundle-renderer/source-map-support.js
new file mode 100644
index 00000000..1010532e
--- /dev/null
+++ b/node_modules/vue/src/server/bundle-renderer/source-map-support.js
@@ -0,0 +1,45 @@
+/* @flow */
+
+const SourceMapConsumer = require('source-map').SourceMapConsumer
+
+const filenameRE = /\(([^)]+\.js):(\d+):(\d+)\)$/
+
+export function createSourceMapConsumers (rawMaps: Object) {
+ const maps = {}
+ Object.keys(rawMaps).forEach(file => {
+ maps[file] = new SourceMapConsumer(rawMaps[file])
+ })
+ return maps
+}
+
+export function rewriteErrorTrace (e: any, mapConsumers: {
+ [key: string]: SourceMapConsumer
+}) {
+ if (e && typeof e.stack === 'string') {
+ e.stack = e.stack.split('\n').map(line => {
+ return rewriteTraceLine(line, mapConsumers)
+ }).join('\n')
+ }
+}
+
+function rewriteTraceLine (trace: string, mapConsumers: {
+ [key: string]: SourceMapConsumer
+}) {
+ const m = trace.match(filenameRE)
+ const map = m && mapConsumers[m[1]]
+ if (m != null && map) {
+ const originalPosition = map.originalPositionFor({
+ line: Number(m[2]),
+ column: Number(m[3])
+ })
+ if (originalPosition.source != null) {
+ const { source, line, column } = originalPosition
+ const mappedPosition = `(${source.replace(/^webpack:\/\/\//, '')}:${String(line)}:${String(column)})`
+ return trace.replace(filenameRE, mappedPosition)
+ } else {
+ return trace
+ }
+ } else {
+ return trace
+ }
+}
diff --git a/node_modules/vue/src/server/create-basic-renderer.js b/node_modules/vue/src/server/create-basic-renderer.js
new file mode 100644
index 00000000..2d53976d
--- /dev/null
+++ b/node_modules/vue/src/server/create-basic-renderer.js
@@ -0,0 +1,37 @@
+/* @flow */
+
+import { createWriteFunction } from './write'
+import { createRenderFunction } from './render'
+import type { RenderOptions } from './create-renderer'
+
+export function createBasicRenderer ({
+ modules = [],
+ directives = {},
+ isUnaryTag = (() => false),
+ cache
+}: RenderOptions = {}) {
+ const render = createRenderFunction(modules, directives, isUnaryTag, cache)
+
+ return function renderToString (
+ component: Component,
+ context: any,
+ done: any
+ ): void {
+ if (typeof context === 'function') {
+ done = context
+ context = {}
+ }
+ let result = ''
+ const write = createWriteFunction(text => {
+ result += text
+ return false
+ }, done)
+ try {
+ render(component, write, context, () => {
+ done(null, result)
+ })
+ } catch (e) {
+ done(e)
+ }
+ }
+}
diff --git a/node_modules/vue/src/server/create-renderer.js b/node_modules/vue/src/server/create-renderer.js
new file mode 100644
index 00000000..c045a426
--- /dev/null
+++ b/node_modules/vue/src/server/create-renderer.js
@@ -0,0 +1,120 @@
+/* @flow */
+
+import RenderStream from './render-stream'
+import { createWriteFunction } from './write'
+import { createRenderFunction } from './render'
+import { createPromiseCallback } from './util'
+import TemplateRenderer from './template-renderer/index'
+import type { ClientManifest } from './template-renderer/index'
+
+export type Renderer = {
+ renderToString: (component: Component, context: any, cb: any) => ?Promise<string>;
+ renderToStream: (component: Component, context?: Object) => stream$Readable;
+};
+
+type RenderCache = {
+ get: (key: string, cb?: Function) => string | void;
+ set: (key: string, val: string) => void;
+ has?: (key: string, cb?: Function) => boolean | void;
+};
+
+export type RenderOptions = {
+ modules?: Array<(vnode: VNode) => ?string>;
+ directives?: Object;
+ isUnaryTag?: Function;
+ cache?: RenderCache;
+ template?: string;
+ inject?: boolean;
+ basedir?: string;
+ shouldPreload?: Function;
+ shouldPrefetch?: Function;
+ clientManifest?: ClientManifest;
+ runInNewContext?: boolean | 'once';
+};
+
+export function createRenderer ({
+ modules = [],
+ directives = {},
+ isUnaryTag = (() => false),
+ template,
+ inject,
+ cache,
+ shouldPreload,
+ shouldPrefetch,
+ clientManifest
+}: RenderOptions = {}): Renderer {
+ const render = createRenderFunction(modules, directives, isUnaryTag, cache)
+ const templateRenderer = new TemplateRenderer({
+ template,
+ inject,
+ shouldPreload,
+ shouldPrefetch,
+ clientManifest
+ })
+
+ return {
+ renderToString (
+ component: Component,
+ context: any,
+ cb: any
+ ): ?Promise<string> {
+ if (typeof context === 'function') {
+ cb = context
+ context = {}
+ }
+ if (context) {
+ templateRenderer.bindRenderFns(context)
+ }
+
+ // no callback, return Promise
+ let promise
+ if (!cb) {
+ ({ promise, cb } = createPromiseCallback())
+ }
+
+ let result = ''
+ const write = createWriteFunction(text => {
+ result += text
+ return false
+ }, cb)
+ try {
+ render(component, write, context, err => {
+ if (template) {
+ result = templateRenderer.renderSync(result, context)
+ }
+ if (err) {
+ cb(err)
+ } else {
+ cb(null, result)
+ }
+ })
+ } catch (e) {
+ cb(e)
+ }
+
+ return promise
+ },
+
+ renderToStream (
+ component: Component,
+ context?: Object
+ ): stream$Readable {
+ if (context) {
+ templateRenderer.bindRenderFns(context)
+ }
+ const renderStream = new RenderStream((write, done) => {
+ render(component, write, context, done)
+ })
+ if (!template) {
+ return renderStream
+ } else {
+ const templateStream = templateRenderer.createStream(context)
+ renderStream.on('error', err => {
+ templateStream.emit('error', err)
+ })
+ renderStream.pipe(templateStream)
+ return templateStream
+ }
+ }
+ }
+}
diff --git a/node_modules/vue/src/server/optimizing-compiler/codegen.js b/node_modules/vue/src/server/optimizing-compiler/codegen.js
new file mode 100644
index 00000000..26097c07
--- /dev/null
+++ b/node_modules/vue/src/server/optimizing-compiler/codegen.js
@@ -0,0 +1,260 @@
+/* @flow */
+
+// The SSR codegen is essentially extending the default codegen to handle
+// SSR-optimizable nodes and turn them into string render fns. In cases where
+// a node is not optimizable it simply falls back to the default codegen.
+
+import {
+ genIf,
+ genFor,
+ genData,
+ genText,
+ genElement,
+ genChildren,
+ CodegenState
+} from 'compiler/codegen/index'
+
+import {
+ genAttrSegments,
+ genDOMPropSegments,
+ genClassSegments,
+ genStyleSegments,
+ applyModelTransform
+} from './modules'
+
+import { escape } from 'web/server/util'
+import { optimizability } from './optimizer'
+import type { CodegenResult } from 'compiler/codegen/index'
+
+export type StringSegment = {
+ type: number;
+ value: string;
+};
+
+// segment types
+export const RAW = 0
+export const INTERPOLATION = 1
+export const EXPRESSION = 2
+
+export function generate (
+ ast: ASTElement | void,
+ options: CompilerOptions
+): CodegenResult {
+ const state = new CodegenState(options)
+ const code = ast ? genSSRElement(ast, state) : '_c("div")'
+ return {
+ render: `with(this){return ${code}}`,
+ staticRenderFns: state.staticRenderFns
+ }
+}
+
+function genSSRElement (el: ASTElement, state: CodegenState): string {
+ if (el.for && !el.forProcessed) {
+ return genFor(el, state, genSSRElement)
+ } else if (el.if && !el.ifProcessed) {
+ return genIf(el, state, genSSRElement)
+ } else if (el.tag === 'template' && !el.slotTarget) {
+ return el.ssrOptimizability === optimizability.FULL
+ ? genChildrenAsStringNode(el, state)
+ : genSSRChildren(el, state) || 'void 0'
+ }
+
+ switch (el.ssrOptimizability) {
+ case optimizability.FULL:
+ // stringify whole tree
+ return genStringElement(el, state)
+ case optimizability.SELF:
+ // stringify self and check children
+ return genStringElementWithChildren(el, state)
+ case optimizability.CHILDREN:
+ // generate self as VNode and stringify children
+ return genNormalElement(el, state, true)
+ case optimizability.PARTIAL:
+ // generate self as VNode and check children
+ return genNormalElement(el, state, false)
+ default:
+ // bail whole tree
+ return genElement(el, state)
+ }
+}
+
+function genNormalElement (el, state, stringifyChildren) {
+ const data = el.plain ? undefined : genData(el, state)
+ const children = stringifyChildren
+ ? `[${genChildrenAsStringNode(el, state)}]`
+ : genSSRChildren(el, state, true)
+ return `_c('${el.tag}'${
+ data ? `,${data}` : ''
+ }${
+ children ? `,${children}` : ''
+ })`
+}
+
+function genSSRChildren (el, state, checkSkip) {
+ return genChildren(el, state, checkSkip, genSSRElement, genSSRNode)
+}
+
+function genSSRNode (el, state) {
+ return el.type === 1
+ ? genSSRElement(el, state)
+ : genText(el)
+}
+
+function genChildrenAsStringNode (el, state) {
+ return el.children.length
+ ? `_ssrNode(${flattenSegments(childrenToSegments(el, state))})`
+ : ''
+}
+
+function genStringElement (el, state) {
+ return `_ssrNode(${elementToString(el, state)})`
+}
+
+function genStringElementWithChildren (el, state) {
+ const children = genSSRChildren(el, state, true)
+ return `_ssrNode(${
+ flattenSegments(elementToOpenTagSegments(el, state))
+ },"</${el.tag}>"${
+ children ? `,${children}` : ''
+ })`
+}
+
+function elementToString (el, state) {
+ return `(${flattenSegments(elementToSegments(el, state))})`
+}
+
+function elementToSegments (el, state): Array<StringSegment> {
+ // v-for / v-if
+ if (el.for && !el.forProcessed) {
+ el.forProcessed = true
+ return [{
+ type: EXPRESSION,
+ value: genFor(el, state, elementToString, '_ssrList')
+ }]
+ } else if (el.if && !el.ifProcessed) {
+ el.ifProcessed = true
+ return [{
+ type: EXPRESSION,
+ value: genIf(el, state, elementToString, '"<!---->"')
+ }]
+ } else if (el.tag === 'template') {
+ return childrenToSegments(el, state)
+ }
+
+ const openSegments = elementToOpenTagSegments(el, state)
+ const childrenSegments = childrenToSegments(el, state)
+ const { isUnaryTag } = state.options
+ const close = (isUnaryTag && isUnaryTag(el.tag))
+ ? []
+ : [{ type: RAW, value: `</${el.tag}>` }]
+ return openSegments.concat(childrenSegments, close)
+}
+
+function elementToOpenTagSegments (el, state): Array<StringSegment> {
+ applyModelTransform(el, state)
+ let binding
+ const segments = [{ type: RAW, value: `<${el.tag}` }]
+ // attrs
+ if (el.attrs) {
+ segments.push.apply(segments, genAttrSegments(el.attrs))
+ }
+ // domProps
+ if (el.props) {
+ segments.push.apply(segments, genDOMPropSegments(el.props, el.attrs))
+ }
+ // v-bind="object"
+ if ((binding = el.attrsMap['v-bind'])) {
+ segments.push({ type: EXPRESSION, value: `_ssrAttrs(${binding})` })
+ }
+ // v-bind.prop="object"
+ if ((binding = el.attrsMap['v-bind.prop'])) {
+ segments.push({ type: EXPRESSION, value: `_ssrDOMProps(${binding})` })
+ }
+ // class
+ if (el.staticClass || el.classBinding) {
+ segments.push.apply(
+ segments,
+ genClassSegments(el.staticClass, el.classBinding)
+ )
+ }
+ // style & v-show
+ if (el.staticStyle || el.styleBinding || el.attrsMap['v-show']) {
+ segments.push.apply(
+ segments,
+ genStyleSegments(
+ el.attrsMap.style,
+ el.staticStyle,
+ el.styleBinding,
+ el.attrsMap['v-show']
+ )
+ )
+ }
+ // _scopedId
+ if (state.options.scopeId) {
+ segments.push({ type: RAW, value: ` ${state.options.scopeId}` })
+ }
+ segments.push({ type: RAW, value: `>` })
+ return segments
+}
+
+function childrenToSegments (el, state): Array<StringSegment> {
+ let binding
+ if ((binding = el.attrsMap['v-html'])) {
+ return [{ type: EXPRESSION, value: `_s(${binding})` }]
+ }
+ if ((binding = el.attrsMap['v-text'])) {
+ return [{ type: INTERPOLATION, value: `_s(${binding})` }]
+ }
+ if (el.tag === 'textarea' && (binding = el.attrsMap['v-model'])) {
+ return [{ type: INTERPOLATION, value: `_s(${binding})` }]
+ }
+ return el.children
+ ? nodesToSegments(el.children, state)
+ : []
+}
+
+function nodesToSegments (
+ children: Array<ASTNode>,
+ state: CodegenState
+): Array<StringSegment> {
+ const segments = []
+ for (let i = 0; i < children.length; i++) {
+ const c = children[i]
+ if (c.type === 1) {
+ segments.push.apply(segments, elementToSegments(c, state))
+ } else if (c.type === 2) {
+ segments.push({ type: INTERPOLATION, value: c.expression })
+ } else if (c.type === 3) {
+ segments.push({ type: RAW, value: escape(c.text) })
+ }
+ }
+ return segments
+}
+
+function flattenSegments (segments: Array<StringSegment>): string {
+ const mergedSegments = []
+ let textBuffer = ''
+
+ const pushBuffer = () => {
+ if (textBuffer) {
+ mergedSegments.push(JSON.stringify(textBuffer))
+ textBuffer = ''
+ }
+ }
+
+ for (let i = 0; i < segments.length; i++) {
+ const s = segments[i]
+ if (s.type === RAW) {
+ textBuffer += s.value
+ } else if (s.type === INTERPOLATION) {
+ pushBuffer()
+ mergedSegments.push(`_ssrEscape(${s.value})`)
+ } else if (s.type === EXPRESSION) {
+ pushBuffer()
+ mergedSegments.push(`(${s.value})`)
+ }
+ }
+ pushBuffer()
+
+ return mergedSegments.join('+')
+}
diff --git a/node_modules/vue/src/server/optimizing-compiler/index.js b/node_modules/vue/src/server/optimizing-compiler/index.js
new file mode 100644
index 00000000..893630d6
--- /dev/null
+++ b/node_modules/vue/src/server/optimizing-compiler/index.js
@@ -0,0 +1,20 @@
+/* @flow */
+
+import { parse } from 'compiler/parser/index'
+import { generate } from './codegen'
+import { optimize } from './optimizer'
+import { createCompilerCreator } from 'compiler/create-compiler'
+
+export const createCompiler = createCompilerCreator(function baseCompile (
+ template: string,
+ options: CompilerOptions
+): CompiledResult {
+ const ast = parse(template.trim(), options)
+ optimize(ast, options)
+ const code = generate(ast, options)
+ return {
+ ast,
+ render: code.render,
+ staticRenderFns: code.staticRenderFns
+ }
+})
diff --git a/node_modules/vue/src/server/optimizing-compiler/modules.js b/node_modules/vue/src/server/optimizing-compiler/modules.js
new file mode 100644
index 00000000..69a7be87
--- /dev/null
+++ b/node_modules/vue/src/server/optimizing-compiler/modules.js
@@ -0,0 +1,126 @@
+/* @flow */
+
+import {
+ RAW,
+ // INTERPOLATION,
+ EXPRESSION
+} from './codegen'
+
+import {
+ propsToAttrMap,
+ isRenderableAttr
+} from 'web/server/util'
+
+import {
+ isBooleanAttr,
+ isEnumeratedAttr
+} from 'web/util/attrs'
+
+import type { StringSegment } from './codegen'
+import type { CodegenState } from 'compiler/codegen/index'
+
+type Attr = { name: string; value: string };
+
+const plainStringRE = /^"(?:[^"\\]|\\.)*"$|^'(?:[^'\\]|\\.)*'$/
+
+// let the model AST transform translate v-model into appropriate
+// props bindings
+export function applyModelTransform (el: ASTElement, state: CodegenState) {
+ if (el.directives) {
+ for (let i = 0; i < el.directives.length; i++) {
+ const dir = el.directives[i]
+ if (dir.name === 'model') {
+ state.directives.model(el, dir, state.warn)
+ // remove value for textarea as its converted to text
+ if (el.tag === 'textarea' && el.props) {
+ el.props = el.props.filter(p => p.name !== 'value')
+ }
+ break
+ }
+ }
+ }
+}
+
+export function genAttrSegments (
+ attrs: Array<Attr>
+): Array<StringSegment> {
+ return attrs.map(({ name, value }) => genAttrSegment(name, value))
+}
+
+export function genDOMPropSegments (
+ props: Array<Attr>,
+ attrs: ?Array<Attr>
+): Array<StringSegment> {
+ const segments = []
+ props.forEach(({ name, value }) => {
+ name = propsToAttrMap[name] || name.toLowerCase()
+ if (isRenderableAttr(name) &&
+ !(attrs && attrs.some(a => a.name === name))
+ ) {
+ segments.push(genAttrSegment(name, value))
+ }
+ })
+ return segments
+}
+
+function genAttrSegment (name: string, value: string): StringSegment {
+ if (plainStringRE.test(value)) {
+ // force double quote
+ value = value.replace(/^'|'$/g, '"')
+ // force enumerated attr to "true"
+ if (isEnumeratedAttr(name) && value !== `"false"`) {
+ value = `"true"`
+ }
+ return {
+ type: RAW,
+ value: isBooleanAttr(name)
+ ? ` ${name}="${name}"`
+ : value === '""'
+ ? ` ${name}`
+ : ` ${name}="${JSON.parse(value)}"`
+ }
+ } else {
+ return {
+ type: EXPRESSION,
+ value: `_ssrAttr(${JSON.stringify(name)},${value})`
+ }
+ }
+}
+
+export function genClassSegments (
+ staticClass: ?string,
+ classBinding: ?string
+): Array<StringSegment> {
+ if (staticClass && !classBinding) {
+ return [{ type: RAW, value: ` class=${staticClass}` }]
+ } else {
+ return [{
+ type: EXPRESSION,
+ value: `_ssrClass(${staticClass || 'null'},${classBinding || 'null'})`
+ }]
+ }
+}
+
+export function genStyleSegments (
+ staticStyle: ?string,
+ parsedStaticStyle: ?string,
+ styleBinding: ?string,
+ vShowExpression: ?string
+): Array<StringSegment> {
+ if (staticStyle && !styleBinding && !vShowExpression) {
+ return [{ type: RAW, value: ` style=${JSON.stringify(staticStyle)}` }]
+ } else {
+ return [{
+ type: EXPRESSION,
+ value: `_ssrStyle(${
+ parsedStaticStyle || 'null'
+ },${
+ styleBinding || 'null'
+ }, ${
+ vShowExpression
+ ? `{ display: (${vShowExpression}) ? '' : 'none' }`
+ : 'null'
+ })`
+ }]
+ }
+}
diff --git a/node_modules/vue/src/server/optimizing-compiler/optimizer.js b/node_modules/vue/src/server/optimizing-compiler/optimizer.js
new file mode 100644
index 00000000..d24acc55
--- /dev/null
+++ b/node_modules/vue/src/server/optimizing-compiler/optimizer.js
@@ -0,0 +1,140 @@
+/* @flow */
+
+/**
+ * In SSR, the vdom tree is generated only once and never patched, so
+ * we can optimize most element / trees into plain string render functions.
+ * The SSR optimizer walks the AST tree to detect optimizable elements and trees.
+ *
+ * The criteria for SSR optimizability is quite a bit looser than static tree
+ * detection (which is designed for client re-render). In SSR we bail only for
+ * components/slots/custom directives.
+ */
+
+import { no, makeMap, isBuiltInTag } from 'shared/util'
+
+// optimizability constants
+export const optimizability = {
+ FALSE: 0, // whole sub tree un-optimizable
+ FULL: 1, // whole sub tree optimizable
+ SELF: 2, // self optimizable but has some un-optimizable children
+ CHILDREN: 3, // self un-optimizable but have fully optimizable children
+ PARTIAL: 4 // self un-optimizable with some un-optimizable children
+}
+
+let isPlatformReservedTag
+
+export function optimize (root: ?ASTElement, options: CompilerOptions) {
+ if (!root) return
+ isPlatformReservedTag = options.isReservedTag || no
+ walk(root, true)
+}
+
+function walk (node: ASTNode, isRoot?: boolean) {
+ if (isUnOptimizableTree(node)) {
+ node.ssrOptimizability = optimizability.FALSE
+ return
+ }
+ // root node or nodes with custom directives should always be a VNode
+ const selfUnoptimizable = isRoot || hasCustomDirective(node)
+ const check = child => {
+ if (child.ssrOptimizability !== optimizability.FULL) {
+ node.ssrOptimizability = selfUnoptimizable
+ ? optimizability.PARTIAL
+ : optimizability.SELF
+ }
+ }
+ if (selfUnoptimizable) {
+ node.ssrOptimizability = optimizability.CHILDREN
+ }
+ if (node.type === 1) {
+ for (let i = 0, l = node.children.length; i < l; i++) {
+ const child = node.children[i]
+ walk(child)
+ check(child)
+ }
+ if (node.ifConditions) {
+ for (let i = 1, l = node.ifConditions.length; i < l; i++) {
+ const block = node.ifConditions[i].block
+ walk(block, isRoot)
+ check(block)
+ }
+ }
+ if (node.ssrOptimizability == null ||
+ (!isRoot && (node.attrsMap['v-html'] || node.attrsMap['v-text']))
+ ) {
+ node.ssrOptimizability = optimizability.FULL
+ } else {
+ node.children = optimizeSiblings(node)
+ }
+ } else {
+ node.ssrOptimizability = optimizability.FULL
+ }
+}
+
+function optimizeSiblings (el) {
+ const children = el.children
+ const optimizedChildren = []
+
+ let currentOptimizableGroup = []
+ const pushGroup = () => {
+ if (currentOptimizableGroup.length) {
+ optimizedChildren.push({
+ type: 1,
+ parent: el,
+ tag: 'template',
+ attrsList: [],
+ attrsMap: {},
+ children: currentOptimizableGroup,
+ ssrOptimizability: optimizability.FULL
+ })
+ }
+ currentOptimizableGroup = []
+ }
+
+ for (let i = 0; i < children.length; i++) {
+ const c = children[i]
+ if (c.ssrOptimizability === optimizability.FULL) {
+ currentOptimizableGroup.push(c)
+ } else {
+ // wrap fully-optimizable adjacent siblings inside a template tag
+ // so that they can be optimized into a single ssrNode by codegen
+ pushGroup()
+ optimizedChildren.push(c)
+ }
+ }
+ pushGroup()
+ return optimizedChildren
+}
+
+function isUnOptimizableTree (node: ASTNode): boolean {
+ if (node.type === 2 || node.type === 3) { // text or expression
+ return false
+ }
+ return (
+ isBuiltInTag(node.tag) || // built-in (slot, component)
+ !isPlatformReservedTag(node.tag) || // custom component
+ !!node.component || // "is" component
+ isSelectWithModel(node) // <select v-model> requires runtime inspection
+ )
+}
+
+const isBuiltInDir = makeMap('text,html,show,on,bind,model,pre,cloak,once')
+
+function hasCustomDirective (node: ASTNode): ?boolean {
+ return (
+ node.type === 1 &&
+ node.directives &&
+ node.directives.some(d => !isBuiltInDir(d.name))
+ )
+}
+
+// <select v-model> cannot be optimized because it requires a runtime check
+// to determine proper selected option
+function isSelectWithModel (node: ASTNode): boolean {
+ return (
+ node.type === 1 &&
+ node.tag === 'select' &&
+ node.directives != null &&
+ node.directives.some(d => d.name === 'model')
+ )
+}
diff --git a/node_modules/vue/src/server/optimizing-compiler/runtime-helpers.js b/node_modules/vue/src/server/optimizing-compiler/runtime-helpers.js
new file mode 100644
index 00000000..6f65de04
--- /dev/null
+++ b/node_modules/vue/src/server/optimizing-compiler/runtime-helpers.js
@@ -0,0 +1,150 @@
+/* @flow */
+
+import { escape, isSSRUnsafeAttr } from 'web/server/util'
+import { isObject, extend } from 'shared/util'
+import { renderAttr } from 'web/server/modules/attrs'
+import { renderClass } from 'web/util/class'
+import { genStyle } from 'web/server/modules/style'
+import { normalizeStyleBinding } from 'web/util/style'
+
+import {
+ normalizeChildren,
+ simpleNormalizeChildren
+} from 'core/vdom/helpers/normalize-children'
+
+import {
+ propsToAttrMap,
+ isRenderableAttr
+} from 'web/server/util'
+
+const ssrHelpers = {
+ _ssrEscape: escape,
+ _ssrNode: renderStringNode,
+ _ssrList: renderStringList,
+ _ssrAttr: renderAttr,
+ _ssrAttrs: renderAttrs,
+ _ssrDOMProps: renderDOMProps,
+ _ssrClass: renderSSRClass,
+ _ssrStyle: renderSSRStyle
+}
+
+export function installSSRHelpers (vm: Component) {
+ if (vm._ssrNode) {
+ return
+ }
+ let Vue = vm.constructor
+ while (Vue.super) {
+ Vue = Vue.super
+ }
+ extend(Vue.prototype, ssrHelpers)
+ if (Vue.FunctionalRenderContext) {
+ extend(Vue.FunctionalRenderContext.prototype, ssrHelpers)
+ }
+}
+
+class StringNode {
+ isString: boolean;
+ open: string;
+ close: ?string;
+ children: ?Array<any>;
+
+ constructor (
+ open: string,
+ close?: string,
+ children?: Array<any>,
+ normalizationType?: number
+ ) {
+ this.isString = true
+ this.open = open
+ this.close = close
+ if (children) {
+ this.children = normalizationType === 1
+ ? simpleNormalizeChildren(children)
+ : normalizationType === 2
+ ? normalizeChildren(children)
+ : children
+ } else {
+ this.children = void 0
+ }
+ }
+}
+
+function renderStringNode (
+ open: string,
+ close?: string,
+ children?: Array<any>,
+ normalizationType?: number
+): StringNode {
+ return new StringNode(open, close, children, normalizationType)
+}
+
+function renderStringList (
+ val: any,
+ render: (
+ val: any,
+ keyOrIndex: string | number,
+ index?: number
+ ) => string
+): string {
+ let ret = ''
+ let i, l, keys, key
+ if (Array.isArray(val) || typeof val === 'string') {
+ for (i = 0, l = val.length; i < l; i++) {
+ ret += render(val[i], i)
+ }
+ } else if (typeof val === 'number') {
+ for (i = 0; i < val; i++) {
+ ret += render(i + 1, i)
+ }
+ } else if (isObject(val)) {
+ keys = Object.keys(val)
+ for (i = 0, l = keys.length; i < l; i++) {
+ key = keys[i]
+ ret += render(val[key], key, i)
+ }
+ }
+ return ret
+}
+
+function renderAttrs (obj: Object): string {
+ let res = ''
+ for (const key in obj) {
+ if (isSSRUnsafeAttr(key)) {
+ continue
+ }
+ res += renderAttr(key, obj[key])
+ }
+ return res
+}
+
+function renderDOMProps (obj: Object): string {
+ let res = ''
+ for (const key in obj) {
+ const attr = propsToAttrMap[key] || key.toLowerCase()
+ if (isRenderableAttr(attr)) {
+ res += renderAttr(attr, obj[key])
+ }
+ }
+ return res
+}
+
+function renderSSRClass (
+ staticClass: ?string,
+ dynamic: any
+): string {
+ const res = renderClass(staticClass, dynamic)
+ return res === '' ? res : ` class="${escape(res)}"`
+}
+
+function renderSSRStyle (
+ staticStyle: ?Object,
+ dynamic: any,
+ extra: ?Object
+): string {
+ const style = {}
+ if (staticStyle) extend(style, staticStyle)
+ if (dynamic) extend(style, normalizeStyleBinding(dynamic))
+ if (extra) extend(style, extra)
+ const res = genStyle(style)
+ return res === '' ? res : ` style=${JSON.stringify(escape(res))}`
+}
diff --git a/node_modules/vue/src/server/render-context.js b/node_modules/vue/src/server/render-context.js
new file mode 100644
index 00000000..178140cd
--- /dev/null
+++ b/node_modules/vue/src/server/render-context.js
@@ -0,0 +1,130 @@
+/* @flow */
+
+import { isUndef } from 'shared/util'
+
+type RenderState = {
+ type: 'Element';
+ rendered: number;
+ total: number;
+ children: Array<VNode>;
+ endTag: string;
+} | {
+ type: 'Fragment';
+ rendered: number;
+ total: number;
+ children: Array<VNode>;
+} | {
+ type: 'Component';
+ prevActive: Component;
+} | {
+ type: 'ComponentWithCache';
+ buffer: Array<string>;
+ bufferIndex: number;
+ componentBuffer: Array<Set<Class<Component>>>;
+ key: string;
+};
+
+export class RenderContext {
+ userContext: ?Object;
+ activeInstance: Component;
+ renderStates: Array<RenderState>;
+ write: (text: string, next: Function) => void;
+ renderNode: (node: VNode, isRoot: boolean, context: RenderContext) => void;
+ next: () => void;
+ done: (err: ?Error) => void;
+
+ modules: Array<(node: VNode) => ?string>;
+ directives: Object;
+ isUnaryTag: (tag: string) => boolean;
+
+ cache: any;
+ get: ?(key: string, cb: Function) => void;
+ has: ?(key: string, cb: Function) => void;
+
+ constructor (options: Object) {
+ this.userContext = options.userContext
+ this.activeInstance = options.activeInstance
+ this.renderStates = []
+
+ this.write = options.write
+ this.done = options.done
+ this.renderNode = options.renderNode
+
+ this.isUnaryTag = options.isUnaryTag
+ this.modules = options.modules
+ this.directives = options.directives
+
+ const cache = options.cache
+ if (cache && (!cache.get || !cache.set)) {
+ throw new Error('renderer cache must implement at least get & set.')
+ }
+ this.cache = cache
+ this.get = cache && normalizeAsync(cache, 'get')
+ this.has = cache && normalizeAsync(cache, 'has')
+
+ this.next = this.next.bind(this)
+ }
+
+ next () {
+ const lastState = this.renderStates[this.renderStates.length - 1]
+ if (isUndef(lastState)) {
+ return this.done()
+ }
+ switch (lastState.type) {
+ case 'Element':
+ case 'Fragment':
+ const { children, total } = lastState
+ const rendered = lastState.rendered++
+ if (rendered < total) {
+ this.renderNode(children[rendered], false, this)
+ } else {
+ this.renderStates.pop()
+ if (lastState.type === 'Element') {
+ this.write(lastState.endTag, this.next)
+ } else {
+ this.next()
+ }
+ }
+ break
+ case 'Component':
+ this.renderStates.pop()
+ this.activeInstance = lastState.prevActive
+ this.next()
+ break
+ case 'ComponentWithCache':
+ this.renderStates.pop()
+ const { buffer, bufferIndex, componentBuffer, key } = lastState
+ const result = {
+ html: buffer[bufferIndex],
+ components: componentBuffer[bufferIndex]
+ }
+ this.cache.set(key, result)
+ if (bufferIndex === 0) {
+ // this is a top-level cached component,
+ // exit caching mode.
+ this.write.caching = false
+ } else {
+ // parent component is also being cached,
+ // merge self into parent's result
+ buffer[bufferIndex - 1] += result.html
+ const prev = componentBuffer[bufferIndex - 1]
+ result.components.forEach(c => prev.add(c))
+ }
+ buffer.length = bufferIndex
+ componentBuffer.length = bufferIndex
+ this.next()
+ break
+ }
+ }
+}
+
+function normalizeAsync (cache, method) {
+ const fn = cache[method]
+ if (isUndef(fn)) {
+ return
+ } else if (fn.length > 1) {
+ return (key, cb) => fn.call(cache, key, cb)
+ } else {
+ return (key, cb) => cb(fn.call(cache, key))
+ }
+}
diff --git a/node_modules/vue/src/server/render-stream.js b/node_modules/vue/src/server/render-stream.js
new file mode 100644
index 00000000..d76012af
--- /dev/null
+++ b/node_modules/vue/src/server/render-stream.js
@@ -0,0 +1,94 @@
+/* @flow */
+
+/**
+ * Original RenderStream implementation by Sasha Aickin (@aickin)
+ * Licensed under the Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Modified by Evan You (@yyx990803)
+ */
+
+const stream = require('stream')
+
+import { isTrue, isUndef } from 'shared/util'
+import { createWriteFunction } from './write'
+
+export default class RenderStream extends stream.Readable {
+ buffer: string;
+ render: (write: Function, done: Function) => void;
+ expectedSize: number;
+ write: Function;
+ next: Function;
+ end: Function;
+ done: boolean;
+
+ constructor (render: Function) {
+ super()
+ this.buffer = ''
+ this.render = render
+ this.expectedSize = 0
+
+ this.write = createWriteFunction((text, next) => {
+ const n = this.expectedSize
+ this.buffer += text
+ if (this.buffer.length >= n) {
+ this.next = next
+ this.pushBySize(n)
+ return true // we will decide when to call next
+ }
+ return false
+ }, err => {
+ this.emit('error', err)
+ })
+
+ this.end = () => {
+ // the rendering is finished; we should push out the last of the buffer.
+ this.done = true
+ this.push(this.buffer)
+ }
+ }
+
+ pushBySize (n: number) {
+ const bufferToPush = this.buffer.substring(0, n)
+ this.buffer = this.buffer.substring(n)
+ this.push(bufferToPush)
+ }
+
+ tryRender () {
+ try {
+ this.render(this.write, this.end)
+ } catch (e) {
+ this.emit('error', e)
+ }
+ }
+
+ tryNext () {
+ try {
+ this.next()
+ } catch (e) {
+ this.emit('error', e)
+ }
+ }
+
+ _read (n: number) {
+ this.expectedSize = n
+ // it's possible that the last chunk added bumped the buffer up to > 2 * n,
+ // which means we will need to go through multiple read calls to drain it
+ // down to < n.
+ if (isTrue(this.done)) {
+ this.push(null)
+ return
+ }
+ if (this.buffer.length >= n) {
+ this.pushBySize(n)
+ return
+ }
+ if (isUndef(this.next)) {
+ // start the rendering chain.
+ this.tryRender()
+ } else {
+ // continue with the rendering.
+ this.tryNext()
+ }
+ }
+}
diff --git a/node_modules/vue/src/server/render.js b/node_modules/vue/src/server/render.js
new file mode 100644
index 00000000..592a6175
--- /dev/null
+++ b/node_modules/vue/src/server/render.js
@@ -0,0 +1,396 @@
+/* @flow */
+
+import { escape } from 'web/server/util'
+import { SSR_ATTR } from 'shared/constants'
+import { RenderContext } from './render-context'
+import { generateComponentTrace } from 'core/util/debug'
+import { ssrCompileToFunctions } from 'web/server/compiler'
+import { installSSRHelpers } from './optimizing-compiler/runtime-helpers'
+
+import { isDef, isUndef, isTrue } from 'shared/util'
+
+import {
+ createComponent,
+ createComponentInstanceForVnode
+} from 'core/vdom/create-component'
+
+let warned = Object.create(null)
+const warnOnce = msg => {
+ if (!warned[msg]) {
+ warned[msg] = true
+ console.warn(`\n\u001b[31m${msg}\u001b[39m\n`)
+ }
+}
+
+const onCompilationError = (err, vm) => {
+ const trace = vm ? generateComponentTrace(vm) : ''
+ throw new Error(`\n\u001b[31m${err}${trace}\u001b[39m\n`)
+}
+
+const normalizeRender = vm => {
+ const { render, template, _scopeId } = vm.$options
+ if (isUndef(render)) {
+ if (template) {
+ const compiled = ssrCompileToFunctions(template, {
+ scopeId: _scopeId,
+ warn: onCompilationError
+ }, vm)
+
+ vm.$options.render = compiled.render
+ vm.$options.staticRenderFns = compiled.staticRenderFns
+ } else {
+ throw new Error(
+ `render function or template not defined in component: ${
+ vm.$options.name || vm.$options._componentTag || 'anonymous'
+ }`
+ )
+ }
+ }
+}
+
+function renderNode (node, isRoot, context) {
+ if (node.isString) {
+ renderStringNode(node, context)
+ } else if (isDef(node.componentOptions)) {
+ renderComponent(node, isRoot, context)
+ } else if (isDef(node.tag)) {
+ renderElement(node, isRoot, context)
+ } else if (isTrue(node.isComment)) {
+ if (isDef(node.asyncFactory)) {
+ // async component
+ renderAsyncComponent(node, isRoot, context)
+ } else {
+ context.write(`<!--${node.text}-->`, context.next)
+ }
+ } else {
+ context.write(
+ node.raw ? node.text : escape(String(node.text)),
+ context.next
+ )
+ }
+}
+
+function registerComponentForCache (options, write) {
+ // exposed by vue-loader, need to call this if cache hit because
+ // component lifecycle hooks will not be called.
+ const register = options._ssrRegister
+ if (write.caching && isDef(register)) {
+ write.componentBuffer[write.componentBuffer.length - 1].add(register)
+ }
+ return register
+}
+
+function renderComponent (node, isRoot, context) {
+ const { write, next, userContext } = context
+
+ // check cache hit
+ const Ctor = node.componentOptions.Ctor
+ const getKey = Ctor.options.serverCacheKey
+ const name = Ctor.options.name
+ const cache = context.cache
+ const registerComponent = registerComponentForCache(Ctor.options, write)
+
+ if (isDef(getKey) && isDef(cache) && isDef(name)) {
+ const key = name + '::' + getKey(node.componentOptions.propsData)
+ const { has, get } = context
+ if (isDef(has)) {
+ has(key, hit => {
+ if (hit === true && isDef(get)) {
+ get(key, res => {
+ if (isDef(registerComponent)) {
+ registerComponent(userContext)
+ }
+ res.components.forEach(register => register(userContext))
+ write(res.html, next)
+ })
+ } else {
+ renderComponentWithCache(node, isRoot, key, context)
+ }
+ })
+ } else if (isDef(get)) {
+ get(key, res => {
+ if (isDef(res)) {
+ if (isDef(registerComponent)) {
+ registerComponent(userContext)
+ }
+ res.components.forEach(register => register(userContext))
+ write(res.html, next)
+ } else {
+ renderComponentWithCache(node, isRoot, key, context)
+ }
+ })
+ }
+ } else {
+ if (isDef(getKey) && isUndef(cache)) {
+ warnOnce(
+ `[vue-server-renderer] Component ${
+ Ctor.options.name || '(anonymous)'
+ } implemented serverCacheKey, ` +
+ 'but no cache was provided to the renderer.'
+ )
+ }
+ if (isDef(getKey) && isUndef(name)) {
+ warnOnce(
+ `[vue-server-renderer] Components that implement "serverCacheKey" ` +
+ `must also define a unique "name" option.`
+ )
+ }
+ renderComponentInner(node, isRoot, context)
+ }
+}
+
+function renderComponentWithCache (node, isRoot, key, context) {
+ const write = context.write
+ write.caching = true
+ const buffer = write.cacheBuffer
+ const bufferIndex = buffer.push('') - 1
+ const componentBuffer = write.componentBuffer
+ componentBuffer.push(new Set())
+ context.renderStates.push({
+ type: 'ComponentWithCache',
+ key,
+ buffer,
+ bufferIndex,
+ componentBuffer
+ })
+ renderComponentInner(node, isRoot, context)
+}
+
+function renderComponentInner (node, isRoot, context) {
+ const prevActive = context.activeInstance
+ // expose userContext on vnode
+ node.ssrContext = context.userContext
+ const child = context.activeInstance = createComponentInstanceForVnode(
+ node,
+ context.activeInstance
+ )
+ normalizeRender(child)
+ const childNode = child._render()
+ childNode.parent = node
+ context.renderStates.push({
+ type: 'Component',
+ prevActive
+ })
+ renderNode(childNode, isRoot, context)
+}
+
+function renderAsyncComponent (node, isRoot, context) {
+ const factory = node.asyncFactory
+
+ const resolve = comp => {
+ if (comp.__esModule && comp.default) {
+ comp = comp.default
+ }
+ const { data, children, tag } = node.asyncMeta
+ const nodeContext = node.asyncMeta.context
+ const resolvedNode: any = createComponent(
+ comp,
+ data,
+ nodeContext,
+ children,
+ tag
+ )
+ if (resolvedNode) {
+ if (resolvedNode.componentOptions) {
+ // normal component
+ renderComponent(resolvedNode, isRoot, context)
+ } else if (!Array.isArray(resolvedNode)) {
+ // single return node from functional component
+ renderNode(resolvedNode, isRoot, context)
+ } else {
+ // multiple return nodes from functional component
+ context.renderStates.push({
+ type: 'Fragment',
+ children: resolvedNode,
+ rendered: 0,
+ total: resolvedNode.length
+ })
+ context.next()
+ }
+ } else {
+ // invalid component, but this does not throw on the client
+ // so render empty comment node
+ context.write(`<!---->`, context.next)
+ }
+ }
+
+ if (factory.resolved) {
+ resolve(factory.resolved)
+ return
+ }
+
+ const reject = context.done
+ let res
+ try {
+ res = factory(resolve, reject)
+ } catch (e) {
+ reject(e)
+ }
+ if (res) {
+ if (typeof res.then === 'function') {
+ res.then(resolve, reject).catch(reject)
+ } else {
+ // new syntax in 2.3
+ const comp = res.component
+ if (comp && typeof comp.then === 'function') {
+ comp.then(resolve, reject).catch(reject)
+ }
+ }
+ }
+}
+
+function renderStringNode (el, context) {
+ const { write, next } = context
+ if (isUndef(el.children) || el.children.length === 0) {
+ write(el.open + (el.close || ''), next)
+ } else {
+ const children: Array<VNode> = el.children
+ context.renderStates.push({
+ type: 'Element',
+ children,
+ rendered: 0,
+ total: children.length,
+ endTag: el.close
+ })
+ write(el.open, next)
+ }
+}
+
+function renderElement (el, isRoot, context) {
+ const { write, next } = context
+
+ if (isTrue(isRoot)) {
+ if (!el.data) el.data = {}
+ if (!el.data.attrs) el.data.attrs = {}
+ el.data.attrs[SSR_ATTR] = 'true'
+ }
+
+ if (el.fnOptions) {
+ registerComponentForCache(el.fnOptions, write)
+ }
+
+ const startTag = renderStartingTag(el, context)
+ const endTag = `</${el.tag}>`
+ if (context.isUnaryTag(el.tag)) {
+ write(startTag, next)
+ } else if (isUndef(el.children) || el.children.length === 0) {
+ write(startTag + endTag, next)
+ } else {
+ const children: Array<VNode> = el.children
+ context.renderStates.push({
+ type: 'Element',
+ children,
+ rendered: 0,
+ total: children.length,
+ endTag
+ })
+ write(startTag, next)
+ }
+}
+
+function hasAncestorData (node: VNode) {
+ const parentNode = node.parent
+ return isDef(parentNode) && (isDef(parentNode.data) || hasAncestorData(parentNode))
+}
+
+function getVShowDirectiveInfo (node: VNode): ?VNodeDirective {
+ let dir: VNodeDirective
+ let tmp
+
+ while (isDef(node)) {
+ if (node.data && node.data.directives) {
+ tmp = node.data.directives.find(dir => dir.name === 'show')
+ if (tmp) {
+ dir = tmp
+ }
+ }
+ node = node.parent
+ }
+ return dir
+}
+
+function renderStartingTag (node: VNode, context) {
+ let markup = `<${node.tag}`
+ const { directives, modules } = context
+
+ // construct synthetic data for module processing
+ // because modules like style also produce code by parent VNode data
+ if (isUndef(node.data) && hasAncestorData(node)) {
+ node.data = {}
+ }
+ if (isDef(node.data)) {
+ // check directives
+ const dirs = node.data.directives
+ if (dirs) {
+ for (let i = 0; i < dirs.length; i++) {
+ const name = dirs[i].name
+ const dirRenderer = directives[name]
+ if (dirRenderer && name !== 'show') {
+ // directives mutate the node's data
+ // which then gets rendered by modules
+ dirRenderer(node, dirs[i])
+ }
+ }
+ }
+
+ // v-show directive needs to be merged from parent to child
+ const vshowDirectiveInfo = getVShowDirectiveInfo(node)
+ if (vshowDirectiveInfo) {
+ directives.show(node, vshowDirectiveInfo)
+ }
+
+ // apply other modules
+ for (let i = 0; i < modules.length; i++) {
+ const res = modules[i](node)
+ if (res) {
+ markup += res
+ }
+ }
+ }
+ // attach scoped CSS ID
+ let scopeId
+ const activeInstance = context.activeInstance
+ if (isDef(activeInstance) &&
+ activeInstance !== node.context &&
+ isDef(scopeId = activeInstance.$options._scopeId)
+ ) {
+ markup += ` ${(scopeId: any)}`
+ }
+ if (isDef(node.fnScopeId)) {
+ markup += ` ${node.fnScopeId}`
+ } else {
+ while (isDef(node)) {
+ if (isDef(scopeId = node.context.$options._scopeId)) {
+ markup += ` ${scopeId}`
+ }
+ node = node.parent
+ }
+ }
+ return markup + '>'
+}
+
+export function createRenderFunction (
+ modules: Array<(node: VNode) => ?string>,
+ directives: Object,
+ isUnaryTag: Function,
+ cache: any
+) {
+ return function render (
+ component: Component,
+ write: (text: string, next: Function) => void,
+ userContext: ?Object,
+ done: Function
+ ) {
+ warned = Object.create(null)
+ const context = new RenderContext({
+ activeInstance: component,
+ userContext,
+ write, done, renderNode,
+ isUnaryTag, modules, directives,
+ cache
+ })
+ installSSRHelpers(component)
+ normalizeRender(component)
+ renderNode(component._render(), true, context)
+ }
+}
diff --git a/node_modules/vue/src/server/template-renderer/create-async-file-mapper.js b/node_modules/vue/src/server/template-renderer/create-async-file-mapper.js
new file mode 100644
index 00000000..64c0647a
--- /dev/null
+++ b/node_modules/vue/src/server/template-renderer/create-async-file-mapper.js
@@ -0,0 +1,53 @@
+/* @flow */
+
+/**
+ * Creates a mapper that maps components used during a server-side render
+ * to async chunk files in the client-side build, so that we can inline them
+ * directly in the rendered HTML to avoid waterfall requests.
+ */
+
+import type { ClientManifest } from './index'
+
+export type AsyncFileMapper = (files: Array<string>) => Array<string>;
+
+export function createMapper (
+ clientManifest: ClientManifest
+): AsyncFileMapper {
+ const map = createMap(clientManifest)
+ // map server-side moduleIds to client-side files
+ return function mapper (moduleIds: Array<string>): Array<string> {
+ const res = new Set()
+ for (let i = 0; i < moduleIds.length; i++) {
+ const mapped = map.get(moduleIds[i])
+ if (mapped) {
+ for (let j = 0; j < mapped.length; j++) {
+ res.add(mapped[j])
+ }
+ }
+ }
+ return Array.from(res)
+ }
+}
+
+function createMap (clientManifest) {
+ const map = new Map()
+ Object.keys(clientManifest.modules).forEach(id => {
+ map.set(id, mapIdToFile(id, clientManifest))
+ })
+ return map
+}
+
+function mapIdToFile (id, clientManifest) {
+ const files = []
+ const fileIndices = clientManifest.modules[id]
+ if (fileIndices) {
+ fileIndices.forEach(index => {
+ const file = clientManifest.all[index]
+ // only include async files or non-js assets
+ if (clientManifest.async.indexOf(file) > -1 || !(/\.js($|\?)/.test(file))) {
+ files.push(file)
+ }
+ })
+ }
+ return files
+}
diff --git a/node_modules/vue/src/server/template-renderer/index.js b/node_modules/vue/src/server/template-renderer/index.js
new file mode 100644
index 00000000..dabc08a1
--- /dev/null
+++ b/node_modules/vue/src/server/template-renderer/index.js
@@ -0,0 +1,257 @@
+/* @flow */
+
+const path = require('path')
+const serialize = require('serialize-javascript')
+
+import { isJS, isCSS } from '../util'
+import TemplateStream from './template-stream'
+import { parseTemplate } from './parse-template'
+import { createMapper } from './create-async-file-mapper'
+import type { ParsedTemplate } from './parse-template'
+import type { AsyncFileMapper } from './create-async-file-mapper'
+
+type TemplateRendererOptions = {
+ template: ?string;
+ inject?: boolean;
+ clientManifest?: ClientManifest;
+ shouldPreload?: (file: string, type: string) => boolean;
+ shouldPrefetch?: (file: string, type: string) => boolean;
+};
+
+export type ClientManifest = {
+ publicPath: string;
+ all: Array<string>;
+ initial: Array<string>;
+ async: Array<string>;
+ modules: {
+ [id: string]: Array<number>;
+ },
+ hasNoCssVersion?: {
+ [file: string]: boolean;
+ }
+};
+
+type Resource = {
+ file: string;
+ extension: string;
+ fileWithoutQuery: string;
+ asType: string;
+};
+
+export default class TemplateRenderer {
+ options: TemplateRendererOptions;
+ inject: boolean;
+ parsedTemplate: ParsedTemplate | null;
+ publicPath: string;
+ clientManifest: ClientManifest;
+ preloadFiles: Array<Resource>;
+ prefetchFiles: Array<Resource>;
+ mapFiles: AsyncFileMapper;
+
+ constructor (options: TemplateRendererOptions) {
+ this.options = options
+ this.inject = options.inject !== false
+ // if no template option is provided, the renderer is created
+ // as a utility object for rendering assets like preload links and scripts.
+ this.parsedTemplate = options.template
+ ? parseTemplate(options.template)
+ : null
+
+ // extra functionality with client manifest
+ if (options.clientManifest) {
+ const clientManifest = this.clientManifest = options.clientManifest
+ this.publicPath = clientManifest.publicPath.replace(/\/$/, '')
+ // preload/prefetch directives
+ this.preloadFiles = (clientManifest.initial || []).map(normalizeFile)
+ this.prefetchFiles = (clientManifest.async || []).map(normalizeFile)
+ // initial async chunk mapping
+ this.mapFiles = createMapper(clientManifest)
+ }
+ }
+
+ bindRenderFns (context: Object) {
+ const renderer: any = this
+ ;['ResourceHints', 'State', 'Scripts', 'Styles'].forEach(type => {
+ context[`render${type}`] = renderer[`render${type}`].bind(renderer, context)
+ })
+ // also expose getPreloadFiles, useful for HTTP/2 push
+ context.getPreloadFiles = renderer.getPreloadFiles.bind(renderer, context)
+ }
+
+ // render synchronously given rendered app content and render context
+ renderSync (content: string, context: ?Object) {
+ const template = this.parsedTemplate
+ if (!template) {
+ throw new Error('renderSync cannot be called without a template.')
+ }
+ context = context || {}
+ if (this.inject) {
+ return (
+ template.head(context) +
+ (context.head || '') +
+ this.renderResourceHints(context) +
+ this.renderStyles(context) +
+ template.neck(context) +
+ content +
+ this.renderState(context) +
+ this.renderScripts(context) +
+ template.tail(context)
+ )
+ } else {
+ return (
+ template.head(context) +
+ template.neck(context) +
+ content +
+ template.tail(context)
+ )
+ }
+ }
+
+ renderStyles (context: Object): string {
+ const cssFiles = this.clientManifest
+ ? this.clientManifest.all.filter(isCSS)
+ : []
+ return (
+ // render links for css files
+ (cssFiles.length
+ ? cssFiles.map(file => `<link rel="stylesheet" href="${this.publicPath}/${file}">`).join('')
+ : '') +
+ // context.styles is a getter exposed by vue-style-loader which contains
+ // the inline component styles collected during SSR
+ (context.styles || '')
+ )
+ }
+
+ renderResourceHints (context: Object): string {
+ return this.renderPreloadLinks(context) + this.renderPrefetchLinks(context)
+ }
+
+ getPreloadFiles (context: Object): Array<Resource> {
+ const usedAsyncFiles = this.getUsedAsyncFiles(context)
+ if (this.preloadFiles || usedAsyncFiles) {
+ return (this.preloadFiles || []).concat(usedAsyncFiles || [])
+ } else {
+ return []
+ }
+ }
+
+ renderPreloadLinks (context: Object): string {
+ const files = this.getPreloadFiles(context)
+ const shouldPreload = this.options.shouldPreload
+ if (files.length) {
+ return files.map(({ file, extension, fileWithoutQuery, asType }) => {
+ let extra = ''
+ // by default, we only preload scripts or css
+ if (!shouldPreload && asType !== 'script' && asType !== 'style') {
+ return ''
+ }
+ // user wants to explicitly control what to preload
+ if (shouldPreload && !shouldPreload(fileWithoutQuery, asType)) {
+ return ''
+ }
+ if (asType === 'font') {
+ extra = ` type="font/${extension}" crossorigin`
+ }
+ return `<link rel="preload" href="${
+ this.publicPath}/${file
+ }"${
+ asType !== '' ? ` as="${asType}"` : ''
+ }${
+ extra
+ }>`
+ }).join('')
+ } else {
+ return ''
+ }
+ }
+
+ renderPrefetchLinks (context: Object): string {
+ const shouldPrefetch = this.options.shouldPrefetch
+ if (this.prefetchFiles) {
+ const usedAsyncFiles = this.getUsedAsyncFiles(context)
+ const alreadyRendered = file => {
+ return usedAsyncFiles && usedAsyncFiles.some(f => f.file === file)
+ }
+ return this.prefetchFiles.map(({ file, fileWithoutQuery, asType }) => {
+ if (shouldPrefetch && !shouldPrefetch(fileWithoutQuery, asType)) {
+ return ''
+ }
+ if (alreadyRendered(file)) {
+ return ''
+ }
+ return `<link rel="prefetch" href="${this.publicPath}/${file}">`
+ }).join('')
+ } else {
+ return ''
+ }
+ }
+
+ renderState (context: Object, options?: Object): string {
+ const {
+ contextKey = 'state',
+ windowKey = '__INITIAL_STATE__'
+ } = options || {}
+ const state = serialize(context[contextKey], { isJSON: true })
+ const autoRemove = process.env.NODE_ENV === 'production'
+ ? ';(function(){var s;(s=document.currentScript||document.scripts[document.scripts.length-1]).parentNode.removeChild(s);}());'
+ : ''
+ return context[contextKey]
+ ? `<script>window.${windowKey}=${state}${autoRemove}</script>`
+ : ''
+ }
+
+ renderScripts (context: Object): string {
+ if (this.clientManifest) {
+ const initial = this.preloadFiles
+ const async = this.getUsedAsyncFiles(context)
+ const needed = [initial[0]].concat(async || [], initial.slice(1))
+ return needed.filter(({ file }) => isJS(file)).map(({ file }) => {
+ return `<script src="${this.publicPath}/${file}" defer></script>`
+ }).join('')
+ } else {
+ return ''
+ }
+ }
+
+ getUsedAsyncFiles (context: Object): ?Array<Resource> {
+ if (!context._mappedFiles && context._registeredComponents && this.mapFiles) {
+ const registered = Array.from(context._registeredComponents)
+ context._mappedFiles = this.mapFiles(registered).map(normalizeFile)
+ }
+ return context._mappedFiles
+ }
+
+ // create a transform stream
+ createStream (context: ?Object): TemplateStream {
+ if (!this.parsedTemplate) {
+ throw new Error('createStream cannot be called without a template.')
+ }
+ return new TemplateStream(this, this.parsedTemplate, context || {})
+ }
+}
+
+function normalizeFile (file: string): Resource {
+ const withoutQuery = file.replace(/\?.*/, '')
+ const extension = path.extname(withoutQuery).slice(1)
+ return {
+ file,
+ extension,
+ fileWithoutQuery: withoutQuery,
+ asType: getPreloadType(extension)
+ }
+}
+
+function getPreloadType (ext: string): string {
+ if (ext === 'js') {
+ return 'script'
+ } else if (ext === 'css') {
+ return 'style'
+ } else if (/jpe?g|png|svg|gif|webp|ico/.test(ext)) {
+ return 'image'
+ } else if (/woff2?|ttf|otf|eot/.test(ext)) {
+ return 'font'
+ } else {
+ // not exhausting all possibilities here, but above covers common cases
+ return ''
+ }
+}
diff --git a/node_modules/vue/src/server/template-renderer/parse-template.js b/node_modules/vue/src/server/template-renderer/parse-template.js
new file mode 100644
index 00000000..1ccfe899
--- /dev/null
+++ b/node_modules/vue/src/server/template-renderer/parse-template.js
@@ -0,0 +1,42 @@
+/* @flow */
+
+const compile = require('lodash.template')
+const compileOptions = {
+ escape: /{{([^{][\s\S]+?[^}])}}/g,
+ interpolate: /{{{([\s\S]+?)}}}/g
+}
+
+export type ParsedTemplate = {
+ head: (data: any) => string;
+ neck: (data: any) => string;
+ tail: (data: any) => string;
+};
+
+export function parseTemplate (
+ template: string,
+ contentPlaceholder?: string = '<!--vue-ssr-outlet-->'
+): ParsedTemplate {
+ if (typeof template === 'object') {
+ return template
+ }
+
+ let i = template.indexOf('</head>')
+ const j = template.indexOf(contentPlaceholder)
+
+ if (j < 0) {
+ throw new Error(`Content placeholder not found in template.`)
+ }
+
+ if (i < 0) {
+ i = template.indexOf('<body>')
+ if (i < 0) {
+ i = j
+ }
+ }
+
+ return {
+ head: compile(template.slice(0, i), compileOptions),
+ neck: compile(template.slice(i, j), compileOptions),
+ tail: compile(template.slice(j + contentPlaceholder.length), compileOptions)
+ }
+}
diff --git a/node_modules/vue/src/server/template-renderer/template-stream.js b/node_modules/vue/src/server/template-renderer/template-stream.js
new file mode 100644
index 00000000..ed4db78f
--- /dev/null
+++ b/node_modules/vue/src/server/template-renderer/template-stream.js
@@ -0,0 +1,82 @@
+/* @flow */
+
+const Transform = require('stream').Transform
+import type TemplateRenderer from './index'
+import type { ParsedTemplate } from './parse-template'
+
+export default class TemplateStream extends Transform {
+ started: boolean;
+ renderer: TemplateRenderer;
+ template: ParsedTemplate;
+ context: Object;
+ inject: boolean;
+
+ constructor (
+ renderer: TemplateRenderer,
+ template: ParsedTemplate,
+ context: Object
+ ) {
+ super()
+ this.started = false
+ this.renderer = renderer
+ this.template = template
+ this.context = context || {}
+ this.inject = renderer.inject
+ }
+
+ _transform (data: Buffer | string, encoding: string, done: Function) {
+ if (!this.started) {
+ this.emit('beforeStart')
+ this.start()
+ }
+ this.push(data)
+ done()
+ }
+
+ start () {
+ this.started = true
+ this.push(this.template.head(this.context))
+
+ if (this.inject) {
+ // inline server-rendered head meta information
+ if (this.context.head) {
+ this.push(this.context.head)
+ }
+
+ // inline preload/prefetch directives for initial/async chunks
+ const links = this.renderer.renderResourceHints(this.context)
+ if (links) {
+ this.push(links)
+ }
+
+ // CSS files and inline server-rendered CSS collected by vue-style-loader
+ const styles = this.renderer.renderStyles(this.context)
+ if (styles) {
+ this.push(styles)
+ }
+ }
+
+ this.push(this.template.neck(this.context))
+ }
+
+ _flush (done: Function) {
+ this.emit('beforeEnd')
+
+ if (this.inject) {
+ // inline initial store state
+ const state = this.renderer.renderState(this.context)
+ if (state) {
+ this.push(state)
+ }
+
+ // embed scripts needed
+ const scripts = this.renderer.renderScripts(this.context)
+ if (scripts) {
+ this.push(scripts)
+ }
+ }
+
+ this.push(this.template.tail(this.context))
+ done()
+ }
+}
diff --git a/node_modules/vue/src/server/util.js b/node_modules/vue/src/server/util.js
new file mode 100644
index 00000000..908f8c9d
--- /dev/null
+++ b/node_modules/vue/src/server/util.js
@@ -0,0 +1,18 @@
+/* @flow */
+
+export const isJS = (file: string): boolean => /\.js(\?[^.]+)?$/.test(file)
+
+export const isCSS = (file: string): boolean => /\.css(\?[^.]+)?$/.test(file)
+
+export function createPromiseCallback () {
+ let resolve, reject
+ const promise: Promise<string> = new Promise((_resolve, _reject) => {
+ resolve = _resolve
+ reject = _reject
+ })
+ const cb = (err: Error, res?: string) => {
+ if (err) return reject(err)
+ resolve(res || '')
+ }
+ return { promise, cb }
+}
diff --git a/node_modules/vue/src/server/webpack-plugin/client.js b/node_modules/vue/src/server/webpack-plugin/client.js
new file mode 100644
index 00000000..5f2cd4bd
--- /dev/null
+++ b/node_modules/vue/src/server/webpack-plugin/client.js
@@ -0,0 +1,70 @@
+const hash = require('hash-sum')
+const uniq = require('lodash.uniq')
+import { isJS } from './util'
+
+export default class VueSSRClientPlugin {
+ constructor (options = {}) {
+ this.options = Object.assign({
+ filename: 'vue-ssr-client-manifest.json'
+ }, options)
+ }
+
+ apply (compiler) {
+ compiler.plugin('emit', (compilation, cb) => {
+ const stats = compilation.getStats().toJson()
+
+ const allFiles = uniq(stats.assets
+ .map(a => a.name))
+
+ const initialFiles = uniq(Object.keys(stats.entrypoints)
+ .map(name => stats.entrypoints[name].assets)
+ .reduce((assets, all) => all.concat(assets), [])
+ .filter(isJS))
+
+ const asyncFiles = allFiles
+ .filter(isJS)
+ .filter(file => initialFiles.indexOf(file) < 0)
+
+ const manifest = {
+ publicPath: stats.publicPath,
+ all: allFiles,
+ initial: initialFiles,
+ async: asyncFiles,
+ modules: { /* [identifier: string]: Array<index: number> */ }
+ }
+
+ const assetModules = stats.modules.filter(m => m.assets.length)
+ const fileToIndex = file => manifest.all.indexOf(file)
+ stats.modules.forEach(m => {
+ // ignore modules duplicated in multiple chunks
+ if (m.chunks.length === 1) {
+ const cid = m.chunks[0]
+ const chunk = stats.chunks.find(c => c.id === cid)
+ if (!chunk || !chunk.files) {
+ return
+ }
+ const files = manifest.modules[hash(m.identifier)] = chunk.files.map(fileToIndex)
+ // find all asset modules associated with the same chunk
+ assetModules.forEach(m => {
+ if (m.chunks.some(id => id === cid)) {
+ files.push.apply(files, m.assets.map(fileToIndex))
+ }
+ })
+ }
+ })
+
+ // const debug = (file, obj) => {
+ // require('fs').writeFileSync(__dirname + '/' + file, JSON.stringify(obj, null, 2))
+ // }
+ // debug('stats.json', stats)
+ // debug('client-manifest.json', manifest)
+
+ const json = JSON.stringify(manifest, null, 2)
+ compilation.assets[this.options.filename] = {
+ source: () => json,
+ size: () => json.length
+ }
+ cb()
+ })
+ }
+}
diff --git a/node_modules/vue/src/server/webpack-plugin/server.js b/node_modules/vue/src/server/webpack-plugin/server.js
new file mode 100644
index 00000000..8ffa58b0
--- /dev/null
+++ b/node_modules/vue/src/server/webpack-plugin/server.js
@@ -0,0 +1,66 @@
+import { validate, isJS } from './util'
+
+export default class VueSSRServerPlugin {
+ constructor (options = {}) {
+ this.options = Object.assign({
+ filename: 'vue-ssr-server-bundle.json'
+ }, options)
+ }
+
+ apply (compiler) {
+ validate(compiler)
+
+ compiler.plugin('emit', (compilation, cb) => {
+ const stats = compilation.getStats().toJson()
+ const entryName = Object.keys(stats.entrypoints)[0]
+ const entryInfo = stats.entrypoints[entryName]
+
+ if (!entryInfo) {
+ // #5553
+ return cb()
+ }
+
+ const entryAssets = entryInfo.assets.filter(isJS)
+
+ if (entryAssets.length > 1) {
+ throw new Error(
+ `Server-side bundle should have one single entry file. ` +
+ `Avoid using CommonsChunkPlugin in the server config.`
+ )
+ }
+
+ const entry = entryAssets[0]
+ if (!entry || typeof entry !== 'string') {
+ throw new Error(
+ `Entry "${entryName}" not found. Did you specify the correct entry option?`
+ )
+ }
+
+ const bundle = {
+ entry,
+ files: {},
+ maps: {}
+ }
+
+ stats.assets.forEach(asset => {
+ if (asset.name.match(/\.js$/)) {
+ bundle.files[asset.name] = compilation.assets[asset.name].source()
+ } else if (asset.name.match(/\.js\.map$/)) {
+ bundle.maps[asset.name.replace(/\.map$/, '')] = JSON.parse(compilation.assets[asset.name].source())
+ }
+ // do not emit anything else for server
+ delete compilation.assets[asset.name]
+ })
+
+ const json = JSON.stringify(bundle, null, 2)
+ const filename = this.options.filename
+
+ compilation.assets[filename] = {
+ source: () => json,
+ size: () => json.length
+ }
+
+ cb()
+ })
+ }
+}
diff --git a/node_modules/vue/src/server/webpack-plugin/util.js b/node_modules/vue/src/server/webpack-plugin/util.js
new file mode 100644
index 00000000..d22e4b2c
--- /dev/null
+++ b/node_modules/vue/src/server/webpack-plugin/util.js
@@ -0,0 +1,24 @@
+const { red, yellow } = require('chalk')
+
+const prefix = `[vue-server-renderer-webpack-plugin]`
+const warn = exports.warn = msg => console.error(red(`${prefix} ${msg}\n`))
+const tip = exports.tip = msg => console.log(yellow(`${prefix} ${msg}\n`))
+
+export const validate = compiler => {
+ if (compiler.options.target !== 'node') {
+ warn('webpack config `target` should be "node".')
+ }
+
+ if (compiler.options.output && compiler.options.output.libraryTarget !== 'commonjs2') {
+ warn('webpack config `output.libraryTarget` should be "commonjs2".')
+ }
+
+ if (!compiler.options.externals) {
+ tip(
+ 'It is recommended to externalize dependencies in the server build for ' +
+ 'better build performance.'
+ )
+ }
+}
+
+export { isJS, isCSS } from '../util'
diff --git a/node_modules/vue/src/server/write.js b/node_modules/vue/src/server/write.js
new file mode 100644
index 00000000..e6420818
--- /dev/null
+++ b/node_modules/vue/src/server/write.js
@@ -0,0 +1,50 @@
+/* @flow */
+
+const MAX_STACK_DEPTH = 1000
+const noop = _ => _
+
+const defer = typeof process !== 'undefined' && process.nextTick
+ ? process.nextTick
+ : typeof Promise !== 'undefined'
+ ? fn => Promise.resolve().then(fn)
+ : typeof setTimeout !== 'undefined'
+ ? setTimeout
+ : noop
+
+if (defer === noop) {
+ throw new Error(
+ 'Your JavaScript runtime does not support any asynchronous primitives ' +
+ 'that are required by vue-server-renderer. Please use a polyfill for ' +
+ 'either Promise or setTimeout.'
+ )
+}
+
+export function createWriteFunction (
+ write: (text: string, next: Function) => boolean,
+ onError: Function
+): Function {
+ let stackDepth = 0
+ const cachedWrite = (text, next) => {
+ if (text && cachedWrite.caching) {
+ cachedWrite.cacheBuffer[cachedWrite.cacheBuffer.length - 1] += text
+ }
+ const waitForNext = write(text, next)
+ if (waitForNext !== true) {
+ if (stackDepth >= MAX_STACK_DEPTH) {
+ defer(() => {
+ try { next() } catch (e) {
+ onError(e)
+ }
+ })
+ } else {
+ stackDepth++
+ next()
+ stackDepth--
+ }
+ }
+ }
+ cachedWrite.caching = false
+ cachedWrite.cacheBuffer = []
+ cachedWrite.componentBuffer = []
+ return cachedWrite
+}
diff --git a/node_modules/vue/src/sfc/parser.js b/node_modules/vue/src/sfc/parser.js
new file mode 100644
index 00000000..868a43ca
--- /dev/null
+++ b/node_modules/vue/src/sfc/parser.js
@@ -0,0 +1,116 @@
+/* @flow */
+
+import deindent from 'de-indent'
+import { parseHTML } from 'compiler/parser/html-parser'
+import { makeMap } from 'shared/util'
+
+const splitRE = /\r?\n/g
+const replaceRE = /./g
+const isSpecialTag = makeMap('script,style,template', true)
+
+type Attribute = {
+ name: string,
+ value: string
+};
+
+/**
+ * Parse a single-file component (*.vue) file into an SFC Descriptor Object.
+ */
+export function parseComponent (
+ content: string,
+ options?: Object = {}
+): SFCDescriptor {
+ const sfc: SFCDescriptor = {
+ template: null,
+ script: null,
+ styles: [],
+ customBlocks: []
+ }
+ let depth = 0
+ let currentBlock: ?SFCBlock = null
+
+ function start (
+ tag: string,
+ attrs: Array<Attribute>,
+ unary: boolean,
+ start: number,
+ end: number
+ ) {
+ if (depth === 0) {
+ currentBlock = {
+ type: tag,
+ content: '',
+ start: end,
+ attrs: attrs.reduce((cumulated, { name, value }) => {
+ cumulated[name] = value || true
+ return cumulated
+ }, {})
+ }
+ if (isSpecialTag(tag)) {
+ checkAttrs(currentBlock, attrs)
+ if (tag === 'style') {
+ sfc.styles.push(currentBlock)
+ } else {
+ sfc[tag] = currentBlock
+ }
+ } else { // custom blocks
+ sfc.customBlocks.push(currentBlock)
+ }
+ }
+ if (!unary) {
+ depth++
+ }
+ }
+
+ function checkAttrs (block: SFCBlock, attrs: Array<Attribute>) {
+ for (let i = 0; i < attrs.length; i++) {
+ const attr = attrs[i]
+ if (attr.name === 'lang') {
+ block.lang = attr.value
+ }
+ if (attr.name === 'scoped') {
+ block.scoped = true
+ }
+ if (attr.name === 'module') {
+ block.module = attr.value || true
+ }
+ if (attr.name === 'src') {
+ block.src = attr.value
+ }
+ }
+ }
+
+ function end (tag: string, start: number, end: number) {
+ if (depth === 1 && currentBlock) {
+ currentBlock.end = start
+ let text = deindent(content.slice(currentBlock.start, currentBlock.end))
+ // pad content so that linters and pre-processors can output correct
+ // line numbers in errors and warnings
+ if (currentBlock.type !== 'template' && options.pad) {
+ text = padContent(currentBlock, options.pad) + text
+ }
+ currentBlock.content = text
+ currentBlock = null
+ }
+ depth--
+ }
+
+ function padContent (block: SFCBlock, pad: true | "line" | "space") {
+ if (pad === 'space') {
+ return content.slice(0, block.start).replace(replaceRE, ' ')
+ } else {
+ const offset = content.slice(0, block.start).split(splitRE).length
+ const padChar = block.type === 'script' && !block.lang
+ ? '//\n'
+ : '\n'
+ return Array(offset).join(padChar)
+ }
+ }
+
+ parseHTML(content, {
+ start,
+ end
+ })
+
+ return sfc
+}
diff --git a/node_modules/vue/src/shared/constants.js b/node_modules/vue/src/shared/constants.js
new file mode 100644
index 00000000..84d019fb
--- /dev/null
+++ b/node_modules/vue/src/shared/constants.js
@@ -0,0 +1,21 @@
+export const SSR_ATTR = 'data-server-rendered'
+
+export const ASSET_TYPES = [
+ 'component',
+ 'directive',
+ 'filter'
+]
+
+export const LIFECYCLE_HOOKS = [
+ 'beforeCreate',
+ 'created',
+ 'beforeMount',
+ 'mounted',
+ 'beforeUpdate',
+ 'updated',
+ 'beforeDestroy',
+ 'destroyed',
+ 'activated',
+ 'deactivated',
+ 'errorCaptured'
+]
diff --git a/node_modules/vue/src/shared/util.js b/node_modules/vue/src/shared/util.js
new file mode 100644
index 00000000..e4884734
--- /dev/null
+++ b/node_modules/vue/src/shared/util.js
@@ -0,0 +1,324 @@
+/* @flow */
+
+export const emptyObject = Object.freeze({})
+
+// these helpers produces better vm code in JS engines due to their
+// explicitness and function inlining
+export function isUndef (v: any): boolean %checks {
+ return v === undefined || v === null
+}
+
+export function isDef (v: any): boolean %checks {
+ return v !== undefined && v !== null
+}
+
+export function isTrue (v: any): boolean %checks {
+ return v === true
+}
+
+export function isFalse (v: any): boolean %checks {
+ return v === false
+}
+
+/**
+ * Check if value is primitive
+ */
+export function isPrimitive (value: any): boolean %checks {
+ return (
+ typeof value === 'string' ||
+ typeof value === 'number' ||
+ // $flow-disable-line
+ typeof value === 'symbol' ||
+ typeof value === 'boolean'
+ )
+}
+
+/**
+ * Quick object check - this is primarily used to tell
+ * Objects from primitive values when we know the value
+ * is a JSON-compliant type.
+ */
+export function isObject (obj: mixed): boolean %checks {
+ return obj !== null && typeof obj === 'object'
+}
+
+/**
+ * Get the raw type string of a value e.g. [object Object]
+ */
+const _toString = Object.prototype.toString
+
+export function toRawType (value: any): string {
+ return _toString.call(value).slice(8, -1)
+}
+
+/**
+ * Strict object type check. Only returns true
+ * for plain JavaScript objects.
+ */
+export function isPlainObject (obj: any): boolean {
+ return _toString.call(obj) === '[object Object]'
+}
+
+export function isRegExp (v: any): boolean {
+ return _toString.call(v) === '[object RegExp]'
+}
+
+/**
+ * Check if val is a valid array index.
+ */
+export function isValidArrayIndex (val: any): boolean {
+ const n = parseFloat(String(val))
+ return n >= 0 && Math.floor(n) === n && isFinite(val)
+}
+
+/**
+ * Convert a value to a string that is actually rendered.
+ */
+export function toString (val: any): string {
+ return val == null
+ ? ''
+ : typeof val === 'object'
+ ? JSON.stringify(val, null, 2)
+ : String(val)
+}
+
+/**
+ * Convert a input value to a number for persistence.
+ * If the conversion fails, return original string.
+ */
+export function toNumber (val: string): number | string {
+ const n = parseFloat(val)
+ return isNaN(n) ? val : n
+}
+
+/**
+ * Make a map and return a function for checking if a key
+ * is in that map.
+ */
+export function makeMap (
+ str: string,
+ expectsLowerCase?: boolean
+): (key: string) => true | void {
+ const map = Object.create(null)
+ const list: Array<string> = str.split(',')
+ for (let i = 0; i < list.length; i++) {
+ map[list[i]] = true
+ }
+ return expectsLowerCase
+ ? val => map[val.toLowerCase()]
+ : val => map[val]
+}
+
+/**
+ * Check if a tag is a built-in tag.
+ */
+export const isBuiltInTag = makeMap('slot,component', true)
+
+/**
+ * Check if a attribute is a reserved attribute.
+ */
+export const isReservedAttribute = makeMap('key,ref,slot,slot-scope,is')
+
+/**
+ * Remove an item from an array
+ */
+export function remove (arr: Array<any>, item: any): Array<any> | void {
+ if (arr.length) {
+ const index = arr.indexOf(item)
+ if (index > -1) {
+ return arr.splice(index, 1)
+ }
+ }
+}
+
+/**
+ * Check whether the object has the property.
+ */
+const hasOwnProperty = Object.prototype.hasOwnProperty
+export function hasOwn (obj: Object | Array<*>, key: string): boolean {
+ return hasOwnProperty.call(obj, key)
+}
+
+/**
+ * Create a cached version of a pure function.
+ */
+export function cached<F: Function> (fn: F): F {
+ const cache = Object.create(null)
+ return (function cachedFn (str: string) {
+ const hit = cache[str]
+ return hit || (cache[str] = fn(str))
+ }: any)
+}
+
+/**
+ * Camelize a hyphen-delimited string.
+ */
+const camelizeRE = /-(\w)/g
+export const camelize = cached((str: string): string => {
+ return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
+})
+
+/**
+ * Capitalize a string.
+ */
+export const capitalize = cached((str: string): string => {
+ return str.charAt(0).toUpperCase() + str.slice(1)
+})
+
+/**
+ * Hyphenate a camelCase string.
+ */
+const hyphenateRE = /\B([A-Z])/g
+export const hyphenate = cached((str: string): string => {
+ return str.replace(hyphenateRE, '-$1').toLowerCase()
+})
+
+/**
+ * Simple bind polyfill for environments that do not support it... e.g.
+ * PhantomJS 1.x. Technically we don't need this anymore since native bind is
+ * now more performant in most browsers, but removing it would be breaking for
+ * code that was able to run in PhantomJS 1.x, so this must be kept for
+ * backwards compatibility.
+ */
+
+/* istanbul ignore next */
+function polyfillBind (fn: Function, ctx: Object): Function {
+ function boundFn (a) {
+ const l = arguments.length
+ return l
+ ? l > 1
+ ? fn.apply(ctx, arguments)
+ : fn.call(ctx, a)
+ : fn.call(ctx)
+ }
+
+ boundFn._length = fn.length
+ return boundFn
+}
+
+function nativeBind (fn: Function, ctx: Object): Function {
+ return fn.bind(ctx)
+}
+
+export const bind = Function.prototype.bind
+ ? nativeBind
+ : polyfillBind
+
+/**
+ * Convert an Array-like object to a real Array.
+ */
+export function toArray (list: any, start?: number): Array<any> {
+ start = start || 0
+ let i = list.length - start
+ const ret: Array<any> = new Array(i)
+ while (i--) {
+ ret[i] = list[i + start]
+ }
+ return ret
+}
+
+/**
+ * Mix properties into target object.
+ */
+export function extend (to: Object, _from: ?Object): Object {
+ for (const key in _from) {
+ to[key] = _from[key]
+ }
+ return to
+}
+
+/**
+ * Merge an Array of Objects into a single Object.
+ */
+export function toObject (arr: Array<any>): Object {
+ const res = {}
+ for (let i = 0; i < arr.length; i++) {
+ if (arr[i]) {
+ extend(res, arr[i])
+ }
+ }
+ return res
+}
+
+/**
+ * Perform no operation.
+ * Stubbing args to make Flow happy without leaving useless transpiled code
+ * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/)
+ */
+export function noop (a?: any, b?: any, c?: any) {}
+
+/**
+ * Always return false.
+ */
+export const no = (a?: any, b?: any, c?: any) => false
+
+/**
+ * Return same value
+ */
+export const identity = (_: any) => _
+
+/**
+ * Generate a static keys string from compiler modules.
+ */
+export function genStaticKeys (modules: Array<ModuleOptions>): string {
+ return modules.reduce((keys, m) => {
+ return keys.concat(m.staticKeys || [])
+ }, []).join(',')
+}
+
+/**
+ * Check if two values are loosely equal - that is,
+ * if they are plain objects, do they have the same shape?
+ */
+export function looseEqual (a: any, b: any): boolean {
+ if (a === b) return true
+ const isObjectA = isObject(a)
+ const isObjectB = isObject(b)
+ if (isObjectA && isObjectB) {
+ try {
+ const isArrayA = Array.isArray(a)
+ const isArrayB = Array.isArray(b)
+ if (isArrayA && isArrayB) {
+ return a.length === b.length && a.every((e, i) => {
+ return looseEqual(e, b[i])
+ })
+ } else if (!isArrayA && !isArrayB) {
+ const keysA = Object.keys(a)
+ const keysB = Object.keys(b)
+ return keysA.length === keysB.length && keysA.every(key => {
+ return looseEqual(a[key], b[key])
+ })
+ } else {
+ /* istanbul ignore next */
+ return false
+ }
+ } catch (e) {
+ /* istanbul ignore next */
+ return false
+ }
+ } else if (!isObjectA && !isObjectB) {
+ return String(a) === String(b)
+ } else {
+ return false
+ }
+}
+
+export function looseIndexOf (arr: Array<mixed>, val: mixed): number {
+ for (let i = 0; i < arr.length; i++) {
+ if (looseEqual(arr[i], val)) return i
+ }
+ return -1
+}
+
+/**
+ * Ensure a function is called only once.
+ */
+export function once (fn: Function): Function {
+ let called = false
+ return function () {
+ if (!called) {
+ called = true
+ fn.apply(this, arguments)
+ }
+ }
+}