From 6a4a89067b8775a3650cb3b3f0823b7634dde2ba Mon Sep 17 00:00:00 2001 From: Kostiantyn Bozhko Date: Tue, 5 Dec 2017 17:30:20 +0200 Subject: [PATCH] Update docs and demo. --- CHANGELOG.md | 3 + README.md | 3 + docs/index.html | 4 + docs/resources/app.js | 5053 +++++++++++++++++++---------- docs/resources/tabs-component.css | 7 +- src/index.js | 6 +- 6 files changed, 3313 insertions(+), 1763 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 096f28e..c89e641 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ All notable changes to `vue-tabs-component` will be documented in this file +## 1.3.1 - 2017-11-06 + - Added `isDisabled` prop to `Tab` + ## 1.3.0 - 2017-10-06 - Added `isVisible` prop to `Tab` diff --git a/README.md b/README.md index d4ea1cb..e6e05bb 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,9 @@ This is how they can be used: This is the content of the second tab + + This content will be unavailable while :is-disabled prop set to true + The fragment that is appended to the url can be customized diff --git a/docs/index.html b/docs/index.html index 541480a..416afac 100644 --- a/docs/index.html +++ b/docs/index.html @@ -154,6 +154,10 @@

First tab

Second tab

This is the content of the second tab. + +

Disabled tab

+ This content will be unavailable while :is-disabled prop set to true +

Custom fragment

