PageRenderTime 58ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/files/vue/1.0.18/vue.common.js

https://gitlab.com/Mirros/jsdelivr
JavaScript | 2220 lines | 1446 code | 189 blank | 585 comment | 217 complexity | d3ddff13d3486a8e1088043084fa637c MD5 | raw file
  1. /*!
  2. * Vue.js v1.0.18
  3. * (c) 2016 Evan You
  4. * Released under the MIT License.
  5. */
  6. 'use strict';
  7. function set(obj, key, val) {
  8. if (hasOwn(obj, key)) {
  9. obj[key] = val;
  10. return;
  11. }
  12. if (obj._isVue) {
  13. set(obj._data, key, val);
  14. return;
  15. }
  16. var ob = obj.__ob__;
  17. if (!ob) {
  18. obj[key] = val;
  19. return;
  20. }
  21. ob.convert(key, val);
  22. ob.dep.notify();
  23. if (ob.vms) {
  24. var i = ob.vms.length;
  25. while (i--) {
  26. var vm = ob.vms[i];
  27. vm._proxy(key);
  28. vm._digest();
  29. }
  30. }
  31. return val;
  32. }
  33. /**
  34. * Delete a property and trigger change if necessary.
  35. *
  36. * @param {Object} obj
  37. * @param {String} key
  38. */
  39. function del(obj, key) {
  40. if (!hasOwn(obj, key)) {
  41. return;
  42. }
  43. delete obj[key];
  44. var ob = obj.__ob__;
  45. if (!ob) {
  46. return;
  47. }
  48. ob.dep.notify();
  49. if (ob.vms) {
  50. var i = ob.vms.length;
  51. while (i--) {
  52. var vm = ob.vms[i];
  53. vm._unproxy(key);
  54. vm._digest();
  55. }
  56. }
  57. }
  58. var hasOwnProperty = Object.prototype.hasOwnProperty;
  59. /**
  60. * Check whether the object has the property.
  61. *
  62. * @param {Object} obj
  63. * @param {String} key
  64. * @return {Boolean}
  65. */
  66. function hasOwn(obj, key) {
  67. return hasOwnProperty.call(obj, key);
  68. }
  69. /**
  70. * Check if an expression is a literal value.
  71. *
  72. * @param {String} exp
  73. * @return {Boolean}
  74. */
  75. var literalValueRE = /^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/;
  76. function isLiteral(exp) {
  77. return literalValueRE.test(exp);
  78. }
  79. /**
  80. * Check if a string starts with $ or _
  81. *
  82. * @param {String} str
  83. * @return {Boolean}
  84. */
  85. function isReserved(str) {
  86. var c = (str + '').charCodeAt(0);
  87. return c === 0x24 || c === 0x5F;
  88. }
  89. /**
  90. * Guard text output, make sure undefined outputs
  91. * empty string
  92. *
  93. * @param {*} value
  94. * @return {String}
  95. */
  96. function _toString(value) {
  97. return value == null ? '' : value.toString();
  98. }
  99. /**
  100. * Check and convert possible numeric strings to numbers
  101. * before setting back to data
  102. *
  103. * @param {*} value
  104. * @return {*|Number}
  105. */
  106. function toNumber(value) {
  107. if (typeof value !== 'string') {
  108. return value;
  109. } else {
  110. var parsed = Number(value);
  111. return isNaN(parsed) ? value : parsed;
  112. }
  113. }
  114. /**
  115. * Convert string boolean literals into real booleans.
  116. *
  117. * @param {*} value
  118. * @return {*|Boolean}
  119. */
  120. function toBoolean(value) {
  121. return value === 'true' ? true : value === 'false' ? false : value;
  122. }
  123. /**
  124. * Strip quotes from a string
  125. *
  126. * @param {String} str
  127. * @return {String | false}
  128. */
  129. function stripQuotes(str) {
  130. var a = str.charCodeAt(0);
  131. var b = str.charCodeAt(str.length - 1);
  132. return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str;
  133. }
  134. /**
  135. * Camelize a hyphen-delmited string.
  136. *
  137. * @param {String} str
  138. * @return {String}
  139. */
  140. var camelizeRE = /-(\w)/g;
  141. function camelize(str) {
  142. return str.replace(camelizeRE, toUpper);
  143. }
  144. function toUpper(_, c) {
  145. return c ? c.toUpperCase() : '';
  146. }
  147. /**
  148. * Hyphenate a camelCase string.
  149. *
  150. * @param {String} str
  151. * @return {String}
  152. */
  153. var hyphenateRE = /([a-z\d])([A-Z])/g;
  154. function hyphenate(str) {
  155. return str.replace(hyphenateRE, '$1-$2').toLowerCase();
  156. }
  157. /**
  158. * Converts hyphen/underscore/slash delimitered names into
  159. * camelized classNames.
  160. *
  161. * e.g. my-component => MyComponent
  162. * some_else => SomeElse
  163. * some/comp => SomeComp
  164. *
  165. * @param {String} str
  166. * @return {String}
  167. */
  168. var classifyRE = /(?:^|[-_\/])(\w)/g;
  169. function classify(str) {
  170. return str.replace(classifyRE, toUpper);
  171. }
  172. /**
  173. * Simple bind, faster than native
  174. *
  175. * @param {Function} fn
  176. * @param {Object} ctx
  177. * @return {Function}
  178. */
  179. function bind(fn, ctx) {
  180. return function (a) {
  181. var l = arguments.length;
  182. return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx);
  183. };
  184. }
  185. /**
  186. * Convert an Array-like object to a real Array.
  187. *
  188. * @param {Array-like} list
  189. * @param {Number} [start] - start index
  190. * @return {Array}
  191. */
  192. function toArray(list, start) {
  193. start = start || 0;
  194. var i = list.length - start;
  195. var ret = new Array(i);
  196. while (i--) {
  197. ret[i] = list[i + start];
  198. }
  199. return ret;
  200. }
  201. /**
  202. * Mix properties into target object.
  203. *
  204. * @param {Object} to
  205. * @param {Object} from
  206. */
  207. function extend(to, from) {
  208. var keys = Object.keys(from);
  209. var i = keys.length;
  210. while (i--) {
  211. to[keys[i]] = from[keys[i]];
  212. }
  213. return to;
  214. }
  215. /**
  216. * Quick object check - this is primarily used to tell
  217. * Objects from primitive values when we know the value
  218. * is a JSON-compliant type.
  219. *
  220. * @param {*} obj
  221. * @return {Boolean}
  222. */
  223. function isObject(obj) {
  224. return obj !== null && typeof obj === 'object';
  225. }
  226. /**
  227. * Strict object type check. Only returns true
  228. * for plain JavaScript objects.
  229. *
  230. * @param {*} obj
  231. * @return {Boolean}
  232. */
  233. var toString = Object.prototype.toString;
  234. var OBJECT_STRING = '[object Object]';
  235. function isPlainObject(obj) {
  236. return toString.call(obj) === OBJECT_STRING;
  237. }
  238. /**
  239. * Array type check.
  240. *
  241. * @param {*} obj
  242. * @return {Boolean}
  243. */
  244. var isArray = Array.isArray;
  245. /**
  246. * Define a property.
  247. *
  248. * @param {Object} obj
  249. * @param {String} key
  250. * @param {*} val
  251. * @param {Boolean} [enumerable]
  252. */
  253. function def(obj, key, val, enumerable) {
  254. Object.defineProperty(obj, key, {
  255. value: val,
  256. enumerable: !!enumerable,
  257. writable: true,
  258. configurable: true
  259. });
  260. }
  261. /**
  262. * Debounce a function so it only gets called after the
  263. * input stops arriving after the given wait period.
  264. *
  265. * @param {Function} func
  266. * @param {Number} wait
  267. * @return {Function} - the debounced function
  268. */
  269. function _debounce(func, wait) {
  270. var timeout, args, context, timestamp, result;
  271. var later = function later() {
  272. var last = Date.now() - timestamp;
  273. if (last < wait && last >= 0) {
  274. timeout = setTimeout(later, wait - last);
  275. } else {
  276. timeout = null;
  277. result = func.apply(context, args);
  278. if (!timeout) context = args = null;
  279. }
  280. };
  281. return function () {
  282. context = this;
  283. args = arguments;
  284. timestamp = Date.now();
  285. if (!timeout) {
  286. timeout = setTimeout(later, wait);
  287. }
  288. return result;
  289. };
  290. }
  291. /**
  292. * Manual indexOf because it's slightly faster than
  293. * native.
  294. *
  295. * @param {Array} arr
  296. * @param {*} obj
  297. */
  298. function indexOf(arr, obj) {
  299. var i = arr.length;
  300. while (i--) {
  301. if (arr[i] === obj) return i;
  302. }
  303. return -1;
  304. }
  305. /**
  306. * Make a cancellable version of an async callback.
  307. *
  308. * @param {Function} fn
  309. * @return {Function}
  310. */
  311. function cancellable(fn) {
  312. var cb = function cb() {
  313. if (!cb.cancelled) {
  314. return fn.apply(this, arguments);
  315. }
  316. };
  317. cb.cancel = function () {
  318. cb.cancelled = true;
  319. };
  320. return cb;
  321. }
  322. /**
  323. * Check if two values are loosely equal - that is,
  324. * if they are plain objects, do they have the same shape?
  325. *
  326. * @param {*} a
  327. * @param {*} b
  328. * @return {Boolean}
  329. */
  330. function looseEqual(a, b) {
  331. /* eslint-disable eqeqeq */
  332. return a == b || (isObject(a) && isObject(b) ? JSON.stringify(a) === JSON.stringify(b) : false);
  333. /* eslint-enable eqeqeq */
  334. }
  335. var hasProto = ('__proto__' in {});
  336. // Browser environment sniffing
  337. var inBrowser = typeof window !== 'undefined' && Object.prototype.toString.call(window) !== '[object Object]';
  338. // detect devtools
  339. var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
  340. // UA sniffing for working around browser-specific quirks
  341. var UA = inBrowser && window.navigator.userAgent.toLowerCase();
  342. var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
  343. var isAndroid = UA && UA.indexOf('android') > 0;
  344. var transitionProp = undefined;
  345. var transitionEndEvent = undefined;
  346. var animationProp = undefined;
  347. var animationEndEvent = undefined;
  348. // Transition property/event sniffing
  349. if (inBrowser && !isIE9) {
  350. var isWebkitTrans = window.ontransitionend === undefined && window.onwebkittransitionend !== undefined;
  351. var isWebkitAnim = window.onanimationend === undefined && window.onwebkitanimationend !== undefined;
  352. transitionProp = isWebkitTrans ? 'WebkitTransition' : 'transition';
  353. transitionEndEvent = isWebkitTrans ? 'webkitTransitionEnd' : 'transitionend';
  354. animationProp = isWebkitAnim ? 'WebkitAnimation' : 'animation';
  355. animationEndEvent = isWebkitAnim ? 'webkitAnimationEnd' : 'animationend';
  356. }
  357. /**
  358. * Defer a task to execute it asynchronously. Ideally this
  359. * should be executed as a microtask, so we leverage
  360. * MutationObserver if it's available, and fallback to
  361. * setTimeout(0).
  362. *
  363. * @param {Function} cb
  364. * @param {Object} ctx
  365. */
  366. var nextTick = (function () {
  367. var callbacks = [];
  368. var pending = false;
  369. var timerFunc;
  370. function nextTickHandler() {
  371. pending = false;
  372. var copies = callbacks.slice(0);
  373. callbacks = [];
  374. for (var i = 0; i < copies.length; i++) {
  375. copies[i]();
  376. }
  377. }
  378. /* istanbul ignore if */
  379. if (typeof MutationObserver !== 'undefined') {
  380. var counter = 1;
  381. var observer = new MutationObserver(nextTickHandler);
  382. var textNode = document.createTextNode(counter);
  383. observer.observe(textNode, {
  384. characterData: true
  385. });
  386. timerFunc = function () {
  387. counter = (counter + 1) % 2;
  388. textNode.data = counter;
  389. };
  390. } else {
  391. // webpack attempts to inject a shim for setImmediate
  392. // if it is used as a global, so we have to work around that to
  393. // avoid bundling unnecessary code.
  394. var context = inBrowser ? window : typeof global !== 'undefined' ? global : {};
  395. timerFunc = context.setImmediate || setTimeout;
  396. }
  397. return function (cb, ctx) {
  398. var func = ctx ? function () {
  399. cb.call(ctx);
  400. } : cb;
  401. callbacks.push(func);
  402. if (pending) return;
  403. pending = true;
  404. timerFunc(nextTickHandler, 0);
  405. };
  406. })();
  407. function Cache(limit) {
  408. this.size = 0;
  409. this.limit = limit;
  410. this.head = this.tail = undefined;
  411. this._keymap = Object.create(null);
  412. }
  413. var p = Cache.prototype;
  414. /**
  415. * Put <value> into the cache associated with <key>.
  416. * Returns the entry which was removed to make room for
  417. * the new entry. Otherwise undefined is returned.
  418. * (i.e. if there was enough room already).
  419. *
  420. * @param {String} key
  421. * @param {*} value
  422. * @return {Entry|undefined}
  423. */
  424. p.put = function (key, value) {
  425. var removed;
  426. if (this.size === this.limit) {
  427. removed = this.shift();
  428. }
  429. var entry = this.get(key, true);
  430. if (!entry) {
  431. entry = {
  432. key: key
  433. };
  434. this._keymap[key] = entry;
  435. if (this.tail) {
  436. this.tail.newer = entry;
  437. entry.older = this.tail;
  438. } else {
  439. this.head = entry;
  440. }
  441. this.tail = entry;
  442. this.size++;
  443. }
  444. entry.value = value;
  445. return removed;
  446. };
  447. /**
  448. * Purge the least recently used (oldest) entry from the
  449. * cache. Returns the removed entry or undefined if the
  450. * cache was empty.
  451. */
  452. p.shift = function () {
  453. var entry = this.head;
  454. if (entry) {
  455. this.head = this.head.newer;
  456. this.head.older = undefined;
  457. entry.newer = entry.older = undefined;
  458. this._keymap[entry.key] = undefined;
  459. this.size--;
  460. }
  461. return entry;
  462. };
  463. /**
  464. * Get and register recent use of <key>. Returns the value
  465. * associated with <key> or undefined if not in cache.
  466. *
  467. * @param {String} key
  468. * @param {Boolean} returnEntry
  469. * @return {Entry|*}
  470. */
  471. p.get = function (key, returnEntry) {
  472. var entry = this._keymap[key];
  473. if (entry === undefined) return;
  474. if (entry === this.tail) {
  475. return returnEntry ? entry : entry.value;
  476. }
  477. // HEAD--------------TAIL
  478. // <.older .newer>
  479. // <--- add direction --
  480. // A B C <D> E
  481. if (entry.newer) {
  482. if (entry === this.head) {
  483. this.head = entry.newer;
  484. }
  485. entry.newer.older = entry.older; // C <-- E.
  486. }
  487. if (entry.older) {
  488. entry.older.newer = entry.newer; // C. --> E
  489. }
  490. entry.newer = undefined; // D --x
  491. entry.older = this.tail; // D. --> E
  492. if (this.tail) {
  493. this.tail.newer = entry; // E. <-- D
  494. }
  495. this.tail = entry;
  496. return returnEntry ? entry : entry.value;
  497. };
  498. var cache$1 = new Cache(1000);
  499. var filterTokenRE = /[^\s'"]+|'[^']*'|"[^"]*"/g;
  500. var reservedArgRE = /^in$|^-?\d+/;
  501. /**
  502. * Parser state
  503. */
  504. var str;
  505. var dir;
  506. var c;
  507. var prev;
  508. var i;
  509. var l;
  510. var lastFilterIndex;
  511. var inSingle;
  512. var inDouble;
  513. var curly;
  514. var square;
  515. var paren;
  516. /**
  517. * Push a filter to the current directive object
  518. */
  519. function pushFilter() {
  520. var exp = str.slice(lastFilterIndex, i).trim();
  521. var filter;
  522. if (exp) {
  523. filter = {};
  524. var tokens = exp.match(filterTokenRE);
  525. filter.name = tokens[0];
  526. if (tokens.length > 1) {
  527. filter.args = tokens.slice(1).map(processFilterArg);
  528. }
  529. }
  530. if (filter) {
  531. (dir.filters = dir.filters || []).push(filter);
  532. }
  533. lastFilterIndex = i + 1;
  534. }
  535. /**
  536. * Check if an argument is dynamic and strip quotes.
  537. *
  538. * @param {String} arg
  539. * @return {Object}
  540. */
  541. function processFilterArg(arg) {
  542. if (reservedArgRE.test(arg)) {
  543. return {
  544. value: toNumber(arg),
  545. dynamic: false
  546. };
  547. } else {
  548. var stripped = stripQuotes(arg);
  549. var dynamic = stripped === arg;
  550. return {
  551. value: dynamic ? arg : stripped,
  552. dynamic: dynamic
  553. };
  554. }
  555. }
  556. /**
  557. * Parse a directive value and extract the expression
  558. * and its filters into a descriptor.
  559. *
  560. * Example:
  561. *
  562. * "a + 1 | uppercase" will yield:
  563. * {
  564. * expression: 'a + 1',
  565. * filters: [
  566. * { name: 'uppercase', args: null }
  567. * ]
  568. * }
  569. *
  570. * @param {String} str
  571. * @return {Object}
  572. */
  573. function parseDirective(s) {
  574. var hit = cache$1.get(s);
  575. if (hit) {
  576. return hit;
  577. }
  578. // reset parser state
  579. str = s;
  580. inSingle = inDouble = false;
  581. curly = square = paren = 0;
  582. lastFilterIndex = 0;
  583. dir = {};
  584. for (i = 0, l = str.length; i < l; i++) {
  585. prev = c;
  586. c = str.charCodeAt(i);
  587. if (inSingle) {
  588. // check single quote
  589. if (c === 0x27 && prev !== 0x5C) inSingle = !inSingle;
  590. } else if (inDouble) {
  591. // check double quote
  592. if (c === 0x22 && prev !== 0x5C) inDouble = !inDouble;
  593. } else if (c === 0x7C && // pipe
  594. str.charCodeAt(i + 1) !== 0x7C && str.charCodeAt(i - 1) !== 0x7C) {
  595. if (dir.expression == null) {
  596. // first filter, end of expression
  597. lastFilterIndex = i + 1;
  598. dir.expression = str.slice(0, i).trim();
  599. } else {
  600. // already has filter
  601. pushFilter();
  602. }
  603. } else {
  604. switch (c) {
  605. case 0x22:
  606. inDouble = true;break; // "
  607. case 0x27:
  608. inSingle = true;break; // '
  609. case 0x28:
  610. paren++;break; // (
  611. case 0x29:
  612. paren--;break; // )
  613. case 0x5B:
  614. square++;break; // [
  615. case 0x5D:
  616. square--;break; // ]
  617. case 0x7B:
  618. curly++;break; // {
  619. case 0x7D:
  620. curly--;break; // }
  621. }
  622. }
  623. }
  624. if (dir.expression == null) {
  625. dir.expression = str.slice(0, i).trim();
  626. } else if (lastFilterIndex !== 0) {
  627. pushFilter();
  628. }
  629. cache$1.put(s, dir);
  630. return dir;
  631. }
  632. var directive = Object.freeze({
  633. parseDirective: parseDirective
  634. });
  635. var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g;
  636. var cache = undefined;
  637. var tagRE = undefined;
  638. var htmlRE = undefined;
  639. /**
  640. * Escape a string so it can be used in a RegExp
  641. * constructor.
  642. *
  643. * @param {String} str
  644. */
  645. function escapeRegex(str) {
  646. return str.replace(regexEscapeRE, '\\$&');
  647. }
  648. function compileRegex() {
  649. var open = escapeRegex(config.delimiters[0]);
  650. var close = escapeRegex(config.delimiters[1]);
  651. var unsafeOpen = escapeRegex(config.unsafeDelimiters[0]);
  652. var unsafeClose = escapeRegex(config.unsafeDelimiters[1]);
  653. tagRE = new RegExp(unsafeOpen + '(.+?)' + unsafeClose + '|' + open + '(.+?)' + close, 'g');
  654. htmlRE = new RegExp('^' + unsafeOpen + '.*' + unsafeClose + '$');
  655. // reset cache
  656. cache = new Cache(1000);
  657. }
  658. /**
  659. * Parse a template text string into an array of tokens.
  660. *
  661. * @param {String} text
  662. * @return {Array<Object> | null}
  663. * - {String} type
  664. * - {String} value
  665. * - {Boolean} [html]
  666. * - {Boolean} [oneTime]
  667. */
  668. function parseText(text) {
  669. if (!cache) {
  670. compileRegex();
  671. }
  672. var hit = cache.get(text);
  673. if (hit) {
  674. return hit;
  675. }
  676. text = text.replace(/\n/g, '');
  677. if (!tagRE.test(text)) {
  678. return null;
  679. }
  680. var tokens = [];
  681. var lastIndex = tagRE.lastIndex = 0;
  682. var match, index, html, value, first, oneTime;
  683. /* eslint-disable no-cond-assign */
  684. while (match = tagRE.exec(text)) {
  685. /* eslint-enable no-cond-assign */
  686. index = match.index;
  687. // push text token
  688. if (index > lastIndex) {
  689. tokens.push({
  690. value: text.slice(lastIndex, index)
  691. });
  692. }
  693. // tag token
  694. html = htmlRE.test(match[0]);
  695. value = html ? match[1] : match[2];
  696. first = value.charCodeAt(0);
  697. oneTime = first === 42; // *
  698. value = oneTime ? value.slice(1) : value;
  699. tokens.push({
  700. tag: true,
  701. value: value.trim(),
  702. html: html,
  703. oneTime: oneTime
  704. });
  705. lastIndex = index + match[0].length;
  706. }
  707. if (lastIndex < text.length) {
  708. tokens.push({
  709. value: text.slice(lastIndex)
  710. });
  711. }
  712. cache.put(text, tokens);
  713. return tokens;
  714. }
  715. /**
  716. * Format a list of tokens into an expression.
  717. * e.g. tokens parsed from 'a {{b}} c' can be serialized
  718. * into one single expression as '"a " + b + " c"'.
  719. *
  720. * @param {Array} tokens
  721. * @param {Vue} [vm]
  722. * @return {String}
  723. */
  724. function tokensToExp(tokens, vm) {
  725. if (tokens.length > 1) {
  726. return tokens.map(function (token) {
  727. return formatToken(token, vm);
  728. }).join('+');
  729. } else {
  730. return formatToken(tokens[0], vm, true);
  731. }
  732. }
  733. /**
  734. * Format a single token.
  735. *
  736. * @param {Object} token
  737. * @param {Vue} [vm]
  738. * @param {Boolean} [single]
  739. * @return {String}
  740. */
  741. function formatToken(token, vm, single) {
  742. return token.tag ? token.oneTime && vm ? '"' + vm.$eval(token.value) + '"' : inlineFilters(token.value, single) : '"' + token.value + '"';
  743. }
  744. /**
  745. * For an attribute with multiple interpolation tags,
  746. * e.g. attr="some-{{thing | filter}}", in order to combine
  747. * the whole thing into a single watchable expression, we
  748. * have to inline those filters. This function does exactly
  749. * that. This is a bit hacky but it avoids heavy changes
  750. * to directive parser and watcher mechanism.
  751. *
  752. * @param {String} exp
  753. * @param {Boolean} single
  754. * @return {String}
  755. */
  756. var filterRE = /[^|]\|[^|]/;
  757. function inlineFilters(exp, single) {
  758. if (!filterRE.test(exp)) {
  759. return single ? exp : '(' + exp + ')';
  760. } else {
  761. var dir = parseDirective(exp);
  762. if (!dir.filters) {
  763. return '(' + exp + ')';
  764. } else {
  765. return 'this._applyFilters(' + dir.expression + // value
  766. ',null,' + // oldValue (null for read)
  767. JSON.stringify(dir.filters) + // filter descriptors
  768. ',false)'; // write?
  769. }
  770. }
  771. }
  772. var text = Object.freeze({
  773. compileRegex: compileRegex,
  774. parseText: parseText,
  775. tokensToExp: tokensToExp
  776. });
  777. var delimiters = ['{{', '}}'];
  778. var unsafeDelimiters = ['{{{', '}}}'];
  779. var config = Object.defineProperties({
  780. /**
  781. * Whether to print debug messages.
  782. * Also enables stack trace for warnings.
  783. *
  784. * @type {Boolean}
  785. */
  786. debug: false,
  787. /**
  788. * Whether to suppress warnings.
  789. *
  790. * @type {Boolean}
  791. */
  792. silent: false,
  793. /**
  794. * Whether to use async rendering.
  795. */
  796. async: true,
  797. /**
  798. * Whether to warn against errors caught when evaluating
  799. * expressions.
  800. */
  801. warnExpressionErrors: true,
  802. /**
  803. * Whether to allow devtools inspection.
  804. * Disabled by default in production builds.
  805. */
  806. devtools: process.env.NODE_ENV !== 'production',
  807. /**
  808. * Internal flag to indicate the delimiters have been
  809. * changed.
  810. *
  811. * @type {Boolean}
  812. */
  813. _delimitersChanged: true,
  814. /**
  815. * List of asset types that a component can own.
  816. *
  817. * @type {Array}
  818. */
  819. _assetTypes: ['component', 'directive', 'elementDirective', 'filter', 'transition', 'partial'],
  820. /**
  821. * prop binding modes
  822. */
  823. _propBindingModes: {
  824. ONE_WAY: 0,
  825. TWO_WAY: 1,
  826. ONE_TIME: 2
  827. },
  828. /**
  829. * Max circular updates allowed in a batcher flush cycle.
  830. */
  831. _maxUpdateCount: 100
  832. }, {
  833. delimiters: { /**
  834. * Interpolation delimiters. Changing these would trigger
  835. * the text parser to re-compile the regular expressions.
  836. *
  837. * @type {Array<String>}
  838. */
  839. get: function get() {
  840. return delimiters;
  841. },
  842. set: function set(val) {
  843. delimiters = val;
  844. compileRegex();
  845. },
  846. configurable: true,
  847. enumerable: true
  848. },
  849. unsafeDelimiters: {
  850. get: function get() {
  851. return unsafeDelimiters;
  852. },
  853. set: function set(val) {
  854. unsafeDelimiters = val;
  855. compileRegex();
  856. },
  857. configurable: true,
  858. enumerable: true
  859. }
  860. });
  861. var warn = undefined;
  862. if (process.env.NODE_ENV !== 'production') {
  863. (function () {
  864. var hasConsole = typeof console !== 'undefined';
  865. warn = function (msg, e) {
  866. if (hasConsole && (!config.silent || config.debug)) {
  867. console.warn('[Vue warn]: ' + msg);
  868. /* istanbul ignore if */
  869. if (config.debug) {
  870. if (e) {
  871. throw e;
  872. } else {
  873. console.warn(new Error('Warning Stack Trace').stack);
  874. }
  875. }
  876. }
  877. };
  878. })();
  879. }
  880. /**
  881. * Append with transition.
  882. *
  883. * @param {Element} el
  884. * @param {Element} target
  885. * @param {Vue} vm
  886. * @param {Function} [cb]
  887. */
  888. function appendWithTransition(el, target, vm, cb) {
  889. applyTransition(el, 1, function () {
  890. target.appendChild(el);
  891. }, vm, cb);
  892. }
  893. /**
  894. * InsertBefore with transition.
  895. *
  896. * @param {Element} el
  897. * @param {Element} target
  898. * @param {Vue} vm
  899. * @param {Function} [cb]
  900. */
  901. function beforeWithTransition(el, target, vm, cb) {
  902. applyTransition(el, 1, function () {
  903. before(el, target);
  904. }, vm, cb);
  905. }
  906. /**
  907. * Remove with transition.
  908. *
  909. * @param {Element} el
  910. * @param {Vue} vm
  911. * @param {Function} [cb]
  912. */
  913. function removeWithTransition(el, vm, cb) {
  914. applyTransition(el, -1, function () {
  915. remove(el);
  916. }, vm, cb);
  917. }
  918. /**
  919. * Apply transitions with an operation callback.
  920. *
  921. * @param {Element} el
  922. * @param {Number} direction
  923. * 1: enter
  924. * -1: leave
  925. * @param {Function} op - the actual DOM operation
  926. * @param {Vue} vm
  927. * @param {Function} [cb]
  928. */
  929. function applyTransition(el, direction, op, vm, cb) {
  930. var transition = el.__v_trans;
  931. if (!transition ||
  932. // skip if there are no js hooks and CSS transition is
  933. // not supported
  934. !transition.hooks && !transitionEndEvent ||
  935. // skip transitions for initial compile
  936. !vm._isCompiled ||
  937. // if the vm is being manipulated by a parent directive
  938. // during the parent's compilation phase, skip the
  939. // animation.
  940. vm.$parent && !vm.$parent._isCompiled) {
  941. op();
  942. if (cb) cb();
  943. return;
  944. }
  945. var action = direction > 0 ? 'enter' : 'leave';
  946. transition[action](op, cb);
  947. }
  948. var transition = Object.freeze({
  949. appendWithTransition: appendWithTransition,
  950. beforeWithTransition: beforeWithTransition,
  951. removeWithTransition: removeWithTransition,
  952. applyTransition: applyTransition
  953. });
  954. /**
  955. * Query an element selector if it's not an element already.
  956. *
  957. * @param {String|Element} el
  958. * @return {Element}
  959. */
  960. function query(el) {
  961. if (typeof el === 'string') {
  962. var selector = el;
  963. el = document.querySelector(el);
  964. if (!el) {
  965. process.env.NODE_ENV !== 'production' && warn('Cannot find element: ' + selector);
  966. }
  967. }
  968. return el;
  969. }
  970. /**
  971. * Check if a node is in the document.
  972. * Note: document.documentElement.contains should work here
  973. * but always returns false for comment nodes in phantomjs,
  974. * making unit tests difficult. This is fixed by doing the
  975. * contains() check on the node's parentNode instead of
  976. * the node itself.
  977. *
  978. * @param {Node} node
  979. * @return {Boolean}
  980. */
  981. function inDoc(node) {
  982. var doc = document.documentElement;
  983. var parent = node && node.parentNode;
  984. return doc === node || doc === parent || !!(parent && parent.nodeType === 1 && doc.contains(parent));
  985. }
  986. /**
  987. * Get and remove an attribute from a node.
  988. *
  989. * @param {Node} node
  990. * @param {String} _attr
  991. */
  992. function getAttr(node, _attr) {
  993. var val = node.getAttribute(_attr);
  994. if (val !== null) {
  995. node.removeAttribute(_attr);
  996. }
  997. return val;
  998. }
  999. /**
  1000. * Get an attribute with colon or v-bind: prefix.
  1001. *
  1002. * @param {Node} node
  1003. * @param {String} name
  1004. * @return {String|null}
  1005. */
  1006. function getBindAttr(node, name) {
  1007. var val = getAttr(node, ':' + name);
  1008. if (val === null) {
  1009. val = getAttr(node, 'v-bind:' + name);
  1010. }
  1011. return val;
  1012. }
  1013. /**
  1014. * Check the presence of a bind attribute.
  1015. *
  1016. * @param {Node} node
  1017. * @param {String} name
  1018. * @return {Boolean}
  1019. */
  1020. function hasBindAttr(node, name) {
  1021. return node.hasAttribute(name) || node.hasAttribute(':' + name) || node.hasAttribute('v-bind:' + name);
  1022. }
  1023. /**
  1024. * Insert el before target
  1025. *
  1026. * @param {Element} el
  1027. * @param {Element} target
  1028. */
  1029. function before(el, target) {
  1030. target.parentNode.insertBefore(el, target);
  1031. }
  1032. /**
  1033. * Insert el after target
  1034. *
  1035. * @param {Element} el
  1036. * @param {Element} target
  1037. */
  1038. function after(el, target) {
  1039. if (target.nextSibling) {
  1040. before(el, target.nextSibling);
  1041. } else {
  1042. target.parentNode.appendChild(el);
  1043. }
  1044. }
  1045. /**
  1046. * Remove el from DOM
  1047. *
  1048. * @param {Element} el
  1049. */
  1050. function remove(el) {
  1051. el.parentNode.removeChild(el);
  1052. }
  1053. /**
  1054. * Prepend el to target
  1055. *
  1056. * @param {Element} el
  1057. * @param {Element} target
  1058. */
  1059. function prepend(el, target) {
  1060. if (target.firstChild) {
  1061. before(el, target.firstChild);
  1062. } else {
  1063. target.appendChild(el);
  1064. }
  1065. }
  1066. /**
  1067. * Replace target with el
  1068. *
  1069. * @param {Element} target
  1070. * @param {Element} el
  1071. */
  1072. function replace(target, el) {
  1073. var parent = target.parentNode;
  1074. if (parent) {
  1075. parent.replaceChild(el, target);
  1076. }
  1077. }
  1078. /**
  1079. * Add event listener shorthand.
  1080. *
  1081. * @param {Element} el
  1082. * @param {String} event
  1083. * @param {Function} cb
  1084. * @param {Boolean} [useCapture]
  1085. */
  1086. function on(el, event, cb, useCapture) {
  1087. el.addEventListener(event, cb, useCapture);
  1088. }
  1089. /**
  1090. * Remove event listener shorthand.
  1091. *
  1092. * @param {Element} el
  1093. * @param {String} event
  1094. * @param {Function} cb
  1095. */
  1096. function off(el, event, cb) {
  1097. el.removeEventListener(event, cb);
  1098. }
  1099. /**
  1100. * In IE9, setAttribute('class') will result in empty class
  1101. * if the element also has the :class attribute; However in
  1102. * PhantomJS, setting `className` does not work on SVG elements...
  1103. * So we have to do a conditional check here.
  1104. *
  1105. * @param {Element} el
  1106. * @param {String} cls
  1107. */
  1108. function setClass(el, cls) {
  1109. /* istanbul ignore if */
  1110. if (isIE9 && !/svg$/.test(el.namespaceURI)) {
  1111. el.className = cls;
  1112. } else {
  1113. el.setAttribute('class', cls);
  1114. }
  1115. }
  1116. /**
  1117. * Add class with compatibility for IE & SVG
  1118. *
  1119. * @param {Element} el
  1120. * @param {String} cls
  1121. */
  1122. function addClass(el, cls) {
  1123. if (el.classList) {
  1124. el.classList.add(cls);
  1125. } else {
  1126. var cur = ' ' + (el.getAttribute('class') || '') + ' ';
  1127. if (cur.indexOf(' ' + cls + ' ') < 0) {
  1128. setClass(el, (cur + cls).trim());
  1129. }
  1130. }
  1131. }
  1132. /**
  1133. * Remove class with compatibility for IE & SVG
  1134. *
  1135. * @param {Element} el
  1136. * @param {String} cls
  1137. */
  1138. function removeClass(el, cls) {
  1139. if (el.classList) {
  1140. el.classList.remove(cls);
  1141. } else {
  1142. var cur = ' ' + (el.getAttribute('class') || '') + ' ';
  1143. var tar = ' ' + cls + ' ';
  1144. while (cur.indexOf(tar) >= 0) {
  1145. cur = cur.replace(tar, ' ');
  1146. }
  1147. setClass(el, cur.trim());
  1148. }
  1149. if (!el.className) {
  1150. el.removeAttribute('class');
  1151. }
  1152. }
  1153. /**
  1154. * Extract raw content inside an element into a temporary
  1155. * container div
  1156. *
  1157. * @param {Element} el
  1158. * @param {Boolean} asFragment
  1159. * @return {Element|DocumentFragment}
  1160. */
  1161. function extractContent(el, asFragment) {
  1162. var child;
  1163. var rawContent;
  1164. /* istanbul ignore if */
  1165. if (isTemplate(el) && isFragment(el.content)) {
  1166. el = el.content;
  1167. }
  1168. if (el.hasChildNodes()) {
  1169. trimNode(el);
  1170. rawContent = asFragment ? document.createDocumentFragment() : document.createElement('div');
  1171. /* eslint-disable no-cond-assign */
  1172. while (child = el.firstChild) {
  1173. /* eslint-enable no-cond-assign */
  1174. rawContent.appendChild(child);
  1175. }
  1176. }
  1177. return rawContent;
  1178. }
  1179. /**
  1180. * Trim possible empty head/tail text and comment
  1181. * nodes inside a parent.
  1182. *
  1183. * @param {Node} node
  1184. */
  1185. function trimNode(node) {
  1186. var child;
  1187. /* eslint-disable no-sequences */
  1188. while ((child = node.firstChild, isTrimmable(child))) {
  1189. node.removeChild(child);
  1190. }
  1191. while ((child = node.lastChild, isTrimmable(child))) {
  1192. node.removeChild(child);
  1193. }
  1194. /* eslint-enable no-sequences */
  1195. }
  1196. function isTrimmable(node) {
  1197. return node && (node.nodeType === 3 && !node.data.trim() || node.nodeType === 8);
  1198. }
  1199. /**
  1200. * Check if an element is a template tag.
  1201. * Note if the template appears inside an SVG its tagName
  1202. * will be in lowercase.
  1203. *
  1204. * @param {Element} el
  1205. */
  1206. function isTemplate(el) {
  1207. return el.tagName && el.tagName.toLowerCase() === 'template';
  1208. }
  1209. /**
  1210. * Create an "anchor" for performing dom insertion/removals.
  1211. * This is used in a number of scenarios:
  1212. * - fragment instance
  1213. * - v-html
  1214. * - v-if
  1215. * - v-for
  1216. * - component
  1217. *
  1218. * @param {String} content
  1219. * @param {Boolean} persist - IE trashes empty textNodes on
  1220. * cloneNode(true), so in certain
  1221. * cases the anchor needs to be
  1222. * non-empty to be persisted in
  1223. * templates.
  1224. * @return {Comment|Text}
  1225. */
  1226. function createAnchor(content, persist) {
  1227. var anchor = config.debug ? document.createComment(content) : document.createTextNode(persist ? ' ' : '');
  1228. anchor.__v_anchor = true;
  1229. return anchor;
  1230. }
  1231. /**
  1232. * Find a component ref attribute that starts with $.
  1233. *
  1234. * @param {Element} node
  1235. * @return {String|undefined}
  1236. */
  1237. var refRE = /^v-ref:/;
  1238. function findRef(node) {
  1239. if (node.hasAttributes()) {
  1240. var attrs = node.attributes;
  1241. for (var i = 0, l = attrs.length; i < l; i++) {
  1242. var name = attrs[i].name;
  1243. if (refRE.test(name)) {
  1244. return camelize(name.replace(refRE, ''));
  1245. }
  1246. }
  1247. }
  1248. }
  1249. /**
  1250. * Map a function to a range of nodes .
  1251. *
  1252. * @param {Node} node
  1253. * @param {Node} end
  1254. * @param {Function} op
  1255. */
  1256. function mapNodeRange(node, end, op) {
  1257. var next;
  1258. while (node !== end) {
  1259. next = node.nextSibling;
  1260. op(node);
  1261. node = next;
  1262. }
  1263. op(end);
  1264. }
  1265. /**
  1266. * Remove a range of nodes with transition, store
  1267. * the nodes in a fragment with correct ordering,
  1268. * and call callback when done.
  1269. *
  1270. * @param {Node} start
  1271. * @param {Node} end
  1272. * @param {Vue} vm
  1273. * @param {DocumentFragment} frag
  1274. * @param {Function} cb
  1275. */
  1276. function removeNodeRange(start, end, vm, frag, cb) {
  1277. var done = false;
  1278. var removed = 0;
  1279. var nodes = [];
  1280. mapNodeRange(start, end, function (node) {
  1281. if (node === end) done = true;
  1282. nodes.push(node);
  1283. removeWithTransition(node, vm, onRemoved);
  1284. });
  1285. function onRemoved() {
  1286. removed++;
  1287. if (done && removed >= nodes.length) {
  1288. for (var i = 0; i < nodes.length; i++) {
  1289. frag.appendChild(nodes[i]);
  1290. }
  1291. cb && cb();
  1292. }
  1293. }
  1294. }
  1295. /**
  1296. * Check if a node is a DocumentFragment.
  1297. *
  1298. * @param {Node} node
  1299. * @return {Boolean}
  1300. */
  1301. function isFragment(node) {
  1302. return node && node.nodeType === 11;
  1303. }
  1304. /**
  1305. * Get outerHTML of elements, taking care
  1306. * of SVG elements in IE as well.
  1307. *
  1308. * @param {Element} el
  1309. * @return {String}
  1310. */
  1311. function getOuterHTML(el) {
  1312. if (el.outerHTML) {
  1313. return el.outerHTML;
  1314. } else {
  1315. var container = document.createElement('div');
  1316. container.appendChild(el.cloneNode(true));
  1317. return container.innerHTML;
  1318. }
  1319. }
  1320. var uid$1 = 0;
  1321. /**
  1322. * A dep is an observable that can have multiple
  1323. * directives subscribing to it.
  1324. *
  1325. * @constructor
  1326. */
  1327. function Dep() {
  1328. this.id = uid$1++;
  1329. this.subs = [];
  1330. }
  1331. // the current target watcher being evaluated.
  1332. // this is globally unique because there could be only one
  1333. // watcher being evaluated at any time.
  1334. Dep.target = null;
  1335. /**
  1336. * Add a directive subscriber.
  1337. *
  1338. * @param {Directive} sub
  1339. */
  1340. Dep.prototype.addSub = function (sub) {
  1341. this.subs.push(sub);
  1342. };
  1343. /**
  1344. * Remove a directive subscriber.
  1345. *
  1346. * @param {Directive} sub
  1347. */
  1348. Dep.prototype.removeSub = function (sub) {
  1349. this.subs.$remove(sub);
  1350. };
  1351. /**
  1352. * Add self as a dependency to the target watcher.
  1353. */
  1354. Dep.prototype.depend = function () {
  1355. Dep.target.addDep(this);
  1356. };
  1357. /**
  1358. * Notify all subscribers of a new value.
  1359. */
  1360. Dep.prototype.notify = function () {
  1361. // stablize the subscriber list first
  1362. var subs = toArray(this.subs);
  1363. for (var i = 0, l = subs.length; i < l; i++) {
  1364. subs[i].update();
  1365. }
  1366. };
  1367. var arrayProto = Array.prototype;
  1368. var arrayMethods = Object.create(arrayProto)
  1369. /**
  1370. * Intercept mutating methods and emit events
  1371. */
  1372. ;['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(function (method) {
  1373. // cache original method
  1374. var original = arrayProto[method];
  1375. def(arrayMethods, method, function mutator() {
  1376. // avoid leaking arguments:
  1377. // http://jsperf.com/closure-with-arguments
  1378. var i = arguments.length;
  1379. var args = new Array(i);
  1380. while (i--) {
  1381. args[i] = arguments[i];
  1382. }
  1383. var result = original.apply(this, args);
  1384. var ob = this.__ob__;
  1385. var inserted;
  1386. switch (method) {
  1387. case 'push':
  1388. inserted = args;
  1389. break;
  1390. case 'unshift':
  1391. inserted = args;
  1392. break;
  1393. case 'splice':
  1394. inserted = args.slice(2);
  1395. break;
  1396. }
  1397. if (inserted) ob.observeArray(inserted);
  1398. // notify change
  1399. ob.dep.notify();
  1400. return result;
  1401. });
  1402. });
  1403. /**
  1404. * Swap the element at the given index with a new value
  1405. * and emits corresponding event.
  1406. *
  1407. * @param {Number} index
  1408. * @param {*} val
  1409. * @return {*} - replaced element
  1410. */
  1411. def(arrayProto, '$set', function $set(index, val) {
  1412. if (index >= this.length) {
  1413. this.length = Number(index) + 1;
  1414. }
  1415. return this.splice(index, 1, val)[0];
  1416. });
  1417. /**
  1418. * Convenience method to remove the element at given index.
  1419. *
  1420. * @param {Number} index
  1421. * @param {*} val
  1422. */
  1423. def(arrayProto, '$remove', function $remove(item) {
  1424. /* istanbul ignore if */
  1425. if (!this.length) return;
  1426. var index = indexOf(this, item);
  1427. if (index > -1) {
  1428. return this.splice(index, 1);
  1429. }
  1430. });
  1431. var arrayKeys = Object.getOwnPropertyNames(arrayMethods);
  1432. /**
  1433. * Observer class that are attached to each observed
  1434. * object. Once attached, the observer converts target
  1435. * object's property keys into getter/setters that
  1436. * collect dependencies and dispatches updates.
  1437. *
  1438. * @param {Array|Object} value
  1439. * @constructor
  1440. */
  1441. function Observer(value) {
  1442. this.value = value;
  1443. this.dep = new Dep();
  1444. def(value, '__ob__', this);
  1445. if (isArray(value)) {
  1446. var augment = hasProto ? protoAugment : copyAugment;
  1447. augment(value, arrayMethods, arrayKeys);
  1448. this.observeArray(value);
  1449. } else {
  1450. this.walk(value);
  1451. }
  1452. }
  1453. // Instance methods
  1454. /**
  1455. * Walk through each property and convert them into
  1456. * getter/setters. This method should only be called when
  1457. * value type is Object.
  1458. *
  1459. * @param {Object} obj
  1460. */
  1461. Observer.prototype.walk = function (obj) {
  1462. var keys = Object.keys(obj);
  1463. for (var i = 0, l = keys.length; i < l; i++) {
  1464. this.convert(keys[i], obj[keys[i]]);
  1465. }
  1466. };
  1467. /**
  1468. * Observe a list of Array items.
  1469. *
  1470. * @param {Array} items
  1471. */
  1472. Observer.prototype.observeArray = function (items) {
  1473. for (var i = 0, l = items.length; i < l; i++) {
  1474. observe(items[i]);
  1475. }
  1476. };
  1477. /**
  1478. * Convert a property into getter/setter so we can emit
  1479. * the events when the property is accessed/changed.
  1480. *
  1481. * @param {String} key
  1482. * @param {*} val
  1483. */
  1484. Observer.prototype.convert = function (key, val) {
  1485. defineReactive(this.value, key, val);
  1486. };
  1487. /**
  1488. * Add an owner vm, so that when $set/$delete mutations
  1489. * happen we can notify owner vms to proxy the keys and
  1490. * digest the watchers. This is only called when the object
  1491. * is observed as an instance's root $data.
  1492. *
  1493. * @param {Vue} vm
  1494. */
  1495. Observer.prototype.addVm = function (vm) {
  1496. (this.vms || (this.vms = [])).push(vm);
  1497. };
  1498. /**
  1499. * Remove an owner vm. This is called when the object is
  1500. * swapped out as an instance's $data object.
  1501. *
  1502. * @param {Vue} vm
  1503. */
  1504. Observer.prototype.removeVm = function (vm) {
  1505. this.vms.$remove(vm);
  1506. };
  1507. // helpers
  1508. /**
  1509. * Augment an target Object or Array by intercepting
  1510. * the prototype chain using __proto__
  1511. *
  1512. * @param {Object|Array} target
  1513. * @param {Object} proto
  1514. */
  1515. function protoAugment(target, src) {
  1516. /* eslint-disable no-proto */
  1517. target.__proto__ = src;
  1518. /* eslint-enable no-proto */
  1519. }
  1520. /**
  1521. * Augment an target Object or Array by defining
  1522. * hidden properties.
  1523. *
  1524. * @param {Object|Array} target
  1525. * @param {Object} proto
  1526. */
  1527. function copyAugment(target, src, keys) {
  1528. for (var i = 0, l = keys.length; i < l; i++) {
  1529. var key = keys[i];
  1530. def(target, key, src[key]);
  1531. }
  1532. }
  1533. /**
  1534. * Attempt to create an observer instance for a value,
  1535. * returns the new observer if successfully observed,
  1536. * or the existing observer if the value already has one.
  1537. *
  1538. * @param {*} value
  1539. * @param {Vue} [vm]
  1540. * @return {Observer|undefined}
  1541. * @static
  1542. */
  1543. function observe(value, vm) {
  1544. if (!value || typeof value !== 'object') {
  1545. return;
  1546. }
  1547. var ob;
  1548. if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
  1549. ob = value.__ob__;
  1550. } else if ((isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue) {
  1551. ob = new Observer(value);
  1552. }
  1553. if (ob && vm) {
  1554. ob.addVm(vm);
  1555. }
  1556. return ob;
  1557. }
  1558. /**
  1559. * Define a reactive property on an Object.
  1560. *
  1561. * @param {Object} obj
  1562. * @param {String} key
  1563. * @param {*} val
  1564. * @param {Boolean} doNotObserve
  1565. */
  1566. function defineReactive(obj, key, val, doNotObserve) {
  1567. var dep = new Dep();
  1568. var property = Object.getOwnPropertyDescriptor(obj, key);
  1569. if (property && property.configurable === false) {
  1570. return;
  1571. }
  1572. // cater for pre-defined getter/setters
  1573. var getter = property && property.get;
  1574. var setter = property && property.set;
  1575. // if doNotObserve is true, only use the child value observer
  1576. // if it already exists, and do not attempt to create it.
  1577. // this allows freezing a large object from the root and
  1578. // avoid unnecessary observation inside v-for fragments.
  1579. var childOb = doNotObserve ? isObject(val) && val.__ob__ : observe(val);
  1580. Object.defineProperty(obj, key, {
  1581. enumerable: true,
  1582. configurable: true,
  1583. get: function reactiveGetter() {
  1584. var value = getter ? getter.call(obj) : val;
  1585. if (Dep.target) {
  1586. dep.depend();
  1587. if (childOb) {
  1588. childOb.dep.depend();
  1589. }
  1590. if (isArray(value)) {
  1591. for (var e, i = 0, l = value.length; i < l; i++) {
  1592. e = value[i];
  1593. e && e.__ob__ && e.__ob__.dep.depend();
  1594. }
  1595. }
  1596. }
  1597. return value;
  1598. },
  1599. set: function reactiveSetter(newVal) {
  1600. var value = getter ? getter.call(obj) : val;
  1601. if (newVal === value) {
  1602. return;
  1603. }
  1604. if (setter) {
  1605. setter.call(obj, newVal);
  1606. } else {
  1607. val = newVal;
  1608. }
  1609. childOb = doNotObserve ? isObject(newVal) && newVal.__ob__ : observe(newVal);
  1610. dep.notify();
  1611. }
  1612. });
  1613. }
  1614. 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;
  1615. var reservedTagRE = /^(slot|partial|component)$/i;
  1616. var isUnknownElement = undefined;
  1617. if (process.env.NODE_ENV !== 'production') {
  1618. isUnknownElement = function (el, tag) {
  1619. if (tag.indexOf('-') > -1) {
  1620. // http://stackoverflow.com/a/28210364/1070244
  1621. return el.constructor === window.HTMLUnknownElement || el.constructor === window.HTMLElement;
  1622. } else {
  1623. return (/HTMLUnknownElement/.test(el.toString()) &&
  1624. // Chrome returns unknown for several HTML5 elements.
  1625. // https://code.google.com/p/chromium/issues/detail?id=540526
  1626. !/^(data|time|rtc|rb)$/.test(tag)
  1627. );
  1628. }
  1629. };
  1630. }
  1631. /**
  1632. * Check if an element is a component, if yes return its
  1633. * component id.
  1634. *
  1635. * @param {Element} el
  1636. * @param {Object} options
  1637. * @return {Object|undefined}
  1638. */
  1639. function checkComponentAttr(el, options) {
  1640. var tag = el.tagName.toLowerCase();
  1641. var hasAttrs = el.hasAttributes();
  1642. if (!commonTagRE.test(tag) && !reservedTagRE.test(tag)) {
  1643. if (resolveAsset(options, 'components', tag)) {
  1644. return { id: tag };
  1645. } else {
  1646. var is = hasAttrs && getIsBinding(el);
  1647. if (is) {
  1648. return is;
  1649. } else if (process.env.NODE_ENV !== 'production') {
  1650. var expectedTag = options._componentNameMap && options._componentNameMap[tag];
  1651. if (expectedTag) {
  1652. warn('Unknown custom element: <' + tag + '> - ' + 'did you mean <' + expectedTag + '>? ' + 'HTML is case-insensitive, remember to use kebab-case in templates.');
  1653. } else if (isUnknownElement(el, tag)) {
  1654. warn('Unknown custom element: <' + tag + '> - did you ' + 'register the component correctly? For recursive components, ' + 'make sure to provide the "name" option.');
  1655. }
  1656. }
  1657. }
  1658. } else if (hasAttrs) {
  1659. return getIsBinding(el);
  1660. }
  1661. }
  1662. /**
  1663. * Get "is" binding from an element.
  1664. *
  1665. * @param {Element} el
  1666. * @return {Object|undefined}
  1667. */
  1668. function getIsBinding(el) {
  1669. // dynamic syntax
  1670. var exp = getAttr(el, 'is');
  1671. if (exp != null) {
  1672. return { id: exp };
  1673. } else {
  1674. exp = getBindAttr(el, 'is');
  1675. if (exp != null) {
  1676. return { id: exp, dynamic: true };
  1677. }
  1678. }
  1679. }
  1680. /**
  1681. * Set a prop's initial value on a vm and its data object.
  1682. *
  1683. * @param {Vue} vm
  1684. * @param {Object} prop
  1685. * @param {*} value
  1686. */
  1687. function initProp(vm, prop, value) {
  1688. var key = prop.path;
  1689. value = coerceProp(prop, value);
  1690. if (value === undefined) {
  1691. value = getPropDefaultValue(vm, prop.options);
  1692. }
  1693. if (assertProp(prop, value)) {
  1694. defineReactive(vm, key, value, true /* doNotObserve */);
  1695. }
  1696. }
  1697. /**
  1698. * Get the default value of a prop.
  1699. *
  1700. * @param {Vue} vm
  1701. * @param {Object} options
  1702. * @return {*}
  1703. */
  1704. function getPropDefaultValue(vm, options) {
  1705. // no default, return undefined
  1706. if (!hasOwn(options, 'default')) {
  1707. // absent boolean value defaults to false
  1708. return options.type === Boolean ? false : undefined;
  1709. }
  1710. var def = options['default'];
  1711. // warn against non-factory defaults for Object & Array
  1712. if (isObject(def)) {
  1713. process.env.NODE_ENV !== 'production' && warn('Object/Array as default prop values will be shared ' + 'across multiple instances. Use a factory function ' + 'to return the default value instead.');
  1714. }
  1715. // call factory function for non-Function types
  1716. return typeof def === 'function' && options.type !== Function ? def.call(vm) : def;
  1717. }
  1718. /**
  1719. * Assert whether a prop is valid.
  1720. *
  1721. * @param {Object} prop
  1722. * @param {*} value
  1723. */
  1724. function assertProp(prop, value) {
  1725. if (!prop.options.required && ( // non-required
  1726. prop.raw === null || // abscent
  1727. value == null) // null or undefined
  1728. ) {
  1729. return true;
  1730. }
  1731. var options = prop.options;
  1732. var type = options.type;
  1733. var valid = true;
  1734. var expectedType;
  1735. if (type) {
  1736. if (type === String) {
  1737. expectedType = 'string';
  1738. valid = typeof value === expectedType;
  1739. } else if (type === Number) {
  1740. expectedType = 'number';
  1741. valid = typeof value === 'number';
  1742. } else if (type === Boolean) {
  1743. expectedType = 'boolean';
  1744. valid = typeof value === 'boolean';
  1745. } else if (type === Function) {
  1746. expectedType = 'function';
  1747. valid = typeof value === 'function';
  1748. } else if (type === Object) {
  1749. expectedType = 'object';
  1750. valid = isPlainObject(value);
  1751. } else if (type === Array) {
  1752. expectedType = 'array';
  1753. valid = isArray(value);
  1754. } else {
  1755. valid = value instanceof type;
  1756. }
  1757. }
  1758. if (!valid) {
  1759. process.env.NODE_ENV !== 'production' && warn('Invalid prop: type check failed for ' + prop.path + '="' + prop.raw + '".' + ' Expected ' + formatType(expectedType) + ', got ' + formatValue(value) + '.');
  1760. return false;
  1761. }
  1762. var validator = options.validator;
  1763. if (validator) {
  1764. if (!validator(value)) {
  1765. process.env.NODE_ENV !== 'production' && warn('Invalid prop: custom validator check failed for ' + prop.path + '="' + prop.raw + '"');
  1766. return false;
  1767. }
  1768. }
  1769. return true;
  1770. }
  1771. /**
  1772. * Force parsing value with coerce option.
  1773. *
  1774. * @param {*} value
  1775. * @param {Object} options
  1776. * @return {*}
  1777. */
  1778. function coerceProp(prop, value) {
  1779. var coerce = prop.options.coerce;
  1780. if (!coerce) {
  1781. return value;
  1782. }
  1783. // coerce is a function
  1784. return coerce(value);
  1785. }
  1786. function formatType(val) {
  1787. return val ? val.charAt(0).toUpperCase() + val.slice(1) : 'custom type';
  1788. }
  1789. function formatValue(val) {
  1790. return Object.prototype.toString.call(val).slice(8, -1);
  1791. }
  1792. /**
  1793. * Option overwriting strategies are functions that handle
  1794. * how to merge a parent option value and a child option
  1795. * value into the final value.
  1796. *
  1797. * All strategy functions follow the same signature:
  1798. *
  1799. * @param {*} parentVal
  1800. * @param {*} childVal
  1801. * @param {Vue} [vm]
  1802. */
  1803. var strats = config.optionMergeStrategies = Object.create(null);
  1804. /**
  1805. * Helper that recursively merges two data objects together.
  1806. */
  1807. function mergeData(to, from) {
  1808. var key, toVal, fromVal;
  1809. for (key in from) {
  1810. toVal = to[key];
  1811. fromVal = from[key];
  1812. if (!hasOwn(to, key)) {
  1813. set(to, key, fromVal);
  1814. } else if (isObject(toVal) && isObject(fromVal)) {
  1815. mergeData(toVal, fromVal);
  1816. }
  1817. }
  1818. return to;
  1819. }
  1820. /**
  1821. * Data
  1822. */
  1823. strats.data = function (parentVal, childVal, vm) {
  1824. if (!vm) {
  1825. // in a Vue.extend merge, both should be functions
  1826. if (!childVal) {
  1827. return parentVal;
  1828. }
  1829. if (typeof childVal !== 'function') {
  1830. process.env.NODE_ENV !== 'production' && warn('The "data" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.');
  1831. return parentVal;
  1832. }
  1833. if (!parentVal) {
  1834. return childVal;
  1835. }
  1836. // when parentVal & childVal are both present,
  1837. // we need to return a function that returns the
  1838. // merged result of both functions... no need to
  1839. // check if parentVal is a function here because
  1840. // it has to be a function to pass previous merges.
  1841. return function mergedDataFn() {
  1842. return mergeData(childVal.call(this), parentVal.call(this));
  1843. };
  1844. } else if (parentVal || childVal) {
  1845. return function mergedInstanceDataFn() {
  1846. // instance merge
  1847. var instanceData = typeof childVal === 'function' ? childVal.call(vm) : childVal;
  1848. var defaultData = typeof parentVal === 'function' ? parentVal.call(vm) : undefined;
  1849. if (instanceData) {
  1850. return mergeData(instanceData, defaultData);
  1851. } else {
  1852. return defaultData;
  1853. }
  1854. };
  1855. }
  1856. };
  1857. /**
  1858. * El
  1859. */
  1860. strats.el = function (parentVal, childVal, vm) {
  1861. if (!vm && childVal && typeof childVal !== 'function') {
  1862. process.env.NODE_ENV !== 'production' && warn('The "el" option should be a function ' + 'that returns a per-instance value in component ' + 'definitions.');
  1863. return;
  1864. }
  1865. var ret = childVal || parentVal;
  1866. // invoke the element factory if this is instance merge
  1867. return vm && typeof ret === 'function' ? ret.call(vm) : ret;
  1868. };
  1869. /**
  1870. * Hooks and param attributes are merged as arrays.
  1871. */
  1872. strats.init = strats.created = strats.ready = strats.attached = strats.detached = strats.beforeCompile = strats.compiled = strats.beforeDestroy = strats.destroyed = strats.activate = function (parentVal, childVal) {
  1873. return childVal ? parentVal ? parentVal.concat(childVal) : isArray(childVal) ? childVal : [childVal] : parentVal;
  1874. };
  1875. /**
  1876. * 0.11 deprecation warning
  1877. */
  1878. strats.paramAttributes = function () {
  1879. /* istanbul ignore next */
  1880. process.env.NODE_ENV !== 'production' && warn('"paramAttributes" option has been deprecated in 0.12. ' + 'Use "props" instead.');
  1881. };
  1882. /**
  1883. * Assets
  1884. *
  1885. * When a vm is present (instance creation), we need to do
  1886. * a three-way merge between constructor options, instance
  1887. * options and parent options.
  1888. */
  1889. function mergeAssets(parentVal, childVal) {
  1890. var res = Object.create(parentVal);
  1891. return childVal ? extend(res, guardArrayAssets(childVal)) : res;
  1892. }
  1893. config._assetTypes.forEach(function (type) {
  1894. strats[type + 's'] = mergeAssets;
  1895. });
  1896. /**
  1897. * Events & Watchers.
  1898. *
  1899. * Events & watchers hashes should not overwrite one
  1900. * another, so we merge them as arrays.
  1901. */
  1902. strats.watch = strats.events = function (parentVal, childVal) {
  1903. if (!childVal) return parentVal;
  1904. if (!parentVal) return childVal;
  1905. var ret = {};
  1906. extend(ret, parentVal);
  1907. for (var key in childVal) {
  1908. var parent = ret[key];
  1909. var child = childVal[key];
  1910. if (parent && !isArray(parent)) {
  1911. parent = [parent];
  1912. }
  1913. ret[key] = parent ? parent.concat(child) : [child];
  1914. }
  1915. return ret;
  1916. };
  1917. /**
  1918. * Other object hashes.
  1919. */
  1920. strats.props = strats.methods = strats.computed = function (parentVal, childVal) {
  1921. if (!childVal) return parentVal;
  1922. if (!parentVal) return childVal;
  1923. var ret = Object.create(null);
  1924. extend(ret, parentVal);
  1925. extend(ret, childVal);
  1926. return ret;
  1927. };
  1928. /**
  1929. * Default strategy.
  1930. */
  1931. var defaultStrat = function defaultStrat(parentVal, childVal) {
  1932. return childVal === undefined ? parentVal : childVal;
  1933. };
  1934. /**
  1935. * Make sure component options get converted to actual
  1936. * constructors.
  1937. *
  1938. * @param {Object} options
  1939. */
  1940. function guardComponents(options) {
  1941. if (options.components) {
  1942. var components = options.components = guardArrayAssets(options.components);
  1943. var ids = Object.keys(components);
  1944. var def;
  1945. if (process.env.NODE_ENV !== 'production') {
  1946. var map = options._componentNameMap = {};
  1947. }
  1948. for (var i = 0, l = ids.length; i < l; i++) {
  1949. var key = ids[i];
  1950. if (commonTagRE.test(key) || reservedTagRE.test(key)) {
  1951. process.env.NODE_ENV !== 'production' && warn('Do not use built-in or reserved HTML elements as component ' + 'id: ' + key);
  1952. continue;
  1953. }
  1954. // record a all lowercase <-> kebab-case mapping for
  1955. // possible custom element case error warning
  1956. if (process.env.NODE_ENV !== 'production') {
  1957. map[key.replace(/-/g, '').toLowerCase()] = hyphenate(key);
  1958. }