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

/files/vue/1.0.9/vue.js

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