The hash that is appended to the url can be customized. diff --git a/docs/resources/app.js b/docs/resources/app.js index 59ab5d9..09cf43e 100644 --- a/docs/resources/app.js +++ b/docs/resources/app.js @@ -63,7 +63,7 @@ /******/ __webpack_require__.p = "/resources/"; /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 9); +/******/ return __webpack_require__(__webpack_require__.s = 10); /******/ }) /************************************************************************/ /******/ ([ @@ -71,67 +71,75 @@ /***/ (function(module, exports, __webpack_require__) { // Thank's IE8 for his funny defineProperty -module.exports = !__webpack_require__(3)(function(){ - return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; +module.exports = !__webpack_require__(3)(function () { + return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7; }); + /***/ }), /* 1 */ /***/ (function(module, exports) { -module.exports = function(it){ +module.exports = function (it) { return typeof it === 'object' ? it !== null : typeof it === 'function'; }; + /***/ }), /* 2 */ /***/ (function(module, exports) { -var core = module.exports = {version: '2.4.0'}; -if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef +var core = module.exports = { version: '2.5.1' }; +if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef + /***/ }), /* 3 */ /***/ (function(module, exports) { -module.exports = function(exec){ +module.exports = function (exec) { try { return !!exec(); - } catch(e){ + } catch (e) { return true; } }; + /***/ }), /* 4 */ /***/ (function(module, exports) { // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 var global = module.exports = typeof window != 'undefined' && window.Math == Math - ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); -if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef + ? window : typeof self != 'undefined' && self.Math == Math ? self + // eslint-disable-next-line no-new-func + : Function('return this')(); +if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef + /***/ }), /* 5 */ /***/ (function(module, exports, __webpack_require__) { -var anObject = __webpack_require__(18) - , IE8_DOM_DEFINE = __webpack_require__(23) - , toPrimitive = __webpack_require__(25) - , dP = Object.defineProperty; +var anObject = __webpack_require__(19); +var IE8_DOM_DEFINE = __webpack_require__(24); +var toPrimitive = __webpack_require__(26); +var dP = Object.defineProperty; -exports.f = __webpack_require__(0) ? Object.defineProperty : function defineProperty(O, P, Attributes){ +exports.f = __webpack_require__(0) ? Object.defineProperty : function defineProperty(O, P, Attributes) { anObject(O); P = toPrimitive(P, true); anObject(Attributes); - if(IE8_DOM_DEFINE)try { + if (IE8_DOM_DEFINE) try { return dP(O, P, Attributes); - } catch(e){ /* empty */ } - if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); - if('value' in Attributes)O[P] = Attributes.value; + } catch (e) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!'); + if ('value' in Attributes) O[P] = Attributes.value; return O; }; + /***/ }), /* 6 */ /***/ (function(module, exports) { @@ -231,55 +239,84 @@ module.exports = function normalizeComponent ( /***/ }), /* 7 */ +/***/ (function(module, exports) { + +var g; + +// This works in non-strict mode +g = (function() { + return this; +})(); + +try { + // This works if eval is allowed (see CSP) + g = g || Function("return this")() || (1,eval)("this"); +} catch(e) { + // This works if the window reference is available + if(typeof window === "object") + g = window; +} + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + +module.exports = g; + + +/***/ }), +/* 8 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (global, factory) { - if (true) { - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [exports, __webpack_require__(28), __webpack_require__(27)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + if (true) { + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [exports, __webpack_require__(31), __webpack_require__(32)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if (typeof exports !== "undefined") { - factory(exports, require('./components/Tabs'), require('./components/Tab')); - } else { - var mod = { - exports: {} - }; - factory(mod.exports, global.Tabs, global.Tab); - global.index = mod.exports; - } -})(this, function (exports, _Tabs, _Tab) { - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - Object.defineProperty(exports, 'Tabs', { - enumerable: true, - get: function () { - return _interopRequireDefault(_Tabs).default; + } else if (typeof exports !== "undefined") { + factory(exports, require('./components/Tab'), require('./components/Tabs')); + } else { + var mod = { + exports: {} + }; + factory(mod.exports, global.Tab, global.Tabs); + global.index = mod.exports; } - }); - Object.defineProperty(exports, 'Tab', { - enumerable: true, - get: function () { - return _interopRequireDefault(_Tab).default; +})(this, function (exports, _Tab, _Tabs) { + 'use strict'; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.Tabs = exports.Tab = undefined; + + var _Tab2 = _interopRequireDefault(_Tab); + + var _Tabs2 = _interopRequireDefault(_Tabs); + + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: obj + }; } - }); - function _interopRequireDefault(obj) { - return obj && obj.__esModule ? obj : { - default: obj + exports.default = { + install: function install(Vue) { + Vue.component('tab', _Tab2.default); + Vue.component('tabs', _Tabs2.default); + } }; - } + exports.Tab = _Tab2.default; + exports.Tabs = _Tabs2.default; }); /***/ }), -/* 8 */ +/* 9 */ /***/ (function(module, exports, __webpack_require__) { -/* WEBPACK VAR INJECTION */(function(global) {/*! - * Vue.js v2.3.3 +/* WEBPACK VAR INJECTION */(function(global, setImmediate) {/*! + * Vue.js v2.5.9 * (c) 2014-2017 Evan You * Released under the MIT License. */ @@ -291,6 +328,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /* */ +var emptyObject = Object.freeze({}); + // these helpers produces better vm code in JS engines due to their // explicitness and function inlining function isUndef (v) { @@ -308,11 +347,16 @@ function isTrue (v) { function isFalse (v) { return v === false } + /** * Check if value is primitive */ function isPrimitive (value) { - return typeof value === 'string' || typeof value === 'number' + return ( + typeof value === 'string' || + typeof value === 'number' || + typeof value === 'boolean' + ) } /** @@ -324,8 +368,15 @@ function isObject (obj) { return obj !== null && typeof obj === 'object' } +/** + * Get the raw type string of a value e.g. [object Object] + */ var _toString = Object.prototype.toString; +function toRawType (value) { + return _toString.call(value).slice(8, -1) +} + /** * Strict object type check. Only returns true * for plain JavaScript objects. @@ -338,6 +389,14 @@ function isRegExp (v) { return _toString.call(v) === '[object RegExp]' } +/** + * Check if val is a valid array index. + */ +function isValidArrayIndex (val) { + var n = parseFloat(String(val)); + return n >= 0 && Math.floor(n) === n && isFinite(val) +} + /** * Convert a value to a string that is actually rendered. */ @@ -381,6 +440,11 @@ function makeMap ( */ var isBuiltInTag = makeMap('slot,component', true); +/** + * Check if a attribute is a reserved attribute. + */ +var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is'); + /** * Remove an item from an array */ @@ -430,12 +494,9 @@ var capitalize = cached(function (str) { /** * Hyphenate a camelCase string. */ -var hyphenateRE = /([^-])([A-Z])/g; +var hyphenateRE = /\B([A-Z])/g; var hyphenate = cached(function (str) { - return str - .replace(hyphenateRE, '$1-$2') - .replace(hyphenateRE, '$1-$2') - .toLowerCase() + return str.replace(hyphenateRE, '-$1').toLowerCase() }); /** @@ -493,13 +554,15 @@ function toObject (arr) { /** * Perform no operation. + * Stubbing args to make Flow happy without leaving useless transpiled code + * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/) */ -function noop () {} +function noop (a, b, c) {} /** * Always return false. */ -var no = function () { return false; }; +var no = function (a, b, c) { return false; }; /** * Return same value @@ -520,14 +583,30 @@ function genStaticKeys (modules) { * if they are plain objects, do they have the same shape? */ function looseEqual (a, b) { + if (a === b) { return true } var isObjectA = isObject(a); var isObjectB = isObject(b); if (isObjectA && isObjectB) { try { - return JSON.stringify(a) === JSON.stringify(b) + var isArrayA = Array.isArray(a); + var isArrayB = Array.isArray(b); + if (isArrayA && isArrayB) { + return a.length === b.length && a.every(function (e, i) { + return looseEqual(e, b[i]) + }) + } else if (!isArrayA && !isArrayB) { + var keysA = Object.keys(a); + var keysB = Object.keys(b); + return keysA.length === keysB.length && keysA.every(function (key) { + return looseEqual(a[key], b[key]) + }) + } else { + /* istanbul ignore next */ + return false + } } catch (e) { - // possible circular reference - return a === b + /* istanbul ignore next */ + return false } } else if (!isObjectA && !isObjectB) { return String(a) === String(b) @@ -574,7 +653,8 @@ var LIFECYCLE_HOOKS = [ 'beforeDestroy', 'destroyed', 'activated', - 'deactivated' + 'deactivated', + 'errorCaptured' ]; /* */ @@ -610,6 +690,11 @@ var config = ({ */ errorHandler: null, + /** + * Warn handler for watcher warns + */ + warnHandler: null, + /** * Ignore certain custom elements */ @@ -662,8 +747,6 @@ var config = ({ /* */ -var emptyObject = Object.freeze({}); - /** * Check if a string starts with $ or _ */ @@ -704,9 +787,99 @@ function parsePath (path) { /* */ + +// can we use __proto__? +var hasProto = '__proto__' in {}; + +// Browser environment sniffing +var inBrowser = typeof window !== 'undefined'; +var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform; +var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase(); +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) || (weexPlatform === 'android'); +var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios'); +var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge; + +// Firefox has a "watch" function on Object.prototype... +var nativeWatch = ({}).watch; + +var supportsPassive = false; +if (inBrowser) { + try { + var opts = {}; + Object.defineProperty(opts, 'passive', ({ + get: function get () { + /* istanbul ignore next */ + supportsPassive = true; + } + })); // https://github.com/facebook/flow/issues/285 + window.addEventListener('test-passive', null, opts); + } catch (e) {} +} + +// this needs to be lazy-evaled because vue may be required before +// vue-server-renderer can set VUE_ENV +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 +}; + +// detect devtools +var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; + +/* istanbul ignore next */ +function isNative (Ctor) { + return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) +} + +var hasSymbol = + typeof Symbol !== 'undefined' && isNative(Symbol) && + typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys); + +var _Set; +/* istanbul ignore if */ // $flow-disable-line +if (typeof Set !== 'undefined' && isNative(Set)) { + // use native Set when available. + _Set = Set; +} else { + // a non-standard Set polyfill that only works with primitive keys. + _Set = (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); + }; + + return Set; + }()); +} + +/* */ + var warn = noop; var tip = noop; -var formatComponentName = (null); // work around flow check +var generateComponentTrace = (noop); // work around flow check +var formatComponentName = (noop); { var hasConsole = typeof console !== 'undefined'; @@ -716,10 +889,12 @@ var formatComponentName = (null); // work around flow check .replace(/[-_]/g, ''); }; warn = function (msg, vm) { - if (hasConsole && (!config.silent)) { - console.error("[Vue warn]: " + msg + ( - vm ? generateComponentTrace(vm) : '' - )); + var trace = vm ? generateComponentTrace(vm) : ''; + + if (config.warnHandler) { + config.warnHandler.call(null, msg, vm, trace); + } else if (hasConsole && (!config.silent)) { + console.error(("[Vue warn]: " + msg + trace)); } }; @@ -735,15 +910,13 @@ var formatComponentName = (null); // work around flow check if (vm.$root === vm) { return '' } - var name = typeof vm === 'string' - ? vm - : typeof vm === 'function' && vm.options - ? vm.options.name - : vm._isVue - ? vm.$options.name || vm.$options._componentTag - : vm.name; - - var file = vm._isVue && vm.$options.__file; + var options = typeof vm === 'function' && vm.cid != null + ? vm.options + : vm._isVue + ? vm.$options || vm.constructor.options + : vm || {}; + var name = options.name || options._componentTag; + var file = options.__file; if (!name && file) { var match = file.match(/([^/\\]+)\.vue$/); name = match && match[1]; @@ -765,7 +938,7 @@ var formatComponentName = (null); // work around flow check return res }; - var generateComponentTrace = function (vm) { + generateComponentTrace = function (vm) { if (vm._isVue && vm.$parent) { var tree = []; var currentRecursiveSequence = 0; @@ -797,241 +970,157 @@ var formatComponentName = (null); // work around flow check /* */ -function handleError (err, vm, info) { - if (config.errorHandler) { - config.errorHandler.call(null, err, vm, info); - } else { - { - warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm); - } - /* istanbul ignore else */ - if (inBrowser && typeof console !== 'undefined') { - console.error(err); - } else { - throw err - } - } -} -/* */ -/* globals MutationObserver */ +var uid = 0; -// can we use __proto__? -var hasProto = '__proto__' in {}; +/** + * A dep is an observable that can have multiple + * directives subscribing to it. + */ +var Dep = function Dep () { + this.id = uid++; + this.subs = []; +}; -// 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); -var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge; +Dep.prototype.addSub = function addSub (sub) { + this.subs.push(sub); +}; -var supportsPassive = false; -if (inBrowser) { - try { - var opts = {}; - Object.defineProperty(opts, 'passive', ({ - get: function get () { - /* istanbul ignore next */ - supportsPassive = true; - } - } )); // https://github.com/facebook/flow/issues/285 - window.addEventListener('test-passive', null, opts); - } catch (e) {} -} +Dep.prototype.removeSub = function removeSub (sub) { + remove(this.subs, sub); +}; -// 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; - } +Dep.prototype.depend = function depend () { + if (Dep.target) { + Dep.target.addDep(this); } - return _isServer }; -// detect devtools -var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; - -/* istanbul ignore next */ -function isNative (Ctor) { - return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) -} +Dep.prototype.notify = function notify () { + // stabilize the subscriber list first + var subs = this.subs.slice(); + for (var i = 0, l = subs.length; i < l; i++) { + subs[i].update(); + } +}; -var hasSymbol = - typeof Symbol !== 'undefined' && isNative(Symbol) && - typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys); - -/** - * 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 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); } - }; - } 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); - }; - } else { - // fallback to setTimeout - /* istanbul ignore next */ - timerFunc = function () { - setTimeout(nextTickHandler, 0); - }; - } - - return function queueNextTick (cb, ctx) { - var _resolve; - callbacks.push(function () { - if (cb) { - try { - cb.call(ctx); - } catch (e) { - handleError(e, ctx, 'nextTick'); - } - } else if (_resolve) { - _resolve(ctx); - } - }); - if (!pending) { - pending = true; - timerFunc(); - } - if (!cb && typeof Promise !== 'undefined') { - return new Promise(function (resolve, reject) { - _resolve = resolve; - }) - } - } -})(); +// 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 = []; -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); - }; +function pushTarget (_target) { + if (Dep.target) { targetStack.push(Dep.target); } + Dep.target = _target; +} - return Set; - }()); +function popTarget () { + Dep.target = targetStack.pop(); } /* */ - -var uid = 0; - -/** - * A dep is an observable that can have multiple - * directives subscribing to it. - */ -var Dep = function Dep () { - this.id = uid++; - this.subs = []; +var VNode = function VNode ( + tag, + data, + children, + text, + elm, + context, + componentOptions, + asyncFactory +) { + this.tag = tag; + this.data = data; + this.children = children; + this.text = text; + this.elm = elm; + this.ns = undefined; + this.context = context; + this.fnContext = undefined; + this.fnOptions = undefined; + this.fnScopeId = undefined; + this.key = data && data.key; + this.componentOptions = componentOptions; + this.componentInstance = undefined; + this.parent = undefined; + this.raw = false; + this.isStatic = false; + this.isRootInsert = true; + this.isComment = false; + this.isCloned = false; + this.isOnce = false; + this.asyncFactory = asyncFactory; + this.asyncMeta = undefined; + this.isAsyncPlaceholder = false; }; -Dep.prototype.addSub = function addSub (sub) { - this.subs.push(sub); -}; +var prototypeAccessors = { child: { configurable: true } }; -Dep.prototype.removeSub = function removeSub (sub) { - remove(this.subs, sub); +// DEPRECATED: alias for componentInstance for backwards compat. +/* istanbul ignore next */ +prototypeAccessors.child.get = function () { + return this.componentInstance }; -Dep.prototype.depend = function depend () { - if (Dep.target) { - Dep.target.addDep(this); - } -}; +Object.defineProperties( VNode.prototype, prototypeAccessors ); -Dep.prototype.notify = function notify () { - // stabilize the subscriber list first - var subs = this.subs.slice(); - for (var i = 0, l = subs.length; i < l; i++) { - subs[i].update(); - } +var createEmptyVNode = function (text) { + if ( text === void 0 ) text = ''; + + var node = new VNode(); + node.text = text; + node.isComment = true; + return node }; -// 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 createTextVNode (val) { + return new VNode(undefined, undefined, undefined, String(val)) +} -function pushTarget (_target) { - if (Dep.target) { targetStack.push(Dep.target); } - Dep.target = _target; +// optimized shallow clone +// used for static nodes and slot nodes because they may be reused across +// multiple renders, cloning them avoids errors when DOM manipulations rely +// on their elm reference. +function cloneVNode (vnode, deep) { + var componentOptions = vnode.componentOptions; + var cloned = new VNode( + vnode.tag, + vnode.data, + vnode.children, + vnode.text, + vnode.elm, + vnode.context, + componentOptions, + vnode.asyncFactory + ); + cloned.ns = vnode.ns; + cloned.isStatic = vnode.isStatic; + cloned.key = vnode.key; + cloned.isComment = vnode.isComment; + cloned.fnContext = vnode.fnContext; + cloned.fnOptions = vnode.fnOptions; + cloned.fnScopeId = vnode.fnScopeId; + cloned.isCloned = true; + if (deep) { + if (vnode.children) { + cloned.children = cloneVNodes(vnode.children, true); + } + if (componentOptions && componentOptions.children) { + componentOptions.children = cloneVNodes(componentOptions.children, true); + } + } + return cloned } -function popTarget () { - Dep.target = targetStack.pop(); +function cloneVNodes (vnodes, deep) { + var len = vnodes.length; + var res = new Array(len); + for (var i = 0; i < len; i++) { + res[i] = cloneVNode(vnodes[i], deep); + } + return res } /* @@ -1053,22 +1142,14 @@ var arrayMethods = Object.create(arrayProto);[ // cache original method var original = arrayProto[method]; def(arrayMethods, method, function mutator () { - var arguments$1 = arguments; + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; - // 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 @@ -1094,8 +1175,7 @@ var arrayKeys = Object.getOwnPropertyNames(arrayMethods); * under a frozen data structure. Converting it would defeat the optimization. */ var observerState = { - shouldConvert: true, - isSettingProps: false + shouldConvert: true }; /** @@ -1128,7 +1208,7 @@ var Observer = function Observer (value) { 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]]); + defineReactive(obj, keys[i], obj[keys[i]]); } }; @@ -1147,7 +1227,7 @@ Observer.prototype.observeArray = function observeArray (items) { * Augment an target Object or Array by intercepting * the prototype chain using __proto__ */ -function protoAugment (target, src) { +function protoAugment (target, src, keys) { /* eslint-disable no-proto */ target.__proto__ = src; /* eslint-enable no-proto */ @@ -1171,7 +1251,7 @@ function copyAugment (target, src, keys) { * or the existing observer if the value already has one. */ function observe (value, asRootData) { - if (!isObject(value)) { + if (!isObject(value) || value instanceof VNode) { return } var ob; @@ -1195,11 +1275,12 @@ function observe (value, asRootData) { /** * Define a reactive property on an Object. */ -function defineReactive$$1 ( +function defineReactive ( obj, key, val, - customSetter + customSetter, + shallow ) { var dep = new Dep(); @@ -1212,7 +1293,7 @@ function defineReactive$$1 ( var getter = property && property.get; var setter = property && property.set; - var childOb = observe(val); + var childOb = !shallow && observe(val); Object.defineProperty(obj, key, { enumerable: true, configurable: true, @@ -1222,9 +1303,9 @@ function defineReactive$$1 ( dep.depend(); if (childOb) { childOb.dep.depend(); - } - if (Array.isArray(value)) { - dependArray(value); + if (Array.isArray(value)) { + dependArray(value); + } } } return value @@ -1244,7 +1325,7 @@ function defineReactive$$1 ( } else { val = newVal; } - childOb = observe(newVal); + childOb = !shallow && observe(newVal); dep.notify(); } }); @@ -1256,16 +1337,16 @@ function defineReactive$$1 ( * already exist. */ function set (target, key, val) { - if (Array.isArray(target) && typeof key === 'number') { + if (Array.isArray(target) && isValidArrayIndex(key)) { target.length = Math.max(target.length, key); target.splice(key, 1, val); return val } - if (hasOwn(target, key)) { + if (key in target && !(key in Object.prototype)) { target[key] = val; return val } - var ob = (target ).__ob__; + var ob = (target).__ob__; if (target._isVue || (ob && ob.vmCount)) { "development" !== 'production' && warn( 'Avoid adding reactive properties to a Vue instance or its root $data ' + @@ -1277,7 +1358,7 @@ function set (target, key, val) { target[key] = val; return val } - defineReactive$$1(ob.value, key, val); + defineReactive(ob.value, key, val); ob.dep.notify(); return val } @@ -1286,11 +1367,11 @@ function set (target, key, val) { * Delete a property and trigger change if necessary. */ function del (target, key) { - if (Array.isArray(target) && typeof key === 'number') { + if (Array.isArray(target) && isValidArrayIndex(key)) { target.splice(key, 1); return } - var ob = (target ).__ob__; + var ob = (target).__ob__; if (target._isVue || (ob && ob.vmCount)) { "development" !== 'production' && warn( 'Avoid deleting properties on a Vue instance or its root $data ' + @@ -1369,7 +1450,7 @@ function mergeData (to, from) { /** * Data */ -strats.data = function ( +function mergeDataOrFn ( parentVal, childVal, vm @@ -1379,15 +1460,6 @@ strats.data = function ( 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 } @@ -1398,11 +1470,11 @@ strats.data = function ( // it has to be a function to pass previous merges. return function mergedDataFn () { return mergeData( - childVal.call(this), - parentVal.call(this) + typeof childVal === 'function' ? childVal.call(this) : childVal, + typeof parentVal === 'function' ? parentVal.call(this) : parentVal ) } - } else if (parentVal || childVal) { + } else { return function mergedInstanceDataFn () { // instance merge var instanceData = typeof childVal === 'function' @@ -1410,7 +1482,7 @@ strats.data = function ( : childVal; var defaultData = typeof parentVal === 'function' ? parentVal.call(vm) - : undefined; + : parentVal; if (instanceData) { return mergeData(instanceData, defaultData) } else { @@ -1418,6 +1490,28 @@ strats.data = function ( } } } +} + +strats.data = function ( + parentVal, + childVal, + vm +) { + if (!vm) { + if (childVal && 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 + } + return mergeDataOrFn(parentVal, childVal) + } + + return mergeDataOrFn(parentVal, childVal, vm) }; /** @@ -1447,11 +1541,19 @@ LIFECYCLE_HOOKS.forEach(function (hook) { * a three-way merge between constructor options, instance * options and parent options. */ -function mergeAssets (parentVal, childVal) { +function mergeAssets ( + parentVal, + childVal, + vm, + key +) { var res = Object.create(parentVal || null); - return childVal - ? extend(res, childVal) - : res + if (childVal) { + "development" !== 'production' && assertObjectType(key, childVal, vm); + return extend(res, childVal) + } else { + return res + } } ASSET_TYPES.forEach(function (type) { @@ -1464,21 +1566,32 @@ ASSET_TYPES.forEach(function (type) { * Watchers hashes should not overwrite one * another, so we merge them as arrays. */ -strats.watch = function (parentVal, childVal) { +strats.watch = function ( + parentVal, + childVal, + vm, + key +) { + // work around Firefox's Object.prototype.watch... + if (parentVal === nativeWatch) { parentVal = undefined; } + if (childVal === nativeWatch) { childVal = undefined; } /* istanbul ignore if */ if (!childVal) { return Object.create(parentVal || null) } + { + assertObjectType(key, childVal, vm); + } if (!parentVal) { return childVal } var ret = {}; extend(ret, parentVal); - for (var key in childVal) { - var parent = ret[key]; - var child = childVal[key]; + for (var key$1 in childVal) { + var parent = ret[key$1]; + var child = childVal[key$1]; if (parent && !Array.isArray(parent)) { parent = [parent]; } - ret[key] = parent + ret[key$1] = parent ? parent.concat(child) - : [child]; + : Array.isArray(child) ? child : [child]; } return ret }; @@ -1488,14 +1601,23 @@ strats.watch = function (parentVal, childVal) { */ strats.props = strats.methods = -strats.computed = function (parentVal, childVal) { - if (!childVal) { return Object.create(parentVal || null) } +strats.inject = +strats.computed = function ( + parentVal, + childVal, + vm, + key +) { + if (childVal && "development" !== 'production') { + assertObjectType(key, childVal, vm); + } if (!parentVal) { return childVal } var ret = Object.create(null); extend(ret, parentVal); - extend(ret, childVal); + if (childVal) { extend(ret, childVal); } return ret }; +strats.provide = mergeDataOrFn; /** * Default strategy. @@ -1525,7 +1647,7 @@ function checkComponents (options) { * Ensure all props option syntax are normalized into the * Object-based format. */ -function normalizeProps (options) { +function normalizeProps (options, vm) { var props = options.props; if (!props) { return } var res = {}; @@ -1549,10 +1671,42 @@ function normalizeProps (options) { ? val : { type: val }; } + } else { + warn( + "Invalid value for option \"props\": expected an Array or an Object, " + + "but got " + (toRawType(props)) + ".", + vm + ); } options.props = res; } +/** + * Normalize all injections into Object-based format + */ +function normalizeInject (options, vm) { + var inject = options.inject; + var normalized = options.inject = {}; + if (Array.isArray(inject)) { + for (var i = 0; i < inject.length; i++) { + normalized[inject[i]] = { from: inject[i] }; + } + } else if (isPlainObject(inject)) { + for (var key in inject) { + var val = inject[key]; + normalized[key] = isPlainObject(val) + ? extend({ from: key }, val) + : { from: val }; + } + } else if ("development" !== 'production' && inject) { + warn( + "Invalid value for option \"inject\": expected an Array or an Object, " + + "but got " + (toRawType(inject)) + ".", + vm + ); + } +} + /** * Normalize raw function directives into object format. */ @@ -1568,6 +1722,16 @@ function normalizeDirectives (options) { } } +function assertObjectType (name, value, vm) { + if (!isPlainObject(value)) { + warn( + "Invalid value for option \"" + name + "\": expected an Object, " + + "but got " + (toRawType(value)) + ".", + vm + ); + } +} + /** * Merge two option objects into a new one. * Core utility used in both instantiation and inheritance. @@ -1585,7 +1749,8 @@ function mergeOptions ( child = child.options; } - normalizeProps(child); + normalizeProps(child, vm); + normalizeInject(child, vm); normalizeDirectives(child); var extendsFrom = child.extends; if (extendsFrom) { @@ -1749,9 +1914,9 @@ function assertProp ( } 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) + '.', + "Invalid prop: type check failed for prop \"" + name + "\"." + + " Expected " + (expectedTypes.map(capitalize).join(', ')) + + ", got " + (toRawType(value)) + ".", vm ); return @@ -1773,7 +1938,12 @@ function assertType (value, type) { var valid; var expectedType = getType(type); if (simpleCheckRE.test(expectedType)) { - valid = typeof value === expectedType.toLowerCase(); + var t = typeof value; + valid = t === expectedType.toLowerCase(); + // for primitive wrapper objects + if (!valid && t === 'object') { + valid = value instanceof type; + } } else if (expectedType === 'Object') { valid = isPlainObject(value); } else if (expectedType === 'Array') { @@ -1812,22 +1982,181 @@ function isType (type, fn) { /* */ -var mark; -var measure; +function handleError (err, vm, info) { + if (vm) { + var cur = vm; + while ((cur = cur.$parent)) { + var hooks = cur.$options.errorCaptured; + if (hooks) { + for (var i = 0; i < hooks.length; i++) { + try { + var capture = hooks[i].call(cur, err, vm, info) === false; + if (capture) { return } + } catch (e) { + globalHandleError(e, cur, 'errorCaptured hook'); + } + } + } + } + } + globalHandleError(err, vm, info); +} -{ - var perf = inBrowser && window.performance; - /* istanbul ignore if */ - if ( - perf && - perf.mark && - perf.measure && - perf.clearMarks && - perf.clearMeasures - ) { - mark = function (tag) { return perf.mark(tag); }; - measure = function (name, startTag, endTag) { - perf.measure(name, startTag, endTag); +function globalHandleError (err, vm, info) { + if (config.errorHandler) { + try { + return config.errorHandler.call(null, err, vm, info) + } catch (e) { + logError(e, null, 'config.errorHandler'); + } + } + logError(err, vm, info); +} + +function logError (err, vm, info) { + { + warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm); + } + /* istanbul ignore else */ + if ((inBrowser || inWeex) && typeof console !== 'undefined') { + console.error(err); + } else { + throw err + } +} + +/* */ +/* globals MessageChannel */ + +var callbacks = []; +var pending = false; + +function flushCallbacks () { + pending = false; + var copies = callbacks.slice(0); + callbacks.length = 0; + for (var i = 0; i < copies.length; i++) { + copies[i](); + } +} + +// Here we have async deferring wrappers using both micro and macro tasks. +// In < 2.4 we used micro tasks everywhere, but there are some scenarios where +// micro tasks have too high a priority and fires in between supposedly +// sequential events (e.g. #4521, #6690) or even between bubbling of the same +// event (#6566). However, using macro tasks everywhere also has subtle problems +// when state is changed right before repaint (e.g. #6813, out-in transitions). +// Here we use micro task by default, but expose a way to force macro task when +// needed (e.g. in event handlers attached by v-on). +var microTimerFunc; +var macroTimerFunc; +var useMacroTask = false; + +// Determine (macro) Task defer implementation. +// Technically setImmediate should be the ideal choice, but it's only available +// in IE. The only polyfill that consistently queues the callback after all DOM +// events triggered in the same loop is by using MessageChannel. +/* istanbul ignore if */ +if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { + macroTimerFunc = function () { + setImmediate(flushCallbacks); + }; +} else if (typeof MessageChannel !== 'undefined' && ( + isNative(MessageChannel) || + // PhantomJS + MessageChannel.toString() === '[object MessageChannelConstructor]' +)) { + var channel = new MessageChannel(); + var port = channel.port2; + channel.port1.onmessage = flushCallbacks; + macroTimerFunc = function () { + port.postMessage(1); + }; +} else { + /* istanbul ignore next */ + macroTimerFunc = function () { + setTimeout(flushCallbacks, 0); + }; +} + +// Determine MicroTask defer implementation. +/* istanbul ignore next, $flow-disable-line */ +if (typeof Promise !== 'undefined' && isNative(Promise)) { + var p = Promise.resolve(); + microTimerFunc = function () { + p.then(flushCallbacks); + // in problematic UIWebViews, Promise.then doesn't completely break, but + // it can get stuck in a weird state where callbacks are pushed into the + // microtask queue but the queue isn't being flushed, until the browser + // needs to do some other work, e.g. handle a timer. Therefore we can + // "force" the microtask queue to be flushed by adding an empty timer. + if (isIOS) { setTimeout(noop); } + }; +} else { + // fallback to macro + microTimerFunc = macroTimerFunc; +} + +/** + * Wrap a function so that if any code inside triggers state change, + * the changes are queued using a Task instead of a MicroTask. + */ +function withMacroTask (fn) { + return fn._withTask || (fn._withTask = function () { + useMacroTask = true; + var res = fn.apply(null, arguments); + useMacroTask = false; + return res + }) +} + +function nextTick (cb, ctx) { + var _resolve; + callbacks.push(function () { + if (cb) { + try { + cb.call(ctx); + } catch (e) { + handleError(e, ctx, 'nextTick'); + } + } else if (_resolve) { + _resolve(ctx); + } + }); + if (!pending) { + pending = true; + if (useMacroTask) { + macroTimerFunc(); + } else { + microTimerFunc(); + } + } + // $flow-disable-line + if (!cb && typeof Promise !== 'undefined') { + return new Promise(function (resolve) { + _resolve = resolve; + }) + } +} + +/* */ + +var mark; +var measure; + +{ + var perf = inBrowser && window.performance; + /* istanbul ignore if */ + if ( + perf && + perf.mark && + perf.measure && + perf.clearMarks && + perf.clearMeasures + ) { + mark = function (tag) { return perf.mark(tag); }; + measure = function (name, startTag, endTag) { + perf.measure(name, startTag, endTag); perf.clearMarks(startTag); perf.clearMarks(endTag); perf.clearMeasures(name); @@ -1850,8 +2179,10 @@ var initProxy; 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.", + 'referenced during render. Make sure that this property is reactive, ' + + 'either in the data option, or for class-based components, by ' + + 'initializing the property. ' + + 'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.', target ); }; @@ -1861,7 +2192,7 @@ var initProxy; Proxy.toString().match(/native code/); if (hasProxy) { - var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta'); + var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact'); config.keyCodes = new Proxy(config.keyCodes, { set: function set (target, key, value) { if (isBuiltInModifier(key)) { @@ -1911,85 +2242,39 @@ var initProxy; /* */ -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.componentInstance = undefined; - this.parent = undefined; - this.raw = false; - this.isStatic = false; - this.isRootInsert = true; - this.isComment = false; - this.isCloned = false; - this.isOnce = false; -}; - -var prototypeAccessors = { child: {} }; - -// DEPRECATED: alias for componentInstance for backwards compat. -/* istanbul ignore next */ -prototypeAccessors.child.get = function () { - return this.componentInstance -}; - -Object.defineProperties( VNode.prototype, prototypeAccessors ); - -var createEmptyVNode = function () { - var node = new VNode(); - node.text = ''; - node.isComment = true; - return node -}; - -function createTextVNode (val) { - return new VNode(undefined, undefined, undefined, String(val)) -} +var seenObjects = new _Set(); -// optimized shallow clone -// used for static nodes and slot nodes because they may be reused across -// multiple renders, cloning them avoids errors when DOM manipulations rely -// on their elm reference. -function cloneVNode (vnode) { - var cloned = new VNode( - vnode.tag, - vnode.data, - vnode.children, - vnode.text, - vnode.elm, - vnode.context, - vnode.componentOptions - ); - cloned.ns = vnode.ns; - cloned.isStatic = vnode.isStatic; - cloned.key = vnode.key; - cloned.isComment = vnode.isComment; - cloned.isCloned = true; - return cloned +/** + * Recursively traverse an object to evoke all converted + * getters, so that every nested property inside the object + * is collected as a "deep" dependency. + */ +function traverse (val) { + _traverse(val, seenObjects); + seenObjects.clear(); } -function cloneVNodes (vnodes) { - var len = vnodes.length; - var res = new Array(len); - for (var i = 0; i < len; i++) { - res[i] = cloneVNode(vnodes[i]); +function _traverse (val, seen) { + var i, keys; + var isA = Array.isArray(val); + if ((!isA && !isObject(val)) || Object.isFrozen(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); } } - return res } /* */ @@ -2015,8 +2300,9 @@ function createFnInvoker (fns) { var fns = invoker.fns; if (Array.isArray(fns)) { - for (var i = 0; i < fns.length; i++) { - fns[i].apply(null, arguments$1); + var cloned = fns.slice(); + for (var i = 0; i < cloned.length; i++) { + cloned[i].apply(null, arguments$1); } } else { // return handler return value for single handlers @@ -2065,6 +2351,9 @@ function updateListeners ( /* */ function mergeVNodeHook (def, hookKey, hook) { + if (def instanceof VNode) { + def = def.data.hook || (def.data.hook = {}); + } var invoker; var oldHook = def[hookKey]; @@ -2203,20 +2492,29 @@ function isTextNode (node) { function normalizeArrayChildren (children, nestedIndex) { var res = []; - var i, c, last; + var i, c, lastIndex, last; for (i = 0; i < children.length; i++) { c = children[i]; if (isUndef(c) || typeof c === 'boolean') { continue } - last = res[res.length - 1]; + lastIndex = res.length - 1; + last = res[lastIndex]; // nested if (Array.isArray(c)) { - res.push.apply(res, normalizeArrayChildren(c, ((nestedIndex || '') + "_" + i))); + if (c.length > 0) { + c = normalizeArrayChildren(c, ((nestedIndex || '') + "_" + i)); + // merge adjacent text nodes + if (isTextNode(c[0]) && isTextNode(last)) { + res[lastIndex] = createTextVNode(last.text + (c[0]).text); + c.shift(); + } + res.push.apply(res, c); + } } else if (isPrimitive(c)) { if (isTextNode(last)) { // merge adjacent text nodes // this is necessary for SSR hydration because text nodes are // essentially merged when rendered to HTML strings - (last).text += String(c); + res[lastIndex] = createTextVNode(last.text + c); } else if (c !== '') { // convert primitive to vnode res.push(createTextVNode(c)); @@ -2224,7 +2522,7 @@ function normalizeArrayChildren (children, nestedIndex) { } else { if (isTextNode(c) && isTextNode(last)) { // merge adjacent text nodes - res[res.length - 1] = createTextVNode(last.text + c.text); + res[lastIndex] = createTextVNode(last.text + c.text); } else { // default key for nested array children (likely generated by v-for) if (isTrue(children._isVList) && @@ -2243,11 +2541,30 @@ function normalizeArrayChildren (children, nestedIndex) { /* */ function ensureCtor (comp, base) { + if ( + comp.__esModule || + (hasSymbol && comp[Symbol.toStringTag] === 'Module') + ) { + comp = comp.default; + } return isObject(comp) ? base.extend(comp) : comp } +function createAsyncPlaceholder ( + factory, + data, + context, + children, + tag +) { + var node = createEmptyVNode(); + node.asyncFactory = factory; + node.asyncMeta = { data: data, context: context, children: children, tag: tag }; + return node +} + function resolveAsyncComponent ( factory, baseCtor, @@ -2350,11 +2667,17 @@ function resolveAsyncComponent ( /* */ +function isAsyncPlaceholder (node) { + return node.isComment && node.asyncFactory +} + +/* */ + function getFirstComponentChild (children) { if (Array.isArray(children)) { for (var i = 0; i < children.length; i++) { var c = children[i]; - if (isDef(c) && isDef(c.componentOptions)) { + if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) { return c } } @@ -2377,8 +2700,8 @@ function initEvents (vm) { var target; -function add (event, fn, once$$1) { - if (once$$1) { +function add (event, fn, once) { + if (once) { target.$once(event, fn); } else { target.$on(event, fn); @@ -2396,6 +2719,7 @@ function updateComponentListeners ( ) { target = vm; updateListeners(listeners, oldListeners || {}, add, remove$1, vm); + target = undefined; } function eventsMixin (Vue) { @@ -2441,8 +2765,8 @@ function eventsMixin (Vue) { } // array of events if (Array.isArray(event)) { - for (var i$1 = 0, l = event.length; i$1 < l; i$1++) { - this$1.$off(event[i$1], fn); + for (var i = 0, l = event.length; i < l; i++) { + this$1.$off(event[i], fn); } return vm } @@ -2451,18 +2775,20 @@ function eventsMixin (Vue) { if (!cbs) { return vm } - if (arguments.length === 1) { + if (!fn) { vm._events[event] = null; return vm } - // specific handler - var cb; - var i = cbs.length; - while (i--) { - cb = cbs[i]; - if (cb === fn || cb.fn === fn) { - cbs.splice(i, 1); - break + if (fn) { + // specific handler + var cb; + var i$1 = cbs.length; + while (i$1--) { + cb = cbs[i$1]; + if (cb === fn || cb.fn === fn) { + cbs.splice(i$1, 1); + break + } } } return vm @@ -2487,7 +2813,11 @@ function eventsMixin (Vue) { cbs = cbs.length > 1 ? toArray(cbs) : cbs; var args = toArray(arguments, 1); for (var i = 0, l = cbs.length; i < l; i++) { - cbs[i].apply(vm, args); + try { + cbs[i].apply(vm, args); + } catch (e) { + handleError(e, vm, ("event handler for \"" + event + "\"")); + } } } return vm @@ -2507,13 +2837,17 @@ function resolveSlots ( if (!children) { return slots } - var defaultSlot = []; for (var i = 0, l = children.length; i < l; i++) { var child = children[i]; + var data = child.data; + // remove slot attribute if the node is resolved as a Vue slot node + if (data && data.attrs && data.attrs.slot) { + delete data.attrs.slot; + } // named slots should only be respected if the vnode was rendered in the // same context. - if ((child.context === context || child.functionalContext === context) && - child.data && child.data.slot != null + if ((child.context === context || child.fnContext === context) && + data && data.slot != null ) { var name = child.data.slot; var slot = (slots[name] || (slots[name] = [])); @@ -2523,18 +2857,20 @@ function resolveSlots ( slot.push(child); } } else { - defaultSlot.push(child); + (slots.default || (slots.default = [])).push(child); } } - // ignore whitespace - if (!defaultSlot.every(isWhitespace)) { - slots.default = defaultSlot; + // ignore slots that contains only whitespace + for (var name$1 in slots) { + if (slots[name$1].every(isWhitespace)) { + delete slots[name$1]; + } } return slots } function isWhitespace (node) { - return node.isComment || node.text === ' ' + return (node.isComment && !node.asyncFactory) || node.text === ' ' } function resolveScopedSlots ( @@ -2555,6 +2891,7 @@ function resolveScopedSlots ( /* */ var activeInstance = null; +var isUpdatingChildComponent = false; function initLifecycle (vm) { var options = vm.$options; @@ -2602,6 +2939,9 @@ function lifecycleMixin (Vue) { vm.$options._parentElm, vm.$options._refElm ); + // no need for the ref nodes after initial patch + // this prevents keeping a detached DOM tree in memory (#5851) + vm.$options._parentElm = vm.$options._refElm = null; } else { // updates vm.$el = vm.__patch__(prevVnode, vnode); @@ -2666,8 +3006,10 @@ function lifecycleMixin (Vue) { if (vm.$el) { vm.$el.__vue__ = null; } - // remove reference to DOM nodes (prevents leak) - vm.$options._parentElm = vm.$options._refElm = null; + // release circular reference (#6759) + if (vm.$vnode) { + vm.$vnode.parent = null; + } }; } @@ -2711,12 +3053,12 @@ function mountComponent ( mark(startTag); var vnode = vm._render(); mark(endTag); - measure((name + " render"), startTag, endTag); + measure(("vue " + name + " render"), startTag, endTag); mark(startTag); vm._update(vnode, hydrating); mark(endTag); - measure((name + " patch"), startTag, endTag); + measure(("vue " + name + " patch"), startTag, endTag); }; } else { updateComponent = function () { @@ -2724,7 +3066,10 @@ function mountComponent ( }; } - vm._watcher = new Watcher(vm, updateComponent, noop); + // we set this to vm._watcher inside the watcher's constructor + // since the watcher's initial patch may call $forceUpdate (e.g. inside child + // component's mounted hook), which relies on vm._watcher being already defined + new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */); hydrating = false; // manually mounted instance, call mounted on self @@ -2743,6 +3088,10 @@ function updateChildComponent ( parentVnode, renderChildren ) { + { + isUpdatingChildComponent = true; + } + // determine whether component has slot children // we need to do this before overwriting $options._renderChildren var hasChildren = !!( @@ -2754,17 +3103,21 @@ function updateChildComponent ( vm.$options._parentVnode = parentVnode; vm.$vnode = parentVnode; // update vm's placeholder node without re-render + if (vm._vnode) { // update child tree's parent vm._vnode.parent = parentVnode; } vm.$options._renderChildren = renderChildren; + // update $attrs and $listeners hash + // these are also reactive so they may trigger child update if the child + // used them during render + vm.$attrs = (parentVnode.data && parentVnode.data.attrs) || emptyObject; + vm.$listeners = listeners || emptyObject; + // update props if (propsData && vm.$options.props) { observerState.shouldConvert = false; - { - observerState.isSettingProps = true; - } var props = vm._props; var propKeys = vm.$options._propKeys || []; for (var i = 0; i < propKeys.length; i++) { @@ -2772,12 +3125,10 @@ function updateChildComponent ( props[key] = validateProp(key, vm.$options.props, propsData, vm); } observerState.shouldConvert = true; - { - observerState.isSettingProps = false; - } // keep a copy of raw propsData vm.$options.propsData = propsData; } + // update listeners if (listeners) { var oldListeners = vm.$options._parentListeners; @@ -2789,6 +3140,10 @@ function updateChildComponent ( vm.$slots = resolveSlots(renderChildren, parentVnode.context); vm.$forceUpdate(); } + + { + isUpdatingChildComponent = false; + } } function isInInactiveTree (vm) { @@ -2922,7 +3277,7 @@ function flushSchedulerQueue () { // call component updated and activated hooks callActivatedHooks(activatedQueue); - callUpdateHooks(updatedQueue); + callUpdatedHooks(updatedQueue); // devtool hook /* istanbul ignore if */ @@ -2931,7 +3286,7 @@ function flushSchedulerQueue () { } } -function callUpdateHooks (queue) { +function callUpdatedHooks (queue) { var i = queue.length; while (i--) { var watcher = queue[i]; @@ -3001,9 +3356,13 @@ var Watcher = function Watcher ( vm, expOrFn, cb, - options + options, + isRenderWatcher ) { this.vm = vm; + if (isRenderWatcher) { + vm._watcher = this; + } vm._watchers.push(this); // options if (options) { @@ -3050,22 +3409,23 @@ Watcher.prototype.get = function get () { pushTarget(this); var value; var vm = this.vm; - if (this.user) { - try { - value = this.getter.call(vm, vm); - } catch (e) { + try { + value = this.getter.call(vm, vm); + } catch (e) { + if (this.user) { handleError(e, vm, ("getter for watcher \"" + (this.expression) + "\"")); + } else { + throw e } - } else { - value = this.getter.call(vm, vm); - } - // "touch" every property so they are all tracked as - // dependencies for deep watching - if (this.deep) { - traverse(value); + } finally { + // "touch" every property so they are all tracked as + // dependencies for deep watching + if (this.deep) { + traverse(value); + } + popTarget(); + this.cleanupDeps(); } - popTarget(); - this.cleanupDeps(); return value }; @@ -3194,40 +3554,6 @@ Watcher.prototype.teardown = function teardown () { } }; -/** - * 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); } - } -} - /* */ var sharedPropertyDefinition = { @@ -3258,15 +3584,11 @@ function initState (vm) { observe(vm._data = {}, true /* asRootData */); } if (opts.computed) { initComputed(vm, opts.computed); } - if (opts.watch) { initWatch(vm, opts.watch); } + if (opts.watch && opts.watch !== nativeWatch) { + initWatch(vm, opts.watch); + } } -var isReservedProp = { - key: 1, - ref: 1, - slot: 1 -}; - function initProps (vm, propsOptions) { var propsData = vm.$options.propsData || {}; var props = vm._props = {}; @@ -3281,14 +3603,16 @@ function initProps (vm, propsOptions) { var value = validateProp(key, propsOptions, propsData, vm); /* istanbul ignore else */ { - if (isReservedProp[key] || config.isReservedAttr(key)) { + var hyphenatedKey = hyphenate(key); + if (isReservedAttribute(hyphenatedKey) || + config.isReservedAttr(hyphenatedKey)) { warn( - ("\"" + key + "\" is a reserved attribute and cannot be used as component prop."), + ("\"" + hyphenatedKey + "\" is a reserved attribute and cannot be used as component prop."), vm ); } - defineReactive$$1(props, key, value, function () { - if (vm.$parent && !observerState.isSettingProps) { + defineReactive(props, key, value, function () { + if (vm.$parent && !isUpdatingChildComponent) { warn( "Avoid mutating a prop directly since the value will be " + "overwritten whenever the parent component re-renders. " + @@ -3327,25 +3651,35 @@ function initData (vm) { // proxy data on instance var keys = Object.keys(data); var props = vm.$options.props; + var methods = vm.$options.methods; var i = keys.length; while (i--) { - if (props && hasOwn(props, keys[i])) { - "development" !== 'production' && warn( - "The data property \"" + (keys[i]) + "\" is already declared as a prop. " + - "Use prop default value instead.", - vm - ); - } else if (!isReserved(keys[i])) { - proxy(vm, "_data", keys[i]); - } - } + var key = keys[i]; + { + if (methods && hasOwn(methods, key)) { + warn( + ("Method \"" + key + "\" has already been defined as a data property."), + vm + ); + } + } + if (props && hasOwn(props, key)) { + "development" !== 'production' && warn( + "The data property \"" + key + "\" is already declared as a prop. " + + "Use prop default value instead.", + vm + ); + } else if (!isReserved(key)) { + proxy(vm, "_data", key); + } + } // observe data observe(data, true /* asRootData */); } function getData (data, vm) { try { - return data.call(vm) + return data.call(vm, vm) } catch (e) { handleError(e, vm, "data()"); return {} @@ -3356,21 +3690,28 @@ var computedWatcherOptions = { lazy: true }; function initComputed (vm, computed) { var watchers = vm._computedWatchers = Object.create(null); + // computed properties are just getters during SSR + var isSSR = isServerRendering(); for (var key in computed) { var userDef = computed[key]; var getter = typeof userDef === 'function' ? userDef : userDef.get; - { - if (getter === undefined) { - warn( - ("No getter function has been defined for computed property \"" + key + "\"."), - vm - ); - getter = noop; - } + if ("development" !== 'production' && getter == null) { + warn( + ("Getter is missing for computed property \"" + key + "\"."), + vm + ); + } + + if (!isSSR) { + // create internal watcher for the computed property. + watchers[key] = new Watcher( + vm, + getter || noop, + noop, + computedWatcherOptions + ); } - // create internal watcher for the computed property. - watchers[key] = new Watcher(vm, getter, noop, computedWatcherOptions); // component-defined computed properties are already defined on the // component prototype. We only need to define computed properties defined @@ -3387,13 +3728,20 @@ function initComputed (vm, computed) { } } -function defineComputed (target, key, userDef) { +function defineComputed ( + target, + key, + userDef +) { + var shouldCache = !isServerRendering(); if (typeof userDef === 'function') { - sharedPropertyDefinition.get = createComputedGetter(key); + sharedPropertyDefinition.get = shouldCache + ? createComputedGetter(key) + : userDef; sharedPropertyDefinition.set = noop; } else { sharedPropertyDefinition.get = userDef.get - ? userDef.cache !== false + ? shouldCache && userDef.cache !== false ? createComputedGetter(key) : userDef.get : noop; @@ -3401,6 +3749,15 @@ function defineComputed (target, key, userDef) { ? userDef.set : noop; } + if ("development" !== 'production' && + sharedPropertyDefinition.set === noop) { + sharedPropertyDefinition.set = function () { + warn( + ("Computed property \"" + key + "\" was assigned to but it has no setter."), + this + ); + }; + } Object.defineProperty(target, key, sharedPropertyDefinition); } @@ -3422,22 +3779,28 @@ function createComputedGetter (key) { function initMethods (vm, methods) { var props = vm.$options.props; for (var key in methods) { - vm[key] = methods[key] == null ? noop : bind(methods[key], vm); { if (methods[key] == null) { warn( - "method \"" + key + "\" has an undefined value in the component definition. " + + "Method \"" + key + "\" has an undefined value in the component definition. " + "Did you reference the function correctly?", vm ); } if (props && hasOwn(props, key)) { warn( - ("method \"" + key + "\" has already been defined as a prop."), + ("Method \"" + key + "\" has already been defined as a prop."), vm ); } + if ((key in vm) && isReserved(key)) { + warn( + "Method \"" + key + "\" conflicts with an existing Vue instance method. " + + "Avoid defining component methods that start with _ or $." + ); + } } + vm[key] = methods[key] == null ? noop : bind(methods[key], vm); } } @@ -3454,8 +3817,12 @@ function initWatch (vm, watch) { } } -function createWatcher (vm, key, handler) { - var options; +function createWatcher ( + vm, + keyOrFn, + handler, + options +) { if (isPlainObject(handler)) { options = handler; handler = handler.handler; @@ -3463,7 +3830,7 @@ function createWatcher (vm, key, handler) { if (typeof handler === 'string') { handler = vm[handler]; } - vm.$watch(key, handler, options); + return vm.$watch(keyOrFn, handler, options) } function stateMixin (Vue) { @@ -3498,6 +3865,9 @@ function stateMixin (Vue) { options ) { var vm = this; + if (isPlainObject(cb)) { + return createWatcher(vm, expOrFn, cb, options) + } options = options || {}; options.user = true; var watcher = new Watcher(vm, expOrFn, cb, options); @@ -3524,10 +3894,11 @@ function initProvide (vm) { function initInjections (vm) { var result = resolveInject(vm.$options.inject, vm); if (result) { + observerState.shouldConvert = false; Object.keys(result).forEach(function (key) { /* istanbul ignore else */ { - defineReactive$$1(vm, key, result[key], function () { + defineReactive(vm, key, result[key], function () { warn( "Avoid mutating an injected value directly since the changes will be " + "overwritten whenever the provided component re-renders. " + @@ -3537,24 +3908,24 @@ function initInjections (vm) { }); } }); + observerState.shouldConvert = true; } } function resolveInject (inject, vm) { if (inject) { // inject is :any because flow is not smart enough to figure out cached - // isArray here - var isArray = Array.isArray(inject); var result = Object.create(null); - var keys = isArray - ? inject - : hasSymbol - ? Reflect.ownKeys(inject) + var keys = hasSymbol + ? Reflect.ownKeys(inject).filter(function (key) { + /* istanbul ignore next */ + return Object.getOwnPropertyDescriptor(inject, key).enumerable + }) : Object.keys(inject); for (var i = 0; i < keys.length; i++) { var key = keys[i]; - var provideKey = isArray ? key : inject[key]; + var provideKey = inject[key].from; var source = vm; while (source) { if (source._provided && provideKey in source._provided) { @@ -3563,6 +3934,16 @@ function resolveInject (inject, vm) { } source = source.$parent; } + if (!source) { + if ('default' in inject[key]) { + var provideDefault = inject[key].default; + result[key] = typeof provideDefault === 'function' + ? provideDefault.call(vm) + : provideDefault; + } else { + warn(("Injection \"" + key + "\" not found"), vm); + } + } } return result } @@ -3570,43 +3951,371 @@ function resolveInject (inject, vm) { /* */ +/** + * Runtime helper for rendering v-for lists. + */ +function renderList ( + val, + render +) { + var ret, i, l, keys, key; + if (Array.isArray(val) || typeof val === 'string') { + ret = new Array(val.length); + for (i = 0, l = val.length; i < l; i++) { + ret[i] = render(val[i], i); + } + } else if (typeof val === 'number') { + ret = new Array(val); + for (i = 0; i < val; i++) { + ret[i] = render(i + 1, i); + } + } else if (isObject(val)) { + keys = Object.keys(val); + ret = new Array(keys.length); + for (i = 0, l = keys.length; i < l; i++) { + key = keys[i]; + ret[i] = render(val[key], key, i); + } + } + if (isDef(ret)) { + (ret)._isVList = true; + } + return ret +} + +/* */ + +/** + * Runtime helper for rendering + */ +function renderSlot ( + name, + fallback, + props, + bindObject +) { + var scopedSlotFn = this.$scopedSlots[name]; + var nodes; + if (scopedSlotFn) { // scoped slot + props = props || {}; + if (bindObject) { + if ("development" !== 'production' && !isObject(bindObject)) { + warn( + 'slot v-bind without argument expects an Object', + this + ); + } + props = extend(extend({}, bindObject), props); + } + nodes = scopedSlotFn(props) || fallback; + } else { + var slotNodes = this.$slots[name]; + // warn duplicate slot usage + if (slotNodes) { + if ("development" !== 'production' && slotNodes._rendered) { + warn( + "Duplicate presence of slot \"" + name + "\" found in the same render tree " + + "- this will likely cause render errors.", + this + ); + } + slotNodes._rendered = true; + } + nodes = slotNodes || fallback; + } + + var target = props && props.slot; + if (target) { + return this.$createElement('template', { slot: target }, nodes) + } else { + return nodes + } +} + +/* */ + +/** + * Runtime helper for resolving filters + */ +function resolveFilter (id) { + return resolveAsset(this.$options, 'filters', id, true) || identity +} + +/* */ + +/** + * Runtime helper for checking keyCodes from config. + * exposed as Vue.prototype._k + * passing in eventKeyName as last argument separately for backwards compat + */ +function checkKeyCodes ( + eventKeyCode, + key, + builtInAlias, + eventKeyName +) { + var keyCodes = config.keyCodes[key] || builtInAlias; + if (keyCodes) { + if (Array.isArray(keyCodes)) { + return keyCodes.indexOf(eventKeyCode) === -1 + } else { + return keyCodes !== eventKeyCode + } + } else if (eventKeyName) { + return hyphenate(eventKeyName) !== key + } +} + +/* */ + +/** + * Runtime helper for merging v-bind="object" into a VNode's data. + */ +function bindObjectProps ( + data, + tag, + value, + asProp, + isSync +) { + if (value) { + if (!isObject(value)) { + "development" !== 'production' && warn( + 'v-bind without argument expects an Object or Array value', + this + ); + } else { + if (Array.isArray(value)) { + value = toObject(value); + } + var hash; + var loop = function ( key ) { + if ( + key === 'class' || + key === 'style' || + isReservedAttribute(key) + ) { + hash = data; + } else { + var type = data.attrs && data.attrs.type; + hash = asProp || config.mustUseProp(tag, type, key) + ? data.domProps || (data.domProps = {}) + : data.attrs || (data.attrs = {}); + } + if (!(key in hash)) { + hash[key] = value[key]; + + if (isSync) { + var on = data.on || (data.on = {}); + on[("update:" + key)] = function ($event) { + value[key] = $event; + }; + } + } + }; + + for (var key in value) loop( key ); + } + } + return data +} + +/* */ + +/** + * Runtime helper for rendering static trees. + */ +function renderStatic ( + index, + isInFor, + isOnce +) { + // render fns generated by compiler < 2.5.4 does not provide v-once + // information to runtime so be conservative + var isOldVersion = arguments.length < 3; + // if a static tree is generated by v-once, it is cached on the instance; + // otherwise it is purely static and can be cached on the shared options + // across all instances. + var renderFns = this.$options.staticRenderFns; + var cached = isOldVersion || isOnce + ? (this._staticTrees || (this._staticTrees = [])) + : (renderFns.cached || (renderFns.cached = [])); + var tree = cached[index]; + // if has already-rendered static tree and not inside v-for, + // we can reuse the same tree by doing a shallow clone. + if (tree && !isInFor) { + return Array.isArray(tree) + ? cloneVNodes(tree) + : cloneVNode(tree) + } + // otherwise, render a fresh tree. + tree = cached[index] = renderFns[index].call(this._renderProxy, null, this); + markStatic(tree, ("__static__" + index), false); + return tree +} + +/** + * Runtime helper for v-once. + * Effectively it means marking the node as static with a unique key. + */ +function markOnce ( + tree, + index, + key +) { + markStatic(tree, ("__once__" + index + (key ? ("_" + key) : "")), true); + return tree +} + +function markStatic ( + tree, + key, + isOnce +) { + if (Array.isArray(tree)) { + for (var i = 0; i < tree.length; i++) { + if (tree[i] && typeof tree[i] !== 'string') { + markStaticNode(tree[i], (key + "_" + i), isOnce); + } + } + } else { + markStaticNode(tree, key, isOnce); + } +} + +function markStaticNode (node, key, isOnce) { + node.isStatic = true; + node.key = key; + node.isOnce = isOnce; +} + +/* */ + +function bindObjectListeners (data, value) { + if (value) { + if (!isPlainObject(value)) { + "development" !== 'production' && warn( + 'v-on without argument expects an Object value', + this + ); + } else { + var on = data.on = data.on ? extend({}, data.on) : {}; + for (var key in value) { + var existing = on[key]; + var ours = value[key]; + on[key] = existing ? [].concat(existing, ours) : ours; + } + } + } + return data +} + +/* */ + +function installRenderHelpers (target) { + target._o = markOnce; + target._n = toNumber; + target._s = toString; + target._l = renderList; + target._t = renderSlot; + target._q = looseEqual; + target._i = looseIndexOf; + target._m = renderStatic; + target._f = resolveFilter; + target._k = checkKeyCodes; + target._b = bindObjectProps; + target._v = createTextVNode; + target._e = createEmptyVNode; + target._u = resolveScopedSlots; + target._g = bindObjectListeners; +} + +/* */ + +function FunctionalRenderContext ( + data, + props, + children, + parent, + Ctor +) { + var options = Ctor.options; + this.data = data; + this.props = props; + this.children = children; + this.parent = parent; + this.listeners = data.on || emptyObject; + this.injections = resolveInject(options.inject, parent); + this.slots = function () { return resolveSlots(children, parent); }; + + // ensure the createElement function in functional components + // gets a unique context - this is necessary for correct named slot check + var contextVm = Object.create(parent); + var isCompiled = isTrue(options._compiled); + var needNormalization = !isCompiled; + + // support for compiled functional template + if (isCompiled) { + // exposing $options for renderStatic() + this.$options = options; + // pre-resolve slots for renderSlot() + this.$slots = this.slots(); + this.$scopedSlots = data.scopedSlots || emptyObject; + } + + if (options._scopeId) { + this._c = function (a, b, c, d) { + var vnode = createElement(contextVm, a, b, c, d, needNormalization); + if (vnode) { + vnode.fnScopeId = options._scopeId; + vnode.fnContext = parent; + } + return vnode + }; + } else { + this._c = function (a, b, c, d) { return createElement(contextVm, a, b, c, d, needNormalization); }; + } +} + +installRenderHelpers(FunctionalRenderContext.prototype); + function createFunctionalComponent ( Ctor, propsData, data, - context, + contextVm, children ) { + var options = Ctor.options; var props = {}; - var propOptions = Ctor.options.props; + var propOptions = options.props; if (isDef(propOptions)) { for (var key in propOptions) { - props[key] = validateProp(key, propOptions, propsData || {}); + props[key] = validateProp(key, propOptions, propsData || emptyObject); } } else { if (isDef(data.attrs)) { mergeProps(props, data.attrs); } if (isDef(data.props)) { mergeProps(props, data.props); } } - // ensure the createElement function in functional components - // gets a unique context - this is necessary for correct named slot check - var _context = Object.create(context); - var h = function (a, b, c, d) { return createElement(_context, a, b, c, d, true); }; - var vnode = Ctor.options.render.call(null, h, { - data: data, - props: props, - children: children, - parent: context, - listeners: data.on || {}, - injections: resolveInject(Ctor.options.inject, context), - slots: function () { return resolveSlots(children, context); } - }); + + var renderContext = new FunctionalRenderContext( + data, + props, + children, + contextVm, + Ctor + ); + + var vnode = options.render.call(null, renderContext._c, renderContext); + if (vnode instanceof VNode) { - vnode.functionalContext = context; - vnode.functionalOptions = Ctor.options; + vnode.fnContext = contextVm; + vnode.fnOptions = options; if (data.slot) { (vnode.data || (vnode.data = {})).slot = data.slot; } } + return vnode } @@ -3716,21 +4425,30 @@ function createComponent ( } // async component + var asyncFactory; if (isUndef(Ctor.cid)) { - Ctor = resolveAsyncComponent(Ctor, baseCtor, context); + asyncFactory = Ctor; + Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context); if (Ctor === undefined) { - // return nothing if this is indeed an async component - // wait for the callback to trigger parent update. - return + // return a placeholder node for async component, which is rendered + // as a comment node but preserves all the raw information for the node. + // the information will be used for async server-rendering and hydration. + return createAsyncPlaceholder( + asyncFactory, + data, + context, + children, + tag + ) } } + data = data || {}; + // resolve constructor options in case global mixins are applied after // component constructor creation resolveConstructorOptions(Ctor); - data = data || {}; - // transform component v-model data into props & events if (isDef(data.model)) { transformModel(Ctor.options, data); @@ -3748,12 +4466,19 @@ function createComponent ( // child component listeners instead of DOM listeners var listeners = data.on; // replace with listeners with .native modifier + // so it gets processed during parent component patch. data.on = data.nativeOn; if (isTrue(Ctor.options.abstract)) { // abstract components do not keep anything - // other than props & listeners + // other than props & listeners & slot + + // work around flow + var slot = data.slot; data = {}; + if (slot) { + data.slot = slot; + } } // merge component management hooks onto the placeholder node @@ -3764,7 +4489,8 @@ function createComponent ( var vnode = new VNode( ("vue-component-" + (Ctor.cid) + (name ? ("-" + name) : '')), data, undefined, undefined, undefined, context, - { Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children } + { Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children }, + asyncFactory ); return vnode } @@ -3869,10 +4595,24 @@ function _createElement ( ); return createEmptyVNode() } + // object syntax in v-bind + if (isDef(data) && isDef(data.is)) { + tag = data.is; + } if (!tag) { // in case of component :is set to falsy value return createEmptyVNode() } + // warn against non-primitive key + if ("development" !== 'production' && + isDef(data) && isDef(data.key) && !isPrimitive(data.key) + ) { + warn( + 'Avoid using non-primitive value as key, ' + + 'use string/number value instead.', + context + ); + } // support single function children as default scoped slot if (Array.isArray(children) && typeof children[0] === 'function' @@ -3889,7 +4629,7 @@ function _createElement ( var vnode, ns; if (typeof tag === 'string') { var Ctor; - ns = config.getTagNamespace(tag); + ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag); if (config.isReservedTag(tag)) { // platform built-in elements vnode = new VNode( @@ -3920,223 +4660,32 @@ function _createElement ( } } -function applyNS (vnode, ns) { +function applyNS (vnode, ns, force) { vnode.ns = ns; if (vnode.tag === 'foreignObject') { // use default namespace inside foreignObject - return + ns = undefined; + force = true; } if (isDef(vnode.children)) { for (var i = 0, l = vnode.children.length; i < l; i++) { var child = vnode.children[i]; - if (isDef(child.tag) && isUndef(child.ns)) { - applyNS(child, ns); - } - } - } -} - -/* */ - -/** - * Runtime helper for rendering v-for lists. - */ -function renderList ( - val, - render -) { - var ret, i, l, keys, key; - if (Array.isArray(val) || typeof val === 'string') { - ret = new Array(val.length); - for (i = 0, l = val.length; i < l; i++) { - ret[i] = render(val[i], i); - } - } else if (typeof val === 'number') { - ret = new Array(val); - for (i = 0; i < val; i++) { - ret[i] = render(i + 1, i); - } - } else if (isObject(val)) { - keys = Object.keys(val); - ret = new Array(keys.length); - for (i = 0, l = keys.length; i < l; i++) { - key = keys[i]; - ret[i] = render(val[key], key, i); - } - } - if (isDef(ret)) { - (ret)._isVList = true; - } - return ret -} - -/* */ - -/** - * Runtime helper for rendering - */ -function renderSlot ( - name, - fallback, - props, - bindObject -) { - var scopedSlotFn = this.$scopedSlots[name]; - if (scopedSlotFn) { // scoped slot - props = props || {}; - if (bindObject) { - extend(props, bindObject); - } - return scopedSlotFn(props) || fallback - } else { - var slotNodes = this.$slots[name]; - // warn duplicate slot usage - if (slotNodes && "development" !== 'production') { - slotNodes._rendered && warn( - "Duplicate presence of slot \"" + name + "\" found in the same render tree " + - "- this will likely cause render errors.", - this - ); - slotNodes._rendered = true; - } - return slotNodes || fallback - } -} - -/* */ - -/** - * Runtime helper for resolving filters - */ -function resolveFilter (id) { - return resolveAsset(this.$options, 'filters', id, true) || identity -} - -/* */ - -/** - * Runtime helper for checking keyCodes from config. - */ -function checkKeyCodes ( - eventKeyCode, - key, - builtInAlias -) { - var keyCodes = config.keyCodes[key] || builtInAlias; - if (Array.isArray(keyCodes)) { - return keyCodes.indexOf(eventKeyCode) === -1 - } else { - return keyCodes !== eventKeyCode - } -} - -/* */ - -/** - * Runtime helper for merging v-bind="object" into a VNode's data. - */ -function bindObjectProps ( - data, - tag, - value, - asProp -) { - if (value) { - if (!isObject(value)) { - "development" !== 'production' && warn( - 'v-bind without argument expects an Object or Array value', - this - ); - } else { - if (Array.isArray(value)) { - value = toObject(value); - } - var hash; - for (var key in value) { - if (key === 'class' || key === 'style') { - hash = data; - } else { - var type = data.attrs && data.attrs.type; - hash = asProp || config.mustUseProp(tag, type, key) - ? data.domProps || (data.domProps = {}) - : data.attrs || (data.attrs = {}); - } - if (!(key in hash)) { - hash[key] = value[key]; - } - } - } - } - return data -} - -/* */ - -/** - * Runtime helper for rendering static trees. - */ -function renderStatic ( - index, - isInFor -) { - var tree = this._staticTrees[index]; - // if has already-rendered static tree and not inside v-for, - // we can reuse the same tree by doing a shallow clone. - if (tree && !isInFor) { - return Array.isArray(tree) - ? cloneVNodes(tree) - : cloneVNode(tree) - } - // otherwise, render a fresh tree. - tree = this._staticTrees[index] = - this.$options.staticRenderFns[index].call(this._renderProxy); - markStatic(tree, ("__static__" + index), false); - return tree -} - -/** - * Runtime helper for v-once. - * Effectively it means marking the node as static with a unique key. - */ -function markOnce ( - tree, - index, - key -) { - markStatic(tree, ("__once__" + index + (key ? ("_" + key) : "")), true); - return tree -} - -function markStatic ( - tree, - key, - isOnce -) { - if (Array.isArray(tree)) { - for (var i = 0; i < tree.length; i++) { - if (tree[i] && typeof tree[i] !== 'string') { - markStaticNode(tree[i], (key + "_" + i), isOnce); + if (isDef(child.tag) && (isUndef(child.ns) || isTrue(force))) { + applyNS(child, ns, force); } } - } else { - markStaticNode(tree, key, isOnce); } } -function markStaticNode (node, key, isOnce) { - node.isStatic = true; - node.key = key; - node.isOnce = isOnce; -} - /* */ function initRender (vm) { vm._vnode = null; // the root of the child tree - vm._staticTrees = null; - var parentVnode = vm.$vnode = vm.$options._parentVnode; // the placeholder node in parent tree + vm._staticTrees = null; // v-once cached trees + var options = vm.$options; + var parentVnode = vm.$vnode = options._parentVnode; // the placeholder node in parent tree var renderContext = parentVnode && parentVnode.context; - vm.$slots = resolveSlots(vm.$options._renderChildren, renderContext); + vm.$slots = resolveSlots(options._renderChildren, renderContext); vm.$scopedSlots = emptyObject; // bind the createElement fn to this instance // so that we get proper render context inside it. @@ -4146,9 +4695,26 @@ function initRender (vm) { // normalization is always applied for the public version, used in // user-written render functions. vm.$createElement = function (a, b, c, d) { return createElement(vm, a, b, c, d, true); }; + + // $attrs & $listeners are exposed for easier HOC creation. + // they need to be reactive so that HOCs using them are always updated + var parentData = parentVnode && parentVnode.data; + + /* istanbul ignore else */ + { + defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, function () { + !isUpdatingChildComponent && warn("$attrs is readonly.", vm); + }, true); + defineReactive(vm, '$listeners', options._parentListeners || emptyObject, function () { + !isUpdatingChildComponent && warn("$listeners is readonly.", vm); + }, true); + } } function renderMixin (Vue) { + // install runtime convenience helpers + installRenderHelpers(Vue.prototype); + Vue.prototype.$nextTick = function (fn) { return nextTick(fn, this) }; @@ -4157,21 +4723,23 @@ function renderMixin (Vue) { var vm = this; var ref = vm.$options; var render = ref.render; - var staticRenderFns = ref.staticRenderFns; var _parentVnode = ref._parentVnode; if (vm._isMounted) { - // clone slot nodes on re-renders + // if the parent didn't update, the slot nodes will be the ones from + // last render. They need to be cloned to ensure "freshness" for this render. for (var key in vm.$slots) { - vm.$slots[key] = cloneVNodes(vm.$slots[key]); + var slot = vm.$slots[key]; + // _rendered is a flag added by renderSlot, but may not be present + // if the slot is passed from manually written render functions + if (slot._rendered || (slot[0] && slot[0].elm)) { + vm.$slots[key] = cloneVNodes(slot, true /* deep */); + } } } vm.$scopedSlots = (_parentVnode && _parentVnode.data.scopedSlots) || emptyObject; - if (staticRenderFns && !vm._staticTrees) { - vm._staticTrees = []; - } // set parent vnode. this allows render functions to have access // to the data on the placeholder node. vm.$vnode = _parentVnode; @@ -4180,14 +4748,21 @@ function renderMixin (Vue) { try { vnode = render.call(vm._renderProxy, vm.$createElement); } catch (e) { - handleError(e, vm, "render function"); + handleError(e, vm, "render"); // return error render result, // or previous vnode to prevent render error causing blank component /* istanbul ignore else */ { - vnode = vm.$options.renderError - ? vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e) - : vm._vnode; + if (vm.$options.renderError) { + try { + vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e); + } catch (e) { + handleError(e, vm, "renderError"); + vnode = vm._vnode; + } + } else { + vnode = vm._vnode; + } } } // return empty vnode in case the render function errored out @@ -4205,24 +4780,6 @@ function renderMixin (Vue) { vnode.parent = _parentVnode; return vnode }; - - // internal render helpers. - // these are exposed on the instance prototype to reduce generated render - // code size. - Vue.prototype._o = markOnce; - Vue.prototype._n = toNumber; - Vue.prototype._s = toString; - Vue.prototype._l = renderList; - Vue.prototype._t = renderSlot; - Vue.prototype._q = looseEqual; - Vue.prototype._i = looseIndexOf; - Vue.prototype._m = renderStatic; - Vue.prototype._f = resolveFilter; - Vue.prototype._k = checkKeyCodes; - Vue.prototype._b = bindObjectProps; - Vue.prototype._v = createTextVNode; - Vue.prototype._e = createEmptyVNode; - Vue.prototype._u = resolveScopedSlots; } /* */ @@ -4238,7 +4795,7 @@ function initMixin (Vue) { var startTag, endTag; /* istanbul ignore if */ if ("development" !== 'production' && config.performance && mark) { - startTag = "vue-perf-init:" + (vm._uid); + startTag = "vue-perf-start:" + (vm._uid); endTag = "vue-perf-end:" + (vm._uid); mark(startTag); } @@ -4277,7 +4834,7 @@ function initMixin (Vue) { if ("development" !== 'production' && config.performance && mark) { vm._name = formatComponentName(vm, false); mark(endTag); - measure(((vm._name) + " init"), startTag, endTag); + measure(("vue " + (vm._name) + " init"), startTag, endTag); } if (vm.$options.el) { @@ -4379,10 +4936,11 @@ renderMixin(Vue$3); function initUse (Vue) { Vue.use = function (plugin) { - /* istanbul ignore if */ - if (plugin.installed) { + var installedPlugins = (this._installedPlugins || (this._installedPlugins = [])); + if (installedPlugins.indexOf(plugin) > -1) { return this } + // additional parameters var args = toArray(arguments, 1); args.unshift(this); @@ -4391,7 +4949,7 @@ function initUse (Vue) { } else if (typeof plugin === 'function') { plugin.apply(null, args); } - plugin.installed = true; + installedPlugins.push(plugin); return this }; } @@ -4542,14 +5100,14 @@ function initAssetRegisters (Vue) { /* */ -var patternTypes = [String, RegExp]; - function getComponentName (opts) { return opts && (opts.Ctor.options.name || opts.tag) } function matches (pattern, name) { - if (typeof pattern === 'string') { + if (Array.isArray(pattern)) { + return pattern.indexOf(name) > -1 + } else if (typeof pattern === 'string') { return pattern.split(',').indexOf(name) > -1 } else if (isRegExp(pattern)) { return pattern.test(name) @@ -4558,82 +5116,113 @@ function matches (pattern, name) { return false } -function pruneCache (cache, current, filter) { +function pruneCache (keepAliveInstance, filter) { + var cache = keepAliveInstance.cache; + var keys = keepAliveInstance.keys; + var _vnode = keepAliveInstance._vnode; for (var key in cache) { var cachedNode = cache[key]; if (cachedNode) { var name = getComponentName(cachedNode.componentOptions); if (name && !filter(name)) { - if (cachedNode !== current) { - pruneCacheEntry(cachedNode); - } - cache[key] = null; + pruneCacheEntry(cache, key, keys, _vnode); } } } } -function pruneCacheEntry (vnode) { - if (vnode) { - vnode.componentInstance.$destroy(); +function pruneCacheEntry ( + cache, + key, + keys, + current +) { + var cached$$1 = cache[key]; + if (cached$$1 && (!current || cached$$1.tag !== current.tag)) { + cached$$1.componentInstance.$destroy(); } + cache[key] = null; + remove(keys, key); } +var patternTypes = [String, RegExp, Array]; + var KeepAlive = { name: 'keep-alive', abstract: true, props: { include: patternTypes, - exclude: patternTypes + exclude: patternTypes, + max: [String, Number] }, created: function created () { this.cache = Object.create(null); + this.keys = []; }, destroyed: function destroyed () { var this$1 = this; for (var key in this$1.cache) { - pruneCacheEntry(this$1.cache[key]); + pruneCacheEntry(this$1.cache, key, this$1.keys); } }, watch: { include: function include (val) { - pruneCache(this.cache, this._vnode, function (name) { return matches(val, name); }); + pruneCache(this, function (name) { return matches(val, name); }); }, exclude: function exclude (val) { - pruneCache(this.cache, this._vnode, function (name) { return !matches(val, name); }); + pruneCache(this, function (name) { return !matches(val, name); }); } }, render: function render () { - var vnode = getFirstComponentChild(this.$slots.default); + var slot = this.$slots.default; + var vnode = getFirstComponentChild(slot); var componentOptions = vnode && vnode.componentOptions; if (componentOptions) { // check pattern var name = getComponentName(componentOptions); - if (name && ( - (this.include && !matches(this.include, name)) || - (this.exclude && matches(this.exclude, name)) - )) { + var ref = this; + var include = ref.include; + var exclude = ref.exclude; + if ( + // not included + (include && (!name || !matches(include, name))) || + // excluded + (exclude && name && matches(exclude, name)) + ) { return vnode } + + var ref$1 = this; + var cache = ref$1.cache; + var keys = ref$1.keys; var key = vnode.key == null // same constructor may get registered as different local components // so cid alone is not enough (#3269) ? componentOptions.Ctor.cid + (componentOptions.tag ? ("::" + (componentOptions.tag)) : '') : vnode.key; - if (this.cache[key]) { - vnode.componentInstance = this.cache[key].componentInstance; + if (cache[key]) { + vnode.componentInstance = cache[key].componentInstance; + // make current key freshest + remove(keys, key); + keys.push(key); } else { - this.cache[key] = vnode; + cache[key] = vnode; + keys.push(key); + // prune oldest entry + if (this.max && keys.length > parseInt(this.max)) { + pruneCacheEntry(cache, keys[0], keys, this._vnode); + } } + vnode.data.keepAlive = true; } - return vnode + return vnode || (slot && slot[0]) } }; @@ -4663,7 +5252,7 @@ function initGlobalAPI (Vue) { warn: warn, extend: extend, mergeOptions: mergeOptions, - defineReactive: defineReactive$$1 + defineReactive: defineReactive }; Vue.set = set; @@ -4696,11 +5285,11 @@ Object.defineProperty(Vue$3.prototype, '$isServer', { Object.defineProperty(Vue$3.prototype, '$ssrContext', { get: function get () { /* istanbul ignore next */ - return this.$vnode.ssrContext + return this.$vnode && this.$vnode.ssrContext } }); -Vue$3.version = '2.3.3'; +Vue$3.version = '2.5.9'; /* */ @@ -4709,7 +5298,7 @@ Vue$3.version = '2.3.3'; var isReservedAttr = makeMap('style,class'); // attributes that should be using props for binding -var acceptValue = makeMap('input,textarea,option,select'); +var acceptValue = makeMap('input,textarea,option,select,progress'); var mustUseProp = function (tag, type, attr) { return ( (attr === 'value' && acceptValue(tag)) && type !== 'button' || @@ -4761,7 +5350,7 @@ function genClassForVnode (vnode) { data = mergeClassData(data, parentNode.data); } } - return genClassFromData(data) + return renderClass(data.staticClass, data.class) } function mergeClassData (child, parent) { @@ -4773,9 +5362,10 @@ function mergeClassData (child, parent) { } } -function genClassFromData (data) { - var dynamicClass = data.class; - var staticClass = data.staticClass; +function renderClass ( + staticClass, + dynamicClass +) { if (isDef(staticClass) || isDef(dynamicClass)) { return concat(staticClass, stringifyClass(dynamicClass)) } @@ -4788,31 +5378,39 @@ function concat (a, b) { } function stringifyClass (value) { - if (isUndef(value)) { - return '' + if (Array.isArray(value)) { + return stringifyArray(value) + } + if (isObject(value)) { + return stringifyObject(value) } if (typeof value === 'string') { return value } + /* istanbul ignore next */ + return '' +} + +function stringifyArray (value) { var res = ''; - if (Array.isArray(value)) { - var stringified; - for (var i = 0, l = value.length; i < l; i++) { - if (isDef(value[i])) { - if (isDef(stringified = stringifyClass(value[i])) && stringified !== '') { - res += stringified + ' '; - } - } + var stringified; + for (var i = 0, l = value.length; i < l; i++) { + if (isDef(stringified = stringifyClass(value[i])) && stringified !== '') { + if (res) { res += ' '; } + res += stringified; } - return res.slice(0, -1) } - if (isObject(value)) { - for (var key in value) { - if (value[key]) { res += key + ' '; } + return res +} + +function stringifyObject (value) { + var res = ''; + for (var key in value) { + if (value[key]) { + if (res) { res += ' '; } + res += key; } - return res.slice(0, -1) } - /* istanbul ignore next */ return res } @@ -4826,7 +5424,7 @@ var namespaceMap = { var isHTMLTag = makeMap( 'html,body,base,head,link,meta,style,title,' + 'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' + - 'div,dd,dl,dt,figcaption,figure,hr,img,li,main,ol,p,pre,ul,' + + 'div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,' + 'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' + 's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' + 'embed,object,param,source,canvas,script,noscript,del,ins,' + @@ -4834,7 +5432,7 @@ var isHTMLTag = makeMap( 'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' + 'output,progress,select,textarea,' + 'details,dialog,menu,menuitem,summary,' + - 'content,element,shadow,template' + 'content,element,shadow,template,blockquote,iframe,tfoot' ); // this map is intentionally selective, only covering SVG elements that may @@ -4889,6 +5487,8 @@ function isUnknownElement (tag) { } } +var isTextInputType = makeMap('text,number,password,search,email,tel,url'); + /* */ /** @@ -5015,10 +5615,11 @@ function registerRef (vnode, isRemoval) { } } else { if (vnode.data.refInFor) { - if (Array.isArray(refs[key]) && refs[key].indexOf(ref) < 0) { - refs[key].push(ref); - } else { + if (!Array.isArray(refs[key])) { refs[key] = [ref]; + } else if (refs[key].indexOf(ref) < 0) { + // $flow-disable-line + refs[key].push(ref); } } else { refs[key] = ref; @@ -5034,8 +5635,6 @@ function registerRef (vnode, isRemoval) { * * modified by Evan You (@yyx990803) * - -/* * Not type-checking this because this file is perf-critical and the cost * of making flow understand it is not worth it. */ @@ -5046,22 +5645,27 @@ var hooks = ['create', 'activate', 'update', 'remove', 'destroy']; function sameVnode (a, b) { return ( - a.key === b.key && - a.tag === b.tag && - a.isComment === b.isComment && - isDef(a.data) === isDef(b.data) && - sameInputType(a, b) + a.key === b.key && ( + ( + a.tag === b.tag && + a.isComment === b.isComment && + isDef(a.data) === isDef(b.data) && + sameInputType(a, b) + ) || ( + isTrue(a.isAsyncPlaceholder) && + a.asyncFactory === b.asyncFactory && + isUndef(b.asyncFactory.error) + ) + ) ) } -// Some browsers do not support dynamically changing type for -// so they need to be treated as different nodes function sameInputType (a, b) { if (a.tag !== 'input') { return true } var i; var typeA = isDef(i = a.data) && isDef(i = i.attrs) && i.type; var typeB = isDef(i = b.data) && isDef(i = i.attrs) && i.type; - return typeA === typeB + return typeA === typeB || isTextInputType(typeA) && isTextInputType(typeB) } function createKeyToOldIdx (children, beginIdx, endIdx) { @@ -5095,13 +5699,13 @@ function createPatchFunction (backend) { } function createRmCb (childElm, listeners) { - function remove$$1 () { - if (--remove$$1.listeners === 0) { + function remove () { + if (--remove.listeners === 0) { removeNode(childElm); } } - remove$$1.listeners = listeners; - return remove$$1 + remove.listeners = listeners; + return remove } function removeNode (el) { @@ -5112,7 +5716,23 @@ function createPatchFunction (backend) { } } - var inPre = 0; + function isUnknownElement$$1 (vnode, inVPre) { + return ( + !inVPre && + !vnode.ns && + !( + config.ignoredElements.length && + config.ignoredElements.some(function (ignore) { + return isRegExp(ignore) + ? ignore.test(vnode.tag) + : ignore === vnode.tag + }) + ) && + config.isUnknownElement(vnode.tag) + ) + } + + var creatingElmInVPre = 0; function createElm (vnode, insertedVnodeQueue, parentElm, refElm, nested) { vnode.isRootInsert = !nested; // for transition enter check if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) { @@ -5125,14 +5745,9 @@ function createPatchFunction (backend) { if (isDef(tag)) { { if (data && data.pre) { - inPre++; + creatingElmInVPre++; } - if ( - !inPre && - !vnode.ns && - !(config.ignoredElements.length && config.ignoredElements.indexOf(tag) > -1) && - config.isUnknownElement(tag) - ) { + if (isUnknownElement$$1(vnode, creatingElmInVPre)) { warn( 'Unknown custom element: <' + tag + '> - did you ' + 'register the component correctly? For recursive components, ' + @@ -5156,7 +5771,7 @@ function createPatchFunction (backend) { } if ("development" !== 'production' && data && data.pre) { - inPre--; + creatingElmInVPre--; } } else if (isTrue(vnode.isComment)) { vnode.elm = nodeOps.createComment(vnode.text); @@ -5191,6 +5806,7 @@ function createPatchFunction (backend) { function initComponent (vnode, insertedVnodeQueue) { if (isDef(vnode.data.pendingInsert)) { insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert); + vnode.data.pendingInsert = null; } vnode.elm = vnode.componentInstance.$el; if (isPatchable(vnode)) { @@ -5227,11 +5843,11 @@ function createPatchFunction (backend) { insert(parentElm, vnode.elm, refElm); } - function insert (parent, elm, ref) { + function insert (parent, elm, ref$$1) { if (isDef(parent)) { - if (isDef(ref)) { - if (ref.parentNode === parent) { - nodeOps.insertBefore(parent, elm, ref); + if (isDef(ref$$1)) { + if (ref$$1.parentNode === parent) { + nodeOps.insertBefore(parent, elm, ref$$1); } } else { nodeOps.appendChild(parent, elm); @@ -5272,16 +5888,21 @@ function createPatchFunction (backend) { // of going through the normal attribute patching process. function setScope (vnode) { var i; - var ancestor = vnode; - while (ancestor) { - if (isDef(i = ancestor.context) && isDef(i = i.$options._scopeId)) { - nodeOps.setAttribute(vnode.elm, i, ''); + if (isDef(i = vnode.fnScopeId)) { + nodeOps.setAttribute(vnode.elm, i, ''); + } else { + var ancestor = vnode; + while (ancestor) { + if (isDef(i = ancestor.context) && isDef(i = i.$options._scopeId)) { + nodeOps.setAttribute(vnode.elm, i, ''); + } + ancestor = ancestor.parent; } - ancestor = ancestor.parent; } // for slot content they should also get the scopeId from the host instance. if (isDef(i = activeInstance) && i !== vnode.context && + i !== vnode.fnContext && isDef(i = i.$options._scopeId) ) { nodeOps.setAttribute(vnode.elm, i, ''); @@ -5360,7 +5981,7 @@ function createPatchFunction (backend) { var newEndIdx = newCh.length - 1; var newStartVnode = newCh[0]; var newEndVnode = newCh[newEndIdx]; - var oldKeyToIdx, idxInOld, elmToMove, refElm; + var oldKeyToIdx, idxInOld, vnodeToMove, refElm; // removeOnly is a special flag used only by // to ensure removed elements stay in correct relative positions @@ -5392,30 +6013,30 @@ function createPatchFunction (backend) { newStartVnode = newCh[++newStartIdx]; } else { if (isUndef(oldKeyToIdx)) { oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); } - idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : null; + idxInOld = isDef(newStartVnode.key) + ? oldKeyToIdx[newStartVnode.key] + : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx); if (isUndef(idxInOld)) { // New element createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm); - newStartVnode = newCh[++newStartIdx]; } else { - elmToMove = oldCh[idxInOld]; + vnodeToMove = oldCh[idxInOld]; /* istanbul ignore if */ - if ("development" !== 'production' && !elmToMove) { + if ("development" !== 'production' && !vnodeToMove) { warn( 'It seems there are duplicate keys that is causing an update error. ' + 'Make sure each v-for item has a unique key.' ); } - if (sameVnode(elmToMove, newStartVnode)) { - patchVnode(elmToMove, newStartVnode, insertedVnodeQueue); + if (sameVnode(vnodeToMove, newStartVnode)) { + patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue); oldCh[idxInOld] = undefined; - canMove && nodeOps.insertBefore(parentElm, newStartVnode.elm, oldStartVnode.elm); - newStartVnode = newCh[++newStartIdx]; + canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm); } else { // same key but different element. treat as new element createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm); - newStartVnode = newCh[++newStartIdx]; } } + newStartVnode = newCh[++newStartIdx]; } } if (oldStartIdx > oldEndIdx) { @@ -5426,10 +6047,29 @@ function createPatchFunction (backend) { } } + function findIdxInOld (node, oldCh, start, end) { + for (var i = start; i < end; i++) { + var c = oldCh[i]; + if (isDef(c) && sameVnode(node, c)) { return i } + } + } + function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) { if (oldVnode === vnode) { return } + + var elm = vnode.elm = oldVnode.elm; + + if (isTrue(oldVnode.isAsyncPlaceholder)) { + if (isDef(vnode.asyncFactory.resolved)) { + hydrate(oldVnode.elm, vnode, insertedVnodeQueue); + } else { + vnode.isAsyncPlaceholder = true; + } + return + } + // reuse element for static trees. // note we only do this if the vnode is cloned - // if the new node is not cloned it means the render functions have been @@ -5439,16 +6079,16 @@ function createPatchFunction (backend) { vnode.key === oldVnode.key && (isTrue(vnode.isCloned) || isTrue(vnode.isOnce)) ) { - vnode.elm = oldVnode.elm; vnode.componentInstance = oldVnode.componentInstance; return } + var i; var data = vnode.data; if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) { i(oldVnode, vnode); } - var elm = vnode.elm = oldVnode.elm; + var oldCh = oldVnode.children; var ch = vnode.children; if (isDef(data) && isPatchable(vnode)) { @@ -5486,22 +6126,32 @@ function createPatchFunction (backend) { } } - var bailed = false; + var hydrationBailed = false; // list of modules that can skip create hook during hydration because they // are already rendered on the client or has no need for initialization - var isRenderedModule = makeMap('attrs,style,class,staticClass,staticStyle,key'); + // Note: style is excluded because it relies on initial clone for future + // deep updates (#7063). + var isRenderedModule = makeMap('attrs,class,staticClass,staticStyle,key'); // Note: this is a browser-only function so we can assume elms are DOM nodes. - function hydrate (elm, vnode, insertedVnodeQueue) { + function hydrate (elm, vnode, insertedVnodeQueue, inVPre) { + var i; + var tag = vnode.tag; + var data = vnode.data; + var children = vnode.children; + inVPre = inVPre || (data && data.pre); + vnode.elm = elm; + + if (isTrue(vnode.isComment) && isDef(vnode.asyncFactory)) { + vnode.isAsyncPlaceholder = true; + return true + } + // assert node match { - if (!assertNodeMatch(elm, vnode)) { + if (!assertNodeMatch(elm, vnode, inVPre)) { return false } } - vnode.elm = elm; - var tag = vnode.tag; - var data = vnode.data; - var children = vnode.children; if (isDef(data)) { if (isDef(i = data.hook) && isDef(i = i.init)) { i(vnode, true /* hydrating */); } if (isDef(i = vnode.componentInstance)) { @@ -5516,37 +6166,62 @@ function createPatchFunction (backend) { if (!elm.hasChildNodes()) { createChildren(vnode, children, insertedVnodeQueue); } else { - var childrenMatch = true; - var childNode = elm.firstChild; - for (var i$1 = 0; i$1 < children.length; i$1++) { - if (!childNode || !hydrate(childNode, children[i$1], insertedVnodeQueue)) { - childrenMatch = false; - break + // v-html and domProps: innerHTML + if (isDef(i = data) && isDef(i = i.domProps) && isDef(i = i.innerHTML)) { + if (i !== elm.innerHTML) { + /* istanbul ignore if */ + if ("development" !== 'production' && + typeof console !== 'undefined' && + !hydrationBailed + ) { + hydrationBailed = true; + console.warn('Parent: ', elm); + console.warn('server innerHTML: ', i); + console.warn('client innerHTML: ', elm.innerHTML); + } + return false } - childNode = childNode.nextSibling; - } - // if childNode is not null, it means the actual childNodes list is - // longer than the virtual children list. - if (!childrenMatch || childNode) { - if ("development" !== 'production' && - typeof console !== 'undefined' && - !bailed - ) { - bailed = true; - console.warn('Parent: ', elm); - console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children); + } else { + // iterate and compare children lists + var childrenMatch = true; + var childNode = elm.firstChild; + for (var i$1 = 0; i$1 < children.length; i$1++) { + if (!childNode || !hydrate(childNode, children[i$1], insertedVnodeQueue, inVPre)) { + childrenMatch = false; + break + } + childNode = childNode.nextSibling; + } + // if childNode is not null, it means the actual childNodes list is + // longer than the virtual children list. + if (!childrenMatch || childNode) { + /* istanbul ignore if */ + if ("development" !== 'production' && + typeof console !== 'undefined' && + !hydrationBailed + ) { + hydrationBailed = true; + console.warn('Parent: ', elm); + console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children); + } + return false } - return false } } } if (isDef(data)) { + var fullInvoke = false; for (var key in data) { if (!isRenderedModule(key)) { + fullInvoke = true; invokeCreateHooks(vnode, insertedVnodeQueue); break } } + if (!fullInvoke && data['class']) { + // ensure collecting deps for deep class bindings for future updates + traverse(data['class']); + } } } else if (elm.data !== vnode.text) { elm.data = vnode.text; @@ -5554,10 +6229,10 @@ function createPatchFunction (backend) { return true } - function assertNodeMatch (node, vnode) { + function assertNodeMatch (node, vnode, inVPre) { if (isDef(vnode.tag)) { - return ( - vnode.tag.indexOf('vue-component') === 0 || + return vnode.tag.indexOf('vue-component') === 0 || ( + !isUnknownElement$$1(vnode, inVPre) && vnode.tag.toLowerCase() === (node.tagName && node.tagName.toLowerCase()) ) } else { @@ -5610,9 +6285,12 @@ function createPatchFunction (backend) { // create an empty node and replace it oldVnode = emptyNodeAt(oldVnode); } + // replacing existing element var oldElm = oldVnode.elm; var parentElm$1 = nodeOps.parentNode(oldElm); + + // create new node createElm( vnode, insertedVnodeQueue, @@ -5623,21 +6301,37 @@ function createPatchFunction (backend) { nodeOps.nextSibling(oldElm) ); + // update parent placeholder node element, recursively if (isDef(vnode.parent)) { - // component root element replaced. - // update parent placeholder node element, recursively var ancestor = vnode.parent; + var patchable = isPatchable(vnode); while (ancestor) { + for (var i = 0; i < cbs.destroy.length; ++i) { + cbs.destroy[i](ancestor); + } ancestor.elm = vnode.elm; - ancestor = ancestor.parent; - } - if (isPatchable(vnode)) { - for (var i = 0; i < cbs.create.length; ++i) { - cbs.create[i](emptyNode, vnode.parent); + if (patchable) { + for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) { + cbs.create[i$1](emptyNode, ancestor); + } + // #6513 + // invoke insert hooks that may have been merged by create hooks. + // e.g. for directives that uses the "inserted" hook. + var insert = ancestor.data.hook.insert; + if (insert.merged) { + // start at index 1 to avoid re-invoking component mounted hook + for (var i$2 = 1; i$2 < insert.fns.length; i$2++) { + insert.fns[i$2](); + } + } + } else { + registerRef(ancestor); } + ancestor = ancestor.parent; } } + // destroy old node if (isDef(parentElm$1)) { removeVnodes(parentElm$1, [oldVnode], 0, 0); } else if (isDef(oldVnode.tag)) { @@ -5703,14 +6397,14 @@ function _update (oldVnode, vnode) { } }; if (isCreate) { - mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'insert', callInsert); + mergeVNodeHook(vnode, 'insert', callInsert); } else { callInsert(); } } if (dirsWithPostpatch.length) { - mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'postpatch', function () { + mergeVNodeHook(vnode, 'postpatch', function () { for (var i = 0; i < dirsWithPostpatch.length; i++) { callHook$1(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode); } @@ -5772,6 +6466,10 @@ var baseModules = [ /* */ function updateAttrs (oldVnode, vnode) { + var opts = vnode.componentOptions; + if (isDef(opts) && opts.Ctor.options.inheritAttrs === false) { + return + } if (isUndef(oldVnode.data.attrs) && isUndef(vnode.data.attrs)) { return } @@ -5792,8 +6490,9 @@ function updateAttrs (oldVnode, vnode) { } } // #4391: in IE9, setting type can reset value for input[type=radio] + // #6666: IE/Edge forces progress value down to 1 before setting a max /* istanbul ignore if */ - if (isIE9 && attrs.value !== oldAttrs.value) { + if ((isIE || isEdge) && attrs.value !== oldAttrs.value) { setAttr(elm, 'value', attrs.value); } for (key in oldAttrs) { @@ -5814,7 +6513,12 @@ function setAttr (el, key, value) { if (isFalsyAttrValue(value)) { el.removeAttribute(key); } else { - el.setAttribute(key, key); + // technically allowfullscreen is a boolean attribute for