/*! */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.vue = factory()); }(this, function () { 'use strict'; function set(obj, key, val) { if (hasown(obj, key)) { obj[key] = val; return; } if (obj._isvue) { set(obj._data, key, val); return; } var ob = obj.__ob__; if (!ob) { obj[key] = val; return; } ob.convert(key, val); ob.dep.notify(); if (ob.vms) { var i = ob.vms.length; while (i--) { var vm = ob.vms[i]; vm._proxy(key); vm._digest(); } } return val; } /** * delete a property and trigger change if necessary. * * @param {object} obj * @param {string} key */ function del(obj, key) { if (!hasown(obj, key)) { return; } delete obj[key]; var ob = obj.__ob__; if (!ob) { if (obj._isvue) { delete obj._data[key]; obj._digest(); } return; } ob.dep.notify(); if (ob.vms) { var i = ob.vms.length; while (i--) { var vm = ob.vms[i]; vm._unproxy(key); vm._digest(); } } } var hasownproperty = object.prototype.hasownproperty; /** * check whether the object has the property. * * @param {object} obj * @param {string} key * @return {boolean} */ function hasown(obj, key) { return hasownproperty.call(obj, key); } /** * check if an expression is a literal value. * * @param {string} exp * @return {boolean} */ var literalvaluere = /^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/; function isliteral(exp) { return literalvaluere.test(exp); } /** * check if a string starts with $ or _ * * @param {string} str * @return {boolean} */ function isreserved(str) { var c = (str + '').charcodeat(0); return c === 0x24 || c === 0x5f; } /** * guard text output, make sure undefined outputs * empty string * * @param {*} value * @return {string} */ function _tostring(value) { return value == null ? '' : value.tostring(); } /** * check and convert possible numeric strings to numbers * before setting back to data * * @param {*} value * @return {*|number} */ function tonumber(value) { if (typeof value !== 'string') { return value; } else { var parsed = number(value); return isnan(parsed) ? value : parsed; } } /** * convert string boolean literals into real booleans. * * @param {*} value * @return {*|boolean} */ function toboolean(value) { return value === 'true' ? true : value === 'false' ? false : value; } /** * strip quotes from a string * * @param {string} str * @return {string | false} */ function stripquotes(str) { var a = str.charcodeat(0); var b = str.charcodeat(str.length - 1); return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str; } /** * camelize a hyphen-delmited string. * * @param {string} str * @return {string} */ var camelizere = /-(\w)/g; function camelize(str) { return str.replace(camelizere, toupper); } function toupper(_, c) { return c ? c.touppercase() : ''; } /** * hyphenate a camelcase string. * * @param {string} str * @return {string} */ var hyphenatere = /([a-z\d])([a-z])/g; function hyphenate(str) { return str.replace(hyphenatere, '$1-$2').tolowercase(); } /** * converts hyphen/underscore/slash delimitered names into * camelized classnames. * * e.g. my-component => mycomponent * some_else => someelse * some/comp => somecomp * * @param {string} str * @return {string} */ var classifyre = /(?:^|[-_\/])(\w)/g; function classify(str) { return str.replace(classifyre, toupper); } /** * simple bind, faster than native * * @param {function} fn * @param {object} ctx * @return {function} */ function bind(fn, ctx) { return function (a) { var l = arguments.length; return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx); }; } /** * convert an array-like object to a real array. * * @param {array-like} list * @param {number} [start] - start index * @return {array} */ function toarray(list, start) { start = start || 0; var i = list.length - start; var ret = new array(i); while (i--) { ret[i] = list[i + start]; } return ret; } /** * mix properties into target object. * * @param {object} to * @param {object} from */ function extend(to, from) { var keys = object.keys(from); var i = keys.length; while (i--) { to[keys[i]] = from[keys[i]]; } return to; } /** * quick object check - this is primarily used to tell * objects from primitive values when we know the value * is a json-compliant type. * * @param {*} obj * @return {boolean} */ function isobject(obj) { return obj !== null && typeof obj === 'object'; } /** * strict object type check. only returns true * for plain javascript objects. * * @param {*} obj * @return {boolean} */ var tostring = object.prototype.tostring; var object_string = '[object object]'; function isplainobject(obj) { return tostring.call(obj) === object_string; } /** * array type check. * * @param {*} obj * @return {boolean} */ var isarray = array.isarray; /** * define a property. * * @param {object} obj * @param {string} key * @param {*} val * @param {boolean} [enumerable] */ function def(obj, key, val, enumerable) { object.defineproperty(obj, key, { value: val, enumerable: !!enumerable, writable: true, configurable: true }); } /** * debounce a function so it only gets called after the * input stops arriving after the given wait period. * * @param {function} func * @param {number} wait * @return {function} - the debounced function */ function _debounce(func, wait) { var timeout, args, context, timestamp, result; var later = function later() { var last = date.now() - timestamp; if (last < wait && last >= 0) { timeout = settimeout(later, wait - last); } else { timeout = null; result = func.apply(context, args); if (!timeout) context = args = null; } }; return function () { context = this; args = arguments; timestamp = date.now(); if (!timeout) { timeout = settimeout(later, wait); } return result; }; } /** * manual indexof because it's slightly faster than * native. * * @param {array} arr * @param {*} obj */ function indexof(arr, obj) { var i = arr.length; while (i--) { if (arr[i] === obj) return i; } return -1; } /** * make a cancellable version of an async callback. * * @param {function} fn * @return {function} */ function cancellable(fn) { var cb = function cb() { if (!cb.cancelled) { return fn.apply(this, arguments); } }; cb.cancel = function () { cb.cancelled = true; }; return cb; } /** * check if two values are loosely equal - that is, * if they are plain objects, do they have the same shape? * * @param {*} a * @param {*} b * @return {boolean} */ function looseequal(a, b) { /* eslint-disable eqeqeq */ return a == b || (isobject(a) && isobject(b) ? json.stringify(a) === json.stringify(b) : false); /* eslint-enable eqeqeq */ } var hasproto = ('__proto__' in {}); // browser environment sniffing var inbrowser = typeof window !== 'undefined' && object.prototype.tostring.call(window) !== '[object object]'; // detect devtools var devtools = inbrowser && window.__vue_devtools_global_hook__; // ua sniffing for working around browser-specific quirks var ua = inbrowser && window.navigator.useragent.tolowercase(); var isie = ua && ua.indexof('trident') > 0; var isie9 = ua && ua.indexof('msie 9.0') > 0; var isandroid = ua && ua.indexof('android') > 0; var isios = ua && /(iphone|ipad|ipod|ios)/i.test(ua); var iosversionmatch = isios && ua.match(/os ([\d_]+)/); var iosversion = iosversionmatch && iosversionmatch[1].split('_'); // detecting ios uiwebview by indexeddb var hasmutationobserverbug = iosversion && number(iosversion[0]) >= 9 && number(iosversion[1]) >= 3 && !window.indexeddb; var transitionprop = undefined; var transitionendevent = undefined; var animationprop = undefined; var animationendevent = undefined; // transition property/event sniffing if (inbrowser && !isie9) { var iswebkittrans = window.ontransitionend === undefined && window.onwebkittransitionend !== undefined; var iswebkitanim = window.onanimationend === undefined && window.onwebkitanimationend !== undefined; transitionprop = iswebkittrans ? 'webkittransition' : 'transition'; transitionendevent = iswebkittrans ? 'webkittransitionend' : 'transitionend'; animationprop = iswebkitanim ? 'webkitanimation' : 'animation'; animationendevent = iswebkitanim ? 'webkitanimationend' : 'animationend'; } /** * defer a task to execute it asynchronously. ideally this * should be executed as a microtask, so we leverage * mutationobserver if it's available, and fallback to * settimeout(0). * * @param {function} cb * @param {object} ctx */ var nexttick = (function () { var callbacks = []; var pending = false; var timerfunc; function nexttickhandler() { pending = false; var copies = callbacks.slice(0); callbacks = []; for (var i = 0; i < copies.length; i++) { copies[i](); } } /* istanbul ignore if */ if (typeof mutationobserver !== 'undefined' && !hasmutationobserverbug) { var counter = 1; var observer = new mutationobserver(nexttickhandler); var textnode = document.createtextnode(counter); observer.observe(textnode, { characterdata: true }); timerfunc = function () { counter = (counter + 1) % 2; textnode.data = counter; }; } else { // webpack attempts to inject a shim for setimmediate // if it is used as a global, so we have to work around that to // avoid bundling unnecessary code. var context = inbrowser ? window : typeof global !== 'undefined' ? global : {}; timerfunc = context.setimmediate || settimeout; } return function (cb, ctx) { var func = ctx ? function () { cb.call(ctx); } : cb; callbacks.push(func); if (pending) return; pending = true; timerfunc(nexttickhandler, 0); }; })(); var _set = undefined; /* istanbul ignore if */ if (typeof set !== 'undefined' && set.tostring().match(/native code/)) { // use native set when available. _set = set; } else { // a non-standard set polyfill that only works with primitive keys. _set = function () { this.set = object.create(null); }; _set.prototype.has = function (key) { return this.set[key] !== undefined; }; _set.prototype.add = function (key) { this.set[key] = 1; }; _set.prototype.clear = function () { this.set = object.create(null); }; } function cache(limit) { this.size = 0; this.limit = limit; this.head = this.tail = undefined; this._keymap = object.create(null); } var p = cache.prototype; /** * put into the cache associated with . * returns the entry which was removed to make room for * the new entry. otherwise undefined is returned. * (i.e. if there was enough room already). * * @param {string} key * @param {*} value * @return {entry|undefined} */ p.put = function (key, value) { var removed; var entry = this.get(key, true); if (!entry) { if (this.size === this.limit) { removed = this.shift(); } entry = { key: key }; this._keymap[key] = entry; if (this.tail) { this.tail.newer = entry; entry.older = this.tail; } else { this.head = entry; } this.tail = entry; this.size++; } entry.value = value; return removed; }; /** * purge the least recently used (oldest) entry from the * cache. returns the removed entry or undefined if the * cache was empty. */ p.shift = function () { var entry = this.head; if (entry) { this.head = this.head.newer; this.head.older = undefined; entry.newer = entry.older = undefined; this._keymap[entry.key] = undefined; this.size--; } return entry; }; /** * get and register recent use of . returns the value * associated with or undefined if not in cache. * * @param {string} key * @param {boolean} returnentry * @return {entry|*} */ p.get = function (key, returnentry) { var entry = this._keymap[key]; if (entry === undefined) return; if (entry === this.tail) { return returnentry ? entry : entry.value; } // head--------------tail // <.older .newer> // <--- add direction -- // a b c e if (entry.newer) { if (entry === this.head) { this.head = entry.newer; } entry.newer.older = entry.older; // c <-- e. } if (entry.older) { entry.older.newer = entry.newer; // c. --> e } entry.newer = undefined; // d --x entry.older = this.tail; // d. --> e if (this.tail) { this.tail.newer = entry; // e. <-- d } this.tail = entry; return returnentry ? entry : entry.value; }; var cache$1 = new cache(1000); var filtertokenre = /[^\s'"]+|'[^']*'|"[^"]*"/g; var reservedargre = /^in$|^-?\d+/; /** * parser state */ var str; var dir; var c; var prev; var i; var l; var lastfilterindex; var insingle; var indouble; var curly; var square; var paren; /** * push a filter to the current directive object */ function pushfilter() { var exp = str.slice(lastfilterindex, i).trim(); var filter; if (exp) { filter = {}; var tokens = exp.match(filtertokenre); filter.name = tokens[0]; if (tokens.length > 1) { filter.args = tokens.slice(1).map(processfilterarg); } } if (filter) { (dir.filters = dir.filters || []).push(filter); } lastfilterindex = i + 1; } /** * check if an argument is dynamic and strip quotes. * * @param {string} arg * @return {object} */ function processfilterarg(arg) { if (reservedargre.test(arg)) { return { value: tonumber(arg), dynamic: false }; } else { var stripped = stripquotes(arg); var dynamic = stripped === arg; return { value: dynamic ? arg : stripped, dynamic: dynamic }; } } /** * parse a directive value and extract the expression * and its filters into a descriptor. * * example: * * "a + 1 | uppercase" will yield: * { * expression: 'a + 1', * filters: [ * { name: 'uppercase', args: null } * ] * } * * @param {string} s * @return {object} */ function parsedirective(s) { var hit = cache$1.get(s); if (hit) { return hit; } // reset parser state str = s; insingle = indouble = false; curly = square = paren = 0; lastfilterindex = 0; dir = {}; for (i = 0, l = str.length; i < l; i++) { prev = c; c = str.charcodeat(i); if (insingle) { // check single quote if (c === 0x27 && prev !== 0x5c) insingle = !insingle; } else if (indouble) { // check double quote if (c === 0x22 && prev !== 0x5c) indouble = !indouble; } else if (c === 0x7c && // pipe str.charcodeat(i + 1) !== 0x7c && str.charcodeat(i - 1) !== 0x7c) { if (dir.expression == null) { // first filter, end of expression lastfilterindex = i + 1; dir.expression = str.slice(0, i).trim(); } else { // already has filter pushfilter(); } } else { switch (c) { case 0x22: indouble = true;break; // " case 0x27: insingle = true;break; // ' case 0x28: paren++;break; // ( case 0x29: paren--;break; // ) case 0x5b: square++;break; // [ case 0x5d: square--;break; // ] case 0x7b: curly++;break; // { case 0x7d: curly--;break; // } } } } if (dir.expression == null) { dir.expression = str.slice(0, i).trim(); } else if (lastfilterindex !== 0) { pushfilter(); } cache$1.put(s, dir); return dir; } var directive = object.freeze({ parsedirective: parsedirective }); var regexescapere = /[-.*+?^${}()|[\]\/\\]/g; var cache = undefined; var tagre = undefined; var htmlre = undefined; /** * escape a string so it can be used in a regexp * constructor. * * @param {string} str */ function escaperegex(str) { return str.replace(regexescapere, '\\$&'); } function compileregex() { var open = escaperegex(config.delimiters[0]); var close = escaperegex(config.delimiters[1]); var unsafeopen = escaperegex(config.unsafedelimiters[0]); var unsafeclose = escaperegex(config.unsafedelimiters[1]); tagre = new regexp(unsafeopen + '((?:.|\\n)+?)' + unsafeclose + '|' + open + '((?:.|\\n)+?)' + close, 'g'); htmlre = new regexp('^' + unsafeopen + '((?:.|\\n)+?)' + unsafeclose + '$'); // reset cache cache = new cache(1000); } /** * parse a template text string into an array of tokens. * * @param {string} text * @return {array | null} * - {string} type * - {string} value * - {boolean} [html] * - {boolean} [onetime] */ function parsetext(text) { if (!cache) { compileregex(); } var hit = cache.get(text); if (hit) { return hit; } if (!tagre.test(text)) { return null; } var tokens = []; var lastindex = tagre.lastindex = 0; var match, index, html, value, first, onetime; /* eslint-disable no-cond-assign */ while (match = tagre.exec(text)) { /* eslint-enable no-cond-assign */ index = match.index; // push text token if (index > lastindex) { tokens.push({ value: text.slice(lastindex, index) }); } // tag token html = htmlre.test(match[0]); value = html ? match[1] : match[2]; first = value.charcodeat(0); onetime = first === 42; // * value = onetime ? value.slice(1) : value; tokens.push({ tag: true, value: value.trim(), html: html, onetime: onetime }); lastindex = index + match[0].length; } if (lastindex < text.length) { tokens.push({ value: text.slice(lastindex) }); } cache.put(text, tokens); return tokens; } /** * format a list of tokens into an expression. * e.g. tokens parsed from 'a {{b}} c' can be serialized * into one single expression as '"a " + b + " c"'. * * @param {array} tokens * @param {vue} [vm] * @return {string} */ function tokenstoexp(tokens, vm) { if (tokens.length > 1) { return tokens.map(function (token) { return formattoken(token, vm); }).join('+'); } else { return formattoken(tokens[0], vm, true); } } /** * format a single token. * * @param {object} token * @param {vue} [vm] * @param {boolean} [single] * @return {string} */ function formattoken(token, vm, single) { return token.tag ? token.onetime && vm ? '"' + vm.$eval(token.value) + '"' : inlinefilters(token.value, single) : '"' + token.value + '"'; } /** * for an attribute with multiple interpolation tags, * e.g. attr="some-{{thing | filter}}", in order to combine * the whole thing into a single watchable expression, we * have to inline those filters. this function does exactly * that. this is a bit hacky but it avoids heavy changes * to directive parser and watcher mechanism. * * @param {string} exp * @param {boolean} single * @return {string} */ var filterre = /[^|]\|[^|]/; function inlinefilters(exp, single) { if (!filterre.test(exp)) { return single ? exp : '(' + exp + ')'; } else { var dir = parsedirective(exp); if (!dir.filters) { return '(' + exp + ')'; } else { return 'this._applyfilters(' + dir.expression + // value ',null,' + // oldvalue (null for read) json.stringify(dir.filters) + // filter descriptors ',false)'; // write? } } } var text = object.freeze({ compileregex: compileregex, parsetext: parsetext, tokenstoexp: tokenstoexp }); var delimiters = ['{{', '}}']; var unsafedelimiters = ['{{{', '}}}']; var config = object.defineproperties({ /** * whether to print debug messages. * also enables stack trace for warnings. * * @type {boolean} */ debug: false, /** * whether to suppress warnings. * * @type {boolean} */ silent: false, /** * whether to use async rendering. */ async: true, /** * whether to warn against errors caught when evaluating * expressions. */ warnexpressionerrors: true, /** * whether to allow devtools inspection. * disabled by default in production builds. */ devtools: 'development' !== 'production', /** * internal flag to indicate the delimiters have been * changed. * * @type {boolean} */ _delimiterschanged: true, /** * list of asset types that a component can own. * * @type {array} */ _assettypes: ['component', 'directive', 'elementdirective', 'filter', 'transition', 'partial'], /** * prop binding modes */ _propbindingmodes: { one_way: 0, two_way: 1, one_time: 2 }, /** * max circular updates allowed in a batcher flush cycle. */ _maxupdatecount: 100 }, { delimiters: { /** * interpolation delimiters. changing these would trigger * the text parser to re-compile the regular expressions. * * @type {array} */ get: function get() { return delimiters; }, set: function set(val) { delimiters = val; compileregex(); }, configurable: true, enumerable: true }, unsafedelimiters: { get: function get() { return unsafedelimiters; }, set: function set(val) { unsafedelimiters = val; compileregex(); }, configurable: true, enumerable: true } }); var warn = undefined; var formatcomponentname = undefined; if ('development' !== 'production') { (function () { var hasconsole = typeof console !== 'undefined'; warn = function (msg, vm) { if (hasconsole && !config.silent) { console.error('[vue warn]: ' + msg + (vm ? formatcomponentname(vm) : '')); } }; formatcomponentname = function (vm) { var name = vm._isvue ? vm.$options.name : vm.name; return name ? ' (found in component: <' + hyphenate(name) + '>)' : ''; }; })(); } /** * append with transition. * * @param {element} el * @param {element} target * @param {vue} vm * @param {function} [cb] */ function appendwithtransition(el, target, vm, cb) { applytransition(el, 1, function () { target.appendchild(el); }, vm, cb); } /** * insertbefore with transition. * * @param {element} el * @param {element} target * @param {vue} vm * @param {function} [cb] */ function beforewithtransition(el, target, vm, cb) { applytransition(el, 1, function () { before(el, target); }, vm, cb); } /** * remove with transition. * * @param {element} el * @param {vue} vm * @param {function} [cb] */ function removewithtransition(el, vm, cb) { applytransition(el, -1, function () { remove(el); }, vm, cb); } /** * apply transitions with an operation callback. * * @param {element} el * @param {number} direction * 1: enter * -1: leave * @param {function} op - the actual dom operation * @param {vue} vm * @param {function} [cb] */ function applytransition(el, direction, op, vm, cb) { var transition = el.__v_trans; if (!transition || // skip if there are no js hooks and css transition is // not supported !transition.hooks && !transitionendevent || // skip transitions for initial compile !vm._iscompiled || // if the vm is being manipulated by a parent directive // during the parent's compilation phase, skip the // animation. vm.$parent && !vm.$parent._iscompiled) { op(); if (cb) cb(); return; } var action = direction > 0 ? 'enter' : 'leave'; transition[action](op, cb); } var transition = object.freeze({ appendwithtransition: appendwithtransition, beforewithtransition: beforewithtransition, removewithtransition: removewithtransition, applytransition: applytransition }); /** * query an element selector if it's not an element already. * * @param {string|element} el * @return {element} */ function query(el) { if (typeof el === 'string') { var selector = el; el = document.queryselector(el); if (!el) { 'development' !== 'production' && warn('cannot find element: ' + selector); } } return el; } /** * check if a node is in the document. * note: document.documentelement.contains should work here * but always returns false for comment nodes in phantomjs, * making unit tests difficult. this is fixed by doing the * contains() check on the node's parentnode instead of * the node itself. * * @param {node} node * @return {boolean} */ function indoc(node) { if (!node) return false; var doc = node.ownerdocument.documentelement; var parent = node.parentnode; return doc === node || doc === parent || !!(parent && parent.nodetype === 1 && doc.contains(parent)); } /** * get and remove an attribute from a node. * * @param {node} node * @param {string} _attr */ function getattr(node, _attr) { var val = node.getattribute(_attr); if (val !== null) { node.removeattribute(_attr); } return val; } /** * get an attribute with colon or v-bind: prefix. * * @param {node} node * @param {string} name * @return {string|null} */ function getbindattr(node, name) { var val = getattr(node, ':' + name); if (val === null) { val = getattr(node, 'v-bind:' + name); } return val; } /** * check the presence of a bind attribute. * * @param {node} node * @param {string} name * @return {boolean} */ function hasbindattr(node, name) { return node.hasattribute(name) || node.hasattribute(':' + name) || node.hasattribute('v-bind:' + name); } /** * insert el before target * * @param {element} el * @param {element} target */ function before(el, target) { target.parentnode.insertbefore(el, target); } /** * insert el after target * * @param {element} el * @param {element} target */ function after(el, target) { if (target.nextsibling) { before(el, target.nextsibling); } else { target.parentnode.appendchild(el); } } /** * remove el from dom * * @param {element} el */ function remove(el) { el.parentnode.removechild(el); } /** * prepend el to target * * @param {element} el * @param {element} target */ function prepend(el, target) { if (target.firstchild) { before(el, target.firstchild); } else { target.appendchild(el); } } /** * replace target with el * * @param {element} target * @param {element} el */ function replace(target, el) { var parent = target.parentnode; if (parent) { parent.replacechild(el, target); } } /** * add event listener shorthand. * * @param {element} el * @param {string} event * @param {function} cb * @param {boolean} [usecapture] */ function on(el, event, cb, usecapture) { el.addeventlistener(event, cb, usecapture); } /** * remove event listener shorthand. * * @param {element} el * @param {string} event * @param {function} cb */ function off(el, event, cb) { el.removeeventlistener(event, cb); } /** * for ie9 compat: when both class and :class are present * getattribute('class') returns wrong value... * * @param {element} el * @return {string} */ function getclass(el) { var classname = el.classname; if (typeof classname === 'object') { classname = classname.baseval || ''; } return classname; } /** * in ie9, setattribute('class') will result in empty class * if the element also has the :class attribute; however in * phantomjs, setting `classname` does not work on svg elements... * so we have to do a conditional check here. * * @param {element} el * @param {string} cls */ function setclass(el, cls) { /* istanbul ignore if */ if (isie9 && !/svg$/.test(el.namespaceuri)) { el.classname = cls; } else { el.setattribute('class', cls); } } /** * add class with compatibility for ie & svg * * @param {element} el * @param {string} cls */ function addclass(el, cls) { if (el.classlist) { el.classlist.add(cls); } else { var cur = ' ' + getclass(el) + ' '; if (cur.indexof(' ' + cls + ' ') < 0) { setclass(el, (cur + cls).trim()); } } } /** * remove class with compatibility for ie & svg * * @param {element} el * @param {string} cls */ function removeclass(el, cls) { if (el.classlist) { el.classlist.remove(cls); } else { var cur = ' ' + getclass(el) + ' '; var tar = ' ' + cls + ' '; while (cur.indexof(tar) >= 0) { cur = cur.replace(tar, ' '); } setclass(el, cur.trim()); } if (!el.classname) { el.removeattribute('class'); } } /** * extract raw content inside an element into a temporary * container div * * @param {element} el * @param {boolean} asfragment * @return {element|documentfragment} */ function extractcontent(el, asfragment) { var child; var rawcontent; /* istanbul ignore if */ if (istemplate(el) && isfragment(el.content)) { el = el.content; } if (el.haschildnodes()) { trimnode(el); rawcontent = asfragment ? document.createdocumentfragment() : document.createelement('div'); /* eslint-disable no-cond-assign */ while (child = el.firstchild) { /* eslint-enable no-cond-assign */ rawcontent.appendchild(child); } } return rawcontent; } /** * trim possible empty head/tail text and comment * nodes inside a parent. * * @param {node} node */ function trimnode(node) { var child; /* eslint-disable no-sequences */ while ((child = node.firstchild, istrimmable(child))) { node.removechild(child); } while ((child = node.lastchild, istrimmable(child))) { node.removechild(child); } /* eslint-enable no-sequences */ } function istrimmable(node) { return node && (node.nodetype === 3 && !node.data.trim() || node.nodetype === 8); } /** * check if an element is a template tag. * note if the template appears inside an svg its tagname * will be in lowercase. * * @param {element} el */ function istemplate(el) { return el.tagname && el.tagname.tolowercase() === 'template'; } /** * create an "anchor" for performing dom insertion/removals. * this is used in a number of scenarios: * - fragment instance * - v-html * - v-if * - v-for * - component * * @param {string} content * @param {boolean} persist - ie trashes empty textnodes on * clonenode(true), so in certain * cases the anchor needs to be * non-empty to be persisted in * templates. * @return {comment|text} */ function createanchor(content, persist) { var anchor = config.debug ? document.createcomment(content) : document.createtextnode(persist ? ' ' : ''); anchor.__v_anchor = true; return anchor; } /** * find a component ref attribute that starts with $. * * @param {element} node * @return {string|undefined} */ var refre = /^v-ref:/; function findref(node) { if (node.hasattributes()) { var attrs = node.attributes; for (var i = 0, l = attrs.length; i < l; i++) { var name = attrs[i].name; if (refre.test(name)) { return camelize(name.replace(refre, '')); } } } } /** * map a function to a range of nodes . * * @param {node} node * @param {node} end * @param {function} op */ function mapnoderange(node, end, op) { var next; while (node !== end) { next = node.nextsibling; op(node); node = next; } op(end); } /** * remove a range of nodes with transition, store * the nodes in a fragment with correct ordering, * and call callback when done. * * @param {node} start * @param {node} end * @param {vue} vm * @param {documentfragment} frag * @param {function} cb */ function removenoderange(start, end, vm, frag, cb) { var done = false; var removed = 0; var nodes = []; mapnoderange(start, end, function (node) { if (node === end) done = true; nodes.push(node); removewithtransition(node, vm, onremoved); }); function onremoved() { removed++; if (done && removed >= nodes.length) { for (var i = 0; i < nodes.length; i++) { frag.appendchild(nodes[i]); } cb && cb(); } } } /** * check if a node is a documentfragment. * * @param {node} node * @return {boolean} */ function isfragment(node) { return node && node.nodetype === 11; } /** * get outerhtml of elements, taking care * of svg elements in ie as well. * * @param {element} el * @return {string} */ function getouterhtml(el) { if (el.outerhtml) { return el.outerhtml; } else { var container = document.createelement('div'); container.appendchild(el.clonenode(true)); return container.innerhtml; } } var commontagre = /^(div|p|span|img|a|b|i|br|ul|ol|li|h1|h2|h3|h4|h5|h6|code|pre|table|th|td|tr|form|label|input|select|option|nav|article|section|header|footer)$/i; var reservedtagre = /^(slot|partial|component)$/i; var isunknownelement = undefined; if ('development' !== 'production') { isunknownelement = function (el, tag) { if (tag.indexof('-') > -1) { // http://stackoverflow.com/a/28210364/1070244 return el.constructor === window.htmlunknownelement || el.constructor === window.htmlelement; } else { return (/htmlunknownelement/.test(el.tostring()) && // chrome returns unknown for several html5 elements. // https://code.google.com/p/chromium/issues/detail?id=540526 // firefox returns unknown for some "interactive elements." !/^(data|time|rtc|rb|details|dialog|summary)$/.test(tag) ); } }; } /** * check if an element is a component, if yes return its * component id. * * @param {element} el * @param {object} options * @return {object|undefined} */ function checkcomponentattr(el, options) { var tag = el.tagname.tolowercase(); var hasattrs = el.hasattributes(); if (!commontagre.test(tag) && !reservedtagre.test(tag)) { if (resolveasset(options, 'components', tag)) { return { id: tag }; } else { var is = hasattrs && getisbinding(el, options); if (is) { return is; } else if ('development' !== 'production') { var expectedtag = options._componentnamemap && options._componentnamemap[tag]; if (expectedtag) { warn('unknown custom element: <' + tag + '> - ' + 'did you mean <' + expectedtag + '>? ' + 'html is case-insensitive, remember to use kebab-case in templates.'); } else if (isunknownelement(el, tag)) { warn('unknown custom element: <' + tag + '> - did you ' + 'register the component correctly? for recursive components, ' + 'make sure to provide the "name" option.'); } } } } else if (hasattrs) { return getisbinding(el, options); } } /** * get "is" binding from an element. * * @param {element} el * @param {object} options * @return {object|undefined} */ function getisbinding(el, options) { // dynamic syntax var exp = el.getattribute('is'); if (exp != null) { if (resolveasset(options, 'components', exp)) { el.removeattribute('is'); return { id: exp }; } } else { exp = getbindattr(el, 'is'); if (exp != null) { return { id: exp, dynamic: true }; } } } /** * option overwriting strategies are functions that handle * how to merge a parent option value and a child option * value into the final value. * * all strategy functions follow the same signature: * * @param {*} parentval * @param {*} childval * @param {vue} [vm] */ var strats = config.optionmergestrategies = object.create(null); /** * helper that recursively merges two data objects together. */ function mergedata(to, from) { var key, toval, fromval; for (key in from) { toval = to[key]; fromval = from[key]; if (!hasown(to, key)) { set(to, key, fromval); } else if (isobject(toval) && isobject(fromval)) { mergedata(toval, fromval); } } return to; } /** * data */ strats.data = function (parentval, childval, vm) { if (!vm) { // in a vue.extend merge, both should be functions if (!childval) { return parentval; } if (typeof childval !== 'function') { 'development' !== 'production' && warn('the "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm); return parentval; } if (!parentval) { return childval; } // when parentval & childval are both present, // we need to return a function that returns the // merged result of both functions... no need to // check if parentval is a function here because // it has to be a function to pass previous merges. return function mergeddatafn() { return mergedata(childval.call(this), parentval.call(this)); }; } else if (parentval || childval) { return function mergedinstancedatafn() { // instance merge var instancedata = typeof childval === 'function' ? childval.call(vm) : childval; var defaultdata = typeof parentval === 'function' ? parentval.call(vm) : undefined; if (instancedata) { return mergedata(instancedata, defaultdata); } else { return defaultdata; } }; } }; /** * el */ strats.el = function (parentval, childval, vm) { if (!vm && childval && typeof childval !== 'function') { 'development' !== 'production' && warn('the "el" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.', vm); return; } var ret = childval || parentval; // invoke the element factory if this is instance merge return vm && typeof ret === 'function' ? ret.call(vm) : ret; }; /** * hooks and param attributes are merged as arrays. */ strats.init = strats.created = strats.ready = strats.attached = strats.detached = strats.beforecompile = strats.compiled = strats.beforedestroy = strats.destroyed = strats.activate = function (parentval, childval) { return childval ? parentval ? parentval.concat(childval) : isarray(childval) ? childval : [childval] : parentval; }; /** * assets * * when a vm is present (instance creation), we need to do * a three-way merge between constructor options, instance * options and parent options. */ function mergeassets(parentval, childval) { var res = object.create(parentval || null); return childval ? extend(res, guardarrayassets(childval)) : res; } config._assettypes.foreach(function (type) { strats[type + 's'] = mergeassets; }); /** * events & watchers. * * events & watchers hashes should not overwrite one * another, so we merge them as arrays. */ strats.watch = strats.events = function (parentval, childval) { if (!childval) return parentval; if (!parentval) return childval; var ret = {}; extend(ret, parentval); for (var key in childval) { var parent = ret[key]; var child = childval[key]; if (parent && !isarray(parent)) { parent = [parent]; } ret[key] = parent ? parent.concat(child) : [child]; } return ret; }; /** * other object hashes. */ strats.props = strats.methods = strats.computed = function (parentval, childval) { if (!childval) return parentval; if (!parentval) return childval; var ret = object.create(null); extend(ret, parentval); extend(ret, childval); return ret; }; /** * default strategy. */ var defaultstrat = function defaultstrat(parentval, childval) { return childval === undefined ? parentval : childval; }; /** * make sure component options get converted to actual * constructors. * * @param {object} options */ function guardcomponents(options) { if (options.components) { var components = options.components = guardarrayassets(options.components); var ids = object.keys(components); var def; if ('development' !== 'production') { var map = options._componentnamemap = {}; } for (var i = 0, l = ids.length; i < l; i++) { var key = ids[i]; if (commontagre.test(key) || reservedtagre.test(key)) { 'development' !== 'production' && warn('do not use built-in or reserved html elements as component ' + 'id: ' + key); continue; } // record a all lowercase <-> kebab-case mapping for // possible custom element case error warning if ('development' !== 'production') { map[key.replace(/-/g, '').tolowercase()] = hyphenate(key); } def = components[key]; if (isplainobject(def)) { components[key] = vue.extend(def); } } } } /** * ensure all props option syntax are normalized into the * object-based format. * * @param {object} options */ function guardprops(options) { var props = options.props; var i, val; if (isarray(props)) { options.props = {}; i = props.length; while (i--) { val = props[i]; if (typeof val === 'string') { options.props[val] = null; } else if (val.name) { options.props[val.name] = val; } } } else if (isplainobject(props)) { var keys = object.keys(props); i = keys.length; while (i--) { val = props[keys[i]]; if (typeof val === 'function') { props[keys[i]] = { type: val }; } } } } /** * guard an array-format assets option and converted it * into the key-value object format. * * @param {object|array} assets * @return {object} */ function guardarrayassets(assets) { if (isarray(assets)) { var res = {}; var i = assets.length; var asset; while (i--) { asset = assets[i]; var id = typeof asset === 'function' ? asset.options && asset.options.name || asset.id : asset.name || asset.id; if (!id) { 'development' !== 'production' && warn('array-syntax assets must provide a "name" or "id" field.'); } else { res[id] = asset; } } return res; } return assets; } /** * merge two option objects into a new one. * core utility used in both instantiation and inheritance. * * @param {object} parent * @param {object} child * @param {vue} [vm] - if vm is present, indicates this is * an instantiation merge. */ function mergeoptions(parent, child, vm) { guardcomponents(child); guardprops(child); if ('development' !== 'production') { if (child.propsdata && !vm) { warn('propsdata can only be used as an instantiation option.'); } } var options = {}; var key; if (child['extends']) { parent = typeof child['extends'] === 'function' ? mergeoptions(parent, child['extends'].options, vm) : mergeoptions(parent, child['extends'], vm); } if (child.mixins) { for (var i = 0, l = child.mixins.length; i < l; i++) { var mixin = child.mixins[i]; var mixinoptions = mixin.prototype instanceof vue ? mixin.options : mixin; parent = mergeoptions(parent, mixinoptions, vm); } } for (key in parent) { mergefield(key); } for (key in child) { if (!hasown(parent, key)) { mergefield(key); } } function mergefield(key) { var strat = strats[key] || defaultstrat; options[key] = strat(parent[key], child[key], vm, key); } return options; } /** * resolve an asset. * this function is used because child instances need access * to assets defined in its ancestor chain. * * @param {object} options * @param {string} type * @param {string} id * @param {boolean} warnmissing * @return {object|function} */ function resolveasset(options, type, id, warnmissing) { /* istanbul ignore if */ if (typeof id !== 'string') { return; } var assets = options[type]; var camelizedid; var res = assets[id] || // camelcase id assets[camelizedid = camelize(id)] || // pascal case id assets[camelizedid.charat(0).touppercase() + camelizedid.slice(1)]; if ('development' !== 'production' && warnmissing && !res) { warn('failed to resolve ' + type.slice(0, -1) + ': ' + id, options); } return res; } var uid$1 = 0; /** * a dep is an observable that can have multiple * directives subscribing to it. * * @constructor */ function dep() { this.id = uid$1++; this.subs = []; } // the current target watcher being evaluated. // this is globally unique because there could be only one // watcher being evaluated at any time. dep.target = null; /** * add a directive subscriber. * * @param {directive} sub */ dep.prototype.addsub = function (sub) { this.subs.push(sub); }; /** * remove a directive subscriber. * * @param {directive} sub */ dep.prototype.removesub = function (sub) { this.subs.$remove(sub); }; /** * add self as a dependency to the target watcher. */ dep.prototype.depend = function () { dep.target.adddep(this); }; /** * notify all subscribers of a new value. */ dep.prototype.notify = function () { // stablize the subscriber list first var subs = toarray(this.subs); for (var i = 0, l = subs.length; i < l; i++) { subs[i].update(); } }; var arrayproto = array.prototype; var arraymethods = object.create(arrayproto) /** * intercept mutating methods and emit events */ ;['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].foreach(function (method) { // cache original method var original = arrayproto[method]; def(arraymethods, method, function mutator() { // avoid leaking arguments: // http://jsperf.com/closure-with-arguments var i = arguments.length; var args = new array(i); while (i--) { args[i] = arguments[i]; } var result = original.apply(this, args); var ob = this.__ob__; var inserted; switch (method) { case 'push': inserted = args; break; case 'unshift': inserted = args; break; case 'splice': inserted = args.slice(2); break; } if (inserted) ob.observearray(inserted); // notify change ob.dep.notify(); return result; }); }); /** * swap the element at the given index with a new value * and emits corresponding event. * * @param {number} index * @param {*} val * @return {*} - replaced element */ def(arrayproto, '$set', function $set(index, val) { if (index >= this.length) { this.length = number(index) + 1; } return this.splice(index, 1, val)[0]; }); /** * convenience method to remove the element at given index or target element reference. * * @param {*} item */ def(arrayproto, '$remove', function $remove(item) { /* istanbul ignore if */ if (!this.length) return; var index = indexof(this, item); if (index > -1) { return this.splice(index, 1); } }); var arraykeys = object.getownpropertynames(arraymethods); /** * by default, when a reactive property is set, the new value is * also converted to become reactive. however in certain cases, e.g. * v-for scope alias and props, we don't want to force conversion * because the value may be a nested value under a frozen data structure. * * so whenever we want to set a reactive property without forcing * conversion on the new value, we wrap that call inside this function. */ var shouldconvert = true; function withoutconversion(fn) { shouldconvert = false; fn(); shouldconvert = true; } /** * observer class that are attached to each observed * object. once attached, the observer converts target * object's property keys into getter/setters that * collect dependencies and dispatches updates. * * @param {array|object} value * @constructor */ function observer(value) { this.value = value; this.dep = new dep(); def(value, '__ob__', this); if (isarray(value)) { var augment = hasproto ? protoaugment : copyaugment; augment(value, arraymethods, arraykeys); this.observearray(value); } else { this.walk(value); } } // instance methods /** * walk through each property and convert them into * getter/setters. this method should only be called when * value type is object. * * @param {object} obj */ observer.prototype.walk = function (obj) { var keys = object.keys(obj); for (var i = 0, l = keys.length; i < l; i++) { this.convert(keys[i], obj[keys[i]]); } }; /** * observe a list of array items. * * @param {array} items */ observer.prototype.observearray = function (items) { for (var i = 0, l = items.length; i < l; i++) { observe(items[i]); } }; /** * convert a property into getter/setter so we can emit * the events when the property is accessed/changed. * * @param {string} key * @param {*} val */ observer.prototype.convert = function (key, val) { definereactive(this.value, key, val); }; /** * add an owner vm, so that when $set/$delete mutations * happen we can notify owner vms to proxy the keys and * digest the watchers. this is only called when the object * is observed as an instance's root $data. * * @param {vue} vm */ observer.prototype.addvm = function (vm) { (this.vms || (this.vms = [])).push(vm); }; /** * remove an owner vm. this is called when the object is * swapped out as an instance's $data object. * * @param {vue} vm */ observer.prototype.removevm = function (vm) { this.vms.$remove(vm); }; // helpers /** * augment an target object or array by intercepting * the prototype chain using __proto__ * * @param {object|array} target * @param {object} src */ function protoaugment(target, src) { /* eslint-disable no-proto */ target.__proto__ = src; /* eslint-enable no-proto */ } /** * augment an target object or array by defining * hidden properties. * * @param {object|array} target * @param {object} proto */ function copyaugment(target, src, keys) { for (var i = 0, l = keys.length; i < l; i++) { var key = keys[i]; def(target, key, src[key]); } } /** * attempt to create an observer instance for a value, * returns the new observer if successfully observed, * or the existing observer if the value already has one. * * @param {*} value * @param {vue} [vm] * @return {observer|undefined} * @static */ function observe(value, vm) { if (!value || typeof value !== 'object') { return; } var ob; if (hasown(value, '__ob__') && value.__ob__ instanceof observer) { ob = value.__ob__; } else if (shouldconvert && (isarray(value) || isplainobject(value)) && object.isextensible(value) && !value._isvue) { ob = new observer(value); } if (ob && vm) { ob.addvm(vm); } return ob; } /** * define a reactive property on an object. * * @param {object} obj * @param {string} key * @param {*} val */ function definereactive(obj, key, val) { var dep = new dep(); var property = object.getownpropertydescriptor(obj, key); if (property && property.configurable === false) { return; } // cater for pre-defined getter/setters var getter = property && property.get; var setter = property && property.set; var childob = observe(val); object.defineproperty(obj, key, { enumerable: true, configurable: true, get: function reactivegetter() { var value = getter ? getter.call(obj) : val; if (dep.target) { dep.depend(); if (childob) { childob.dep.depend(); } if (isarray(value)) { for (var e, i = 0, l = value.length; i < l; i++) { e = value[i]; e && e.__ob__ && e.__ob__.dep.depend(); } } } return value; }, set: function reactivesetter(newval) { var value = getter ? getter.call(obj) : val; if (newval === value) { return; } if (setter) { setter.call(obj, newval); } else { val = newval; } childob = observe(newval); dep.notify(); } }); } var util = object.freeze({ definereactive: definereactive, set: set, del: del, hasown: hasown, isliteral: isliteral, isreserved: isreserved, _tostring: _tostring, tonumber: tonumber, toboolean: toboolean, stripquotes: stripquotes, camelize: camelize, hyphenate: hyphenate, classify: classify, bind: bind, toarray: toarray, extend: extend, isobject: isobject, isplainobject: isplainobject, def: def, debounce: _debounce, indexof: indexof, cancellable: cancellable, looseequal: looseequal, isarray: isarray, hasproto: hasproto, inbrowser: inbrowser, devtools: devtools, isie: isie, isie9: isie9, isandroid: isandroid, isios: isios, iosversionmatch: iosversionmatch, iosversion: iosversion, hasmutationobserverbug: hasmutationobserverbug, get transitionprop () { return transitionprop; }, get transitionendevent () { return transitionendevent; }, get animationprop () { return animationprop; }, get animationendevent () { return animationendevent; }, nexttick: nexttick, get _set () { return _set; }, query: query, indoc: indoc, getattr: getattr, getbindattr: getbindattr, hasbindattr: hasbindattr, before: before, after: after, remove: remove, prepend: prepend, replace: replace, on: on, off: off, setclass: setclass, addclass: addclass, removeclass: removeclass, extractcontent: extractcontent, trimnode: trimnode, istemplate: istemplate, createanchor: createanchor, findref: findref, mapnoderange: mapnoderange, removenoderange: removenoderange, isfragment: isfragment, getouterhtml: getouterhtml, mergeoptions: mergeoptions, resolveasset: resolveasset, checkcomponentattr: checkcomponentattr, commontagre: commontagre, reservedtagre: reservedtagre, get warn () { return warn; } }); var uid = 0; function initmixin (vue) { /** * the main init sequence. this is called for every * instance, including ones that are created from extended * constructors. * * @param {object} options - this options object should be * the result of merging class * options and the options passed * in to the constructor. */ vue.prototype._init = function (options) { options = options || {}; this.$el = null; this.$parent = options.parent; this.$root = this.$parent ? this.$parent.$root : this; this.$children = []; this.$refs = {}; // child vm references this.$els = {}; // element references this._watchers = []; // all watchers as an array this._directives = []; // all directives // a uid this._uid = uid++; // a flag to avoid this being observed this._isvue = true; // events bookkeeping this._events = {}; // registered callbacks this._eventscount = {}; // for $broadcast optimization // fragment instance properties this._isfragment = false; this._fragment = // @type {documentfragment} this._fragmentstart = // @type {text|comment} this._fragmentend = null; // @type {text|comment} // lifecycle state this._iscompiled = this._isdestroyed = this._isready = this._isattached = this._isbeingdestroyed = this._vforremoving = false; this._unlinkfn = null; // context: // if this is a transcluded component, context // will be the common parent vm of this instance // and its host. this._context = options._context || this.$parent; // scope: // if this is inside an inline v-for, the scope // will be the intermediate scope created for this // repeat fragment. this is used for linking props // and container directives. this._scope = options._scope; // fragment: // if this instance is compiled inside a fragment, it // needs to reigster itself as a child of that fragment // for attach/detach to work properly. this._frag = options._frag; if (this._frag) { this._frag.children.push(this); } // push self into parent / transclusion host if (this.$parent) { this.$parent.$children.push(this); } // merge options. options = this.$options = mergeoptions(this.constructor.options, options, this); // set ref this._updateref(); // initialize data as empty object. // it will be filled up in _initdata(). this._data = {}; // call init hook this._callhook('init'); // initialize data observation and scope inheritance. this._initstate(); // setup event system and option events. this._initevents(); // call created hook this._callhook('created'); // if `el` option is passed, start compilation. if (options.el) { this.$mount(options.el); } }; } var pathcache = new cache(1000); // actions var append = 0; var push = 1; var inc_sub_path_depth = 2; var push_sub_path = 3; // states var before_path = 0; var in_path = 1; var before_ident = 2; var in_ident = 3; var in_sub_path = 4; var in_single_quote = 5; var in_double_quote = 6; var after_path = 7; var error = 8; var pathstatemachine = []; pathstatemachine[before_path] = { 'ws': [before_path], 'ident': [in_ident, append], '[': [in_sub_path], 'eof': [after_path] }; pathstatemachine[in_path] = { 'ws': [in_path], '.': [before_ident], '[': [in_sub_path], 'eof': [after_path] }; pathstatemachine[before_ident] = { 'ws': [before_ident], 'ident': [in_ident, append] }; pathstatemachine[in_ident] = { 'ident': [in_ident, append], '0': [in_ident, append], 'number': [in_ident, append], 'ws': [in_path, push], '.': [before_ident, push], '[': [in_sub_path, push], 'eof': [after_path, push] }; pathstatemachine[in_sub_path] = { "'": [in_single_quote, append], '"': [in_double_quote, append], '[': [in_sub_path, inc_sub_path_depth], ']': [in_path, push_sub_path], 'eof': error, 'else': [in_sub_path, append] }; pathstatemachine[in_single_quote] = { "'": [in_sub_path, append], 'eof': error, 'else': [in_single_quote, append] }; pathstatemachine[in_double_quote] = { '"': [in_sub_path, append], 'eof': error, 'else': [in_double_quote, append] }; /** * determine the type of a character in a keypath. * * @param {char} ch * @return {string} type */ function getpathchartype(ch) { if (ch === undefined) { return 'eof'; } var code = ch.charcodeat(0); switch (code) { case 0x5b: // [ case 0x5d: // ] case 0x2e: // . case 0x22: // " case 0x27: // ' case 0x30: // 0 return ch; case 0x5f: // _ case 0x24: // $ return 'ident'; case 0x20: // space case 0x09: // tab case 0x0a: // newline case 0x0d: // return case 0xa0: // no-break space case 0xfeff: // byte order mark case 0x2028: // line separator case 0x2029: // paragraph separator return 'ws'; } // a-z, a-z if (code >= 0x61 && code <= 0x7a || code >= 0x41 && code <= 0x5a) { return 'ident'; } // 1-9 if (code >= 0x31 && code <= 0x39) { return 'number'; } return 'else'; } /** * format a subpath, return its plain form if it is * a literal string or number. otherwise prepend the * dynamic indicator (*). * * @param {string} path * @return {string} */ function formatsubpath(path) { var trimmed = path.trim(); // invalid leading 0 if (path.charat(0) === '0' && isnan(path)) { return false; } return isliteral(trimmed) ? stripquotes(trimmed) : '*' + trimmed; } /** * parse a string path into an array of segments * * @param {string} path * @return {array|undefined} */ function parse(path) { var keys = []; var index = -1; var mode = before_path; var subpathdepth = 0; var c, newchar, key, type, transition, action, typemap; var actions = []; actions[push] = function () { if (key !== undefined) { keys.push(key); key = undefined; } }; actions[append] = function () { if (key === undefined) { key = newchar; } else { key += newchar; } }; actions[inc_sub_path_depth] = function () { actions[append](); subpathdepth++; }; actions[push_sub_path] = function () { if (subpathdepth > 0) { subpathdepth--; mode = in_sub_path; actions[append](); } else { subpathdepth = 0; key = formatsubpath(key); if (key === false) { return false; } else { actions[push](); } } }; function maybeunescapequote() { var nextchar = path[index + 1]; if (mode === in_single_quote && nextchar === "'" || mode === in_double_quote && nextchar === '"') { index++; newchar = '\\' + nextchar; actions[append](); return true; } } while (mode != null) { index++; c = path[index]; if (c === '\\' && maybeunescapequote()) { continue; } type = getpathchartype(c); typemap = pathstatemachine[mode]; transition = typemap[type] || typemap['else'] || error; if (transition === error) { return; // parse error } mode = transition[0]; action = actions[transition[1]]; if (action) { newchar = transition[2]; newchar = newchar === undefined ? c : newchar; if (action() === false) { return; } } if (mode === after_path) { keys.raw = path; return keys; } } } /** * external parse that check for a cache hit first * * @param {string} path * @return {array|undefined} */ function parsepath(path) { var hit = pathcache.get(path); if (!hit) { hit = parse(path); if (hit) { pathcache.put(path, hit); } } return hit; } /** * get from an object from a path string * * @param {object} obj * @param {string} path */ function getpath(obj, path) { return parseexpression(path).get(obj); } /** * warn against setting non-existent root path on a vm. */ var warnnonexistent; if ('development' !== 'production') { warnnonexistent = function (path, vm) { warn('you are setting a non-existent path "' + path.raw + '" ' + 'on a vm instance. consider pre-initializing the property ' + 'with the "data" option for more reliable reactivity ' + 'and better performance.', vm); }; } /** * set on an object from a path * * @param {object} obj * @param {string | array} path * @param {*} val */ function setpath(obj, path, val) { var original = obj; if (typeof path === 'string') { path = parse(path); } if (!path || !isobject(obj)) { return false; } var last, key; for (var i = 0, l = path.length; i < l; i++) { last = obj; key = path[i]; if (key.charat(0) === '*') { key = parseexpression(key.slice(1)).get.call(original, original); } if (i < l - 1) { obj = obj[key]; if (!isobject(obj)) { obj = {}; if ('development' !== 'production' && last._isvue) { warnnonexistent(path, last); } set(last, key, obj); } } else { if (isarray(obj)) { obj.$set(key, val); } else if (key in obj) { obj[key] = val; } else { if ('development' !== 'production' && obj._isvue) { warnnonexistent(path, obj); } set(obj, key, val); } } } return true; } var path = object.freeze({ parsepath: parsepath, getpath: getpath, setpath: setpath }); var expressioncache = new cache(1000); var allowedkeywords = 'math,date,this,true,false,null,undefined,infinity,nan,' + 'isnan,isfinite,decodeuri,decodeuricomponent,encodeuri,' + 'encodeuricomponent,parseint,parsefloat'; var allowedkeywordsre = new regexp('^(' + allowedkeywords.replace(/,/g, '\\b|') + '\\b)'); // keywords that don't make sense inside expressions var improperkeywords = 'break,case,class,catch,const,continue,debugger,default,' + 'delete,do,else,export,extends,finally,for,function,if,' + 'import,in,instanceof,let,return,super,switch,throw,try,' + 'var,while,with,yield,enum,await,implements,package,' + 'protected,static,interface,private,public'; var improperkeywordsre = new regexp('^(' + improperkeywords.replace(/,/g, '\\b|') + '\\b)'); var wsre = /\s/g; var newlinere = /\n/g; var savere = /[\{,]\s*[\w\$_]+\s*:|('(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`)|new |typeof |void /g; var restorere = /"(\d+)"/g; var pathtestre = /^[a-za-z_$][\w$]*(?:\.[a-za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[a-za-z_$][\w$]*\])*$/; var identre = /[^\w$\.](?:[a-za-z_$][\w$]*)/g; var literalvaluere$1 = /^(?:true|false|null|undefined|infinity|nan)$/; function noop() {} /** * save / rewrite / restore * * when rewriting paths found in an expression, it is * possible for the same letter sequences to be found in * strings and object literal property keys. therefore we * remove and store these parts in a temporary array, and * restore them after the path rewrite. */ var saved = []; /** * save replacer * * the save regex can match two possible cases: * 1. an opening object literal * 2. a string * if matched as a plain string, we need to escape its * newlines, since the string needs to be preserved when * generating the function body. * * @param {string} str * @param {string} isstring - str if matched as a string * @return {string} - placeholder with index */ function save(str, isstring) { var i = saved.length; saved[i] = isstring ? str.replace(newlinere, '\\n') : str; return '"' + i + '"'; } /** * path rewrite replacer * * @param {string} raw * @return {string} */ function rewrite(raw) { var c = raw.charat(0); var path = raw.slice(1); if (allowedkeywordsre.test(path)) { return raw; } else { path = path.indexof('"') > -1 ? path.replace(restorere, restore) : path; return c + 'scope.' + path; } } /** * restore replacer * * @param {string} str * @param {string} i - matched save index * @return {string} */ function restore(str, i) { return saved[i]; } /** * rewrite an expression, prefixing all path accessors with * `scope.` and generate getter/setter functions. * * @param {string} exp * @return {function} */ function compilegetter(exp) { if (improperkeywordsre.test(exp)) { 'development' !== 'production' && warn('avoid using reserved keywords in expression: ' + exp); } // reset state saved.length = 0; // save strings and object literal keys var body = exp.replace(savere, save).replace(wsre, ''); // rewrite all paths // pad 1 space here because the regex matches 1 extra char body = (' ' + body).replace(identre, rewrite).replace(restorere, restore); return makegetterfn(body); } /** * build a getter function. requires eval. * * we isolate the try/catch so it doesn't affect the * optimization of the parse function when it is not called. * * @param {string} body * @return {function|undefined} */ function makegetterfn(body) { try { /* eslint-disable no-new-func */ return new function('scope', 'return ' + body + ';'); /* eslint-enable no-new-func */ } catch (e) { if ('development' !== 'production') { /* istanbul ignore if */ if (e.tostring().match(/unsafe-eval|csp/)) { warn('it seems you are using the default build of vue.js in an environment ' + 'with content security policy that prohibits unsafe-eval. ' + 'use the csp-compliant build instead: ' + 'http://vuejs.org/guide/installation.html#csp-compliant-build'); } else { warn('invalid expression. ' + 'generated function body: ' + body); } } return noop; } } /** * compile a setter function for the expression. * * @param {string} exp * @return {function|undefined} */ function compilesetter(exp) { var path = parsepath(exp); if (path) { return function (scope, val) { setpath(scope, path, val); }; } else { 'development' !== 'production' && warn('invalid setter expression: ' + exp); } } /** * parse an expression into re-written getter/setters. * * @param {string} exp * @param {boolean} needset * @return {function} */ function parseexpression(exp, needset) { exp = exp.trim(); // try cache var hit = expressioncache.get(exp); if (hit) { if (needset && !hit.set) { hit.set = compilesetter(hit.exp); } return hit; } var res = { exp: exp }; res.get = issimplepath(exp) && exp.indexof('[') < 0 // optimized super simple getter ? makegetterfn('scope.' + exp) // dynamic getter : compilegetter(exp); if (needset) { res.set = compilesetter(exp); } expressioncache.put(exp, res); return res; } /** * check if an expression is a simple path. * * @param {string} exp * @return {boolean} */ function issimplepath(exp) { return pathtestre.test(exp) && // don't treat literal values as paths !literalvaluere$1.test(exp) && // math constants e.g. math.pi, math.e etc. exp.slice(0, 5) !== 'math.'; } var expression = object.freeze({ parseexpression: parseexpression, issimplepath: issimplepath }); // we have two separate queues: one for directive updates // and one for user watcher registered via $watch(). // we want to guarantee directive updates to be called // before user watchers so that when user watchers are // triggered, the dom would have already been in updated // state. var queue = []; var userqueue = []; var has = {}; var circular = {}; var waiting = false; /** * reset the batcher's state. */ function resetbatcherstate() { queue.length = 0; userqueue.length = 0; has = {}; circular = {}; waiting = false; } /** * flush both queues and run the watchers. */ function flushbatcherqueue() { var _again = true; _function: while (_again) { _again = false; runbatcherqueue(queue); runbatcherqueue(userqueue); // user watchers triggered more watchers, // keep flushing until it depletes if (queue.length) { _again = true; continue _function; } // dev tool hook /* istanbul ignore if */ if (devtools && config.devtools) { devtools.emit('flush'); } resetbatcherstate(); } } /** * run the watchers in a single queue. * * @param {array} queue */ function runbatcherqueue(queue) { // do not cache length because more watchers might be pushed // as we run existing watchers for (var i = 0; i < queue.length; i++) { var watcher = queue[i]; var id = watcher.id; has[id] = null; watcher.run(); // in dev build, check and stop circular updates. if ('development' !== 'production' && has[id] != null) { circular[id] = (circular[id] || 0) + 1; if (circular[id] > config._maxupdatecount) { warn('you may have an infinite update loop for watcher ' + 'with expression "' + watcher.expression + '"', watcher.vm); break; } } } queue.length = 0; } /** * push a watcher into the watcher queue. * jobs with duplicate ids will be skipped unless it's * pushed when the queue is being flushed. * * @param {watcher} watcher * properties: * - {number} id * - {function} run */ function pushwatcher(watcher) { var id = watcher.id; if (has[id] == null) { // push watcher into appropriate queue var q = watcher.user ? userqueue : queue; has[id] = q.length; q.push(watcher); // queue the flush if (!waiting) { waiting = true; nexttick(flushbatcherqueue); } } } var uid$2 = 0; /** * a watcher parses an expression, collects dependencies, * and fires callback when the expression value changes. * this is used for both the $watch() api and directives. * * @param {vue} vm * @param {string|function} exporfn * @param {function} cb * @param {object} options * - {array} filters * - {boolean} twoway * - {boolean} deep * - {boolean} user * - {boolean} sync * - {boolean} lazy * - {function} [preprocess] * - {function} [postprocess] * @constructor */ function watcher(vm, exporfn, cb, options) { // mix in options if (options) { extend(this, options); } var isfn = typeof exporfn === 'function'; this.vm = vm; vm._watchers.push(this); this.expression = exporfn; this.cb = cb; this.id = ++uid$2; // uid for batching this.active = true; this.dirty = this.lazy; // for lazy watchers this.deps = []; this.newdeps = []; this.depids = new _set(); this.newdepids = new _set(); this.preverror = null; // for async error stacks // parse expression for getter/setter if (isfn) { this.getter = exporfn; this.setter = undefined; } else { var res = parseexpression(exporfn, this.twoway); this.getter = res.get; this.setter = res.set; } this.value = this.lazy ? undefined : this.get(); // state for avoiding false triggers for deep and array // watchers during vm._digest() this.queued = this.shallow = false; } /** * evaluate the getter, and re-collect dependencies. */ watcher.prototype.get = function () { this.beforeget(); var scope = this.scope || this.vm; var value; try { value = this.getter.call(scope, scope); } catch (e) { if ('development' !== 'production' && config.warnexpressionerrors) { warn('error when evaluating expression ' + '"' + this.expression + '": ' + e.tostring(), this.vm); } } // "touch" every property so they are all tracked as // dependencies for deep watching if (this.deep) { traverse(value); } if (this.preprocess) { value = this.preprocess(value); } if (this.filters) { value = scope._applyfilters(value, null, this.filters, false); } if (this.postprocess) { value = this.postprocess(value); } this.afterget(); return value; }; /** * set the corresponding value with the setter. * * @param {*} value */ watcher.prototype.set = function (value) { var scope = this.scope || this.vm; if (this.filters) { value = scope._applyfilters(value, this.value, this.filters, true); } try { this.setter.call(scope, scope, value); } catch (e) { if ('development' !== 'production' && config.warnexpressionerrors) { warn('error when evaluating setter ' + '"' + this.expression + '": ' + e.tostring(), this.vm); } } // two-way sync for v-for alias var forcontext = scope.$forcontext; if (forcontext && forcontext.alias === this.expression) { if (forcontext.filters) { 'development' !== 'production' && warn('it seems you are using two-way binding on ' + 'a v-for alias (' + this.expression + '), and the ' + 'v-for has filters. this will not work properly. ' + 'either remove the filters or use an array of ' + 'objects and bind to object properties instead.', this.vm); return; } forcontext._withlock(function () { if (scope.$key) { // original is an object forcontext.rawvalue[scope.$key] = value; } else { forcontext.rawvalue.$set(scope.$index, value); } }); } }; /** * prepare for dependency collection. */ watcher.prototype.beforeget = function () { dep.target = this; }; /** * add a dependency to this directive. * * @param {dep} dep */ watcher.prototype.adddep = function (dep) { var id = dep.id; if (!this.newdepids.has(id)) { this.newdepids.add(id); this.newdeps.push(dep); if (!this.depids.has(id)) { dep.addsub(this); } } }; /** * clean up for dependency collection. */ watcher.prototype.afterget = function () { dep.target = null; var i = this.deps.length; while (i--) { var dep = this.deps[i]; if (!this.newdepids.has(dep.id)) { dep.removesub(this); } } var tmp = this.depids; this.depids = this.newdepids; this.newdepids = tmp; this.newdepids.clear(); tmp = this.deps; this.deps = this.newdeps; this.newdeps = tmp; this.newdeps.length = 0; }; /** * subscriber interface. * will be called when a dependency changes. * * @param {boolean} shallow */ watcher.prototype.update = function (shallow) { if (this.lazy) { this.dirty = true; } else if (this.sync || !config.async) { this.run(); } else { // if queued, only overwrite shallow with non-shallow, // but not the other way around. this.shallow = this.queued ? shallow ? this.shallow : false : !!shallow; this.queued = true; // record before-push error stack in debug mode /* istanbul ignore if */ if ('development' !== 'production' && config.debug) { this.preverror = new error('[vue] async stack trace'); } pushwatcher(this); } }; /** * batcher job interface. * will be called by the batcher. */ watcher.prototype.run = function () { if (this.active) { var value = this.get(); if (value !== this.value || // deep watchers and watchers on object/arrays should fire even // when the value is the same, because the value may // have mutated; but only do so if this is a // non-shallow update (caused by a vm digest). (isobject(value) || this.deep) && !this.shallow) { // set new value var oldvalue = this.value; this.value = value; // in debug + async mode, when a watcher callbacks // throws, we also throw the saved before-push error // so the full cross-tick stack trace is available. var preverror = this.preverror; /* istanbul ignore if */ if ('development' !== 'production' && config.debug && preverror) { this.preverror = null; try { this.cb.call(this.vm, value, oldvalue); } catch (e) { nexttick(function () { throw preverror; }, 0); throw e; } } else { this.cb.call(this.vm, value, oldvalue); } } this.queued = this.shallow = false; } }; /** * evaluate the value of the watcher. * this only gets called for lazy watchers. */ watcher.prototype.evaluate = function () { // avoid overwriting another watcher that is being // collected. var current = dep.target; this.value = this.get(); this.dirty = false; dep.target = current; }; /** * depend on all deps collected by this watcher. */ watcher.prototype.depend = function () { var i = this.deps.length; while (i--) { this.deps[i].depend(); } }; /** * remove self from all dependencies' subcriber list. */ watcher.prototype.teardown = function () { if (this.active) { // remove self from vm's watcher list // this is a somewhat expensive operation so we skip it // if the vm is being destroyed or is performing a v-for // re-render (the watcher list is then filtered by v-for). if (!this.vm._isbeingdestroyed && !this.vm._vforremoving) { this.vm._watchers.$remove(this); } var i = this.deps.length; while (i--) { this.deps[i].removesub(this); } this.active = false; this.vm = this.cb = this.value = null; } }; /** * recrusively traverse an object to evoke all converted * getters, so that every nested property inside the object * is collected as a "deep" dependency. * * @param {*} val */ var seenobjects = new _set(); function traverse(val, seen) { var i = undefined, keys = undefined; if (!seen) { seen = seenobjects; seen.clear(); } var isa = isarray(val); var iso = isobject(val); if ((isa || iso) && object.isextensible(val)) { if (val.__ob__) { var depid = val.__ob__.dep.id; if (seen.has(depid)) { return; } else { seen.add(depid); } } if (isa) { i = val.length; while (i--) traverse(val[i], seen); } else if (iso) { keys = object.keys(val); i = keys.length; while (i--) traverse(val[keys[i]], seen); } } } var text$1 = { bind: function bind() { this.attr = this.el.nodetype === 3 ? 'data' : 'textcontent'; }, update: function update(value) { this.el[this.attr] = _tostring(value); } }; var templatecache = new cache(1000); var idselectorcache = new cache(1000); var map = { efault: [0, '', ''], legend: [1, '
', '
'], tr: [2, '', '
'], col: [2, '', '
'] }; map.td = map.th = [3, '', '
']; map.option = map.optgroup = [1, '']; map.thead = map.tbody = map.colgroup = map.caption = map.tfoot = [1, '', '
']; map.g = map.defs = map.symbol = map.use = map.image = map.text = map.circle = map.ellipse = map.line = map.path = map.polygon = map.polyline = map.rect = [1, '', '']; /** * check if a node is a supported template node with a * documentfragment content. * * @param {node} node * @return {boolean} */ function isrealtemplate(node) { return istemplate(node) && isfragment(node.content); } var tagre$1 = /<([\w:-]+)/; var entityre = /&#?\w+?;/; var commentre = /