diff --git a/README.md b/README.md index a0d24d8..360d564 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The demo page is [HERE](http://haixing-hu.github.io/vue-html-editor/demo.html). # Requirements -- [Vue.js](https://github.com/yyx990803/vue) `^1.0.24` +- [Vue.js](https://github.com/yyx990803/vue) `^2.0.0` - [Summernote](https://github.com/summernote/summernote) `^0.8.1` # Instllation @@ -39,7 +39,7 @@ The HTML snippets are as follows: ```html
- +
The HTML contents are as follows:

@@ -62,13 +62,18 @@ var vm = new Vue({ text: "Hello World!" } }); + +var editor = vm.$refs.editor; +editor.$on('input', function(inputed) { + vm.$data.text = inputed; +}); ``` # Component Properties ## `model` -The model bind to the control, which must be a two way binding variable. +The model bind to the control. Note that the value of model could be set to `null`, and in that case the text content of the editor will be set to an empty string. While, if the text diff --git a/bower.json b/bower.json index 002726d..21869e9 100644 --- a/bower.json +++ b/bower.json @@ -26,7 +26,7 @@ "node_modules" ], "dependencies": { - "vue": "^1.0.26", + "vue": "^2.0.0", "bootstrap": "^3.3.6", "font-awesome": "^4.2.0", "jquery": "^2.2.4", diff --git a/demo/demo.all.js b/demo/demo.all.js index 70d523c..27ec6d3 100644 --- a/demo/demo.all.js +++ b/demo/demo.all.js @@ -1,6 +1,6 @@ /*! * vue-html-editor v0.2.1 - * (c) 2016 Haixing Hu + * (c) 2017 Haixing Hu * Released under the MIT License. */ /******/ (function(modules) { // webpackBootstrap @@ -61,10091 +61,8677 @@ } }); + var editor = vm.$refs.editor; + editor.$on('input', function(inputed) { + vm.$data.text = inputed; + }); + /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { - module.exports = __webpack_require__(2); + /* WEBPACK VAR INJECTION */(function(process, global) {/*! + * Vue.js v2.1.7 + * (c) 2014-2016 Evan You + * Released under the MIT License. + */ + 'use strict'; -/***/ }, -/* 2 */ -/***/ function(module, exports, __webpack_require__) { + /* */ - /* WEBPACK VAR INJECTION */(function(global) {/*! - * Vue.js v1.0.26 - * (c) 2016 Evan You - * Released under the MIT License. + /** + * Convert a value to a string that is actually rendered. */ - (function (global, factory) { - true ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.Vue = factory()); - }(this, function () { 'use strict'; - - function set(obj, key, val) { - if (hasOwn(obj, key)) { - obj[key] = val; - return; - } - if (obj._isVue) { - set(obj._data, key, val); - return; - } - var ob = obj.__ob__; - if (!ob) { - obj[key] = val; - return; - } - ob.convert(key, val); - ob.dep.notify(); - if (ob.vms) { - var i = ob.vms.length; - while (i--) { - var vm = ob.vms[i]; - vm._proxy(key); - vm._digest(); - } - } - return val; - } + function _toString (val) { + return val == null + ? '' + : typeof val === 'object' + ? JSON.stringify(val, null, 2) + : String(val) + } - /** - * Delete a property and trigger change if necessary. - * - * @param {Object} obj - * @param {String} key - */ + /** + * Convert a input value to a number for persistence. + * If the conversion fails, return original string. + */ + function toNumber (val) { + var n = parseFloat(val, 10); + return (n || n === 0) ? n : val + } - function del(obj, key) { - if (!hasOwn(obj, key)) { - return; - } - delete obj[key]; - var ob = obj.__ob__; - if (!ob) { - if (obj._isVue) { - delete obj._data[key]; - obj._digest(); - } - return; - } - ob.dep.notify(); - if (ob.vms) { - var i = ob.vms.length; - while (i--) { - var vm = ob.vms[i]; - vm._unproxy(key); - vm._digest(); - } - } - } + /** + * Make a map and return a function for checking if a key + * is in that map. + */ + function makeMap ( + str, + expectsLowerCase + ) { + var map = Object.create(null); + var list = str.split(','); + for (var i = 0; i < list.length; i++) { + map[list[i]] = true; + } + return expectsLowerCase + ? function (val) { return map[val.toLowerCase()]; } + : function (val) { return map[val]; } + } - var hasOwnProperty = Object.prototype.hasOwnProperty; - /** - * Check whether the object has the property. - * - * @param {Object} obj - * @param {String} key - * @return {Boolean} - */ + /** + * Check if a tag is a built-in tag. + */ + var isBuiltInTag = makeMap('slot,component', true); - function hasOwn(obj, key) { - return hasOwnProperty.call(obj, key); + /** + * Remove an item from an array + */ + function remove$1 (arr, item) { + if (arr.length) { + var index = arr.indexOf(item); + if (index > -1) { + return arr.splice(index, 1) + } } + } - /** - * Check if an expression is a literal value. - * - * @param {String} exp - * @return {Boolean} - */ + /** + * Check whether the object has the property. + */ + var hasOwnProperty = Object.prototype.hasOwnProperty; + function hasOwn (obj, key) { + return hasOwnProperty.call(obj, key) + } - var literalValueRE = /^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/; + /** + * Check if value is primitive + */ + function isPrimitive (value) { + return typeof value === 'string' || typeof value === 'number' + } - function isLiteral(exp) { - return literalValueRE.test(exp); + /** + * Create a cached version of a pure function. + */ + function cached (fn) { + var cache = Object.create(null); + return function cachedFn (str) { + var hit = cache[str]; + return hit || (cache[str] = fn(str)) } + } - /** - * Check if a string starts with $ or _ - * - * @param {String} str - * @return {Boolean} - */ + /** + * Camelize a hyphen-delmited string. + */ + var camelizeRE = /-(\w)/g; + var camelize = cached(function (str) { + return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; }) + }); - function isReserved(str) { - var c = (str + '').charCodeAt(0); - return c === 0x24 || c === 0x5F; - } + /** + * Capitalize a string. + */ + var capitalize = cached(function (str) { + return str.charAt(0).toUpperCase() + str.slice(1) + }); - /** - * Guard text output, make sure undefined outputs - * empty string - * - * @param {*} value - * @return {String} - */ + /** + * Hyphenate a camelCase string. + */ + var hyphenateRE = /([^-])([A-Z])/g; + var hyphenate = cached(function (str) { + return str + .replace(hyphenateRE, '$1-$2') + .replace(hyphenateRE, '$1-$2') + .toLowerCase() + }); - function _toString(value) { - return value == null ? '' : value.toString(); - } + /** + * Simple bind, faster than native + */ + function bind$1 (fn, ctx) { + function boundFn (a) { + var l = arguments.length; + return l + ? l > 1 + ? fn.apply(ctx, arguments) + : fn.call(ctx, a) + : fn.call(ctx) + } + // record original fn length + boundFn._length = fn.length; + return boundFn + } - /** - * Check and convert possible numeric strings to numbers - * before setting back to data - * - * @param {*} value - * @return {*|Number} - */ + /** + * Convert an Array-like object to a real Array. + */ + function toArray (list, start) { + start = start || 0; + var i = list.length - start; + var ret = new Array(i); + while (i--) { + ret[i] = list[i + start]; + } + return ret + } - function toNumber(value) { - if (typeof value !== 'string') { - return value; - } else { - var parsed = Number(value); - return isNaN(parsed) ? value : parsed; - } + /** + * Mix properties into target object. + */ + function extend (to, _from) { + for (var key in _from) { + to[key] = _from[key]; } + return to + } - /** - * Convert string boolean literals into real booleans. - * - * @param {*} value - * @return {*|Boolean} - */ + /** + * Quick object check - this is primarily used to tell + * Objects from primitive values when we know the value + * is a JSON-compliant type. + */ + function isObject (obj) { + return obj !== null && typeof obj === 'object' + } - function toBoolean(value) { - return value === 'true' ? true : value === 'false' ? false : value; + /** + * Strict object type check. Only returns true + * for plain JavaScript objects. + */ + var toString = Object.prototype.toString; + var OBJECT_STRING = '[object Object]'; + function isPlainObject (obj) { + return toString.call(obj) === OBJECT_STRING + } + + /** + * Merge an Array of Objects into a single Object. + */ + function toObject (arr) { + var res = {}; + for (var i = 0; i < arr.length; i++) { + if (arr[i]) { + extend(res, arr[i]); + } } + return res + } - /** - * Strip quotes from a string - * - * @param {String} str - * @return {String | false} - */ + /** + * Perform no operation. + */ + function noop () {} - function stripQuotes(str) { - var a = str.charCodeAt(0); - var b = str.charCodeAt(str.length - 1); - return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str; - } + /** + * Always return false. + */ + var no = function () { return false; }; - /** - * Camelize a hyphen-delmited string. - * - * @param {String} str - * @return {String} - */ + /** + * Return same value + */ + var identity = function (_) { return _; }; - var camelizeRE = /-(\w)/g; + /** + * Generate a static keys string from compiler modules. + */ + function genStaticKeys (modules) { + return modules.reduce(function (keys, m) { + return keys.concat(m.staticKeys || []) + }, []).join(',') + } - function camelize(str) { - return str.replace(camelizeRE, toUpper); + /** + * Check if two values are loosely equal - that is, + * if they are plain objects, do they have the same shape? + */ + function looseEqual (a, b) { + var isObjectA = isObject(a); + var isObjectB = isObject(b); + if (isObjectA && isObjectB) { + return JSON.stringify(a) === JSON.stringify(b) + } else if (!isObjectA && !isObjectB) { + return String(a) === String(b) + } else { + return false } + } - function toUpper(_, c) { - return c ? c.toUpperCase() : ''; + function looseIndexOf (arr, val) { + for (var i = 0; i < arr.length; i++) { + if (looseEqual(arr[i], val)) { return i } } + return -1 + } + /* */ + + var config = { /** - * Hyphenate a camelCase string. - * - * @param {String} str - * @return {String} + * Option merge strategies (used in core/util/options) */ - - var hyphenateRE = /([a-z\d])([A-Z])/g; - - function hyphenate(str) { - return str.replace(hyphenateRE, '$1-$2').toLowerCase(); - } + optionMergeStrategies: Object.create(null), /** - * Converts hyphen/underscore/slash delimitered names into - * camelized classNames. - * - * e.g. my-component => MyComponent - * some_else => SomeElse - * some/comp => SomeComp - * - * @param {String} str - * @return {String} + * Whether to suppress warnings. */ - - var classifyRE = /(?:^|[-_\/])(\w)/g; - - function classify(str) { - return str.replace(classifyRE, toUpper); - } + silent: false, /** - * Simple bind, faster than native - * - * @param {Function} fn - * @param {Object} ctx - * @return {Function} + * Whether to enable devtools */ - - function bind(fn, ctx) { - return function (a) { - var l = arguments.length; - return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx); - }; - } + devtools: process.env.NODE_ENV !== 'production', /** - * Convert an Array-like object to a real Array. - * - * @param {Array-like} list - * @param {Number} [start] - start index - * @return {Array} + * Error handler for watcher errors */ - - function toArray(list, start) { - start = start || 0; - var i = list.length - start; - var ret = new Array(i); - while (i--) { - ret[i] = list[i + start]; - } - return ret; - } + errorHandler: null, /** - * Mix properties into target object. - * - * @param {Object} to - * @param {Object} from + * Ignore certain custom elements */ - - function extend(to, from) { - var keys = Object.keys(from); - var i = keys.length; - while (i--) { - to[keys[i]] = from[keys[i]]; - } - return to; - } + ignoredElements: [], /** - * Quick object check - this is primarily used to tell - * Objects from primitive values when we know the value - * is a JSON-compliant type. - * - * @param {*} obj - * @return {Boolean} + * Custom user key aliases for v-on */ - - function isObject(obj) { - return obj !== null && typeof obj === 'object'; - } + keyCodes: Object.create(null), /** - * Strict object type check. Only returns true - * for plain JavaScript objects. - * - * @param {*} obj - * @return {Boolean} + * Check if a tag is reserved so that it cannot be registered as a + * component. This is platform-dependent and may be overwritten. */ - - var toString = Object.prototype.toString; - var OBJECT_STRING = '[object Object]'; - - function isPlainObject(obj) { - return toString.call(obj) === OBJECT_STRING; - } + isReservedTag: no, /** - * Array type check. - * - * @param {*} obj - * @return {Boolean} + * Check if a tag is an unknown element. + * Platform-dependent. */ - - var isArray = Array.isArray; + isUnknownElement: no, /** - * Define a property. - * - * @param {Object} obj - * @param {String} key - * @param {*} val - * @param {Boolean} [enumerable] + * Get the namespace of an element */ - - function def(obj, key, val, enumerable) { - Object.defineProperty(obj, key, { - value: val, - enumerable: !!enumerable, - writable: true, - configurable: true - }); - } + getTagNamespace: noop, /** - * Debounce a function so it only gets called after the - * input stops arriving after the given wait period. - * - * @param {Function} func - * @param {Number} wait - * @return {Function} - the debounced function + * Parse the real tag name for the specific platform. */ - - function _debounce(func, wait) { - var timeout, args, context, timestamp, result; - var later = function later() { - var last = Date.now() - timestamp; - if (last < wait && last >= 0) { - timeout = setTimeout(later, wait - last); - } else { - timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; - } - }; - return function () { - context = this; - args = arguments; - timestamp = Date.now(); - if (!timeout) { - timeout = setTimeout(later, wait); - } - return result; - }; - } + parsePlatformTagName: identity, /** - * Manual indexOf because it's slightly faster than - * native. - * - * @param {Array} arr - * @param {*} obj + * Check if an attribute must be bound using property, e.g. value + * Platform-dependent. */ - - function indexOf(arr, obj) { - var i = arr.length; - while (i--) { - if (arr[i] === obj) return i; - } - return -1; - } + mustUseProp: no, /** - * Make a cancellable version of an async callback. - * - * @param {Function} fn - * @return {Function} + * List of asset types that a component can own. */ + _assetTypes: [ + 'component', + 'directive', + 'filter' + ], - function cancellable(fn) { - var cb = function cb() { - if (!cb.cancelled) { - return fn.apply(this, arguments); - } - }; - cb.cancel = function () { - cb.cancelled = true; - }; - return cb; - } + /** + * List of lifecycle hooks. + */ + _lifecycleHooks: [ + 'beforeCreate', + 'created', + 'beforeMount', + 'mounted', + 'beforeUpdate', + 'updated', + 'beforeDestroy', + 'destroyed', + 'activated', + 'deactivated' + ], /** - * Check if two values are loosely equal - that is, - * if they are plain objects, do they have the same shape? - * - * @param {*} a - * @param {*} b - * @return {Boolean} + * Max circular updates allowed in a scheduler flush cycle. */ + _maxUpdateCount: 100 + }; - function looseEqual(a, b) { - /* eslint-disable eqeqeq */ - return a == b || (isObject(a) && isObject(b) ? JSON.stringify(a) === JSON.stringify(b) : false); - /* eslint-enable eqeqeq */ - } + /* */ - var hasProto = ('__proto__' in {}); + /** + * Check if a string starts with $ or _ + */ + function isReserved (str) { + var c = (str + '').charCodeAt(0); + return c === 0x24 || c === 0x5F + } - // Browser environment sniffing - var inBrowser = typeof window !== 'undefined' && Object.prototype.toString.call(window) !== '[object Object]'; + /** + * Define a property. + */ + function def (obj, key, val, enumerable) { + Object.defineProperty(obj, key, { + value: val, + enumerable: !!enumerable, + writable: true, + configurable: true + }); + } - // detect devtools - var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; + /** + * Parse simple path. + */ + var bailRE = /[^\w.$]/; + function parsePath (path) { + if (bailRE.test(path)) { + return + } else { + var segments = path.split('.'); + return function (obj) { + for (var i = 0; i < segments.length; i++) { + if (!obj) { return } + obj = obj[segments[i]]; + } + return obj + } + } + } - // UA sniffing for working around browser-specific quirks - var UA = inBrowser && window.navigator.userAgent.toLowerCase(); - var isIE = UA && UA.indexOf('trident') > 0; - var isIE9 = UA && UA.indexOf('msie 9.0') > 0; - var isAndroid = UA && UA.indexOf('android') > 0; - var isIos = UA && /(iphone|ipad|ipod|ios)/i.test(UA); - var iosVersionMatch = isIos && UA.match(/os ([\d_]+)/); - var iosVersion = iosVersionMatch && iosVersionMatch[1].split('_'); + /* */ + /* globals MutationObserver */ - // detecting iOS UIWebView by indexedDB - var hasMutationObserverBug = iosVersion && Number(iosVersion[0]) >= 9 && Number(iosVersion[1]) >= 3 && !window.indexedDB; + // can we use __proto__? + var hasProto = '__proto__' in {}; - var transitionProp = undefined; - var transitionEndEvent = undefined; - var animationProp = undefined; - var animationEndEvent = undefined; + // Browser environment sniffing + var inBrowser = typeof window !== 'undefined'; + var UA = inBrowser && window.navigator.userAgent.toLowerCase(); + var isIE = UA && /msie|trident/.test(UA); + var isIE9 = UA && UA.indexOf('msie 9.0') > 0; + var isEdge = UA && UA.indexOf('edge/') > 0; + var isAndroid = UA && UA.indexOf('android') > 0; + var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA); - // Transition property/event sniffing - if (inBrowser && !isIE9) { - var isWebkitTrans = window.ontransitionend === undefined && window.onwebkittransitionend !== undefined; - var isWebkitAnim = window.onanimationend === undefined && window.onwebkitanimationend !== undefined; - transitionProp = isWebkitTrans ? 'WebkitTransition' : 'transition'; - transitionEndEvent = isWebkitTrans ? 'webkitTransitionEnd' : 'transitionend'; - animationProp = isWebkitAnim ? 'WebkitAnimation' : 'animation'; - animationEndEvent = isWebkitAnim ? 'webkitAnimationEnd' : 'animationend'; + // this needs to be lazy-evaled because vue may be required before + // vue-server-renderer can set VUE_ENV + var _isServer; + var isServerRendering = function () { + if (_isServer === undefined) { + /* istanbul ignore if */ + if (!inBrowser && typeof global !== 'undefined') { + // detect presence of vue-server-renderer and avoid + // Webpack shimming the process + _isServer = global['process'].env.VUE_ENV === 'server'; + } else { + _isServer = false; + } } + return _isServer + }; - /** - * Defer a task to execute it asynchronously. Ideally this - * should be executed as a microtask, so we leverage - * MutationObserver if it's available, and fallback to - * setTimeout(0). - * - * @param {Function} cb - * @param {Object} ctx - */ - - var nextTick = (function () { - var callbacks = []; - var pending = false; - var timerFunc; - function nextTickHandler() { - pending = false; - var copies = callbacks.slice(0); - callbacks = []; - for (var i = 0; i < copies.length; i++) { - copies[i](); - } - } + // detect devtools + var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; - /* istanbul ignore if */ - if (typeof MutationObserver !== 'undefined' && !hasMutationObserverBug) { - var counter = 1; - var observer = new MutationObserver(nextTickHandler); - var textNode = document.createTextNode(counter); - observer.observe(textNode, { - characterData: true - }); - timerFunc = function () { - counter = (counter + 1) % 2; - textNode.data = counter; - }; - } else { - // webpack attempts to inject a shim for setImmediate - // if it is used as a global, so we have to work around that to - // avoid bundling unnecessary code. - var context = inBrowser ? window : typeof global !== 'undefined' ? global : {}; - timerFunc = context.setImmediate || setTimeout; - } - return function (cb, ctx) { - var func = ctx ? function () { - cb.call(ctx); - } : cb; - callbacks.push(func); - if (pending) return; - pending = true; - timerFunc(nextTickHandler, 0); - }; - })(); + /* istanbul ignore next */ + function isNative (Ctor) { + return /native code/.test(Ctor.toString()) + } - var _Set = undefined; + /** + * Defer a task to execute it asynchronously. + */ + var nextTick = (function () { + var callbacks = []; + var pending = false; + var timerFunc; + + function nextTickHandler () { + pending = false; + var copies = callbacks.slice(0); + callbacks.length = 0; + for (var i = 0; i < copies.length; i++) { + copies[i](); + } + } + + // the nextTick behavior leverages the microtask queue, which can be accessed + // via either native Promise.then or MutationObserver. + // MutationObserver has wider support, however it is seriously bugged in + // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It + // completely stops working after triggering a few times... so, if native + // Promise is available, we will use it: /* istanbul ignore if */ - if (typeof Set !== 'undefined' && Set.toString().match(/native code/)) { - // use native Set when available. - _Set = Set; - } else { - // a non-standard Set polyfill that only works with primitive keys. - _Set = function () { - this.set = Object.create(null); - }; - _Set.prototype.has = function (key) { - return this.set[key] !== undefined; + if (typeof Promise !== 'undefined' && isNative(Promise)) { + var p = Promise.resolve(); + var logError = function (err) { console.error(err); }; + timerFunc = function () { + p.then(nextTickHandler).catch(logError); + // in problematic UIWebViews, Promise.then doesn't completely break, but + // it can get stuck in a weird state where callbacks are pushed into the + // microtask queue but the queue isn't being flushed, until the browser + // needs to do some other work, e.g. handle a timer. Therefore we can + // "force" the microtask queue to be flushed by adding an empty timer. + if (isIOS) { setTimeout(noop); } }; - _Set.prototype.add = function (key) { - this.set[key] = 1; + } else if (typeof MutationObserver !== 'undefined' && ( + isNative(MutationObserver) || + // PhantomJS and iOS 7.x + MutationObserver.toString() === '[object MutationObserverConstructor]' + )) { + // use MutationObserver where native Promise is not available, + // e.g. PhantomJS IE11, iOS7, Android 4.4 + var counter = 1; + var observer = new MutationObserver(nextTickHandler); + var textNode = document.createTextNode(String(counter)); + observer.observe(textNode, { + characterData: true + }); + timerFunc = function () { + counter = (counter + 1) % 2; + textNode.data = String(counter); }; - _Set.prototype.clear = function () { - this.set = Object.create(null); + } else { + // fallback to setTimeout + /* istanbul ignore next */ + timerFunc = function () { + setTimeout(nextTickHandler, 0); }; } - function Cache(limit) { - this.size = 0; - this.limit = limit; - this.head = this.tail = undefined; - this._keymap = Object.create(null); + return function queueNextTick (cb, ctx) { + var _resolve; + callbacks.push(function () { + if (cb) { cb.call(ctx); } + if (_resolve) { _resolve(ctx); } + }); + if (!pending) { + pending = true; + timerFunc(); + } + if (!cb && typeof Promise !== 'undefined') { + return new Promise(function (resolve) { + _resolve = resolve; + }) + } } + })(); - var p = Cache.prototype; + var _Set; + /* istanbul ignore if */ + if (typeof Set !== 'undefined' && isNative(Set)) { + // use native Set when available. + _Set = Set; + } else { + // a non-standard Set polyfill that only works with primitive keys. + _Set = (function () { + function Set () { + this.set = Object.create(null); + } + Set.prototype.has = function has (key) { + return this.set[key] === true + }; + Set.prototype.add = function add (key) { + this.set[key] = true; + }; + Set.prototype.clear = function clear () { + this.set = Object.create(null); + }; - /** - * Put into the cache associated with . - * Returns the entry which was removed to make room for - * the new entry. Otherwise undefined is returned. - * (i.e. if there was enough room already). - * - * @param {String} key - * @param {*} value - * @return {Entry|undefined} - */ + return Set; + }()); + } - p.put = function (key, value) { - var removed; + var warn = noop; + var formatComponentName; - var entry = this.get(key, true); - if (!entry) { - if (this.size === this.limit) { - removed = this.shift(); - } - entry = { - key: key - }; - this._keymap[key] = entry; - if (this.tail) { - this.tail.newer = entry; - entry.older = this.tail; - } else { - this.head = entry; - } - this.tail = entry; - this.size++; - } - entry.value = value; + if (process.env.NODE_ENV !== 'production') { + var hasConsole = typeof console !== 'undefined'; - return removed; + warn = function (msg, vm) { + if (hasConsole && (!config.silent)) { + console.error("[Vue warn]: " + msg + " " + ( + vm ? formatLocation(formatComponentName(vm)) : '' + )); + } }; - /** - * Purge the least recently used (oldest) entry from the - * cache. Returns the removed entry or undefined if the - * cache was empty. - */ + formatComponentName = function (vm) { + if (vm.$root === vm) { + return 'root instance' + } + var name = vm._isVue + ? vm.$options.name || vm.$options._componentTag + : vm.name; + return ( + (name ? ("component <" + name + ">") : "anonymous component") + + (vm._isVue && vm.$options.__file ? (" at " + (vm.$options.__file)) : '') + ) + }; - p.shift = function () { - var entry = this.head; - if (entry) { - this.head = this.head.newer; - this.head.older = undefined; - entry.newer = entry.older = undefined; - this._keymap[entry.key] = undefined; - this.size--; + var formatLocation = function (str) { + if (str === 'anonymous component') { + str += " - use the \"name\" option for better debugging messages."; } - return entry; + return ("\n(found in " + str + ")") }; + } - /** - * Get and register recent use of . Returns the value - * associated with or undefined if not in cache. - * - * @param {String} key - * @param {Boolean} returnEntry - * @return {Entry|*} - */ + /* */ - p.get = function (key, returnEntry) { - var entry = this._keymap[key]; - if (entry === undefined) return; - if (entry === this.tail) { - return returnEntry ? entry : entry.value; - } - // HEAD--------------TAIL - // <.older .newer> - // <--- add direction -- - // A B C E - if (entry.newer) { - if (entry === this.head) { - this.head = entry.newer; - } - entry.newer.older = entry.older; // C <-- E. - } - if (entry.older) { - entry.older.newer = entry.newer; // C. --> E - } - entry.newer = undefined; // D --x - entry.older = this.tail; // D. --> E - if (this.tail) { - this.tail.newer = entry; // E. <-- D - } - this.tail = entry; - return returnEntry ? entry : entry.value; - }; - var cache$1 = new Cache(1000); - var filterTokenRE = /[^\s'"]+|'[^']*'|"[^"]*"/g; - var reservedArgRE = /^in$|^-?\d+/; + var uid$1 = 0; - /** - * Parser state - */ + /** + * A dep is an observable that can have multiple + * directives subscribing to it. + */ + var Dep = function Dep () { + this.id = uid$1++; + this.subs = []; + }; - var str; - var dir; - var c; - var prev; - var i; - var l; - var lastFilterIndex; - var inSingle; - var inDouble; - var curly; - var square; - var paren; - /** - * Push a filter to the current directive object - */ + Dep.prototype.addSub = function addSub (sub) { + this.subs.push(sub); + }; - function pushFilter() { - var exp = str.slice(lastFilterIndex, i).trim(); - var filter; - if (exp) { - filter = {}; - var tokens = exp.match(filterTokenRE); - filter.name = tokens[0]; - if (tokens.length > 1) { - filter.args = tokens.slice(1).map(processFilterArg); - } - } - if (filter) { - (dir.filters = dir.filters || []).push(filter); - } - lastFilterIndex = i + 1; - } + Dep.prototype.removeSub = function removeSub (sub) { + remove$1(this.subs, sub); + }; - /** - * Check if an argument is dynamic and strip quotes. - * - * @param {String} arg - * @return {Object} - */ + Dep.prototype.depend = function depend () { + if (Dep.target) { + Dep.target.addDep(this); + } + }; - function processFilterArg(arg) { - if (reservedArgRE.test(arg)) { - return { - value: toNumber(arg), - dynamic: false - }; - } else { - var stripped = stripQuotes(arg); - var dynamic = stripped === arg; - return { - value: dynamic ? arg : stripped, - dynamic: dynamic - }; - } + Dep.prototype.notify = function notify () { + // stablize the subscriber list first + var subs = this.subs.slice(); + for (var i = 0, l = subs.length; i < l; i++) { + subs[i].update(); } + }; - /** - * Parse a directive value and extract the expression - * and its filters into a descriptor. - * - * Example: - * - * "a + 1 | uppercase" will yield: - * { - * expression: 'a + 1', - * filters: [ - * { name: 'uppercase', args: null } - * ] - * } - * - * @param {String} s - * @return {Object} - */ + // the current target watcher being evaluated. + // this is globally unique because there could be only one + // watcher being evaluated at any time. + Dep.target = null; + var targetStack = []; - function parseDirective(s) { - var hit = cache$1.get(s); - if (hit) { - return hit; - } - - // reset parser state - str = s; - inSingle = inDouble = false; - curly = square = paren = 0; - lastFilterIndex = 0; - dir = {}; - - for (i = 0, l = str.length; i < l; i++) { - prev = c; - c = str.charCodeAt(i); - if (inSingle) { - // check single quote - if (c === 0x27 && prev !== 0x5C) inSingle = !inSingle; - } else if (inDouble) { - // check double quote - if (c === 0x22 && prev !== 0x5C) inDouble = !inDouble; - } else if (c === 0x7C && // pipe - str.charCodeAt(i + 1) !== 0x7C && str.charCodeAt(i - 1) !== 0x7C) { - if (dir.expression == null) { - // first filter, end of expression - lastFilterIndex = i + 1; - dir.expression = str.slice(0, i).trim(); - } else { - // already has filter - pushFilter(); - } - } else { - switch (c) { - case 0x22: - inDouble = true;break; // " - case 0x27: - inSingle = true;break; // ' - case 0x28: - paren++;break; // ( - case 0x29: - paren--;break; // ) - case 0x5B: - square++;break; // [ - case 0x5D: - square--;break; // ] - case 0x7B: - curly++;break; // { - case 0x7D: - curly--;break; // } - } - } - } + function pushTarget (_target) { + if (Dep.target) { targetStack.push(Dep.target); } + Dep.target = _target; + } - if (dir.expression == null) { - dir.expression = str.slice(0, i).trim(); - } else if (lastFilterIndex !== 0) { - pushFilter(); - } + function popTarget () { + Dep.target = targetStack.pop(); + } - cache$1.put(s, dir); - return dir; - } + /* + * not type checking this file because flow doesn't play well with + * dynamically accessing methods on Array prototype + */ - var directive = Object.freeze({ - parseDirective: parseDirective + var arrayProto = Array.prototype; + var arrayMethods = Object.create(arrayProto);[ + 'push', + 'pop', + 'shift', + 'unshift', + 'splice', + 'sort', + 'reverse' + ] + .forEach(function (method) { + // cache original method + var original = arrayProto[method]; + def(arrayMethods, method, function mutator () { + var arguments$1 = arguments; + + // avoid leaking arguments: + // http://jsperf.com/closure-with-arguments + var i = arguments.length; + var args = new Array(i); + while (i--) { + args[i] = arguments$1[i]; + } + var result = original.apply(this, args); + var ob = this.__ob__; + var inserted; + switch (method) { + case 'push': + inserted = args; + break + case 'unshift': + inserted = args; + break + case 'splice': + inserted = args.slice(2); + break + } + if (inserted) { ob.observeArray(inserted); } + // notify change + ob.dep.notify(); + return result }); + }); - var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g; - var cache = undefined; - var tagRE = undefined; - var htmlRE = undefined; - /** - * Escape a string so it can be used in a RegExp - * constructor. - * - * @param {String} str - */ + /* */ + + var arrayKeys = Object.getOwnPropertyNames(arrayMethods); + + /** + * By default, when a reactive property is set, the new value is + * also converted to become reactive. However when passing down props, + * we don't want to force conversion because the value may be a nested value + * under a frozen data structure. Converting it would defeat the optimization. + */ + var observerState = { + shouldConvert: true, + isSettingProps: false + }; - function escapeRegex(str) { - return str.replace(regexEscapeRE, '\\$&'); + /** + * Observer class that are attached to each observed + * object. Once attached, the observer converts target + * object's property keys into getter/setters that + * collect dependencies and dispatches updates. + */ + var Observer = function Observer (value) { + this.value = value; + this.dep = new Dep(); + this.vmCount = 0; + def(value, '__ob__', this); + if (Array.isArray(value)) { + var augment = hasProto + ? protoAugment + : copyAugment; + augment(value, arrayMethods, arrayKeys); + this.observeArray(value); + } else { + this.walk(value); } + }; - function compileRegex() { - var open = escapeRegex(config.delimiters[0]); - var close = escapeRegex(config.delimiters[1]); - var unsafeOpen = escapeRegex(config.unsafeDelimiters[0]); - var unsafeClose = escapeRegex(config.unsafeDelimiters[1]); - tagRE = new RegExp(unsafeOpen + '((?:.|\\n)+?)' + unsafeClose + '|' + open + '((?:.|\\n)+?)' + close, 'g'); - htmlRE = new RegExp('^' + unsafeOpen + '((?:.|\\n)+?)' + unsafeClose + '$'); - // reset cache - cache = new Cache(1000); + /** + * Walk through each property and convert them into + * getter/setters. This method should only be called when + * value type is Object. + */ + Observer.prototype.walk = function walk (obj) { + var keys = Object.keys(obj); + for (var i = 0; i < keys.length; i++) { + defineReactive$$1(obj, keys[i], obj[keys[i]]); } + }; - /** - * Parse a template text string into an array of tokens. - * - * @param {String} text - * @return {Array | null} - * - {String} type - * - {String} value - * - {Boolean} [html] - * - {Boolean} [oneTime] - */ - - function parseText(text) { - if (!cache) { - compileRegex(); - } - var hit = cache.get(text); - if (hit) { - return hit; - } - if (!tagRE.test(text)) { - return null; - } - var tokens = []; - var lastIndex = tagRE.lastIndex = 0; - var match, index, html, value, first, oneTime; - /* eslint-disable no-cond-assign */ - while (match = tagRE.exec(text)) { - /* eslint-enable no-cond-assign */ - index = match.index; - // push text token - if (index > lastIndex) { - tokens.push({ - value: text.slice(lastIndex, index) - }); - } - // tag token - html = htmlRE.test(match[0]); - value = html ? match[1] : match[2]; - first = value.charCodeAt(0); - oneTime = first === 42; // * - value = oneTime ? value.slice(1) : value; - tokens.push({ - tag: true, - value: value.trim(), - html: html, - oneTime: oneTime - }); - lastIndex = index + match[0].length; - } - if (lastIndex < text.length) { - tokens.push({ - value: text.slice(lastIndex) - }); - } - cache.put(text, tokens); - return tokens; + /** + * Observe a list of Array items. + */ + Observer.prototype.observeArray = function observeArray (items) { + for (var i = 0, l = items.length; i < l; i++) { + observe(items[i]); } + }; - /** - * Format a list of tokens into an expression. - * e.g. tokens parsed from 'a {{b}} c' can be serialized - * into one single expression as '"a " + b + " c"'. - * - * @param {Array} tokens - * @param {Vue} [vm] - * @return {String} - */ - - function tokensToExp(tokens, vm) { - if (tokens.length > 1) { - return tokens.map(function (token) { - return formatToken(token, vm); - }).join('+'); - } else { - return formatToken(tokens[0], vm, true); - } - } + // helpers - /** - * Format a single token. - * - * @param {Object} token - * @param {Vue} [vm] - * @param {Boolean} [single] - * @return {String} - */ + /** + * Augment an target Object or Array by intercepting + * the prototype chain using __proto__ + */ + function protoAugment (target, src) { + /* eslint-disable no-proto */ + target.__proto__ = src; + /* eslint-enable no-proto */ + } - function formatToken(token, vm, single) { - return token.tag ? token.oneTime && vm ? '"' + vm.$eval(token.value) + '"' : inlineFilters(token.value, single) : '"' + token.value + '"'; + /** + * Augment an target Object or Array by defining + * hidden properties. + */ + /* istanbul ignore next */ + function copyAugment (target, src, keys) { + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + def(target, key, src[key]); } + } - /** - * For an attribute with multiple interpolation tags, - * e.g. attr="some-{{thing | filter}}", in order to combine - * the whole thing into a single watchable expression, we - * have to inline those filters. This function does exactly - * that. This is a bit hacky but it avoids heavy changes - * to directive parser and watcher mechanism. - * - * @param {String} exp - * @param {Boolean} single - * @return {String} - */ + /** + * Attempt to create an observer instance for a value, + * returns the new observer if successfully observed, + * or the existing observer if the value already has one. + */ + function observe (value, asRootData) { + if (!isObject(value)) { + return + } + var ob; + if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { + ob = value.__ob__; + } else if ( + observerState.shouldConvert && + !isServerRendering() && + (Array.isArray(value) || isPlainObject(value)) && + Object.isExtensible(value) && + !value._isVue + ) { + ob = new Observer(value); + } + if (asRootData && ob) { + ob.vmCount++; + } + return ob + } - var filterRE = /[^|]\|[^|]/; - function inlineFilters(exp, single) { - if (!filterRE.test(exp)) { - return single ? exp : '(' + exp + ')'; - } else { - var dir = parseDirective(exp); - if (!dir.filters) { - return '(' + exp + ')'; + /** + * Define a reactive property on an Object. + */ + function defineReactive$$1 ( + obj, + key, + val, + customSetter + ) { + var dep = new Dep(); + + var property = Object.getOwnPropertyDescriptor(obj, key); + if (property && property.configurable === false) { + return + } + + // cater for pre-defined getter/setters + var getter = property && property.get; + var setter = property && property.set; + + var childOb = observe(val); + Object.defineProperty(obj, key, { + enumerable: true, + configurable: true, + get: function reactiveGetter () { + var value = getter ? getter.call(obj) : val; + if (Dep.target) { + dep.depend(); + if (childOb) { + childOb.dep.depend(); + } + if (Array.isArray(value)) { + dependArray(value); + } + } + return value + }, + set: function reactiveSetter (newVal) { + var value = getter ? getter.call(obj) : val; + /* eslint-disable no-self-compare */ + if (newVal === value || (newVal !== newVal && value !== value)) { + return + } + /* eslint-enable no-self-compare */ + if (process.env.NODE_ENV !== 'production' && customSetter) { + customSetter(); + } + if (setter) { + setter.call(obj, newVal); } else { - return 'this._applyFilters(' + dir.expression + // value - ',null,' + // oldValue (null for read) - JSON.stringify(dir.filters) + // filter descriptors - ',false)'; // write? + val = newVal; } + childOb = observe(newVal); + dep.notify(); } - } - - var text = Object.freeze({ - compileRegex: compileRegex, - parseText: parseText, - tokensToExp: tokensToExp }); + } - var delimiters = ['{{', '}}']; - var unsafeDelimiters = ['{{{', '}}}']; - - var config = Object.defineProperties({ - - /** - * Whether to print debug messages. - * Also enables stack trace for warnings. - * - * @type {Boolean} - */ - - debug: false, - - /** - * Whether to suppress warnings. - * - * @type {Boolean} - */ - - silent: false, - - /** - * Whether to use async rendering. - */ - - async: true, - - /** - * Whether to warn against errors caught when evaluating - * expressions. - */ - - warnExpressionErrors: true, - - /** - * Whether to allow devtools inspection. - * Disabled by default in production builds. - */ - - devtools: 'development' !== 'production', - - /** - * Internal flag to indicate the delimiters have been - * changed. - * - * @type {Boolean} - */ - - _delimitersChanged: true, - - /** - * List of asset types that a component can own. - * - * @type {Array} - */ - - _assetTypes: ['component', 'directive', 'elementDirective', 'filter', 'transition', 'partial'], - - /** - * prop binding modes - */ + /** + * Set a property on an object. Adds the new property and + * triggers change notification if the property doesn't + * already exist. + */ + function set$1 (obj, key, val) { + if (Array.isArray(obj)) { + obj.length = Math.max(obj.length, key); + obj.splice(key, 1, val); + return val + } + if (hasOwn(obj, key)) { + obj[key] = val; + return + } + var ob = obj.__ob__; + if (obj._isVue || (ob && ob.vmCount)) { + process.env.NODE_ENV !== 'production' && warn( + 'Avoid adding reactive properties to a Vue instance or its root $data ' + + 'at runtime - declare it upfront in the data option.' + ); + return + } + if (!ob) { + obj[key] = val; + return + } + defineReactive$$1(ob.value, key, val); + ob.dep.notify(); + return val + } - _propBindingModes: { - ONE_WAY: 0, - TWO_WAY: 1, - ONE_TIME: 2 - }, + /** + * Delete a property and trigger change if necessary. + */ + function del (obj, key) { + var ob = obj.__ob__; + if (obj._isVue || (ob && ob.vmCount)) { + process.env.NODE_ENV !== 'production' && warn( + 'Avoid deleting properties on a Vue instance or its root $data ' + + '- just set it to null.' + ); + return + } + if (!hasOwn(obj, key)) { + return + } + delete obj[key]; + if (!ob) { + return + } + ob.dep.notify(); + } - /** - * Max circular updates allowed in a batcher flush cycle. - */ + /** + * Collect dependencies on array elements when the array is touched, since + * we cannot intercept array element access like property getters. + */ + function dependArray (value) { + for (var e = (void 0), i = 0, l = value.length; i < l; i++) { + e = value[i]; + e && e.__ob__ && e.__ob__.dep.depend(); + if (Array.isArray(e)) { + dependArray(e); + } + } + } - _maxUpdateCount: 100 + /* */ - }, { - delimiters: { /** - * Interpolation delimiters. Changing these would trigger - * the text parser to re-compile the regular expressions. - * - * @type {Array} - */ + /** + * Option overwriting strategies are functions that handle + * how to merge a parent option value and a child option + * value into the final value. + */ + var strats = config.optionMergeStrategies; - get: function get() { - return delimiters; - }, - set: function set(val) { - delimiters = val; - compileRegex(); - }, - configurable: true, - enumerable: true - }, - unsafeDelimiters: { - get: function get() { - return unsafeDelimiters; - }, - set: function set(val) { - unsafeDelimiters = val; - compileRegex(); - }, - configurable: true, - enumerable: true + /** + * Options with restrictions + */ + if (process.env.NODE_ENV !== 'production') { + strats.el = strats.propsData = function (parent, child, vm, key) { + if (!vm) { + warn( + "option \"" + key + "\" can only be used during instance " + + 'creation with the `new` keyword.' + ); } - }); - - var warn = undefined; - var formatComponentName = undefined; - - if (true) { - (function () { - var hasConsole = typeof console !== 'undefined'; + return defaultStrat(parent, child) + }; + } - warn = function (msg, vm) { - if (hasConsole && !config.silent) { - console.error('[Vue warn]: ' + msg + (vm ? formatComponentName(vm) : '')); - } - }; + /** + * Helper that recursively merges two data objects together. + */ + function mergeData (to, from) { + if (!from) { return to } + var key, toVal, fromVal; + var keys = Object.keys(from); + for (var i = 0; i < keys.length; i++) { + key = keys[i]; + toVal = to[key]; + fromVal = from[key]; + if (!hasOwn(to, key)) { + set$1(to, key, fromVal); + } else if (isPlainObject(toVal) && isPlainObject(fromVal)) { + mergeData(toVal, fromVal); + } + } + return to + } - formatComponentName = function (vm) { - var name = vm._isVue ? vm.$options.name : vm.name; - return name ? ' (found in component: <' + hyphenate(name) + '>)' : ''; - }; - })(); + /** + * Data + */ + strats.data = function ( + parentVal, + childVal, + vm + ) { + if (!vm) { + // in a Vue.extend merge, both should be functions + if (!childVal) { + return parentVal + } + if (typeof childVal !== 'function') { + process.env.NODE_ENV !== 'production' && warn( + 'The "data" option should be a function ' + + 'that returns a per-instance value in component ' + + 'definitions.', + vm + ); + return parentVal + } + if (!parentVal) { + return childVal + } + // when parentVal & childVal are both present, + // we need to return a function that returns the + // merged result of both functions... no need to + // check if parentVal is a function here because + // it has to be a function to pass previous merges. + return function mergedDataFn () { + return mergeData( + childVal.call(this), + parentVal.call(this) + ) + } + } else if (parentVal || childVal) { + return function mergedInstanceDataFn () { + // instance merge + var instanceData = typeof childVal === 'function' + ? childVal.call(vm) + : childVal; + var defaultData = typeof parentVal === 'function' + ? parentVal.call(vm) + : undefined; + if (instanceData) { + return mergeData(instanceData, defaultData) + } else { + return defaultData + } + } } + }; - /** - * Append with transition. - * - * @param {Element} el - * @param {Element} target - * @param {Vue} vm - * @param {Function} [cb] - */ + /** + * Hooks and param attributes are merged as arrays. + */ + function mergeHook ( + parentVal, + childVal + ) { + return childVal + ? parentVal + ? parentVal.concat(childVal) + : Array.isArray(childVal) + ? childVal + : [childVal] + : parentVal + } + + config._lifecycleHooks.forEach(function (hook) { + strats[hook] = mergeHook; + }); - function appendWithTransition(el, target, vm, cb) { - applyTransition(el, 1, function () { - target.appendChild(el); - }, vm, cb); - } + /** + * Assets + * + * When a vm is present (instance creation), we need to do + * a three-way merge between constructor options, instance + * options and parent options. + */ + function mergeAssets (parentVal, childVal) { + var res = Object.create(parentVal || null); + return childVal + ? extend(res, childVal) + : res + } + + config._assetTypes.forEach(function (type) { + strats[type + 's'] = mergeAssets; + }); - /** - * InsertBefore with transition. - * - * @param {Element} el - * @param {Element} target - * @param {Vue} vm - * @param {Function} [cb] - */ + /** + * Watchers. + * + * Watchers hashes should not overwrite one + * another, so we merge them as arrays. + */ + strats.watch = function (parentVal, childVal) { + /* istanbul ignore if */ + if (!childVal) { return parentVal } + if (!parentVal) { return childVal } + var ret = {}; + extend(ret, parentVal); + for (var key in childVal) { + var parent = ret[key]; + var child = childVal[key]; + if (parent && !Array.isArray(parent)) { + parent = [parent]; + } + ret[key] = parent + ? parent.concat(child) + : [child]; + } + return ret + }; - function beforeWithTransition(el, target, vm, cb) { - applyTransition(el, 1, function () { - before(el, target); - }, vm, cb); - } + /** + * Other object hashes. + */ + strats.props = + strats.methods = + strats.computed = function (parentVal, childVal) { + if (!childVal) { return parentVal } + if (!parentVal) { return childVal } + var ret = Object.create(null); + extend(ret, parentVal); + extend(ret, childVal); + return ret + }; - /** - * Remove with transition. - * - * @param {Element} el - * @param {Vue} vm - * @param {Function} [cb] - */ + /** + * Default strategy. + */ + var defaultStrat = function (parentVal, childVal) { + return childVal === undefined + ? parentVal + : childVal + }; - function removeWithTransition(el, vm, cb) { - applyTransition(el, -1, function () { - remove(el); - }, vm, cb); + /** + * Validate component names + */ + function checkComponents (options) { + for (var key in options.components) { + var lower = key.toLowerCase(); + if (isBuiltInTag(lower) || config.isReservedTag(lower)) { + warn( + 'Do not use built-in or reserved HTML elements as component ' + + 'id: ' + key + ); + } } + } - /** - * Apply transitions with an operation callback. - * - * @param {Element} el - * @param {Number} direction - * 1: enter - * -1: leave - * @param {Function} op - the actual DOM operation - * @param {Vue} vm - * @param {Function} [cb] - */ - - function applyTransition(el, direction, op, vm, cb) { - var transition = el.__v_trans; - if (!transition || - // skip if there are no js hooks and CSS transition is - // not supported - !transition.hooks && !transitionEndEvent || - // skip transitions for initial compile - !vm._isCompiled || - // if the vm is being manipulated by a parent directive - // during the parent's compilation phase, skip the - // animation. - vm.$parent && !vm.$parent._isCompiled) { - op(); - if (cb) cb(); - return; - } - var action = direction > 0 ? 'enter' : 'leave'; - transition[action](op, cb); - } - - var transition = Object.freeze({ - appendWithTransition: appendWithTransition, - beforeWithTransition: beforeWithTransition, - removeWithTransition: removeWithTransition, - applyTransition: applyTransition - }); - - /** - * Query an element selector if it's not an element already. - * - * @param {String|Element} el - * @return {Element} - */ - - function query(el) { - if (typeof el === 'string') { - var selector = el; - el = document.querySelector(el); - if (!el) { - 'development' !== 'production' && warn('Cannot find element: ' + selector); + /** + * Ensure all props option syntax are normalized into the + * Object-based format. + */ + function normalizeProps (options) { + var props = options.props; + if (!props) { return } + var res = {}; + var i, val, name; + if (Array.isArray(props)) { + i = props.length; + while (i--) { + val = props[i]; + if (typeof val === 'string') { + name = camelize(val); + res[name] = { type: null }; + } else if (process.env.NODE_ENV !== 'production') { + warn('props must be strings when using array syntax.'); } } - return el; - } - - /** - * Check if a node is in the document. - * Note: document.documentElement.contains should work here - * but always returns false for comment nodes in phantomjs, - * making unit tests difficult. This is fixed by doing the - * contains() check on the node's parentNode instead of - * the node itself. - * - * @param {Node} node - * @return {Boolean} - */ - - function inDoc(node) { - if (!node) return false; - var doc = node.ownerDocument.documentElement; - var parent = node.parentNode; - return doc === node || doc === parent || !!(parent && parent.nodeType === 1 && doc.contains(parent)); + } else if (isPlainObject(props)) { + for (var key in props) { + val = props[key]; + name = camelize(key); + res[name] = isPlainObject(val) + ? val + : { type: val }; + } } + options.props = res; + } - /** - * Get and remove an attribute from a node. - * - * @param {Node} node - * @param {String} _attr - */ - - function getAttr(node, _attr) { - var val = node.getAttribute(_attr); - if (val !== null) { - node.removeAttribute(_attr); + /** + * Normalize raw function directives into object format. + */ + function normalizeDirectives (options) { + var dirs = options.directives; + if (dirs) { + for (var key in dirs) { + var def = dirs[key]; + if (typeof def === 'function') { + dirs[key] = { bind: def, update: def }; + } } - return val; } + } - /** - * Get an attribute with colon or v-bind: prefix. - * - * @param {Node} node - * @param {String} name - * @return {String|null} - */ - - function getBindAttr(node, name) { - var val = getAttr(node, ':' + name); - if (val === null) { - val = getAttr(node, 'v-bind:' + name); + /** + * Merge two option objects into a new one. + * Core utility used in both instantiation and inheritance. + */ + function mergeOptions ( + parent, + child, + vm + ) { + if (process.env.NODE_ENV !== 'production') { + checkComponents(child); + } + normalizeProps(child); + normalizeDirectives(child); + var extendsFrom = child.extends; + if (extendsFrom) { + parent = typeof extendsFrom === 'function' + ? mergeOptions(parent, extendsFrom.options, vm) + : mergeOptions(parent, extendsFrom, vm); + } + if (child.mixins) { + for (var i = 0, l = child.mixins.length; i < l; i++) { + var mixin = child.mixins[i]; + if (mixin.prototype instanceof Vue$3) { + mixin = mixin.options; + } + parent = mergeOptions(parent, mixin, vm); + } + } + var options = {}; + var key; + for (key in parent) { + mergeField(key); + } + for (key in child) { + if (!hasOwn(parent, key)) { + mergeField(key); } - return val; } + function mergeField (key) { + var strat = strats[key] || defaultStrat; + options[key] = strat(parent[key], child[key], vm, key); + } + return options + } - /** - * Check the presence of a bind attribute. - * - * @param {Node} node - * @param {String} name - * @return {Boolean} - */ + /** + * Resolve an asset. + * This function is used because child instances need access + * to assets defined in its ancestor chain. + */ + function resolveAsset ( + options, + type, + id, + warnMissing + ) { + /* istanbul ignore if */ + if (typeof id !== 'string') { + return + } + var assets = options[type]; + // check local registration variations first + if (hasOwn(assets, id)) { return assets[id] } + var camelizedId = camelize(id); + if (hasOwn(assets, camelizedId)) { return assets[camelizedId] } + var PascalCaseId = capitalize(camelizedId); + if (hasOwn(assets, PascalCaseId)) { return assets[PascalCaseId] } + // fallback to prototype chain + var res = assets[id] || assets[camelizedId] || assets[PascalCaseId]; + if (process.env.NODE_ENV !== 'production' && warnMissing && !res) { + warn( + 'Failed to resolve ' + type.slice(0, -1) + ': ' + id, + options + ); + } + return res + } + + /* */ + + function validateProp ( + key, + propOptions, + propsData, + vm + ) { + var prop = propOptions[key]; + var absent = !hasOwn(propsData, key); + var value = propsData[key]; + // handle boolean props + if (isType(Boolean, prop.type)) { + if (absent && !hasOwn(prop, 'default')) { + value = false; + } else if (!isType(String, prop.type) && (value === '' || value === hyphenate(key))) { + value = true; + } + } + // check default value + if (value === undefined) { + value = getPropDefaultValue(vm, prop, key); + // since the default value is a fresh copy, + // make sure to observe it. + var prevShouldConvert = observerState.shouldConvert; + observerState.shouldConvert = true; + observe(value); + observerState.shouldConvert = prevShouldConvert; + } + if (process.env.NODE_ENV !== 'production') { + assertProp(prop, key, value, vm, absent); + } + return value + } - function hasBindAttr(node, name) { - return node.hasAttribute(name) || node.hasAttribute(':' + name) || node.hasAttribute('v-bind:' + name); - } + /** + * Get the default value of a prop. + */ + function getPropDefaultValue (vm, prop, key) { + // no default, return undefined + if (!hasOwn(prop, 'default')) { + return undefined + } + var def = prop.default; + // warn against non-factory defaults for Object & Array + if (isObject(def)) { + process.env.NODE_ENV !== 'production' && warn( + 'Invalid default value for prop "' + key + '": ' + + 'Props with type Object/Array must use a factory function ' + + 'to return the default value.', + vm + ); + } + // the raw prop value was also undefined from previous render, + // return previous default value to avoid unnecessary watcher trigger + if (vm && vm.$options.propsData && + vm.$options.propsData[key] === undefined && + vm[key] !== undefined) { + return vm[key] + } + // call factory function for non-Function types + return typeof def === 'function' && prop.type !== Function + ? def.call(vm) + : def + } - /** - * Insert el before target - * - * @param {Element} el - * @param {Element} target - */ + /** + * Assert whether a prop is valid. + */ + function assertProp ( + prop, + name, + value, + vm, + absent + ) { + if (prop.required && absent) { + warn( + 'Missing required prop: "' + name + '"', + vm + ); + return + } + if (value == null && !prop.required) { + return + } + var type = prop.type; + var valid = !type || type === true; + var expectedTypes = []; + if (type) { + if (!Array.isArray(type)) { + type = [type]; + } + for (var i = 0; i < type.length && !valid; i++) { + var assertedType = assertType(value, type[i]); + expectedTypes.push(assertedType.expectedType); + valid = assertedType.valid; + } + } + if (!valid) { + warn( + 'Invalid prop: type check failed for prop "' + name + '".' + + ' Expected ' + expectedTypes.map(capitalize).join(', ') + + ', got ' + Object.prototype.toString.call(value).slice(8, -1) + '.', + vm + ); + return + } + var validator = prop.validator; + if (validator) { + if (!validator(value)) { + warn( + 'Invalid prop: custom validator check failed for prop "' + name + '".', + vm + ); + } + } + } - function before(el, target) { - target.parentNode.insertBefore(el, target); + /** + * Assert the type of a value + */ + function assertType (value, type) { + var valid; + var expectedType = getType(type); + if (expectedType === 'String') { + valid = typeof value === (expectedType = 'string'); + } else if (expectedType === 'Number') { + valid = typeof value === (expectedType = 'number'); + } else if (expectedType === 'Boolean') { + valid = typeof value === (expectedType = 'boolean'); + } else if (expectedType === 'Function') { + valid = typeof value === (expectedType = 'function'); + } else if (expectedType === 'Object') { + valid = isPlainObject(value); + } else if (expectedType === 'Array') { + valid = Array.isArray(value); + } else { + valid = value instanceof type; + } + return { + valid: valid, + expectedType: expectedType } + } - /** - * Insert el after target - * - * @param {Element} el - * @param {Element} target - */ + /** + * Use function string name to check built-in types, + * because a simple equality check will fail when running + * across different vms / iframes. + */ + function getType (fn) { + var match = fn && fn.toString().match(/^\s*function (\w+)/); + return match && match[1] + } - function after(el, target) { - if (target.nextSibling) { - before(el, target.nextSibling); - } else { - target.parentNode.appendChild(el); + function isType (type, fn) { + if (!Array.isArray(fn)) { + return getType(fn) === getType(type) + } + for (var i = 0, len = fn.length; i < len; i++) { + if (getType(fn[i]) === getType(type)) { + return true } } + /* istanbul ignore next */ + return false + } + + + + var util = Object.freeze({ + defineReactive: defineReactive$$1, + _toString: _toString, + toNumber: toNumber, + makeMap: makeMap, + isBuiltInTag: isBuiltInTag, + remove: remove$1, + hasOwn: hasOwn, + isPrimitive: isPrimitive, + cached: cached, + camelize: camelize, + capitalize: capitalize, + hyphenate: hyphenate, + bind: bind$1, + toArray: toArray, + extend: extend, + isObject: isObject, + isPlainObject: isPlainObject, + toObject: toObject, + noop: noop, + no: no, + identity: identity, + genStaticKeys: genStaticKeys, + looseEqual: looseEqual, + looseIndexOf: looseIndexOf, + isReserved: isReserved, + def: def, + parsePath: parsePath, + hasProto: hasProto, + inBrowser: inBrowser, + UA: UA, + isIE: isIE, + isIE9: isIE9, + isEdge: isEdge, + isAndroid: isAndroid, + isIOS: isIOS, + isServerRendering: isServerRendering, + devtools: devtools, + nextTick: nextTick, + get _Set () { return _Set; }, + mergeOptions: mergeOptions, + resolveAsset: resolveAsset, + get warn () { return warn; }, + get formatComponentName () { return formatComponentName; }, + validateProp: validateProp + }); - /** - * Remove el from DOM - * - * @param {Element} el - */ + /* not type checking this file because flow doesn't play well with Proxy */ + + var initProxy; + + if (process.env.NODE_ENV !== 'production') { + var 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 + ); + + var warnNonPresent = function (target, key) { + warn( + "Property or method \"" + key + "\" is not defined on the instance but " + + "referenced during render. Make sure to declare reactive data " + + "properties in the data option.", + target + ); + }; - function remove(el) { - el.parentNode.removeChild(el); + var hasProxy = + typeof Proxy !== 'undefined' && + Proxy.toString().match(/native code/); + + if (hasProxy) { + var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta'); + config.keyCodes = new Proxy(config.keyCodes, { + set: function 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 + } + } + }); } - /** - * Prepend el to target - * - * @param {Element} el - * @param {Element} target - */ - - function prepend(el, target) { - if (target.firstChild) { - before(el, target.firstChild); - } else { - target.appendChild(el); + var hasHandler = { + has: function has (target, key) { + var has = key in target; + var isAllowed = allowedGlobals(key) || key.charAt(0) === '_'; + if (!has && !isAllowed) { + warnNonPresent(target, key); + } + return has || !isAllowed } - } - - /** - * Replace target with el - * - * @param {Element} target - * @param {Element} el - */ + }; - function replace(target, el) { - var parent = target.parentNode; - if (parent) { - parent.replaceChild(el, target); + var getHandler = { + get: function get (target, key) { + if (typeof key === 'string' && !(key in target)) { + warnNonPresent(target, key); + } + return target[key] } - } - - /** - * Add event listener shorthand. - * - * @param {Element} el - * @param {String} event - * @param {Function} cb - * @param {Boolean} [useCapture] - */ + }; - function on(el, event, cb, useCapture) { - el.addEventListener(event, cb, useCapture); - } + initProxy = function initProxy (vm) { + if (hasProxy) { + // determine which proxy handler to use + var options = vm.$options; + var handlers = options.render && options.render._withStripped + ? getHandler + : hasHandler; + vm._renderProxy = new Proxy(vm, handlers); + } else { + vm._renderProxy = vm; + } + }; + } - /** - * Remove event listener shorthand. - * - * @param {Element} el - * @param {String} event - * @param {Function} cb - */ + /* */ - function off(el, event, cb) { - el.removeEventListener(event, cb); - } - /** - * For IE9 compat: when both class and :class are present - * getAttribute('class') returns wrong value... - * - * @param {Element} el - * @return {String} - */ + var queue = []; + var has$1 = {}; + var circular = {}; + var waiting = false; + var flushing = false; + var index = 0; - function getClass(el) { - var classname = el.className; - if (typeof classname === 'object') { - classname = classname.baseVal || ''; - } - return classname; + /** + * Reset the scheduler's state. + */ + function resetSchedulerState () { + queue.length = 0; + has$1 = {}; + if (process.env.NODE_ENV !== 'production') { + circular = {}; } + waiting = flushing = false; + } - /** - * In IE9, setAttribute('class') will result in empty class - * if the element also has the :class attribute; However in - * PhantomJS, setting `className` does not work on SVG elements... - * So we have to do a conditional check here. - * - * @param {Element} el - * @param {String} cls - */ - - function setClass(el, cls) { - /* istanbul ignore if */ - if (isIE9 && !/svg$/.test(el.namespaceURI)) { - el.className = cls; - } else { - el.setAttribute('class', cls); + /** + * Flush both queues and run the watchers. + */ + function flushSchedulerQueue () { + flushing = true; + + // Sort queue before flush. + // This ensures that: + // 1. Components are updated from parent to child. (because parent is always + // created before the child) + // 2. A component's user watchers are run before its render watcher (because + // user watchers are created before the render watcher) + // 3. If a component is destroyed during a parent component's watcher run, + // its watchers can be skipped. + queue.sort(function (a, b) { return a.id - b.id; }); + + // do not cache length because more watchers might be pushed + // as we run existing watchers + for (index = 0; index < queue.length; index++) { + var watcher = queue[index]; + var id = watcher.id; + has$1[id] = null; + watcher.run(); + // in dev build, check and stop circular updates. + if (process.env.NODE_ENV !== 'production' && has$1[id] != null) { + circular[id] = (circular[id] || 0) + 1; + if (circular[id] > config._maxUpdateCount) { + warn( + 'You may have an infinite update loop ' + ( + watcher.user + ? ("in watcher with expression \"" + (watcher.expression) + "\"") + : "in a component render function." + ), + watcher.vm + ); + break + } } } - /** - * Add class with compatibility for IE & SVG - * - * @param {Element} el - * @param {String} cls - */ - - function addClass(el, cls) { - if (el.classList) { - el.classList.add(cls); - } else { - var cur = ' ' + getClass(el) + ' '; - if (cur.indexOf(' ' + cls + ' ') < 0) { - setClass(el, (cur + cls).trim()); - } - } + // devtool hook + /* istanbul ignore if */ + if (devtools && config.devtools) { + devtools.emit('flush'); } - /** - * Remove class with compatibility for IE & SVG - * - * @param {Element} el - * @param {String} cls - */ + resetSchedulerState(); + } - function removeClass(el, cls) { - if (el.classList) { - el.classList.remove(cls); + /** + * Push a watcher into the watcher queue. + * Jobs with duplicate IDs will be skipped unless it's + * pushed when the queue is being flushed. + */ + function queueWatcher (watcher) { + var id = watcher.id; + if (has$1[id] == null) { + has$1[id] = true; + if (!flushing) { + queue.push(watcher); } else { - var cur = ' ' + getClass(el) + ' '; - var tar = ' ' + cls + ' '; - while (cur.indexOf(tar) >= 0) { - cur = cur.replace(tar, ' '); + // if already flushing, splice the watcher based on its id + // if already past its id, it will be run next immediately. + var i = queue.length - 1; + while (i >= 0 && queue[i].id > watcher.id) { + i--; } - setClass(el, cur.trim()); + queue.splice(Math.max(i, index) + 1, 0, watcher); } - if (!el.className) { - el.removeAttribute('class'); + // queue the flush + if (!waiting) { + waiting = true; + nextTick(flushSchedulerQueue); } } + } - /** - * Extract raw content inside an element into a temporary - * container div - * - * @param {Element} el - * @param {Boolean} asFragment - * @return {Element|DocumentFragment} - */ + /* */ - function extractContent(el, asFragment) { - var child; - var rawContent; - /* istanbul ignore if */ - if (isTemplate(el) && isFragment(el.content)) { - el = el.content; - } - if (el.hasChildNodes()) { - trimNode(el); - rawContent = asFragment ? document.createDocumentFragment() : document.createElement('div'); - /* eslint-disable no-cond-assign */ - while (child = el.firstChild) { - /* eslint-enable no-cond-assign */ - rawContent.appendChild(child); - } - } - return rawContent; - } + var uid$2 = 0; - /** - * Trim possible empty head/tail text and comment - * nodes inside a parent. - * - * @param {Node} node - */ + /** + * A watcher parses an expression, collects dependencies, + * and fires callback when the expression value changes. + * This is used for both the $watch() api and directives. + */ + var Watcher = function Watcher ( + vm, + expOrFn, + cb, + options + ) { + this.vm = vm; + vm._watchers.push(this); + // options + if (options) { + this.deep = !!options.deep; + this.user = !!options.user; + this.lazy = !!options.lazy; + this.sync = !!options.sync; + } else { + this.deep = this.user = this.lazy = this.sync = false; + } + this.cb = cb; + this.id = ++uid$2; // uid for batching + this.active = true; + this.dirty = this.lazy; // for lazy watchers + this.deps = []; + this.newDeps = []; + this.depIds = new _Set(); + this.newDepIds = new _Set(); + this.expression = process.env.NODE_ENV !== 'production' + ? expOrFn.toString() + : ''; + // parse expression for getter + if (typeof expOrFn === 'function') { + this.getter = expOrFn; + } else { + this.getter = parsePath(expOrFn); + if (!this.getter) { + this.getter = function () {}; + process.env.NODE_ENV !== 'production' && warn( + "Failed watching path: \"" + expOrFn + "\" " + + 'Watcher only accepts simple dot-delimited paths. ' + + 'For full control, use a function instead.', + vm + ); + } + } + this.value = this.lazy + ? undefined + : this.get(); + }; - function trimNode(node) { - var child; - /* eslint-disable no-sequences */ - while ((child = node.firstChild, isTrimmable(child))) { - node.removeChild(child); - } - while ((child = node.lastChild, isTrimmable(child))) { - node.removeChild(child); + /** + * Evaluate the getter, and re-collect dependencies. + */ + Watcher.prototype.get = function get () { + pushTarget(this); + var value = this.getter.call(this.vm, this.vm); + // "touch" every property so they are all tracked as + // dependencies for deep watching + if (this.deep) { + traverse(value); + } + popTarget(); + this.cleanupDeps(); + return value + }; + + /** + * Add a dependency to this directive. + */ + Watcher.prototype.addDep = function addDep (dep) { + var id = dep.id; + if (!this.newDepIds.has(id)) { + this.newDepIds.add(id); + this.newDeps.push(dep); + if (!this.depIds.has(id)) { + dep.addSub(this); } - /* eslint-enable no-sequences */ } + }; - function isTrimmable(node) { - return node && (node.nodeType === 3 && !node.data.trim() || node.nodeType === 8); - } + /** + * Clean up for dependency collection. + */ + Watcher.prototype.cleanupDeps = function cleanupDeps () { + var this$1 = this; + + var i = this.deps.length; + while (i--) { + var dep = this$1.deps[i]; + if (!this$1.newDepIds.has(dep.id)) { + dep.removeSub(this$1); + } + } + var tmp = this.depIds; + this.depIds = this.newDepIds; + this.newDepIds = tmp; + this.newDepIds.clear(); + tmp = this.deps; + this.deps = this.newDeps; + this.newDeps = tmp; + this.newDeps.length = 0; + }; - /** - * Check if an element is a template tag. - * Note if the template appears inside an SVG its tagName - * will be in lowercase. - * - * @param {Element} el - */ - - function isTemplate(el) { - return el.tagName && el.tagName.toLowerCase() === 'template'; - } - - /** - * Create an "anchor" for performing dom insertion/removals. - * This is used in a number of scenarios: - * - fragment instance - * - v-html - * - v-if - * - v-for - * - component - * - * @param {String} content - * @param {Boolean} persist - IE trashes empty textNodes on - * cloneNode(true), so in certain - * cases the anchor needs to be - * non-empty to be persisted in - * templates. - * @return {Comment|Text} - */ - - function createAnchor(content, persist) { - var anchor = config.debug ? document.createComment(content) : document.createTextNode(persist ? ' ' : ''); - anchor.__v_anchor = true; - return anchor; + /** + * Subscriber interface. + * Will be called when a dependency changes. + */ + Watcher.prototype.update = function update () { + /* istanbul ignore else */ + if (this.lazy) { + this.dirty = true; + } else if (this.sync) { + this.run(); + } else { + queueWatcher(this); } + }; - /** - * Find a component ref attribute that starts with $. - * - * @param {Element} node - * @return {String|undefined} - */ - - var refRE = /^v-ref:/; - - function findRef(node) { - if (node.hasAttributes()) { - var attrs = node.attributes; - for (var i = 0, l = attrs.length; i < l; i++) { - var name = attrs[i].name; - if (refRE.test(name)) { - return camelize(name.replace(refRE, '')); + /** + * Scheduler job interface. + * Will be called by the scheduler. + */ + Watcher.prototype.run = function run () { + if (this.active) { + var value = this.get(); + if ( + value !== this.value || + // Deep watchers and watchers on Object/Arrays should fire even + // when the value is the same, because the value may + // have mutated. + isObject(value) || + this.deep + ) { + // set new value + var oldValue = this.value; + this.value = value; + if (this.user) { + try { + this.cb.call(this.vm, value, oldValue); + } catch (e) { + /* istanbul ignore else */ + if (config.errorHandler) { + config.errorHandler.call(null, e, this.vm); + } else { + process.env.NODE_ENV !== 'production' && warn( + ("Error in watcher \"" + (this.expression) + "\""), + this.vm + ); + throw e + } } + } else { + this.cb.call(this.vm, value, oldValue); } } } + }; - /** - * Map a function to a range of nodes . - * - * @param {Node} node - * @param {Node} end - * @param {Function} op - */ - - function mapNodeRange(node, end, op) { - var next; - while (node !== end) { - next = node.nextSibling; - op(node); - node = next; - } - op(end); - } - - /** - * Remove a range of nodes with transition, store - * the nodes in a fragment with correct ordering, - * and call callback when done. - * - * @param {Node} start - * @param {Node} end - * @param {Vue} vm - * @param {DocumentFragment} frag - * @param {Function} cb - */ - - function removeNodeRange(start, end, vm, frag, cb) { - var done = false; - var removed = 0; - var nodes = []; - mapNodeRange(start, end, function (node) { - if (node === end) done = true; - nodes.push(node); - removeWithTransition(node, vm, onRemoved); - }); - function onRemoved() { - removed++; - if (done && removed >= nodes.length) { - for (var i = 0; i < nodes.length; i++) { - frag.appendChild(nodes[i]); - } - cb && cb(); - } - } - } + /** + * Evaluate the value of the watcher. + * This only gets called for lazy watchers. + */ + Watcher.prototype.evaluate = function evaluate () { + this.value = this.get(); + this.dirty = false; + }; - /** - * Check if a node is a DocumentFragment. - * - * @param {Node} node - * @return {Boolean} - */ + /** + * Depend on all deps collected by this watcher. + */ + Watcher.prototype.depend = function depend () { + var this$1 = this; - function isFragment(node) { - return node && node.nodeType === 11; + var i = this.deps.length; + while (i--) { + this$1.deps[i].depend(); } + }; - /** - * Get outerHTML of elements, taking care - * of SVG elements in IE as well. - * - * @param {Element} el - * @return {String} - */ + /** + * Remove self from all dependencies' subscriber list. + */ + Watcher.prototype.teardown = function teardown () { + var this$1 = this; - function getOuterHTML(el) { - if (el.outerHTML) { - return el.outerHTML; - } else { - var container = document.createElement('div'); - container.appendChild(el.cloneNode(true)); - return container.innerHTML; + if (this.active) { + // remove self from vm's watcher list + // this is a somewhat expensive operation so we skip it + // if the vm is being destroyed or is performing a v-for + // re-render (the watcher list is then filtered by v-for). + if (!this.vm._isBeingDestroyed && !this.vm._vForRemoving) { + remove$1(this.vm._watchers, this); } - } - - var commonTagRE = /^(div|p|span|img|a|b|i|br|ul|ol|li|h1|h2|h3|h4|h5|h6|code|pre|table|th|td|tr|form|label|input|select|option|nav|article|section|header|footer)$/i; - var reservedTagRE = /^(slot|partial|component)$/i; - - var isUnknownElement = undefined; - if (true) { - isUnknownElement = function (el, tag) { - if (tag.indexOf('-') > -1) { - // http://stackoverflow.com/a/28210364/1070244 - return el.constructor === window.HTMLUnknownElement || el.constructor === window.HTMLElement; - } else { - return (/HTMLUnknownElement/.test(el.toString()) && - // Chrome returns unknown for several HTML5 elements. - // https://code.google.com/p/chromium/issues/detail?id=540526 - // Firefox returns unknown for some "Interactive elements." - !/^(data|time|rtc|rb|details|dialog|summary)$/.test(tag) - ); - } - }; - } - - /** - * Check if an element is a component, if yes return its - * component id. - * - * @param {Element} el - * @param {Object} options - * @return {Object|undefined} - */ - - function checkComponentAttr(el, options) { - var tag = el.tagName.toLowerCase(); - var hasAttrs = el.hasAttributes(); - if (!commonTagRE.test(tag) && !reservedTagRE.test(tag)) { - if (resolveAsset(options, 'components', tag)) { - return { id: tag }; - } else { - var is = hasAttrs && getIsBinding(el, options); - if (is) { - return is; - } else if (true) { - var expectedTag = options._componentNameMap && options._componentNameMap[tag]; - if (expectedTag) { - warn('Unknown custom element: <' + tag + '> - ' + 'did you mean <' + expectedTag + '>? ' + 'HTML is case-insensitive, remember to use kebab-case in templates.'); - } else if (isUnknownElement(el, tag)) { - warn('Unknown custom element: <' + tag + '> - did you ' + 'register the component correctly? For recursive components, ' + 'make sure to provide the "name" option.'); - } - } - } - } else if (hasAttrs) { - return getIsBinding(el, options); + var i = this.deps.length; + while (i--) { + this$1.deps[i].removeSub(this$1); } + this.active = false; } + }; - /** - * Get "is" binding from an element. - * - * @param {Element} el - * @param {Object} options - * @return {Object|undefined} - */ - - function getIsBinding(el, options) { - // dynamic syntax - var exp = el.getAttribute('is'); - if (exp != null) { - if (resolveAsset(options, 'components', exp)) { - el.removeAttribute('is'); - return { id: exp }; - } - } else { - exp = getBindAttr(el, 'is'); - if (exp != null) { - return { id: exp, dynamic: true }; - } - } + /** + * Recursively traverse an object to evoke all converted + * getters, so that every nested property inside the object + * is collected as a "deep" dependency. + */ + var seenObjects = new _Set(); + function traverse (val) { + seenObjects.clear(); + _traverse(val, seenObjects); + } + + function _traverse (val, seen) { + var i, keys; + var isA = Array.isArray(val); + if ((!isA && !isObject(val)) || !Object.isExtensible(val)) { + return + } + if (val.__ob__) { + var depId = val.__ob__.dep.id; + if (seen.has(depId)) { + return + } + seen.add(depId); + } + if (isA) { + i = val.length; + while (i--) { _traverse(val[i], seen); } + } else { + keys = Object.keys(val); + i = keys.length; + while (i--) { _traverse(val[keys[i]], seen); } } + } - /** - * Option overwriting strategies are functions that handle - * how to merge a parent option value and a child option - * value into the final value. - * - * All strategy functions follow the same signature: - * - * @param {*} parentVal - * @param {*} childVal - * @param {Vue} [vm] - */ - - var strats = config.optionMergeStrategies = Object.create(null); - - /** - * Helper that recursively merges two data objects together. - */ + /* */ - function mergeData(to, from) { - var key, toVal, fromVal; - for (key in from) { - toVal = to[key]; - fromVal = from[key]; - if (!hasOwn(to, key)) { - set(to, key, fromVal); - } else if (isObject(toVal) && isObject(fromVal)) { - mergeData(toVal, fromVal); + function initState (vm) { + vm._watchers = []; + var 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) { initWatch(vm, opts.watch); } + } + + var isReservedProp = { key: 1, ref: 1, slot: 1 }; + + function initProps (vm, props) { + var propsData = vm.$options.propsData || {}; + var keys = vm.$options._propKeys = Object.keys(props); + var isRoot = !vm.$parent; + // root instance props should be converted + observerState.shouldConvert = isRoot; + var loop = function ( i ) { + var key = keys[i]; + /* istanbul ignore else */ + if (process.env.NODE_ENV !== 'production') { + if (isReservedProp[key]) { + warn( + ("\"" + key + "\" is a reserved attribute and cannot be used as component prop."), + vm + ); } - } - return to; - } - - /** - * Data - */ - - strats.data = function (parentVal, childVal, vm) { - if (!vm) { - // in a Vue.extend merge, both should be functions - if (!childVal) { - return parentVal; - } - if (typeof childVal !== 'function') { - 'development' !== 'production' && warn('The "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm); - return parentVal; - } - if (!parentVal) { - return childVal; - } - // when parentVal & childVal are both present, - // we need to return a function that returns the - // merged result of both functions... no need to - // check if parentVal is a function here because - // it has to be a function to pass previous merges. - return function mergedDataFn() { - return mergeData(childVal.call(this), parentVal.call(this)); - }; - } else if (parentVal || childVal) { - return function mergedInstanceDataFn() { - // instance merge - var instanceData = typeof childVal === 'function' ? childVal.call(vm) : childVal; - var defaultData = typeof parentVal === 'function' ? parentVal.call(vm) : undefined; - if (instanceData) { - return mergeData(instanceData, defaultData); - } else { - return defaultData; + defineReactive$$1(vm, key, validateProp(key, props, propsData, vm), function () { + if (vm.$parent && !observerState.isSettingProps) { + 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$$1(vm, key, validateProp(key, props, propsData, vm)); } }; - /** - * El - */ - - strats.el = function (parentVal, childVal, vm) { - if (!vm && childVal && typeof childVal !== 'function') { - 'development' !== 'production' && warn('The "el" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm); - return; + for (var i = 0; i < keys.length; i++) loop( i ); + observerState.shouldConvert = true; + } + + function initData (vm) { + var data = vm.$options.data; + data = vm._data = typeof data === 'function' + ? data.call(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 + var keys = Object.keys(data); + var props = vm.$options.props; + var i = keys.length; + while (i--) { + if (props && hasOwn(props, keys[i])) { + process.env.NODE_ENV !== 'production' && warn( + "The data property \"" + (keys[i]) + "\" is already declared as a prop. " + + "Use prop default value instead.", + vm + ); + } else { + proxy(vm, keys[i]); } - var ret = childVal || parentVal; - // invoke the element factory if this is instance merge - return vm && typeof ret === 'function' ? ret.call(vm) : ret; - }; - - /** - * Hooks and param attributes are merged as arrays. - */ - - strats.init = strats.created = strats.ready = strats.attached = strats.detached = strats.beforeCompile = strats.compiled = strats.beforeDestroy = strats.destroyed = strats.activate = function (parentVal, childVal) { - return childVal ? parentVal ? parentVal.concat(childVal) : isArray(childVal) ? childVal : [childVal] : parentVal; - }; - - /** - * Assets - * - * When a vm is present (instance creation), we need to do - * a three-way merge between constructor options, instance - * options and parent options. - */ - - function mergeAssets(parentVal, childVal) { - var res = Object.create(parentVal || null); - return childVal ? extend(res, guardArrayAssets(childVal)) : res; } + // observe data + observe(data, true /* asRootData */); + } - config._assetTypes.forEach(function (type) { - strats[type + 's'] = mergeAssets; - }); - - /** - * Events & Watchers. - * - * Events & watchers hashes should not overwrite one - * another, so we merge them as arrays. - */ - - strats.watch = strats.events = function (parentVal, childVal) { - if (!childVal) return parentVal; - if (!parentVal) return childVal; - var ret = {}; - extend(ret, parentVal); - for (var key in childVal) { - var parent = ret[key]; - var child = childVal[key]; - if (parent && !isArray(parent)) { - parent = [parent]; - } - ret[key] = parent ? parent.concat(child) : [child]; - } - return ret; - }; - - /** - * Other object hashes. - */ - - strats.props = strats.methods = strats.computed = function (parentVal, childVal) { - if (!childVal) return parentVal; - if (!parentVal) return childVal; - var ret = Object.create(null); - extend(ret, parentVal); - extend(ret, childVal); - return ret; - }; - - /** - * Default strategy. - */ - - var defaultStrat = function defaultStrat(parentVal, childVal) { - return childVal === undefined ? parentVal : childVal; - }; - - /** - * Make sure component options get converted to actual - * constructors. - * - * @param {Object} options - */ + var computedSharedDefinition = { + enumerable: true, + configurable: true, + get: noop, + set: noop + }; - function guardComponents(options) { - if (options.components) { - var components = options.components = guardArrayAssets(options.components); - var ids = Object.keys(components); - var def; - if (true) { - var map = options._componentNameMap = {}; - } - for (var i = 0, l = ids.length; i < l; i++) { - var key = ids[i]; - if (commonTagRE.test(key) || reservedTagRE.test(key)) { - 'development' !== 'production' && warn('Do not use built-in or reserved HTML elements as component ' + 'id: ' + key); - continue; - } - // record a all lowercase <-> kebab-case mapping for - // possible custom element case error warning - if (true) { - map[key.replace(/-/g, '').toLowerCase()] = hyphenate(key); - } - def = components[key]; - if (isPlainObject(def)) { - components[key] = Vue.extend(def); - } - } + function initComputed (vm, computed) { + for (var key in computed) { + var userDef = computed[key]; + if (typeof userDef === 'function') { + computedSharedDefinition.get = makeComputedGetter(userDef, vm); + computedSharedDefinition.set = noop; + } else { + computedSharedDefinition.get = userDef.get + ? userDef.cache !== false + ? makeComputedGetter(userDef.get, vm) + : bind$1(userDef.get, vm) + : noop; + computedSharedDefinition.set = userDef.set + ? bind$1(userDef.set, vm) + : noop; + } + Object.defineProperty(vm, key, computedSharedDefinition); + } + } + + function makeComputedGetter (getter, owner) { + var watcher = new Watcher(owner, getter, noop, { + lazy: true + }); + return function computedGetter () { + if (watcher.dirty) { + watcher.evaluate(); } - } - - /** - * Ensure all props option syntax are normalized into the - * Object-based format. - * - * @param {Object} options - */ - - function guardProps(options) { - var props = options.props; - var i, val; - if (isArray(props)) { - options.props = {}; - i = props.length; - while (i--) { - val = props[i]; - if (typeof val === 'string') { - options.props[val] = null; - } else if (val.name) { - options.props[val.name] = val; - } - } - } else if (isPlainObject(props)) { - var keys = Object.keys(props); - i = keys.length; - while (i--) { - val = props[keys[i]]; - if (typeof val === 'function') { - props[keys[i]] = { type: val }; - } - } + if (Dep.target) { + watcher.depend(); } + return watcher.value } + } - /** - * Guard an Array-format assets option and converted it - * into the key-value Object format. - * - * @param {Object|Array} assets - * @return {Object} - */ - - function guardArrayAssets(assets) { - if (isArray(assets)) { - var res = {}; - var i = assets.length; - var asset; - while (i--) { - asset = assets[i]; - var id = typeof asset === 'function' ? asset.options && asset.options.name || asset.id : asset.name || asset.id; - if (!id) { - 'development' !== 'production' && warn('Array-syntax assets must provide a "name" or "id" field.'); - } else { - res[id] = asset; - } - } - return res; + function initMethods (vm, methods) { + for (var key in methods) { + vm[key] = methods[key] == null ? noop : bind$1(methods[key], vm); + if (process.env.NODE_ENV !== 'production' && methods[key] == null) { + warn( + "method \"" + key + "\" has an undefined value in the component definition. " + + "Did you reference the function correctly?", + vm + ); } - return assets; } + } - /** - * Merge two option objects into a new one. - * Core utility used in both instantiation and inheritance. - * - * @param {Object} parent - * @param {Object} child - * @param {Vue} [vm] - if vm is present, indicates this is - * an instantiation merge. - */ - - function mergeOptions(parent, child, vm) { - guardComponents(child); - guardProps(child); - if (true) { - if (child.propsData && !vm) { - warn('propsData can only be used as an instantiation option.'); - } - } - var options = {}; - var key; - if (child['extends']) { - parent = typeof child['extends'] === 'function' ? mergeOptions(parent, child['extends'].options, vm) : mergeOptions(parent, child['extends'], vm); - } - if (child.mixins) { - for (var i = 0, l = child.mixins.length; i < l; i++) { - var mixin = child.mixins[i]; - var mixinOptions = mixin.prototype instanceof Vue ? mixin.options : mixin; - parent = mergeOptions(parent, mixinOptions, vm); - } - } - for (key in parent) { - mergeField(key); - } - for (key in child) { - if (!hasOwn(parent, key)) { - mergeField(key); + function initWatch (vm, watch) { + for (var key in watch) { + var handler = watch[key]; + if (Array.isArray(handler)) { + for (var i = 0; i < handler.length; i++) { + createWatcher(vm, key, handler[i]); } + } else { + createWatcher(vm, key, handler); } - function mergeField(key) { - var strat = strats[key] || defaultStrat; - options[key] = strat(parent[key], child[key], vm, key); - } - return options; } + } - /** - * Resolve an asset. - * This function is used because child instances need access - * to assets defined in its ancestor chain. - * - * @param {Object} options - * @param {String} type - * @param {String} id - * @param {Boolean} warnMissing - * @return {Object|Function} - */ - - function resolveAsset(options, type, id, warnMissing) { - /* istanbul ignore if */ - if (typeof id !== 'string') { - return; - } - var assets = options[type]; - var camelizedId; - var res = assets[id] || - // camelCase ID - assets[camelizedId = camelize(id)] || - // Pascal Case ID - assets[camelizedId.charAt(0).toUpperCase() + camelizedId.slice(1)]; - if ('development' !== 'production' && warnMissing && !res) { - warn('Failed to resolve ' + type.slice(0, -1) + ': ' + id, options); - } - return res; + function createWatcher (vm, key, handler) { + var options; + if (isPlainObject(handler)) { + options = handler; + handler = handler.handler; } - - var uid$1 = 0; - - /** - * A dep is an observable that can have multiple - * directives subscribing to it. - * - * @constructor - */ - function Dep() { - this.id = uid$1++; - this.subs = []; + if (typeof handler === 'string') { + handler = vm[handler]; } + vm.$watch(key, handler, options); + } - // the current target watcher being evaluated. - // this is globally unique because there could be only one - // watcher being evaluated at any time. - Dep.target = null; - - /** - * Add a directive subscriber. - * - * @param {Directive} sub - */ - - Dep.prototype.addSub = function (sub) { - this.subs.push(sub); - }; - - /** - * Remove a directive subscriber. - * - * @param {Directive} sub - */ - - Dep.prototype.removeSub = function (sub) { - this.subs.$remove(sub); - }; - - /** - * Add self as a dependency to the target watcher. - */ - - Dep.prototype.depend = function () { - Dep.target.addDep(this); - }; - - /** - * Notify all subscribers of a new value. - */ - - Dep.prototype.notify = function () { - // stablize the subscriber list first - var subs = toArray(this.subs); - for (var i = 0, l = subs.length; i < l; i++) { - subs[i].update(); - } + function stateMixin (Vue) { + // flow somehow has problems with directly declared definition object + // when using Object.defineProperty, so we have to procedurally build up + // the object here. + var dataDef = {}; + dataDef.get = function () { + return this._data }; - - var arrayProto = Array.prototype; - var arrayMethods = Object.create(arrayProto) - - /** - * Intercept mutating methods and emit events - */ - - ;['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function (method) { - // cache original method - var original = arrayProto[method]; - def(arrayMethods, method, function mutator() { - // avoid leaking arguments: - // http://jsperf.com/closure-with-arguments - var i = arguments.length; - var args = new Array(i); - while (i--) { - args[i] = arguments[i]; - } - var result = original.apply(this, args); - var ob = this.__ob__; - var inserted; - switch (method) { - case 'push': - inserted = args; - break; - case 'unshift': - inserted = args; - break; - case 'splice': - inserted = args.slice(2); - break; - } - if (inserted) ob.observeArray(inserted); - // notify change - ob.dep.notify(); - return result; - }); - }); - - /** - * Swap the element at the given index with a new value - * and emits corresponding event. - * - * @param {Number} index - * @param {*} val - * @return {*} - replaced element - */ - - def(arrayProto, '$set', function $set(index, val) { - if (index >= this.length) { - this.length = Number(index) + 1; - } - return this.splice(index, 1, val)[0]; - }); - - /** - * Convenience method to remove the element at given index or target element reference. - * - * @param {*} item - */ - - def(arrayProto, '$remove', function $remove(item) { - /* istanbul ignore if */ - if (!this.length) return; - var index = indexOf(this, item); - if (index > -1) { - return this.splice(index, 1); - } - }); - - var arrayKeys = Object.getOwnPropertyNames(arrayMethods); - - /** - * By default, when a reactive property is set, the new value is - * also converted to become reactive. However in certain cases, e.g. - * v-for scope alias and props, we don't want to force conversion - * because the value may be a nested value under a frozen data structure. - * - * So whenever we want to set a reactive property without forcing - * conversion on the new value, we wrap that call inside this function. - */ - - var shouldConvert = true; - - function withoutConversion(fn) { - shouldConvert = false; - fn(); - shouldConvert = true; + if (process.env.NODE_ENV !== 'production') { + dataDef.set = function (newData) { + warn( + 'Avoid replacing instance root $data. ' + + 'Use nested data properties instead.', + this + ); + }; } + Object.defineProperty(Vue.prototype, '$data', dataDef); - /** - * Observer class that are attached to each observed - * object. Once attached, the observer converts target - * object's property keys into getter/setters that - * collect dependencies and dispatches updates. - * - * @param {Array|Object} value - * @constructor - */ + Vue.prototype.$set = set$1; + Vue.prototype.$delete = del; - function Observer(value) { - this.value = value; - this.dep = new Dep(); - def(value, '__ob__', this); - if (isArray(value)) { - var augment = hasProto ? protoAugment : copyAugment; - augment(value, arrayMethods, arrayKeys); - this.observeArray(value); - } else { - this.walk(value); + Vue.prototype.$watch = function ( + expOrFn, + cb, + options + ) { + var vm = this; + options = options || {}; + options.user = true; + var watcher = new Watcher(vm, expOrFn, cb, options); + if (options.immediate) { + cb.call(vm, watcher.value); } - } - - // Instance methods - - /** - * Walk through each property and convert them into - * getter/setters. This method should only be called when - * value type is Object. - * - * @param {Object} obj - */ - - Observer.prototype.walk = function (obj) { - var keys = Object.keys(obj); - for (var i = 0, l = keys.length; i < l; i++) { - this.convert(keys[i], obj[keys[i]]); + return function unwatchFn () { + watcher.teardown(); } }; + } - /** - * Observe a list of Array items. - * - * @param {Array} items - */ + function proxy (vm, key) { + if (!isReserved(key)) { + Object.defineProperty(vm, key, { + configurable: true, + enumerable: true, + get: function proxyGetter () { + return vm._data[key] + }, + set: function proxySetter (val) { + vm._data[key] = val; + } + }); + } + } + + /* */ + + var VNode = function VNode ( + tag, + data, + children, + text, + elm, + context, + componentOptions + ) { + this.tag = tag; + this.data = data; + this.children = children; + this.text = text; + this.elm = elm; + this.ns = undefined; + this.context = context; + this.functionalContext = undefined; + this.key = data && data.key; + this.componentOptions = componentOptions; + this.child = undefined; + this.parent = undefined; + this.raw = false; + this.isStatic = false; + this.isRootInsert = true; + this.isComment = false; + this.isCloned = false; + this.isOnce = false; + }; - Observer.prototype.observeArray = function (items) { - for (var i = 0, l = items.length; i < l; i++) { - observe(items[i]); - } - }; + var createEmptyVNode = function () { + var node = new VNode(); + node.text = ''; + node.isComment = true; + return node + }; - /** - * Convert a property into getter/setter so we can emit - * the events when the property is accessed/changed. - * - * @param {String} key - * @param {*} val - */ - - Observer.prototype.convert = function (key, val) { - defineReactive(this.value, key, val); - }; - - /** - * Add an owner vm, so that when $set/$delete mutations - * happen we can notify owner vms to proxy the keys and - * digest the watchers. This is only called when the object - * is observed as an instance's root $data. - * - * @param {Vue} vm - */ - - Observer.prototype.addVm = function (vm) { - (this.vms || (this.vms = [])).push(vm); - }; - - /** - * Remove an owner vm. This is called when the object is - * swapped out as an instance's $data object. - * - * @param {Vue} vm - */ - - Observer.prototype.removeVm = function (vm) { - this.vms.$remove(vm); - }; - - // helpers - - /** - * Augment an target Object or Array by intercepting - * the prototype chain using __proto__ - * - * @param {Object|Array} target - * @param {Object} src - */ - - function protoAugment(target, src) { - /* eslint-disable no-proto */ - target.__proto__ = src; - /* eslint-enable no-proto */ - } - - /** - * Augment an target Object or Array by defining - * hidden properties. - * - * @param {Object|Array} target - * @param {Object} proto - */ - - function copyAugment(target, src, keys) { - for (var i = 0, l = keys.length; i < l; i++) { - var key = keys[i]; - def(target, key, src[key]); - } - } - - /** - * Attempt to create an observer instance for a value, - * returns the new observer if successfully observed, - * or the existing observer if the value already has one. - * - * @param {*} value - * @param {Vue} [vm] - * @return {Observer|undefined} - * @static - */ - - function observe(value, vm) { - if (!value || typeof value !== 'object') { - return; - } - var ob; - if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { - ob = value.__ob__; - } else if (shouldConvert && (isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue) { - ob = new Observer(value); - } - if (ob && vm) { - ob.addVm(vm); - } - return ob; - } - - /** - * Define a reactive property on an Object. - * - * @param {Object} obj - * @param {String} key - * @param {*} val - */ - - function defineReactive(obj, key, val) { - var dep = new Dep(); - - var property = Object.getOwnPropertyDescriptor(obj, key); - if (property && property.configurable === false) { - return; - } - - // cater for pre-defined getter/setters - var getter = property && property.get; - var setter = property && property.set; - - var childOb = observe(val); - Object.defineProperty(obj, key, { - enumerable: true, - configurable: true, - get: function reactiveGetter() { - var value = getter ? getter.call(obj) : val; - if (Dep.target) { - dep.depend(); - if (childOb) { - childOb.dep.depend(); - } - if (isArray(value)) { - for (var e, i = 0, l = value.length; i < l; i++) { - e = value[i]; - e && e.__ob__ && e.__ob__.dep.depend(); - } - } - } - return value; - }, - set: function reactiveSetter(newVal) { - var value = getter ? getter.call(obj) : val; - if (newVal === value) { - return; - } - if (setter) { - setter.call(obj, newVal); - } else { - val = newVal; - } - childOb = observe(newVal); - dep.notify(); - } - }); - } - - - - var util = Object.freeze({ - defineReactive: defineReactive, - set: set, - del: del, - hasOwn: hasOwn, - isLiteral: isLiteral, - isReserved: isReserved, - _toString: _toString, - toNumber: toNumber, - toBoolean: toBoolean, - stripQuotes: stripQuotes, - camelize: camelize, - hyphenate: hyphenate, - classify: classify, - bind: bind, - toArray: toArray, - extend: extend, - isObject: isObject, - isPlainObject: isPlainObject, - def: def, - debounce: _debounce, - indexOf: indexOf, - cancellable: cancellable, - looseEqual: looseEqual, - isArray: isArray, - hasProto: hasProto, - inBrowser: inBrowser, - devtools: devtools, - isIE: isIE, - isIE9: isIE9, - isAndroid: isAndroid, - isIos: isIos, - iosVersionMatch: iosVersionMatch, - iosVersion: iosVersion, - hasMutationObserverBug: hasMutationObserverBug, - get transitionProp () { return transitionProp; }, - get transitionEndEvent () { return transitionEndEvent; }, - get animationProp () { return animationProp; }, - get animationEndEvent () { return animationEndEvent; }, - nextTick: nextTick, - get _Set () { return _Set; }, - query: query, - inDoc: inDoc, - getAttr: getAttr, - getBindAttr: getBindAttr, - hasBindAttr: hasBindAttr, - before: before, - after: after, - remove: remove, - prepend: prepend, - replace: replace, - on: on, - off: off, - setClass: setClass, - addClass: addClass, - removeClass: removeClass, - extractContent: extractContent, - trimNode: trimNode, - isTemplate: isTemplate, - createAnchor: createAnchor, - findRef: findRef, - mapNodeRange: mapNodeRange, - removeNodeRange: removeNodeRange, - isFragment: isFragment, - getOuterHTML: getOuterHTML, - mergeOptions: mergeOptions, - resolveAsset: resolveAsset, - checkComponentAttr: checkComponentAttr, - commonTagRE: commonTagRE, - reservedTagRE: reservedTagRE, - get warn () { return warn; } - }); - - var uid = 0; - - function initMixin (Vue) { - /** - * The main init sequence. This is called for every - * instance, including ones that are created from extended - * constructors. - * - * @param {Object} options - this options object should be - * the result of merging class - * options and the options passed - * in to the constructor. - */ - - Vue.prototype._init = function (options) { - options = options || {}; - - this.$el = null; - this.$parent = options.parent; - this.$root = this.$parent ? this.$parent.$root : this; - this.$children = []; - this.$refs = {}; // child vm references - this.$els = {}; // element references - this._watchers = []; // all watchers as an array - this._directives = []; // all directives - - // a uid - this._uid = uid++; - - // a flag to avoid this being observed - this._isVue = true; - - // events bookkeeping - this._events = {}; // registered callbacks - this._eventsCount = {}; // for $broadcast optimization - - // fragment instance properties - this._isFragment = false; - this._fragment = // @type {DocumentFragment} - this._fragmentStart = // @type {Text|Comment} - this._fragmentEnd = null; // @type {Text|Comment} - - // lifecycle state - this._isCompiled = this._isDestroyed = this._isReady = this._isAttached = this._isBeingDestroyed = this._vForRemoving = false; - this._unlinkFn = null; - - // context: - // if this is a transcluded component, context - // will be the common parent vm of this instance - // and its host. - this._context = options._context || this.$parent; - - // scope: - // if this is inside an inline v-for, the scope - // will be the intermediate scope created for this - // repeat fragment. this is used for linking props - // and container directives. - this._scope = options._scope; - - // fragment: - // if this instance is compiled inside a Fragment, it - // needs to reigster itself as a child of that fragment - // for attach/detach to work properly. - this._frag = options._frag; - if (this._frag) { - this._frag.children.push(this); - } - - // push self into parent / transclusion host - if (this.$parent) { - this.$parent.$children.push(this); - } - - // merge options. - options = this.$options = mergeOptions(this.constructor.options, options, this); - - // set ref - this._updateRef(); - - // initialize data as empty object. - // it will be filled up in _initData(). - this._data = {}; - - // call init hook - this._callHook('init'); - - // initialize data observation and scope inheritance. - this._initState(); - - // setup event system and option events. - this._initEvents(); - - // call created hook - this._callHook('created'); - - // if `el` option is passed, start compilation. - if (options.el) { - this.$mount(options.el); - } - }; - } - - var pathCache = new Cache(1000); - - // actions - var APPEND = 0; - var PUSH = 1; - var INC_SUB_PATH_DEPTH = 2; - var PUSH_SUB_PATH = 3; - - // states - var BEFORE_PATH = 0; - var IN_PATH = 1; - var BEFORE_IDENT = 2; - var IN_IDENT = 3; - var IN_SUB_PATH = 4; - var IN_SINGLE_QUOTE = 5; - var IN_DOUBLE_QUOTE = 6; - var AFTER_PATH = 7; - var ERROR = 8; - - var pathStateMachine = []; - - pathStateMachine[BEFORE_PATH] = { - 'ws': [BEFORE_PATH], - 'ident': [IN_IDENT, APPEND], - '[': [IN_SUB_PATH], - 'eof': [AFTER_PATH] - }; - - pathStateMachine[IN_PATH] = { - 'ws': [IN_PATH], - '.': [BEFORE_IDENT], - '[': [IN_SUB_PATH], - 'eof': [AFTER_PATH] - }; - - pathStateMachine[BEFORE_IDENT] = { - 'ws': [BEFORE_IDENT], - 'ident': [IN_IDENT, APPEND] - }; - - pathStateMachine[IN_IDENT] = { - 'ident': [IN_IDENT, APPEND], - '0': [IN_IDENT, APPEND], - 'number': [IN_IDENT, APPEND], - 'ws': [IN_PATH, PUSH], - '.': [BEFORE_IDENT, PUSH], - '[': [IN_SUB_PATH, PUSH], - 'eof': [AFTER_PATH, PUSH] - }; - - pathStateMachine[IN_SUB_PATH] = { - "'": [IN_SINGLE_QUOTE, APPEND], - '"': [IN_DOUBLE_QUOTE, APPEND], - '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH], - ']': [IN_PATH, PUSH_SUB_PATH], - 'eof': ERROR, - 'else': [IN_SUB_PATH, APPEND] - }; - - pathStateMachine[IN_SINGLE_QUOTE] = { - "'": [IN_SUB_PATH, APPEND], - 'eof': ERROR, - 'else': [IN_SINGLE_QUOTE, APPEND] - }; - - pathStateMachine[IN_DOUBLE_QUOTE] = { - '"': [IN_SUB_PATH, APPEND], - 'eof': ERROR, - 'else': [IN_DOUBLE_QUOTE, APPEND] - }; - - /** - * Determine the type of a character in a keypath. - * - * @param {Char} ch - * @return {String} type - */ - - function getPathCharType(ch) { - if (ch === undefined) { - return 'eof'; - } - - var code = ch.charCodeAt(0); - - switch (code) { - case 0x5B: // [ - case 0x5D: // ] - case 0x2E: // . - case 0x22: // " - case 0x27: // ' - case 0x30: - // 0 - return ch; - - case 0x5F: // _ - case 0x24: - // $ - return 'ident'; - - case 0x20: // Space - case 0x09: // Tab - case 0x0A: // Newline - case 0x0D: // Return - case 0xA0: // No-break space - case 0xFEFF: // Byte Order Mark - case 0x2028: // Line Separator - case 0x2029: - // Paragraph Separator - return 'ws'; - } - - // a-z, A-Z - if (code >= 0x61 && code <= 0x7A || code >= 0x41 && code <= 0x5A) { - return 'ident'; - } - - // 1-9 - if (code >= 0x31 && code <= 0x39) { - return 'number'; - } - - return 'else'; - } - - /** - * Format a subPath, return its plain form if it is - * a literal string or number. Otherwise prepend the - * dynamic indicator (*). - * - * @param {String} path - * @return {String} - */ - - function formatSubPath(path) { - var trimmed = path.trim(); - // invalid leading 0 - if (path.charAt(0) === '0' && isNaN(path)) { - return false; - } - return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed; - } - - /** - * Parse a string path into an array of segments - * - * @param {String} path - * @return {Array|undefined} - */ - - function parse(path) { - var keys = []; - var index = -1; - var mode = BEFORE_PATH; - var subPathDepth = 0; - var c, newChar, key, type, transition, action, typeMap; - - var actions = []; - - actions[PUSH] = function () { - if (key !== undefined) { - keys.push(key); - key = undefined; - } - }; - - actions[APPEND] = function () { - if (key === undefined) { - key = newChar; - } else { - key += newChar; - } - }; - - actions[INC_SUB_PATH_DEPTH] = function () { - actions[APPEND](); - subPathDepth++; - }; - - actions[PUSH_SUB_PATH] = function () { - if (subPathDepth > 0) { - subPathDepth--; - mode = IN_SUB_PATH; - actions[APPEND](); - } else { - subPathDepth = 0; - key = formatSubPath(key); - if (key === false) { - return false; - } else { - actions[PUSH](); - } - } - }; - - function maybeUnescapeQuote() { - var nextChar = path[index + 1]; - if (mode === IN_SINGLE_QUOTE && nextChar === "'" || mode === IN_DOUBLE_QUOTE && nextChar === '"') { - index++; - newChar = '\\' + nextChar; - actions[APPEND](); - return true; - } - } - - while (mode != null) { - index++; - c = path[index]; - - if (c === '\\' && maybeUnescapeQuote()) { - continue; - } - - type = getPathCharType(c); - typeMap = pathStateMachine[mode]; - transition = typeMap[type] || typeMap['else'] || ERROR; - - if (transition === ERROR) { - return; // parse error - } - - mode = transition[0]; - action = actions[transition[1]]; - if (action) { - newChar = transition[2]; - newChar = newChar === undefined ? c : newChar; - if (action() === false) { - return; - } - } - - if (mode === AFTER_PATH) { - keys.raw = path; - return keys; - } - } - } - - /** - * External parse that check for a cache hit first - * - * @param {String} path - * @return {Array|undefined} - */ - - function parsePath(path) { - var hit = pathCache.get(path); - if (!hit) { - hit = parse(path); - if (hit) { - pathCache.put(path, hit); - } - } - return hit; - } - - /** - * Get from an object from a path string - * - * @param {Object} obj - * @param {String} path - */ - - function getPath(obj, path) { - return parseExpression(path).get(obj); - } - - /** - * Warn against setting non-existent root path on a vm. - */ - - var warnNonExistent; - if (true) { - warnNonExistent = function (path, vm) { - warn('You are setting a non-existent path "' + path.raw + '" ' + 'on a vm instance. Consider pre-initializing the property ' + 'with the "data" option for more reliable reactivity ' + 'and better performance.', vm); - }; - } - - /** - * Set on an object from a path - * - * @param {Object} obj - * @param {String | Array} path - * @param {*} val - */ - - function setPath(obj, path, val) { - var original = obj; - if (typeof path === 'string') { - path = parse(path); - } - if (!path || !isObject(obj)) { - return false; - } - var last, key; - for (var i = 0, l = path.length; i < l; i++) { - last = obj; - key = path[i]; - if (key.charAt(0) === '*') { - key = parseExpression(key.slice(1)).get.call(original, original); - } - if (i < l - 1) { - obj = obj[key]; - if (!isObject(obj)) { - obj = {}; - if ('development' !== 'production' && last._isVue) { - warnNonExistent(path, last); - } - set(last, key, obj); - } - } else { - if (isArray(obj)) { - obj.$set(key, val); - } else if (key in obj) { - obj[key] = val; - } else { - if ('development' !== 'production' && obj._isVue) { - warnNonExistent(path, obj); - } - set(obj, key, val); - } - } - } - return true; - } - - var path = Object.freeze({ - parsePath: parsePath, - getPath: getPath, - setPath: setPath - }); - - var expressionCache = new Cache(1000); - - var allowedKeywords = 'Math,Date,this,true,false,null,undefined,Infinity,NaN,' + 'isNaN,isFinite,decodeURI,decodeURIComponent,encodeURI,' + 'encodeURIComponent,parseInt,parseFloat'; - var allowedKeywordsRE = new RegExp('^(' + allowedKeywords.replace(/,/g, '\\b|') + '\\b)'); - - // keywords that don't make sense inside expressions - var improperKeywords = 'break,case,class,catch,const,continue,debugger,default,' + 'delete,do,else,export,extends,finally,for,function,if,' + 'import,in,instanceof,let,return,super,switch,throw,try,' + 'var,while,with,yield,enum,await,implements,package,' + 'protected,static,interface,private,public'; - var improperKeywordsRE = new RegExp('^(' + improperKeywords.replace(/,/g, '\\b|') + '\\b)'); - - var wsRE = /\s/g; - var newlineRE = /\n/g; - var saveRE = /[\{,]\s*[\w\$_]+\s*:|('(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`)|new |typeof |void /g; - var restoreRE = /"(\d+)"/g; - var pathTestRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/; - var identRE = /[^\w$\.](?:[A-Za-z_$][\w$]*)/g; - var literalValueRE$1 = /^(?:true|false|null|undefined|Infinity|NaN)$/; - - function noop() {} - - /** - * Save / Rewrite / Restore - * - * When rewriting paths found in an expression, it is - * possible for the same letter sequences to be found in - * strings and Object literal property keys. Therefore we - * remove and store these parts in a temporary array, and - * restore them after the path rewrite. - */ - - var saved = []; - - /** - * Save replacer - * - * The save regex can match two possible cases: - * 1. An opening object literal - * 2. A string - * If matched as a plain string, we need to escape its - * newlines, since the string needs to be preserved when - * generating the function body. - * - * @param {String} str - * @param {String} isString - str if matched as a string - * @return {String} - placeholder with index - */ - - function save(str, isString) { - var i = saved.length; - saved[i] = isString ? str.replace(newlineRE, '\\n') : str; - return '"' + i + '"'; - } - - /** - * Path rewrite replacer - * - * @param {String} raw - * @return {String} - */ - - function rewrite(raw) { - var c = raw.charAt(0); - var path = raw.slice(1); - if (allowedKeywordsRE.test(path)) { - return raw; - } else { - path = path.indexOf('"') > -1 ? path.replace(restoreRE, restore) : path; - return c + 'scope.' + path; - } - } - - /** - * Restore replacer - * - * @param {String} str - * @param {String} i - matched save index - * @return {String} - */ - - function restore(str, i) { - return saved[i]; - } - - /** - * Rewrite an expression, prefixing all path accessors with - * `scope.` and generate getter/setter functions. - * - * @param {String} exp - * @return {Function} - */ - - function compileGetter(exp) { - if (improperKeywordsRE.test(exp)) { - 'development' !== 'production' && warn('Avoid using reserved keywords in expression: ' + exp); - } - // reset state - saved.length = 0; - // save strings and object literal keys - var body = exp.replace(saveRE, save).replace(wsRE, ''); - // rewrite all paths - // pad 1 space here because the regex matches 1 extra char - body = (' ' + body).replace(identRE, rewrite).replace(restoreRE, restore); - return makeGetterFn(body); - } - - /** - * Build a getter function. Requires eval. - * - * We isolate the try/catch so it doesn't affect the - * optimization of the parse function when it is not called. - * - * @param {String} body - * @return {Function|undefined} - */ - - function makeGetterFn(body) { - try { - /* eslint-disable no-new-func */ - return new Function('scope', 'return ' + body + ';'); - /* eslint-enable no-new-func */ - } catch (e) { - if (true) { - /* istanbul ignore if */ - if (e.toString().match(/unsafe-eval|CSP/)) { - warn('It seems you are using the default build of Vue.js in an environment ' + 'with Content Security Policy that prohibits unsafe-eval. ' + 'Use the CSP-compliant build instead: ' + 'http://vuejs.org/guide/installation.html#CSP-compliant-build'); - } else { - warn('Invalid expression. ' + 'Generated function body: ' + body); - } - } - return noop; - } - } - - /** - * Compile a setter function for the expression. - * - * @param {String} exp - * @return {Function|undefined} - */ - - function compileSetter(exp) { - var path = parsePath(exp); - if (path) { - return function (scope, val) { - setPath(scope, path, val); - }; - } else { - 'development' !== 'production' && warn('Invalid setter expression: ' + exp); - } - } - - /** - * Parse an expression into re-written getter/setters. - * - * @param {String} exp - * @param {Boolean} needSet - * @return {Function} - */ - - function parseExpression(exp, needSet) { - exp = exp.trim(); - // try cache - var hit = expressionCache.get(exp); - if (hit) { - if (needSet && !hit.set) { - hit.set = compileSetter(hit.exp); - } - return hit; - } - var res = { exp: exp }; - res.get = isSimplePath(exp) && exp.indexOf('[') < 0 - // optimized super simple getter - ? makeGetterFn('scope.' + exp) - // dynamic getter - : compileGetter(exp); - if (needSet) { - res.set = compileSetter(exp); - } - expressionCache.put(exp, res); - return res; - } - - /** - * Check if an expression is a simple path. - * - * @param {String} exp - * @return {Boolean} - */ - - function isSimplePath(exp) { - return pathTestRE.test(exp) && - // don't treat literal values as paths - !literalValueRE$1.test(exp) && - // Math constants e.g. Math.PI, Math.E etc. - exp.slice(0, 5) !== 'Math.'; - } - - var expression = Object.freeze({ - parseExpression: parseExpression, - isSimplePath: isSimplePath - }); - - // we have two separate queues: one for directive updates - // and one for user watcher registered via $watch(). - // we want to guarantee directive updates to be called - // before user watchers so that when user watchers are - // triggered, the DOM would have already been in updated - // state. - - var queue = []; - var userQueue = []; - var has = {}; - var circular = {}; - var waiting = false; - - /** - * Reset the batcher's state. - */ - - function resetBatcherState() { - queue.length = 0; - userQueue.length = 0; - has = {}; - circular = {}; - waiting = false; - } - - /** - * Flush both queues and run the watchers. - */ - - function flushBatcherQueue() { - var _again = true; - - _function: while (_again) { - _again = false; - - runBatcherQueue(queue); - runBatcherQueue(userQueue); - // user watchers triggered more watchers, - // keep flushing until it depletes - if (queue.length) { - _again = true; - continue _function; - } - // dev tool hook - /* istanbul ignore if */ - if (devtools && config.devtools) { - devtools.emit('flush'); - } - resetBatcherState(); - } - } - - /** - * Run the watchers in a single queue. - * - * @param {Array} queue - */ - - function runBatcherQueue(queue) { - // do not cache length because more watchers might be pushed - // as we run existing watchers - for (var i = 0; i < queue.length; i++) { - var watcher = queue[i]; - var id = watcher.id; - has[id] = null; - watcher.run(); - // in dev build, check and stop circular updates. - if ('development' !== 'production' && has[id] != null) { - circular[id] = (circular[id] || 0) + 1; - if (circular[id] > config._maxUpdateCount) { - warn('You may have an infinite update loop for watcher ' + 'with expression "' + watcher.expression + '"', watcher.vm); - break; - } - } - } - queue.length = 0; - } - - /** - * Push a watcher into the watcher queue. - * Jobs with duplicate IDs will be skipped unless it's - * pushed when the queue is being flushed. - * - * @param {Watcher} watcher - * properties: - * - {Number} id - * - {Function} run - */ - - function pushWatcher(watcher) { - var id = watcher.id; - if (has[id] == null) { - // push watcher into appropriate queue - var q = watcher.user ? userQueue : queue; - has[id] = q.length; - q.push(watcher); - // queue the flush - if (!waiting) { - waiting = true; - nextTick(flushBatcherQueue); - } - } - } - - var uid$2 = 0; - - /** - * A watcher parses an expression, collects dependencies, - * and fires callback when the expression value changes. - * This is used for both the $watch() api and directives. - * - * @param {Vue} vm - * @param {String|Function} expOrFn - * @param {Function} cb - * @param {Object} options - * - {Array} filters - * - {Boolean} twoWay - * - {Boolean} deep - * - {Boolean} user - * - {Boolean} sync - * - {Boolean} lazy - * - {Function} [preProcess] - * - {Function} [postProcess] - * @constructor - */ - function Watcher(vm, expOrFn, cb, options) { - // mix in options - if (options) { - extend(this, options); - } - var isFn = typeof expOrFn === 'function'; - this.vm = vm; - vm._watchers.push(this); - this.expression = expOrFn; - this.cb = cb; - this.id = ++uid$2; // uid for batching - this.active = true; - this.dirty = this.lazy; // for lazy watchers - this.deps = []; - this.newDeps = []; - this.depIds = new _Set(); - this.newDepIds = new _Set(); - this.prevError = null; // for async error stacks - // parse expression for getter/setter - if (isFn) { - this.getter = expOrFn; - this.setter = undefined; - } else { - var res = parseExpression(expOrFn, this.twoWay); - this.getter = res.get; - this.setter = res.set; - } - this.value = this.lazy ? undefined : this.get(); - // state for avoiding false triggers for deep and Array - // watchers during vm._digest() - this.queued = this.shallow = false; - } - - /** - * Evaluate the getter, and re-collect dependencies. - */ - - Watcher.prototype.get = function () { - this.beforeGet(); - var scope = this.scope || this.vm; - var value; - try { - value = this.getter.call(scope, scope); - } catch (e) { - if ('development' !== 'production' && config.warnExpressionErrors) { - warn('Error when evaluating expression ' + '"' + this.expression + '": ' + e.toString(), this.vm); - } - } - // "touch" every property so they are all tracked as - // dependencies for deep watching - if (this.deep) { - traverse(value); - } - if (this.preProcess) { - value = this.preProcess(value); - } - if (this.filters) { - value = scope._applyFilters(value, null, this.filters, false); - } - if (this.postProcess) { - value = this.postProcess(value); - } - this.afterGet(); - return value; - }; - - /** - * Set the corresponding value with the setter. - * - * @param {*} value - */ - - Watcher.prototype.set = function (value) { - var scope = this.scope || this.vm; - if (this.filters) { - value = scope._applyFilters(value, this.value, this.filters, true); - } - try { - this.setter.call(scope, scope, value); - } catch (e) { - if ('development' !== 'production' && config.warnExpressionErrors) { - warn('Error when evaluating setter ' + '"' + this.expression + '": ' + e.toString(), this.vm); - } - } - // two-way sync for v-for alias - var forContext = scope.$forContext; - if (forContext && forContext.alias === this.expression) { - if (forContext.filters) { - 'development' !== 'production' && warn('It seems you are using two-way binding on ' + 'a v-for alias (' + this.expression + '), and the ' + 'v-for has filters. This will not work properly. ' + 'Either remove the filters or use an array of ' + 'objects and bind to object properties instead.', this.vm); - return; - } - forContext._withLock(function () { - if (scope.$key) { - // original is an object - forContext.rawValue[scope.$key] = value; - } else { - forContext.rawValue.$set(scope.$index, value); - } - }); - } - }; - - /** - * Prepare for dependency collection. - */ - - Watcher.prototype.beforeGet = function () { - Dep.target = this; - }; - - /** - * Add a dependency to this directive. - * - * @param {Dep} dep - */ - - Watcher.prototype.addDep = function (dep) { - var id = dep.id; - if (!this.newDepIds.has(id)) { - this.newDepIds.add(id); - this.newDeps.push(dep); - if (!this.depIds.has(id)) { - dep.addSub(this); - } - } - }; - - /** - * Clean up for dependency collection. - */ - - Watcher.prototype.afterGet = function () { - Dep.target = null; - var i = this.deps.length; - while (i--) { - var dep = this.deps[i]; - if (!this.newDepIds.has(dep.id)) { - dep.removeSub(this); - } - } - var tmp = this.depIds; - this.depIds = this.newDepIds; - this.newDepIds = tmp; - this.newDepIds.clear(); - tmp = this.deps; - this.deps = this.newDeps; - this.newDeps = tmp; - this.newDeps.length = 0; - }; - - /** - * Subscriber interface. - * Will be called when a dependency changes. - * - * @param {Boolean} shallow - */ - - Watcher.prototype.update = function (shallow) { - if (this.lazy) { - this.dirty = true; - } else if (this.sync || !config.async) { - this.run(); - } else { - // if queued, only overwrite shallow with non-shallow, - // but not the other way around. - this.shallow = this.queued ? shallow ? this.shallow : false : !!shallow; - this.queued = true; - // record before-push error stack in debug mode - /* istanbul ignore if */ - if ('development' !== 'production' && config.debug) { - this.prevError = new Error('[vue] async stack trace'); - } - pushWatcher(this); - } - }; - - /** - * Batcher job interface. - * Will be called by the batcher. - */ - - Watcher.prototype.run = function () { - if (this.active) { - var value = this.get(); - if (value !== this.value || - // Deep watchers and watchers on Object/Arrays should fire even - // when the value is the same, because the value may - // have mutated; but only do so if this is a - // non-shallow update (caused by a vm digest). - (isObject(value) || this.deep) && !this.shallow) { - // set new value - var oldValue = this.value; - this.value = value; - // in debug + async mode, when a watcher callbacks - // throws, we also throw the saved before-push error - // so the full cross-tick stack trace is available. - var prevError = this.prevError; - /* istanbul ignore if */ - if ('development' !== 'production' && config.debug && prevError) { - this.prevError = null; - try { - this.cb.call(this.vm, value, oldValue); - } catch (e) { - nextTick(function () { - throw prevError; - }, 0); - throw e; - } - } else { - this.cb.call(this.vm, value, oldValue); - } - } - this.queued = this.shallow = false; - } - }; - - /** - * Evaluate the value of the watcher. - * This only gets called for lazy watchers. - */ - - Watcher.prototype.evaluate = function () { - // avoid overwriting another watcher that is being - // collected. - var current = Dep.target; - this.value = this.get(); - this.dirty = false; - Dep.target = current; - }; - - /** - * Depend on all deps collected by this watcher. - */ - - Watcher.prototype.depend = function () { - var i = this.deps.length; - while (i--) { - this.deps[i].depend(); - } - }; - - /** - * Remove self from all dependencies' subcriber list. - */ - - Watcher.prototype.teardown = function () { - if (this.active) { - // remove self from vm's watcher list - // this is a somewhat expensive operation so we skip it - // if the vm is being destroyed or is performing a v-for - // re-render (the watcher list is then filtered by v-for). - if (!this.vm._isBeingDestroyed && !this.vm._vForRemoving) { - this.vm._watchers.$remove(this); - } - var i = this.deps.length; - while (i--) { - this.deps[i].removeSub(this); - } - this.active = false; - this.vm = this.cb = this.value = null; - } - }; - - /** - * Recrusively traverse an object to evoke all converted - * getters, so that every nested property inside the object - * is collected as a "deep" dependency. - * - * @param {*} val - */ - - var seenObjects = new _Set(); - function traverse(val, seen) { - var i = undefined, - keys = undefined; - if (!seen) { - seen = seenObjects; - seen.clear(); - } - var isA = isArray(val); - var isO = isObject(val); - if ((isA || isO) && Object.isExtensible(val)) { - if (val.__ob__) { - var depId = val.__ob__.dep.id; - if (seen.has(depId)) { - return; - } else { - seen.add(depId); - } - } - if (isA) { - i = val.length; - while (i--) traverse(val[i], seen); - } else if (isO) { - keys = Object.keys(val); - i = keys.length; - while (i--) traverse(val[keys[i]], seen); - } - } - } - - var text$1 = { - - bind: function bind() { - this.attr = this.el.nodeType === 3 ? 'data' : 'textContent'; - }, - - update: function update(value) { - this.el[this.attr] = _toString(value); - } - }; - - var templateCache = new Cache(1000); - var idSelectorCache = new Cache(1000); - - var map = { - efault: [0, '', ''], - legend: [1, '
', '
'], - tr: [2, '', '
'], - col: [2, '', '
'] - }; - - map.td = map.th = [3, '', '
']; - - map.option = map.optgroup = [1, '']; - - map.thead = map.tbody = map.colgroup = map.caption = map.tfoot = [1, '', '
']; - - map.g = map.defs = map.symbol = map.use = map.image = map.text = map.circle = map.ellipse = map.line = map.path = map.polygon = map.polyline = map.rect = [1, '', '']; - - /** - * Check if a node is a supported template node with a - * DocumentFragment content. - * - * @param {Node} node - * @return {Boolean} - */ - - function isRealTemplate(node) { - return isTemplate(node) && isFragment(node.content); - } - - var tagRE$1 = /<([\w:-]+)/; - var entityRE = /&#?\w+?;/; - var commentRE = /'); + + if (commentEnd >= 0) { + advance(commentEnd + 3); + continue + } + } - Vue.prototype._initEvents = function () { - var options = this.$options; - if (options._asComponent) { - registerComponentEvents(this, options.el); - } - registerCallbacks(this, '$on', options.events); - registerCallbacks(this, '$watch', options.watch); - }; + // http://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment + if (conditionalComment.test(html)) { + var conditionalEnd = html.indexOf(']>'); - /** - * Register v-on events on a child component - * - * @param {Vue} vm - * @param {Element} el - */ - - function registerComponentEvents(vm, el) { - var attrs = el.attributes; - var name, value, handler; - for (var i = 0, l = attrs.length; i < l; i++) { - name = attrs[i].name; - if (eventRE.test(name)) { - name = name.replace(eventRE, ''); - // force the expression into a statement so that - // it always dynamically resolves the method to call (#2670) - // kinda ugly hack, but does the job. - value = attrs[i].value; - if (isSimplePath(value)) { - value += '.apply(this, $arguments)'; + if (conditionalEnd >= 0) { + advance(conditionalEnd + 2); + continue } - handler = (vm._scope || vm._context).$eval(value, true); - handler._fromParent = true; - vm.$on(name.replace(eventRE), handler); } - } - } - /** - * Register callbacks for option events and watchers. - * - * @param {Vue} vm - * @param {String} action - * @param {Object} hash - */ + // Doctype: + var doctypeMatch = html.match(doctype); + if (doctypeMatch) { + advance(doctypeMatch[0].length); + continue + } - function registerCallbacks(vm, action, hash) { - if (!hash) return; - var handlers, key, i, j; - for (key in hash) { - handlers = hash[key]; - if (isArray(handlers)) { - for (i = 0, j = handlers.length; i < j; i++) { - register(vm, action, key, handlers[i]); - } - } else { - register(vm, action, key, handlers); + // End tag: + var endTagMatch = html.match(endTag); + if (endTagMatch) { + var curIndex = index; + advance(endTagMatch[0].length); + parseEndTag(endTagMatch[0], endTagMatch[1], curIndex, index); + continue + } + + // Start tag: + var startTagMatch = parseStartTag(); + if (startTagMatch) { + handleStartTag(startTagMatch); + continue } } - } - /** - * Helper to register an event/watch callback. - * - * @param {Vue} vm - * @param {String} action - * @param {String} key - * @param {Function|String|Object} handler - * @param {Object} [options] - */ - - function register(vm, action, key, handler, options) { - var type = typeof handler; - if (type === 'function') { - vm[action](key, handler, options); - } else if (type === 'string') { - var methods = vm.$options.methods; - var method = methods && methods[handler]; - if (method) { - vm[action](key, method, options); - } else { - 'development' !== 'production' && warn('Unknown method: "' + handler + '" when ' + 'registering callback for ' + action + ': "' + key + '".', vm); + var text = (void 0), rest$1 = (void 0), next = (void 0); + if (textEnd > 0) { + rest$1 = html.slice(textEnd); + while ( + !endTag.test(rest$1) && + !startTagOpen.test(rest$1) && + !comment.test(rest$1) && + !conditionalComment.test(rest$1) + ) { + // < in plain text, be forgiving and treat it as text + next = rest$1.indexOf('<', 1); + if (next < 0) { break } + textEnd += next; + rest$1 = html.slice(textEnd); } - } else if (handler && type === 'object') { - register(vm, action, key, handler.handler, handler); + text = html.substring(0, textEnd); + advance(textEnd); + } + + if (textEnd < 0) { + text = html; + html = ''; + } + + if (options.chars && text) { + options.chars(text); } + } else { + var stackedTag = lastTag.toLowerCase(); + var reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\s\\S]*?)(]*>)', 'i')); + var endTagLength = 0; + var rest = html.replace(reStackedTag, function (all, text, endTag) { + endTagLength = endTag.length; + if (stackedTag !== 'script' && stackedTag !== 'style' && stackedTag !== 'noscript') { + text = text + .replace(//g, '$1') + .replace(//g, '$1'); + } + if (options.chars) { + options.chars(text); + } + return '' + }); + index += html.length - rest.length; + html = rest; + parseEndTag('', stackedTag, index - endTagLength, index); } - /** - * Setup recursive attached/detached calls - */ + if (html === last && options.chars) { + options.chars(html); + break + } + } - Vue.prototype._initDOMHooks = function () { - this.$on('hook:attached', onAttached); - this.$on('hook:detached', onDetached); - }; + // Clean up any remaining tags + parseEndTag(); - /** - * Callback to recursively call attached hook on children - */ + function advance (n) { + index += n; + html = html.substring(n); + } - function onAttached() { - if (!this._isAttached) { - this._isAttached = true; - this.$children.forEach(callAttach); + function parseStartTag () { + var start = html.match(startTagOpen); + if (start) { + var match = { + tagName: start[1], + attrs: [], + start: index + }; + advance(start[0].length); + var end, attr; + while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) { + advance(attr[0].length); + match.attrs.push(attr); + } + if (end) { + match.unarySlash = end[1]; + advance(end[0].length); + match.end = index; + return match } } + } - /** - * Iterator to call attached hook - * - * @param {Vue} child - */ + function handleStartTag (match) { + var tagName = match.tagName; + var unarySlash = match.unarySlash; - function callAttach(child) { - if (!child._isAttached && inDoc(child.$el)) { - child._callHook('attached'); + if (expectHTML) { + if (lastTag === 'p' && isNonPhrasingTag(tagName)) { + parseEndTag('', lastTag); + } + if (canBeLeftOpenTag(tagName) && lastTag === tagName) { + parseEndTag('', tagName); } } - /** - * Callback to recursively call detached hook on children - */ + var unary = isUnaryTag$$1(tagName) || tagName === 'html' && lastTag === 'head' || !!unarySlash; - function onDetached() { - if (this._isAttached) { - this._isAttached = false; - this.$children.forEach(callDetach); + var l = match.attrs.length; + var attrs = new Array(l); + for (var i = 0; i < l; i++) { + var args = match.attrs[i]; + // hackish work around FF bug https://bugzilla.mozilla.org/show_bug.cgi?id=369778 + if (IS_REGEX_CAPTURING_BROKEN && args[0].indexOf('""') === -1) { + if (args[3] === '') { delete args[3]; } + if (args[4] === '') { delete args[4]; } + if (args[5] === '') { delete args[5]; } } + var value = args[3] || args[4] || args[5] || ''; + attrs[i] = { + name: args[1], + value: decodeAttr( + value, + options.shouldDecodeNewlines + ) + }; } - /** - * Iterator to call detached hook - * - * @param {Vue} child - */ + if (!unary) { + stack.push({ tag: tagName, attrs: attrs }); + lastTag = tagName; + unarySlash = ''; + } - function callDetach(child) { - if (child._isAttached && !inDoc(child.$el)) { - child._callHook('detached'); - } + if (options.start) { + options.start(tagName, attrs, unary, match.start, match.end); } + } - /** - * Trigger all handlers for a hook - * - * @param {String} hook - */ + function parseEndTag (tag, tagName, start, end) { + var pos; + if (start == null) { start = index; } + if (end == null) { end = index; } - Vue.prototype._callHook = function (hook) { - this.$emit('pre-hook:' + hook); - var handlers = this.$options[hook]; - if (handlers) { - for (var i = 0, j = handlers.length; i < j; i++) { - handlers[i].call(this); + // Find the closest opened tag of the same type + if (tagName) { + var needle = tagName.toLowerCase(); + for (pos = stack.length - 1; pos >= 0; pos--) { + if (stack[pos].tag.toLowerCase() === needle) { + break } } - this.$emit('hook:' + hook); - }; + } else { + // If no tag name is provided, clean shop + pos = 0; + } + + if (pos >= 0) { + // Close all the open elements, up the stack + for (var i = stack.length - 1; i >= pos; i--) { + if (options.end) { + options.end(stack[i].tag, start, end); + } + } + + // Remove the open elements from the stack + stack.length = pos; + lastTag = pos && stack[pos - 1].tag; + } else if (tagName.toLowerCase() === 'br') { + if (options.start) { + options.start(tagName, [], true, start, end); + } + } else if (tagName.toLowerCase() === 'p') { + if (options.start) { + options.start(tagName, [], false, start, end); + } + if (options.end) { + options.end(tagName, start, end); + } + } + } + } + + /* */ + + function parseFilters (exp) { + var inSingle = false; + var inDouble = false; + var inTemplateString = false; + var inRegex = false; + var curly = 0; + var square = 0; + var paren = 0; + var lastFilterIndex = 0; + var c, prev, i, expression, filters; + + for (i = 0; i < exp.length; i++) { + prev = c; + c = exp.charCodeAt(i); + if (inSingle) { + if (c === 0x27 && prev !== 0x5C) { inSingle = false; } + } else if (inDouble) { + if (c === 0x22 && prev !== 0x5C) { inDouble = false; } + } else if (inTemplateString) { + if (c === 0x60 && prev !== 0x5C) { inTemplateString = false; } + } else if (inRegex) { + if (c === 0x2f && prev !== 0x5C) { inRegex = false; } + } else if ( + c === 0x7C && // pipe + exp.charCodeAt(i + 1) !== 0x7C && + exp.charCodeAt(i - 1) !== 0x7C && + !curly && !square && !paren + ) { + if (expression === undefined) { + // first filter, end of expression + lastFilterIndex = i + 1; + expression = exp.slice(0, i).trim(); + } else { + pushFilter(); + } + } else { + switch (c) { + case 0x22: inDouble = true; break // " + case 0x27: inSingle = true; break // ' + case 0x60: inTemplateString = true; break // ` + case 0x28: paren++; break // ( + case 0x29: paren--; break // ) + case 0x5B: square++; break // [ + case 0x5D: square--; break // ] + case 0x7B: curly++; break // { + case 0x7D: curly--; break // } + } + if (c === 0x2f) { // / + var j = i - 1; + var p = (void 0); + // find first non-whitespace prev char + for (; j >= 0; j--) { + p = exp.charAt(j); + if (p !== ' ') { break } + } + if (!p || !/[\w$]/.test(p)) { + inRegex = true; + } + } + } } - function noop$1() {} + if (expression === undefined) { + expression = exp.slice(0, i).trim(); + } else if (lastFilterIndex !== 0) { + pushFilter(); + } - /** - * A directive links a DOM element with a piece of data, - * which is the result of evaluating an expression. - * It registers a watcher with the expression and calls - * the DOM update function when a change is triggered. - * - * @param {Object} descriptor - * - {String} name - * - {Object} def - * - {String} expression - * - {Array} [filters] - * - {Object} [modifiers] - * - {Boolean} literal - * - {String} attr - * - {String} arg - * - {String} raw - * - {String} [ref] - * - {Array} [interp] - * - {Boolean} [hasOneTime] - * @param {Vue} vm - * @param {Node} el - * @param {Vue} [host] - transclusion host component - * @param {Object} [scope] - v-for scope - * @param {Fragment} [frag] - owner fragment - * @constructor - */ - function Directive(descriptor, vm, el, host, scope, frag) { - this.vm = vm; - this.el = el; - // copy descriptor properties - this.descriptor = descriptor; - this.name = descriptor.name; - this.expression = descriptor.expression; - this.arg = descriptor.arg; - this.modifiers = descriptor.modifiers; - this.filters = descriptor.filters; - this.literal = this.modifiers && this.modifiers.literal; - // private - this._locked = false; - this._bound = false; - this._listeners = null; - // link context - this._host = host; - this._scope = scope; - this._frag = frag; - // store directives on node in dev mode - if ('development' !== 'production' && this.el) { - this.el._vue_directives = this.el._vue_directives || []; - this.el._vue_directives.push(this); + function pushFilter () { + (filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim()); + lastFilterIndex = i + 1; + } + + if (filters) { + for (i = 0; i < filters.length; i++) { + expression = wrapFilter(expression, filters[i]); } } - /** - * Initialize the directive, mixin definition properties, - * setup the watcher, call definition bind() and update() - * if present. - */ + return expression + } - Directive.prototype._bind = function () { - var name = this.name; - var descriptor = this.descriptor; + function wrapFilter (exp, filter) { + var i = filter.indexOf('('); + if (i < 0) { + // _f: resolveFilter + return ("_f(\"" + filter + "\")(" + exp + ")") + } else { + var name = filter.slice(0, i); + var args = filter.slice(i + 1); + return ("_f(\"" + name + "\")(" + exp + "," + args) + } + } - // remove attribute - if ((name !== 'cloak' || this.vm._isCompiled) && this.el && this.el.removeAttribute) { - var attr = descriptor.attr || 'v-' + name; - this.el.removeAttribute(attr); - } + /* */ - // copy def properties - var def = descriptor.def; - if (typeof def === 'function') { - this.update = def; - } else { - extend(this, def); - } + var defaultTagRE = /\{\{((?:.|\n)+?)\}\}/g; + var regexEscapeRE = /[-.*+?^${}()|[\]/\\]/g; - // setup directive params - this._setupParams(); + var buildRegex = cached(function (delimiters) { + var open = delimiters[0].replace(regexEscapeRE, '\\$&'); + var close = delimiters[1].replace(regexEscapeRE, '\\$&'); + return new RegExp(open + '((?:.|\\n)+?)' + close, 'g') + }); - // initial bind - if (this.bind) { - this.bind(); - } - this._bound = true; + function parseText ( + text, + delimiters + ) { + var tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE; + if (!tagRE.test(text)) { + return + } + var tokens = []; + var lastIndex = tagRE.lastIndex = 0; + var match, index; + while ((match = tagRE.exec(text))) { + index = match.index; + // push text token + if (index > lastIndex) { + tokens.push(JSON.stringify(text.slice(lastIndex, index))); + } + // tag token + var exp = parseFilters(match[1].trim()); + tokens.push(("_s(" + exp + ")")); + lastIndex = index + match[0].length; + } + if (lastIndex < text.length) { + tokens.push(JSON.stringify(text.slice(lastIndex))); + } + return tokens.join('+') + } + + /* */ + + function baseWarn (msg) { + console.error(("[Vue parser]: " + msg)); + } + + function pluckModuleFunction ( + modules, + key + ) { + return modules + ? modules.map(function (m) { return m[key]; }).filter(function (_) { return _; }) + : [] + } + + function addProp (el, name, value) { + (el.props || (el.props = [])).push({ name: name, value: value }); + } + + function addAttr (el, name, value) { + (el.attrs || (el.attrs = [])).push({ name: name, value: value }); + } + + function addDirective ( + el, + name, + rawName, + value, + arg, + modifiers + ) { + (el.directives || (el.directives = [])).push({ name: name, rawName: rawName, value: value, arg: arg, modifiers: modifiers }); + } + + function addHandler ( + el, + name, + value, + modifiers, + important + ) { + // check capture modifier + if (modifiers && modifiers.capture) { + delete modifiers.capture; + name = '!' + name; // mark the event as captured + } + if (modifiers && modifiers.once) { + delete modifiers.once; + name = '~' + name; // mark the event as once + } + var events; + if (modifiers && modifiers.native) { + delete modifiers.native; + events = el.nativeEvents || (el.nativeEvents = {}); + } else { + events = el.events || (el.events = {}); + } + var newHandler = { value: value, modifiers: modifiers }; + var handlers = events[name]; + /* istanbul ignore if */ + if (Array.isArray(handlers)) { + important ? handlers.unshift(newHandler) : handlers.push(newHandler); + } else if (handlers) { + events[name] = important ? [newHandler, handlers] : [handlers, newHandler]; + } else { + events[name] = newHandler; + } + } - if (this.literal) { - this.update && this.update(descriptor.raw); - } else if ((this.expression || this.modifiers) && (this.update || this.twoWay) && !this._checkStatement()) { - // wrapped updater for context - var dir = this; - if (this.update) { - this._update = function (val, oldVal) { - if (!dir._locked) { - dir.update(val, oldVal); - } - }; - } else { - this._update = noop$1; - } - var preProcess = this._preProcess ? bind(this._preProcess, this) : null; - var postProcess = this._postProcess ? bind(this._postProcess, this) : null; - var watcher = this._watcher = new Watcher(this.vm, this.expression, this._update, // callback - { - filters: this.filters, - twoWay: this.twoWay, - deep: this.deep, - preProcess: preProcess, - postProcess: postProcess, - scope: this._scope - }); - // v-model with inital inline value need to sync back to - // model instead of update to DOM on init. They would - // set the afterBind hook to indicate that. - if (this.afterBind) { - this.afterBind(); - } else if (this.update) { - this.update(watcher.value); - } + function getBindingAttr ( + el, + name, + getStatic + ) { + var dynamicValue = + getAndRemoveAttr(el, ':' + name) || + getAndRemoveAttr(el, 'v-bind:' + name); + if (dynamicValue != null) { + return parseFilters(dynamicValue) + } else if (getStatic !== false) { + var staticValue = getAndRemoveAttr(el, name); + if (staticValue != null) { + return JSON.stringify(staticValue) } - }; - - /** - * Setup all param attributes, e.g. track-by, - * transition-mode, etc... - */ + } + } - Directive.prototype._setupParams = function () { - if (!this.params) { - return; - } - var params = this.params; - // swap the params array with a fresh object. - this.params = Object.create(null); - var i = params.length; - var key, val, mappedKey; - while (i--) { - key = hyphenate(params[i]); - mappedKey = camelize(key); - val = getBindAttr(this.el, key); - if (val != null) { - // dynamic - this._setupParamWatcher(mappedKey, val); - } else { - // static - val = getAttr(this.el, key); - if (val != null) { - this.params[mappedKey] = val === '' ? true : val; - } + function getAndRemoveAttr (el, name) { + var val; + if ((val = el.attrsMap[name]) != null) { + var list = el.attrsList; + for (var i = 0, l = list.length; i < l; i++) { + if (list[i].name === name) { + list.splice(i, 1); + break } } - }; + } + return val + } - /** - * Setup a watcher for a dynamic param. - * - * @param {String} key - * @param {String} expression - */ + var len; + var str; + var chr; + var index$1; + var expressionPos; + var expressionEndPos; - Directive.prototype._setupParamWatcher = function (key, expression) { - var self = this; - var called = false; - var unwatch = (this._scope || this.vm).$watch(expression, function (val, oldVal) { - self.params[key] = val; - // since we are in immediate mode, - // only call the param change callbacks if this is not the first update. - if (called) { - var cb = self.paramWatchers && self.paramWatchers[key]; - if (cb) { - cb.call(self, val, oldVal); - } - } else { - called = true; - } - }, { - immediate: true, - user: false - });(this._paramUnwatchFns || (this._paramUnwatchFns = [])).push(unwatch); - }; + /** + * parse directive model to do the array update transform. a[idx] = val => $$a.splice($$idx, 1, val) + * + * for loop possible cases: + * + * - test + * - test[idx] + * - test[test1[idx]] + * - test["a"][idx] + * - xxx.test[a[a].test1[idx]] + * - test.xxx.a["asa"][test1[idx]] + * + */ - /** - * Check if the directive is a function caller - * and if the expression is a callable one. If both true, - * we wrap up the expression and use it as the event - * handler. - * - * e.g. on-click="a++" - * - * @return {Boolean} - */ + function parseModel (val) { + str = val; + len = str.length; + index$1 = expressionPos = expressionEndPos = 0; - Directive.prototype._checkStatement = function () { - var expression = this.expression; - if (expression && this.acceptStatement && !isSimplePath(expression)) { - var fn = parseExpression(expression).get; - var scope = this._scope || this.vm; - var handler = function handler(e) { - scope.$event = e; - fn.call(scope, scope); - scope.$event = null; - }; - if (this.filters) { - handler = scope._applyFilters(handler, null, this.filters); - } - this.update(handler); - return true; + if (val.indexOf('[') < 0 || val.lastIndexOf(']') < len - 1) { + return { + exp: val, + idx: null } - }; - - /** - * Set the corresponding value with the setter. - * This should only be used in two-way directives - * e.g. v-model. - * - * @param {*} value - * @public - */ + } - Directive.prototype.set = function (value) { - /* istanbul ignore else */ - if (this.twoWay) { - this._withLock(function () { - this._watcher.set(value); - }); - } else if (true) { - warn('Directive.set() can only be used inside twoWay' + 'directives.'); + while (!eof()) { + chr = next(); + /* istanbul ignore if */ + if (isStringStart(chr)) { + parseString(chr); + } else if (chr === 0x5B) { + parseBracket(chr); } - }; - - /** - * Execute a function while preventing that function from - * triggering updates on this directive instance. - * - * @param {Function} fn - */ + } - Directive.prototype._withLock = function (fn) { - var self = this; - self._locked = true; - fn.call(self); - nextTick(function () { - self._locked = false; - }); - }; + return { + exp: val.substring(0, expressionPos), + idx: val.substring(expressionPos + 1, expressionEndPos) + } + } - /** - * Convenience method that attaches a DOM event listener - * to the directive element and autometically tears it down - * during unbind. - * - * @param {String} event - * @param {Function} handler - * @param {Boolean} [useCapture] - */ + function next () { + return str.charCodeAt(++index$1) + } - Directive.prototype.on = function (event, handler, useCapture) { - on(this.el, event, handler, useCapture);(this._listeners || (this._listeners = [])).push([event, handler]); - }; + function eof () { + return index$1 >= len + } - /** - * Teardown the watcher and call unbind. - */ + function isStringStart (chr) { + return chr === 0x22 || chr === 0x27 + } - Directive.prototype._teardown = function () { - if (this._bound) { - this._bound = false; - if (this.unbind) { - this.unbind(); - } - if (this._watcher) { - this._watcher.teardown(); - } - var listeners = this._listeners; - var i; - if (listeners) { - i = listeners.length; - while (i--) { - off(this.el, listeners[i][0], listeners[i][1]); - } - } - var unwatchFns = this._paramUnwatchFns; - if (unwatchFns) { - i = unwatchFns.length; - while (i--) { - unwatchFns[i](); - } - } - if ('development' !== 'production' && this.el) { - this.el._vue_directives.$remove(this); - } - this.vm = this.el = this._watcher = this._listeners = null; + function parseBracket (chr) { + var inBracket = 1; + expressionPos = index$1; + while (!eof()) { + chr = next(); + if (isStringStart(chr)) { + parseString(chr); + continue } - }; + if (chr === 0x5B) { inBracket++; } + if (chr === 0x5D) { inBracket--; } + if (inBracket === 0) { + expressionEndPos = index$1; + break + } + } + } - function lifecycleMixin (Vue) { - /** - * Update v-ref for component. - * - * @param {Boolean} remove - */ + function parseString (chr) { + var stringQuote = chr; + while (!eof()) { + chr = next(); + if (chr === stringQuote) { + break + } + } + } - Vue.prototype._updateRef = function (remove) { - var ref = this.$options._ref; - if (ref) { - var refs = (this._scope || this._context).$refs; - if (remove) { - if (refs[ref] === this) { - refs[ref] = null; - } - } else { - refs[ref] = this; - } - } - }; + /* */ - /** - * Transclude, compile and link element. - * - * If a pre-compiled linker is available, that means the - * passed in element will be pre-transcluded and compiled - * as well - all we need to do is to call the linker. - * - * Otherwise we need to call transclude/compile/link here. - * - * @param {Element} el - */ - - Vue.prototype._compile = function (el) { - var options = this.$options; - - // transclude and init element - // transclude can potentially replace original - // so we need to keep reference; this step also injects - // the template and caches the original attributes - // on the container node and replacer node. - var original = el; - el = transclude(el, options); - this._initElement(el); - - // handle v-pre on root node (#2026) - if (el.nodeType === 1 && getAttr(el, 'v-pre') !== null) { - return; - } + var dirRE = /^v-|^@|^:/; + var forAliasRE = /(.*?)\s+(?:in|of)\s+(.*)/; + var forIteratorRE = /\((\{[^}]*\}|[^,]*),([^,]*)(?:,([^,]*))?\)/; + var bindRE = /^:|^v-bind:/; + var onRE = /^@|^v-on:/; + var argRE = /:(.*)$/; + var modifierRE = /\.[^.]+/g; - // root is always compiled per-instance, because - // container attrs and props can be different every time. - var contextOptions = this._context && this._context.$options; - var rootLinker = compileRoot(el, options, contextOptions); + var decodeHTMLCached = cached(decode); - // resolve slot distribution - resolveSlots(this, options._content); + // configurable state + var warn$1; + var platformGetTagNamespace; + var platformMustUseProp; + var platformIsPreTag; + var preTransforms; + var transforms; + var postTransforms; + var delimiters; - // compile and link the rest - var contentLinkFn; - var ctor = this.constructor; - // component compilation can be cached - // as long as it's not using inline-template - if (options._linkerCachable) { - contentLinkFn = ctor.linker; - if (!contentLinkFn) { - contentLinkFn = ctor.linker = compile(el, options); - } + /** + * Convert HTML string to AST. + */ + function parse ( + template, + options + ) { + warn$1 = options.warn || baseWarn; + platformGetTagNamespace = options.getTagNamespace || no; + platformMustUseProp = options.mustUseProp || no; + platformIsPreTag = options.isPreTag || no; + preTransforms = pluckModuleFunction(options.modules, 'preTransformNode'); + transforms = pluckModuleFunction(options.modules, 'transformNode'); + postTransforms = pluckModuleFunction(options.modules, 'postTransformNode'); + delimiters = options.delimiters; + var stack = []; + var preserveWhitespace = options.preserveWhitespace !== false; + var root; + var currentParent; + var inVPre = false; + var inPre = false; + var warned = false; + parseHTML(template, { + expectHTML: options.expectHTML, + isUnaryTag: options.isUnaryTag, + shouldDecodeNewlines: options.shouldDecodeNewlines, + start: function start (tag, attrs, unary) { + // check namespace. + // inherit parent ns if there is one + var ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag); + + // handle IE svg bug + /* istanbul ignore if */ + if (isIE && ns === 'svg') { + attrs = guardIESVGBug(attrs); } - // link phase - // make sure to link root with prop scope! - var rootUnlinkFn = rootLinker(this, el, this._scope); - var contentUnlinkFn = contentLinkFn ? contentLinkFn(this, el) : compile(el, options)(this, el); - - // register composite unlink function - // to be called during instance destruction - this._unlinkFn = function () { - rootUnlinkFn(); - // passing destroying: true to avoid searching and - // splicing the directives - contentUnlinkFn(true); + var element = { + type: 1, + tag: tag, + attrsList: attrs, + attrsMap: makeAttrsMap(attrs), + parent: currentParent, + children: [] }; - - // finally replace original - if (options.replace) { - replace(original, el); + if (ns) { + element.ns = ns; } - this._isCompiled = true; - this._callHook('compiled'); - }; - - /** - * Initialize instance element. Called in the public - * $mount() method. - * - * @param {Element} el - */ - - Vue.prototype._initElement = function (el) { - if (isFragment(el)) { - this._isFragment = true; - this.$el = this._fragmentStart = el.firstChild; - this._fragmentEnd = el.lastChild; - // set persisted text anchors to empty - if (this._fragmentStart.nodeType === 3) { - this._fragmentStart.data = this._fragmentEnd.data = ''; - } - this._fragment = el; - } else { - this.$el = el; + if (isForbiddenTag(element) && !isServerRendering()) { + element.forbidden = true; + process.env.NODE_ENV !== 'production' && warn$1( + 'Templates should only be responsible for mapping the state to the ' + + 'UI. Avoid placing tags with side-effects in your templates, such as ' + + "<" + tag + ">" + ', as they will not be parsed.' + ); } - this.$el.__vue__ = this; - this._callHook('beforeCompile'); - }; - /** - * Create and bind a directive to an element. - * - * @param {Object} descriptor - parsed directive descriptor - * @param {Node} node - target node - * @param {Vue} [host] - transclusion host component - * @param {Object} [scope] - v-for scope - * @param {Fragment} [frag] - owner fragment - */ - - Vue.prototype._bindDir = function (descriptor, node, host, scope, frag) { - this._directives.push(new Directive(descriptor, this, node, host, scope, frag)); - }; - - /** - * Teardown an instance, unobserves the data, unbind all the - * directives, turn off all the event listeners, etc. - * - * @param {Boolean} remove - whether to remove the DOM node. - * @param {Boolean} deferCleanup - if true, defer cleanup to - * be called later - */ - - Vue.prototype._destroy = function (remove, deferCleanup) { - if (this._isBeingDestroyed) { - if (!deferCleanup) { - this._cleanup(); - } - return; + // apply pre-transforms + for (var i = 0; i < preTransforms.length; i++) { + preTransforms[i](element, options); } - var destroyReady; - var pendingRemoval; - - var self = this; - // Cleanup should be called either synchronously or asynchronoysly as - // callback of this.$remove(), or if remove and deferCleanup are false. - // In any case it should be called after all other removing, unbinding and - // turning of is done - var cleanupIfPossible = function cleanupIfPossible() { - if (destroyReady && !pendingRemoval && !deferCleanup) { - self._cleanup(); + if (!inVPre) { + processPre(element); + if (element.pre) { + inVPre = true; } - }; - - // remove DOM element - if (remove && this.$el) { - pendingRemoval = true; - this.$remove(function () { - pendingRemoval = false; - cleanupIfPossible(); - }); } - - this._callHook('beforeDestroy'); - this._isBeingDestroyed = true; - var i; - // remove self from parent. only necessary - // if parent is not being destroyed as well. - var parent = this.$parent; - if (parent && !parent._isBeingDestroyed) { - parent.$children.$remove(this); - // unregister ref (remove: true) - this._updateRef(true); - } - // destroy all children. - i = this.$children.length; - while (i--) { - this.$children[i].$destroy(); - } - // teardown props - if (this._propsUnlinkFn) { - this._propsUnlinkFn(); - } - // teardown all directives. this also tearsdown all - // directive-owned watchers. - if (this._unlinkFn) { - this._unlinkFn(); - } - i = this._watchers.length; - while (i--) { - this._watchers[i].teardown(); - } - // remove reference to self on $el - if (this.$el) { - this.$el.__vue__ = null; - } - - destroyReady = true; - cleanupIfPossible(); - }; - - /** - * Clean up to ensure garbage collection. - * This is called after the leave transition if there - * is any. - */ - - Vue.prototype._cleanup = function () { - if (this._isDestroyed) { - return; + if (platformIsPreTag(element.tag)) { + inPre = true; } - // remove self from owner fragment - // do it in cleanup so that we can call $destroy with - // defer right when a fragment is about to be removed. - if (this._frag) { - this._frag.children.$remove(this); - } - // remove reference from data ob - // frozen object may not have observer. - if (this._data && this._data.__ob__) { - this._data.__ob__.removeVm(this); - } - // Clean up references to private properties and other - // instances. preserve reference to _data so that proxy - // accessors still work. The only potential side effect - // here is that mutating the instance after it's destroyed - // may affect the state of other components that are still - // observing the same object, but that seems to be a - // reasonable responsibility for the user rather than - // always throwing an error on them. - this.$el = this.$parent = this.$root = this.$children = this._watchers = this._context = this._scope = this._directives = null; - // call the last hook... - this._isDestroyed = true; - this._callHook('destroyed'); - // turn off all instance listeners. - this.$off(); - }; - } - - function miscMixin (Vue) { - /** - * Apply a list of filter (descriptors) to a value. - * Using plain for loops here because this will be called in - * the getter of any watcher with filters so it is very - * performance sensitive. - * - * @param {*} value - * @param {*} [oldValue] - * @param {Array} filters - * @param {Boolean} write - * @return {*} - */ - - Vue.prototype._applyFilters = function (value, oldValue, filters, write) { - var filter, fn, args, arg, offset, i, l, j, k; - for (i = 0, l = filters.length; i < l; i++) { - filter = filters[write ? l - i - 1 : i]; - fn = resolveAsset(this.$options, 'filters', filter.name, true); - if (!fn) continue; - fn = write ? fn.write : fn.read || fn; - if (typeof fn !== 'function') continue; - args = write ? [value, oldValue] : [value]; - offset = write ? 2 : 1; - if (filter.args) { - for (j = 0, k = filter.args.length; j < k; j++) { - arg = filter.args[j]; - args[j + offset] = arg.dynamic ? this.$get(arg.value) : arg.value; + if (inVPre) { + processRawAttrs(element); + } else { + processFor(element); + processIf(element); + processOnce(element); + processKey(element); + + // determine whether this is a plain element after + // removing structural attributes + element.plain = !element.key && !attrs.length; + + processRef(element); + processSlot(element); + processComponent(element); + for (var i$1 = 0; i$1 < transforms.length; i$1++) { + transforms[i$1](element, options); + } + processAttrs(element); + } + + function checkRootConstraints (el) { + if (process.env.NODE_ENV !== 'production' && !warned) { + if (el.tag === 'slot' || el.tag === 'template') { + warned = true; + warn$1( + "Cannot use <" + (el.tag) + "> as component root element because it may " + + 'contain multiple nodes:\n' + template + ); + } + if (el.attrsMap.hasOwnProperty('v-for')) { + warned = true; + warn$1( + 'Cannot use v-for on stateful component root element because ' + + 'it renders multiple elements:\n' + template + ); } } - value = fn.apply(this, args); } - return value; - }; - /** - * Resolve a component, depending on whether the component - * is defined normally or using an async factory function. - * Resolves synchronously if already resolved, otherwise - * resolves asynchronously and caches the resolved - * constructor on the factory. - * - * @param {String|Function} value - * @param {Function} cb - */ - - Vue.prototype._resolveComponent = function (value, cb) { - var factory; - if (typeof value === 'function') { - factory = value; - } else { - factory = resolveAsset(this.$options, 'components', value, true); - } - /* istanbul ignore if */ - if (!factory) { - return; - } - // async component factory - if (!factory.options) { - if (factory.resolved) { - // cached - cb(factory.resolved); - } else if (factory.requested) { - // pool callbacks - factory.pendingCallbacks.push(cb); - } else { - factory.requested = true; - var cbs = factory.pendingCallbacks = [cb]; - factory.call(this, function resolve(res) { - if (isPlainObject(res)) { - res = Vue.extend(res); - } - // cache resolved - factory.resolved = res; - // invoke callbacks - for (var i = 0, l = cbs.length; i < l; i++) { - cbs[i](res); - } - }, function reject(reason) { - 'development' !== 'production' && warn('Failed to resolve async component' + (typeof value === 'string' ? ': ' + value : '') + '. ' + (reason ? '\nReason: ' + reason : '')); + // tree management + if (!root) { + root = element; + checkRootConstraints(root); + } else if (!stack.length) { + // allow root elements with v-if, v-else-if and v-else + if (root.if && (element.elseif || element.else)) { + checkRootConstraints(element); + addIfCondition(root, { + exp: element.elseif, + block: element }); - } - } else { - // normal component - cb(factory); - } - }; - } - - var filterRE$1 = /[^|]\|[^|]/; - - function dataAPI (Vue) { - /** - * Get the value from an expression on this vm. - * - * @param {String} exp - * @param {Boolean} [asStatement] - * @return {*} - */ - - Vue.prototype.$get = function (exp, asStatement) { - var res = parseExpression(exp); - if (res) { - if (asStatement) { - var self = this; - return function statementHandler() { - self.$arguments = toArray(arguments); - var result = res.get.call(self, self); - self.$arguments = null; - return result; - }; + } else if (process.env.NODE_ENV !== 'production' && !warned) { + warned = true; + warn$1( + "Component template should contain exactly one root element:" + + "\n\n" + template + "\n\n" + + "If you are using v-if on multiple elements, " + + "use v-else-if to chain them instead." + ); + } + } + if (currentParent && !element.forbidden) { + if (element.elseif || element.else) { + processIfConditions(element, currentParent); + } else if (element.slotScope) { // scoped slot + currentParent.plain = false; + var name = element.slotTarget || 'default';(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element; } else { - try { - return res.get.call(this, this); - } catch (e) {} + currentParent.children.push(element); + element.parent = currentParent; } } - }; - - /** - * Set the value from an expression on this vm. - * The expression must be a valid left-hand - * expression in an assignment. - * - * @param {String} exp - * @param {*} val - */ - - Vue.prototype.$set = function (exp, val) { - var res = parseExpression(exp, true); - if (res && res.set) { - res.set.call(this, this, val); + if (!unary) { + currentParent = element; + stack.push(element); } - }; - - /** - * Delete a property on the VM - * - * @param {String} key - */ - - Vue.prototype.$delete = function (key) { - del(this._data, key); - }; - - /** - * Watch an expression, trigger callback when its - * value changes. - * - * @param {String|Function} expOrFn - * @param {Function} cb - * @param {Object} [options] - * - {Boolean} deep - * - {Boolean} immediate - * @return {Function} - unwatchFn - */ - - Vue.prototype.$watch = function (expOrFn, cb, options) { - var vm = this; - var parsed; - if (typeof expOrFn === 'string') { - parsed = parseDirective(expOrFn); - expOrFn = parsed.expression; - } - var watcher = new Watcher(vm, expOrFn, cb, { - deep: options && options.deep, - sync: options && options.sync, - filters: parsed && parsed.filters, - user: !options || options.user !== false - }); - if (options && options.immediate) { - cb.call(vm, watcher.value); + // apply post-transforms + for (var i$2 = 0; i$2 < postTransforms.length; i$2++) { + postTransforms[i$2](element, options); } - return function unwatchFn() { - watcher.teardown(); - }; - }; + }, - /** - * Evaluate a text directive, including filters. - * - * @param {String} text - * @param {Boolean} [asStatement] - * @return {String} - */ - - Vue.prototype.$eval = function (text, asStatement) { - // check for filters. - if (filterRE$1.test(text)) { - var dir = parseDirective(text); - // the filter regex check might give false positive - // for pipes inside strings, so it's possible that - // we don't get any filters here - var val = this.$get(dir.expression, asStatement); - return dir.filters ? this._applyFilters(val, null, dir.filters) : val; - } else { - // no filter - return this.$get(text, asStatement); + end: function end () { + // remove trailing whitespace + var element = stack[stack.length - 1]; + var lastNode = element.children[element.children.length - 1]; + if (lastNode && lastNode.type === 3 && lastNode.text === ' ') { + element.children.pop(); } - }; - - /** - * Interpolate a piece of template text. - * - * @param {String} text - * @return {String} - */ - - Vue.prototype.$interpolate = function (text) { - var tokens = parseText(text); - var vm = this; - if (tokens) { - if (tokens.length === 1) { - return vm.$eval(tokens[0].value) + ''; - } else { - return tokens.map(function (token) { - return token.tag ? vm.$eval(token.value) : token.value; - }).join(''); - } - } else { - return text; + // pop stack + stack.length -= 1; + currentParent = stack[stack.length - 1]; + // check pre state + if (element.pre) { + inVPre = false; } - }; + if (platformIsPreTag(element.tag)) { + inPre = false; + } + }, - /** - * Log instance data as a plain JS object - * so that it is easier to inspect in console. - * This method assumes console is available. - * - * @param {String} [path] - */ - - Vue.prototype.$log = function (path) { - var data = path ? getPath(this._data, path) : this._data; - if (data) { - data = clean(data); - } - // include computed fields - if (!path) { - var key; - for (key in this.$options.computed) { - data[key] = clean(this[key]); + chars: function chars (text) { + if (!currentParent) { + if (process.env.NODE_ENV !== 'production' && !warned && text === template) { + warned = true; + warn$1( + 'Component template requires a root element, rather than just text:\n\n' + template + ); } - if (this._props) { - for (key in this._props) { - data[key] = clean(this[key]); - } + return + } + // IE textarea placeholder bug + /* istanbul ignore if */ + if (isIE && + currentParent.tag === 'textarea' && + currentParent.attrsMap.placeholder === text) { + return + } + var children = currentParent.children; + text = inPre || text.trim() + ? decodeHTMLCached(text) + // only preserve whitespace if its not right after a starting tag + : preserveWhitespace && children.length ? ' ' : ''; + if (text) { + var expression; + if (!inVPre && text !== ' ' && (expression = parseText(text, delimiters))) { + children.push({ + type: 2, + expression: expression, + text: text + }); + } else if (text !== ' ' || children[children.length - 1].text !== ' ') { + currentParent.children.push({ + type: 3, + text: text + }); } } - console.log(data); - }; - - /** - * "clean" a getter/setter converted object into a plain - * object copy. - * - * @param {Object} - obj - * @return {Object} - */ - - function clean(obj) { - return JSON.parse(JSON.stringify(obj)); } - } - - function domAPI (Vue) { - /** - * Convenience on-instance nextTick. The callback is - * auto-bound to the instance, and this avoids component - * modules having to rely on the global Vue. - * - * @param {Function} fn - */ - - Vue.prototype.$nextTick = function (fn) { - nextTick(fn, this); - }; - - /** - * Append instance to target - * - * @param {Node} target - * @param {Function} [cb] - * @param {Boolean} [withTransition] - defaults to true - */ - - Vue.prototype.$appendTo = function (target, cb, withTransition) { - return insert(this, target, cb, withTransition, append, appendWithTransition); - }; - - /** - * Prepend instance to target - * - * @param {Node} target - * @param {Function} [cb] - * @param {Boolean} [withTransition] - defaults to true - */ - - Vue.prototype.$prependTo = function (target, cb, withTransition) { - target = query(target); - if (target.hasChildNodes()) { - this.$before(target.firstChild, cb, withTransition); - } else { - this.$appendTo(target, cb, withTransition); - } - return this; - }; - - /** - * Insert instance before target - * - * @param {Node} target - * @param {Function} [cb] - * @param {Boolean} [withTransition] - defaults to true - */ - - Vue.prototype.$before = function (target, cb, withTransition) { - return insert(this, target, cb, withTransition, beforeWithCb, beforeWithTransition); - }; - - /** - * Insert instance after target - * - * @param {Node} target - * @param {Function} [cb] - * @param {Boolean} [withTransition] - defaults to true - */ - - Vue.prototype.$after = function (target, cb, withTransition) { - target = query(target); - if (target.nextSibling) { - this.$before(target.nextSibling, cb, withTransition); - } else { - this.$appendTo(target.parentNode, cb, withTransition); - } - return this; - }; - - /** - * Remove instance from DOM - * - * @param {Function} [cb] - * @param {Boolean} [withTransition] - defaults to true - */ - - Vue.prototype.$remove = function (cb, withTransition) { - if (!this.$el.parentNode) { - return cb && cb(); - } - var inDocument = this._isAttached && inDoc(this.$el); - // if we are not in document, no need to check - // for transitions - if (!inDocument) withTransition = false; - var self = this; - var realCb = function realCb() { - if (inDocument) self._callHook('detached'); - if (cb) cb(); + }); + return root + } + + function processPre (el) { + if (getAndRemoveAttr(el, 'v-pre') != null) { + el.pre = true; + } + } + + function processRawAttrs (el) { + var l = el.attrsList.length; + if (l) { + var attrs = el.attrs = new Array(l); + for (var i = 0; i < l; i++) { + attrs[i] = { + name: el.attrsList[i].name, + value: JSON.stringify(el.attrsList[i].value) }; - if (this._isFragment) { - removeNodeRange(this._fragmentStart, this._fragmentEnd, this, this._fragment, realCb); - } else { - var op = withTransition === false ? removeWithCb : removeWithTransition; - op(this.$el, this, realCb); - } - return this; - }; - - /** - * Shared DOM insertion function. - * - * @param {Vue} vm - * @param {Element} target - * @param {Function} [cb] - * @param {Boolean} [withTransition] - * @param {Function} op1 - op for non-transition insert - * @param {Function} op2 - op for transition insert - * @return vm - */ - - function insert(vm, target, cb, withTransition, op1, op2) { - target = query(target); - var targetIsDetached = !inDoc(target); - var op = withTransition === false || targetIsDetached ? op1 : op2; - var shouldCallHook = !targetIsDetached && !vm._isAttached && !inDoc(vm.$el); - if (vm._isFragment) { - mapNodeRange(vm._fragmentStart, vm._fragmentEnd, function (node) { - op(node, target, vm); - }); - cb && cb(); - } else { - op(vm.$el, target, vm, cb); - } - if (shouldCallHook) { - vm._callHook('attached'); + } + } else if (!el.pre) { + // non root node in pre blocks with no attributes + el.plain = true; + } + } + + function processKey (el) { + var exp = getBindingAttr(el, 'key'); + if (exp) { + if (process.env.NODE_ENV !== 'production' && el.tag === 'template') { + warn$1("