From 26105034da4fcce7ac883c899d781f016559310d Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 8 Nov 2018 00:38:48 +0800 Subject: switch to vuepress --- .../src/platforms/web/compiler/directives/html.js | 9 + .../src/platforms/web/compiler/directives/index.js | 9 + .../src/platforms/web/compiler/directives/model.js | 172 +++++++++++ .../src/platforms/web/compiler/directives/text.js | 9 + .../vue/src/platforms/web/compiler/index.js | 8 + .../src/platforms/web/compiler/modules/class.js | 48 +++ .../src/platforms/web/compiler/modules/index.js | 9 + .../src/platforms/web/compiler/modules/model.js | 94 ++++++ .../src/platforms/web/compiler/modules/style.js | 51 +++ .../vue/src/platforms/web/compiler/options.js | 26 ++ .../vue/src/platforms/web/compiler/util.js | 24 ++ .../vue/src/platforms/web/entry-compiler.js | 5 + .../platforms/web/entry-runtime-with-compiler.js | 100 ++++++ .../vue/src/platforms/web/entry-runtime.js | 5 + .../platforms/web/entry-server-basic-renderer.js | 13 + .../vue/src/platforms/web/entry-server-renderer.js | 27 ++ .../vue/src/platforms/web/runtime/class-util.js | 61 ++++ .../src/platforms/web/runtime/components/index.js | 7 + .../web/runtime/components/transition-group.js | 180 +++++++++++ .../platforms/web/runtime/components/transition.js | 194 ++++++++++++ .../src/platforms/web/runtime/directives/index.js | 7 + .../src/platforms/web/runtime/directives/model.js | 147 +++++++++ .../src/platforms/web/runtime/directives/show.js | 60 ++++ .../vue/src/platforms/web/runtime/index.js | 77 +++++ .../vue/src/platforms/web/runtime/modules/attrs.js | 118 +++++++ .../vue/src/platforms/web/runtime/modules/class.js | 48 +++ .../src/platforms/web/runtime/modules/dom-props.js | 95 ++++++ .../src/platforms/web/runtime/modules/events.js | 87 ++++++ .../vue/src/platforms/web/runtime/modules/index.js | 15 + .../vue/src/platforms/web/runtime/modules/style.js | 93 ++++++ .../platforms/web/runtime/modules/transition.js | 343 +++++++++++++++++++++ .../vue/src/platforms/web/runtime/node-ops.js | 59 ++++ .../vue/src/platforms/web/runtime/patch.js | 12 + .../src/platforms/web/runtime/transition-util.js | 185 +++++++++++ .../vue/src/platforms/web/server/compiler.js | 11 + .../src/platforms/web/server/directives/index.js | 7 + .../src/platforms/web/server/directives/model.js | 44 +++ .../src/platforms/web/server/directives/show.js | 12 + .../vue/src/platforms/web/server/modules/attrs.js | 62 ++++ .../vue/src/platforms/web/server/modules/class.js | 11 + .../src/platforms/web/server/modules/dom-props.js | 50 +++ .../vue/src/platforms/web/server/modules/index.js | 11 + .../vue/src/platforms/web/server/modules/style.js | 28 ++ node_modules/vue/src/platforms/web/server/util.js | 56 ++++ node_modules/vue/src/platforms/web/util/attrs.js | 43 +++ node_modules/vue/src/platforms/web/util/class.js | 85 +++++ node_modules/vue/src/platforms/web/util/compat.js | 16 + node_modules/vue/src/platforms/web/util/element.js | 77 +++++ node_modules/vue/src/platforms/web/util/index.js | 25 ++ node_modules/vue/src/platforms/web/util/style.js | 72 +++++ .../platforms/weex/compiler/directives/index.js | 5 + .../platforms/weex/compiler/directives/model.js | 34 ++ .../vue/src/platforms/weex/compiler/index.js | 52 ++++ .../src/platforms/weex/compiler/modules/append.js | 27 ++ .../src/platforms/weex/compiler/modules/class.js | 73 +++++ .../src/platforms/weex/compiler/modules/index.js | 13 + .../src/platforms/weex/compiler/modules/props.js | 32 ++ .../modules/recycle-list/component-root.js | 16 + .../compiler/modules/recycle-list/component.js | 16 + .../weex/compiler/modules/recycle-list/index.js | 60 ++++ .../compiler/modules/recycle-list/recycle-list.js | 50 +++ .../weex/compiler/modules/recycle-list/text.js | 23 ++ .../weex/compiler/modules/recycle-list/v-bind.js | 21 ++ .../weex/compiler/modules/recycle-list/v-for.js | 33 ++ .../weex/compiler/modules/recycle-list/v-if.js | 63 ++++ .../weex/compiler/modules/recycle-list/v-on.js | 25 ++ .../weex/compiler/modules/recycle-list/v-once.js | 19 ++ .../src/platforms/weex/compiler/modules/style.js | 86 ++++++ .../vue/src/platforms/weex/entry-compiler.js | 1 + .../vue/src/platforms/weex/entry-framework.js | 187 +++++++++++ .../src/platforms/weex/entry-runtime-factory.js | 6 + .../src/platforms/weex/runtime/components/index.js | 9 + .../platforms/weex/runtime/components/richtext.js | 82 +++++ .../weex/runtime/components/transition-group.js | 148 +++++++++ .../weex/runtime/components/transition.js | 9 + .../src/platforms/weex/runtime/directives/index.js | 2 + .../vue/src/platforms/weex/runtime/index.js | 42 +++ .../src/platforms/weex/runtime/modules/attrs.js | 44 +++ .../src/platforms/weex/runtime/modules/class.js | 75 +++++ .../src/platforms/weex/runtime/modules/events.js | 57 ++++ .../src/platforms/weex/runtime/modules/index.js | 13 + .../src/platforms/weex/runtime/modules/style.js | 84 +++++ .../platforms/weex/runtime/modules/transition.js | 270 ++++++++++++++++ .../vue/src/platforms/weex/runtime/node-ops.js | 91 ++++++ .../vue/src/platforms/weex/runtime/patch.js | 16 + .../recycle-list/render-component-template.js | 34 ++ .../weex/runtime/recycle-list/virtual-component.js | 136 ++++++++ .../vue/src/platforms/weex/runtime/text-node.js | 9 + .../vue/src/platforms/weex/util/element.js | 52 ++++ node_modules/vue/src/platforms/weex/util/index.js | 40 +++ node_modules/vue/src/platforms/weex/util/parser.js | 60 ++++ 91 files changed, 5122 insertions(+) create mode 100644 node_modules/vue/src/platforms/web/compiler/directives/html.js create mode 100644 node_modules/vue/src/platforms/web/compiler/directives/index.js create mode 100644 node_modules/vue/src/platforms/web/compiler/directives/model.js create mode 100644 node_modules/vue/src/platforms/web/compiler/directives/text.js create mode 100644 node_modules/vue/src/platforms/web/compiler/index.js create mode 100644 node_modules/vue/src/platforms/web/compiler/modules/class.js create mode 100644 node_modules/vue/src/platforms/web/compiler/modules/index.js create mode 100644 node_modules/vue/src/platforms/web/compiler/modules/model.js create mode 100644 node_modules/vue/src/platforms/web/compiler/modules/style.js create mode 100644 node_modules/vue/src/platforms/web/compiler/options.js create mode 100644 node_modules/vue/src/platforms/web/compiler/util.js create mode 100644 node_modules/vue/src/platforms/web/entry-compiler.js create mode 100644 node_modules/vue/src/platforms/web/entry-runtime-with-compiler.js create mode 100644 node_modules/vue/src/platforms/web/entry-runtime.js create mode 100644 node_modules/vue/src/platforms/web/entry-server-basic-renderer.js create mode 100644 node_modules/vue/src/platforms/web/entry-server-renderer.js create mode 100644 node_modules/vue/src/platforms/web/runtime/class-util.js create mode 100644 node_modules/vue/src/platforms/web/runtime/components/index.js create mode 100644 node_modules/vue/src/platforms/web/runtime/components/transition-group.js create mode 100644 node_modules/vue/src/platforms/web/runtime/components/transition.js create mode 100644 node_modules/vue/src/platforms/web/runtime/directives/index.js create mode 100644 node_modules/vue/src/platforms/web/runtime/directives/model.js create mode 100644 node_modules/vue/src/platforms/web/runtime/directives/show.js create mode 100644 node_modules/vue/src/platforms/web/runtime/index.js create mode 100644 node_modules/vue/src/platforms/web/runtime/modules/attrs.js create mode 100644 node_modules/vue/src/platforms/web/runtime/modules/class.js create mode 100644 node_modules/vue/src/platforms/web/runtime/modules/dom-props.js create mode 100644 node_modules/vue/src/platforms/web/runtime/modules/events.js create mode 100644 node_modules/vue/src/platforms/web/runtime/modules/index.js create mode 100644 node_modules/vue/src/platforms/web/runtime/modules/style.js create mode 100644 node_modules/vue/src/platforms/web/runtime/modules/transition.js create mode 100644 node_modules/vue/src/platforms/web/runtime/node-ops.js create mode 100644 node_modules/vue/src/platforms/web/runtime/patch.js create mode 100644 node_modules/vue/src/platforms/web/runtime/transition-util.js create mode 100644 node_modules/vue/src/platforms/web/server/compiler.js create mode 100644 node_modules/vue/src/platforms/web/server/directives/index.js create mode 100644 node_modules/vue/src/platforms/web/server/directives/model.js create mode 100644 node_modules/vue/src/platforms/web/server/directives/show.js create mode 100644 node_modules/vue/src/platforms/web/server/modules/attrs.js create mode 100644 node_modules/vue/src/platforms/web/server/modules/class.js create mode 100644 node_modules/vue/src/platforms/web/server/modules/dom-props.js create mode 100644 node_modules/vue/src/platforms/web/server/modules/index.js create mode 100644 node_modules/vue/src/platforms/web/server/modules/style.js create mode 100644 node_modules/vue/src/platforms/web/server/util.js create mode 100644 node_modules/vue/src/platforms/web/util/attrs.js create mode 100644 node_modules/vue/src/platforms/web/util/class.js create mode 100644 node_modules/vue/src/platforms/web/util/compat.js create mode 100644 node_modules/vue/src/platforms/web/util/element.js create mode 100644 node_modules/vue/src/platforms/web/util/index.js create mode 100644 node_modules/vue/src/platforms/web/util/style.js create mode 100755 node_modules/vue/src/platforms/weex/compiler/directives/index.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/directives/model.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/index.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/append.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/class.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/index.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/props.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/component-root.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/component.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/index.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/recycle-list.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/text.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-bind.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-for.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-if.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-on.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/recycle-list/v-once.js create mode 100644 node_modules/vue/src/platforms/weex/compiler/modules/style.js create mode 100644 node_modules/vue/src/platforms/weex/entry-compiler.js create mode 100644 node_modules/vue/src/platforms/weex/entry-framework.js create mode 100644 node_modules/vue/src/platforms/weex/entry-runtime-factory.js create mode 100644 node_modules/vue/src/platforms/weex/runtime/components/index.js create mode 100644 node_modules/vue/src/platforms/weex/runtime/components/richtext.js create mode 100644 node_modules/vue/src/platforms/weex/runtime/components/transition-group.js create mode 100644 node_modules/vue/src/platforms/weex/runtime/components/transition.js create mode 100755 node_modules/vue/src/platforms/weex/runtime/directives/index.js create mode 100755 node_modules/vue/src/platforms/weex/runtime/index.js create mode 100755 node_modules/vue/src/platforms/weex/runtime/modules/attrs.js create mode 100755 node_modules/vue/src/platforms/weex/runtime/modules/class.js create mode 100755 node_modules/vue/src/platforms/weex/runtime/modules/events.js create mode 100755 node_modules/vue/src/platforms/weex/runtime/modules/index.js create mode 100755 node_modules/vue/src/platforms/weex/runtime/modules/style.js create mode 100644 node_modules/vue/src/platforms/weex/runtime/modules/transition.js create mode 100755 node_modules/vue/src/platforms/weex/runtime/node-ops.js create mode 100644 node_modules/vue/src/platforms/weex/runtime/patch.js create mode 100644 node_modules/vue/src/platforms/weex/runtime/recycle-list/render-component-template.js create mode 100644 node_modules/vue/src/platforms/weex/runtime/recycle-list/virtual-component.js create mode 100644 node_modules/vue/src/platforms/weex/runtime/text-node.js create mode 100644 node_modules/vue/src/platforms/weex/util/element.js create mode 100755 node_modules/vue/src/platforms/weex/util/index.js create mode 100644 node_modules/vue/src/platforms/weex/util/parser.js (limited to 'node_modules/vue/src/platforms') 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
, use
.' + ) + } + } + 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: + * + * into this: + * + * + * + */ + +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
, use
.' + ) + } + } + 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 or - 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 = this.prevChildren = this.children + const rawChildren: Array = this.$slots.default || [] + const children: Array = 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(` children must be keyed: <${name}>`) + } + } + } + + if (prevChildren) { + const kept: Array = [] + const removed: Array = [] + 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 = 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. +// 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( + ' can only be used on a single element. Use ' + + ' 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 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( + `