aboutsummaryrefslogtreecommitdiff
path: root/node_modules/vue/src/core/instance
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/core/instance
parent2c77f00f1a7ecb6c8192f9c16d3b2001b254a107 (diff)
downloadxmake-docs-26105034da4fcce7ac883c899d781f016559310d.tar.gz
xmake-docs-26105034da4fcce7ac883c899d781f016559310d.zip
switch to vuepress
Diffstat (limited to 'node_modules/vue/src/core/instance')
-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
17 files changed, 1653 insertions, 0 deletions
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()
+ }
+ }
+}