PageRenderTime 63ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/files/vue/1.0.14/vue.js

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