vue 2.6.2 → 2.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vue.js v2.6.2
2
+ * Vue.js v2.6.6
3
3
  * (c) 2014-2019 Evan You
4
4
  * Released under the MIT License.
5
5
  */
@@ -532,6 +532,7 @@ const isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'androi
532
532
  const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');
533
533
  const isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
534
534
  const isPhantomJS = UA && /phantomjs/.test(UA);
535
+ const isFF = UA && UA.match(/firefox\/(\d+)/);
535
536
 
536
537
  // Firefox has a "watch" function on Object.prototype...
537
538
  const nativeWatch = ({}).watch;
@@ -1894,7 +1895,11 @@ function globalHandleError (err, vm, info) {
1894
1895
  try {
1895
1896
  return config.errorHandler.call(null, err, vm, info)
1896
1897
  } catch (e) {
1897
- logError(e, null, 'config.errorHandler');
1898
+ // if the user intentionally throws the original error in the handler,
1899
+ // do not log it twice
1900
+ if (e !== err) {
1901
+ logError(e, null, 'config.errorHandler');
1902
+ }
1898
1903
  }
1899
1904
  }
1900
1905
  logError(err, vm, info);
@@ -2432,2448 +2437,2494 @@ function normalizeArrayChildren (children, nestedIndex) {
2432
2437
 
2433
2438
  /* */
2434
2439
 
2435
- function ensureCtor (comp, base) {
2436
- if (
2437
- comp.__esModule ||
2438
- (hasSymbol && comp[Symbol.toStringTag] === 'Module')
2439
- ) {
2440
- comp = comp.default;
2440
+ function initProvide (vm) {
2441
+ const provide = vm.$options.provide;
2442
+ if (provide) {
2443
+ vm._provided = typeof provide === 'function'
2444
+ ? provide.call(vm)
2445
+ : provide;
2441
2446
  }
2442
- return isObject(comp)
2443
- ? base.extend(comp)
2444
- : comp
2445
2447
  }
2446
2448
 
2447
- function createAsyncPlaceholder (
2448
- factory,
2449
- data,
2450
- context,
2451
- children,
2452
- tag
2453
- ) {
2454
- const node = createEmptyVNode();
2455
- node.asyncFactory = factory;
2456
- node.asyncMeta = { data, context, children, tag };
2457
- return node
2458
- }
2459
-
2460
- function resolveAsyncComponent (
2461
- factory,
2462
- baseCtor,
2463
- context
2464
- ) {
2465
- if (isTrue(factory.error) && isDef(factory.errorComp)) {
2466
- return factory.errorComp
2467
- }
2468
-
2469
- if (isDef(factory.resolved)) {
2470
- return factory.resolved
2471
- }
2472
-
2473
- if (isTrue(factory.loading) && isDef(factory.loadingComp)) {
2474
- return factory.loadingComp
2475
- }
2476
-
2477
- if (isDef(factory.contexts)) {
2478
- // already pending
2479
- factory.contexts.push(context);
2480
- } else {
2481
- const contexts = factory.contexts = [context];
2482
- let sync = true;
2483
-
2484
- const forceRender = (renderCompleted) => {
2485
- for (let i = 0, l = contexts.length; i < l; i++) {
2486
- contexts[i].$forceUpdate();
2487
- }
2488
-
2489
- if (renderCompleted) {
2490
- contexts.length = 0;
2491
- }
2492
- };
2493
-
2494
- const resolve = once((res) => {
2495
- // cache resolved
2496
- factory.resolved = ensureCtor(res, baseCtor);
2497
- // invoke callbacks only if this is not a synchronous resolve
2498
- // (async resolves are shimmed as synchronous during SSR)
2499
- if (!sync) {
2500
- forceRender(true);
2501
- } else {
2502
- contexts.length = 0;
2503
- }
2504
- });
2505
-
2506
- const reject = once(reason => {
2507
- warn(
2508
- `Failed to resolve async component: ${String(factory)}` +
2509
- (reason ? `\nReason: ${reason}` : '')
2510
- );
2511
- if (isDef(factory.errorComp)) {
2512
- factory.error = true;
2513
- forceRender(true);
2449
+ function initInjections (vm) {
2450
+ const result = resolveInject(vm.$options.inject, vm);
2451
+ if (result) {
2452
+ toggleObserving(false);
2453
+ Object.keys(result).forEach(key => {
2454
+ /* istanbul ignore else */
2455
+ {
2456
+ defineReactive$$1(vm, key, result[key], () => {
2457
+ warn(
2458
+ `Avoid mutating an injected value directly since the changes will be ` +
2459
+ `overwritten whenever the provided component re-renders. ` +
2460
+ `injection being mutated: "${key}"`,
2461
+ vm
2462
+ );
2463
+ });
2514
2464
  }
2515
2465
  });
2466
+ toggleObserving(true);
2467
+ }
2468
+ }
2516
2469
 
2517
- const res = factory(resolve, reject);
2518
-
2519
- if (isObject(res)) {
2520
- if (isPromise(res)) {
2521
- // () => Promise
2522
- if (isUndef(factory.resolved)) {
2523
- res.then(resolve, reject);
2524
- }
2525
- } else if (isPromise(res.component)) {
2526
- res.component.then(resolve, reject);
2527
-
2528
- if (isDef(res.error)) {
2529
- factory.errorComp = ensureCtor(res.error, baseCtor);
2530
- }
2470
+ function resolveInject (inject, vm) {
2471
+ if (inject) {
2472
+ // inject is :any because flow is not smart enough to figure out cached
2473
+ const result = Object.create(null);
2474
+ const keys = hasSymbol
2475
+ ? Reflect.ownKeys(inject)
2476
+ : Object.keys(inject);
2531
2477
 
2532
- if (isDef(res.loading)) {
2533
- factory.loadingComp = ensureCtor(res.loading, baseCtor);
2534
- if (res.delay === 0) {
2535
- factory.loading = true;
2536
- } else {
2537
- setTimeout(() => {
2538
- if (isUndef(factory.resolved) && isUndef(factory.error)) {
2539
- factory.loading = true;
2540
- forceRender(false);
2541
- }
2542
- }, res.delay || 200);
2543
- }
2478
+ for (let i = 0; i < keys.length; i++) {
2479
+ const key = keys[i];
2480
+ // #6574 in case the inject object is observed...
2481
+ if (key === '__ob__') continue
2482
+ const provideKey = inject[key].from;
2483
+ let source = vm;
2484
+ while (source) {
2485
+ if (source._provided && hasOwn(source._provided, provideKey)) {
2486
+ result[key] = source._provided[provideKey];
2487
+ break
2544
2488
  }
2545
-
2546
- if (isDef(res.timeout)) {
2547
- setTimeout(() => {
2548
- if (isUndef(factory.resolved)) {
2549
- reject(
2550
- `timeout (${res.timeout}ms)`
2551
- );
2552
- }
2553
- }, res.timeout);
2489
+ source = source.$parent;
2490
+ }
2491
+ if (!source) {
2492
+ if ('default' in inject[key]) {
2493
+ const provideDefault = inject[key].default;
2494
+ result[key] = typeof provideDefault === 'function'
2495
+ ? provideDefault.call(vm)
2496
+ : provideDefault;
2497
+ } else {
2498
+ warn(`Injection "${key}" not found`, vm);
2554
2499
  }
2555
2500
  }
2556
2501
  }
2557
-
2558
- sync = false;
2559
- // return in case resolved synchronously
2560
- return factory.loading
2561
- ? factory.loadingComp
2562
- : factory.resolved
2502
+ return result
2563
2503
  }
2564
2504
  }
2565
2505
 
2566
2506
  /* */
2567
2507
 
2568
- function isAsyncPlaceholder (node) {
2569
- return node.isComment && node.asyncFactory
2570
- }
2571
2508
 
2572
- /* */
2573
2509
 
2574
- function getFirstComponentChild (children) {
2575
- if (Array.isArray(children)) {
2576
- for (let i = 0; i < children.length; i++) {
2577
- const c = children[i];
2578
- if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
2579
- return c
2510
+ /**
2511
+ * Runtime helper for resolving raw children VNodes into a slot object.
2512
+ */
2513
+ function resolveSlots (
2514
+ children,
2515
+ context
2516
+ ) {
2517
+ if (!children || !children.length) {
2518
+ return {}
2519
+ }
2520
+ const slots = {};
2521
+ for (let i = 0, l = children.length; i < l; i++) {
2522
+ const child = children[i];
2523
+ const data = child.data;
2524
+ // remove slot attribute if the node is resolved as a Vue slot node
2525
+ if (data && data.attrs && data.attrs.slot) {
2526
+ delete data.attrs.slot;
2527
+ }
2528
+ // named slots should only be respected if the vnode was rendered in the
2529
+ // same context.
2530
+ if ((child.context === context || child.fnContext === context) &&
2531
+ data && data.slot != null
2532
+ ) {
2533
+ const name = data.slot;
2534
+ const slot = (slots[name] || (slots[name] = []));
2535
+ if (child.tag === 'template') {
2536
+ slot.push.apply(slot, child.children || []);
2537
+ } else {
2538
+ slot.push(child);
2580
2539
  }
2540
+ } else {
2541
+ (slots.default || (slots.default = [])).push(child);
2542
+ }
2543
+ }
2544
+ // ignore slots that contains only whitespace
2545
+ for (const name in slots) {
2546
+ if (slots[name].every(isWhitespace)) {
2547
+ delete slots[name];
2581
2548
  }
2582
2549
  }
2550
+ return slots
2583
2551
  }
2584
2552
 
2585
- /* */
2553
+ function isWhitespace (node) {
2554
+ return (node.isComment && !node.asyncFactory) || node.text === ' '
2555
+ }
2586
2556
 
2587
2557
  /* */
2588
2558
 
2589
- function initEvents (vm) {
2590
- vm._events = Object.create(null);
2591
- vm._hasHookEvent = false;
2592
- // init parent attached events
2593
- const listeners = vm.$options._parentListeners;
2594
- if (listeners) {
2595
- updateComponentListeners(vm, listeners);
2559
+ function normalizeScopedSlots (
2560
+ slots,
2561
+ normalSlots,
2562
+ prevSlots
2563
+ ) {
2564
+ let res;
2565
+ if (!slots) {
2566
+ res = {};
2567
+ } else if (slots._normalized) {
2568
+ // fast path 1: child component re-render only, parent did not change
2569
+ return slots._normalized
2570
+ } else if (
2571
+ slots.$stable &&
2572
+ prevSlots &&
2573
+ prevSlots !== emptyObject &&
2574
+ Object.keys(normalSlots).length === 0
2575
+ ) {
2576
+ // fast path 2: stable scoped slots w/ no normal slots to proxy,
2577
+ // only need to normalize once
2578
+ return prevSlots
2579
+ } else {
2580
+ res = {};
2581
+ for (const key in slots) {
2582
+ if (slots[key] && key[0] !== '$') {
2583
+ res[key] = normalizeScopedSlot(normalSlots, key, slots[key]);
2584
+ }
2585
+ }
2586
+ }
2587
+ // expose normal slots on scopedSlots
2588
+ for (const key in normalSlots) {
2589
+ if (!(key in res)) {
2590
+ res[key] = proxyNormalSlot(normalSlots, key);
2591
+ }
2592
+ }
2593
+ // avoriaz seems to mock a non-extensible $scopedSlots object
2594
+ // and when that is passed down this would cause an error
2595
+ if (slots && Object.isExtensible(slots)) {
2596
+ (slots)._normalized = res;
2596
2597
  }
2598
+ def(res, '$stable', slots ? !!slots.$stable : true);
2599
+ return res
2597
2600
  }
2598
2601
 
2599
- let target;
2602
+ function normalizeScopedSlot(normalSlots, key, fn) {
2603
+ const normalized = function () {
2604
+ let res = arguments.length ? fn.apply(null, arguments) : fn({});
2605
+ res = res && typeof res === 'object' && !Array.isArray(res)
2606
+ ? [res] // single vnode
2607
+ : normalizeChildren(res);
2608
+ return res && res.length === 0
2609
+ ? undefined
2610
+ : res
2611
+ };
2612
+ // this is a slot using the new v-slot syntax without scope. although it is
2613
+ // compiled as a scoped slot, render fn users would expect it to be present
2614
+ // on this.$slots because the usage is semantically a normal slot.
2615
+ if (fn.proxy) {
2616
+ Object.defineProperty(normalSlots, key, {
2617
+ get: normalized,
2618
+ enumerable: true,
2619
+ configurable: true
2620
+ });
2621
+ }
2622
+ return normalized
2623
+ }
2600
2624
 
2601
- function add (event, fn) {
2602
- target.$on(event, fn);
2603
- }
2604
-
2605
- function remove$1 (event, fn) {
2606
- target.$off(event, fn);
2625
+ function proxyNormalSlot(slots, key) {
2626
+ return () => slots[key]
2607
2627
  }
2608
2628
 
2609
- function createOnceHandler (event, fn) {
2610
- const _target = target;
2611
- return function onceHandler () {
2612
- const res = fn.apply(null, arguments);
2613
- if (res !== null) {
2614
- _target.$off(event, onceHandler);
2615
- }
2616
- }
2617
- }
2629
+ /* */
2618
2630
 
2619
- function updateComponentListeners (
2620
- vm,
2621
- listeners,
2622
- oldListeners
2631
+ /**
2632
+ * Runtime helper for rendering v-for lists.
2633
+ */
2634
+ function renderList (
2635
+ val,
2636
+ render
2623
2637
  ) {
2624
- target = vm;
2625
- updateListeners(listeners, oldListeners || {}, add, remove$1, createOnceHandler, vm);
2626
- target = undefined;
2627
- }
2628
-
2629
- function eventsMixin (Vue) {
2630
- const hookRE = /^hook:/;
2631
- Vue.prototype.$on = function (event, fn) {
2632
- const vm = this;
2633
- if (Array.isArray(event)) {
2634
- for (let i = 0, l = event.length; i < l; i++) {
2635
- vm.$on(event[i], fn);
2636
- }
2637
- } else {
2638
- (vm._events[event] || (vm._events[event] = [])).push(fn);
2639
- // optimize hook:event cost by using a boolean flag marked at registration
2640
- // instead of a hash lookup
2641
- if (hookRE.test(event)) {
2642
- vm._hasHookEvent = true;
2643
- }
2644
- }
2645
- return vm
2646
- };
2647
-
2648
- Vue.prototype.$once = function (event, fn) {
2649
- const vm = this;
2650
- function on () {
2651
- vm.$off(event, on);
2652
- fn.apply(vm, arguments);
2653
- }
2654
- on.fn = fn;
2655
- vm.$on(event, on);
2656
- return vm
2657
- };
2658
-
2659
- Vue.prototype.$off = function (event, fn) {
2660
- const vm = this;
2661
- // all
2662
- if (!arguments.length) {
2663
- vm._events = Object.create(null);
2664
- return vm
2665
- }
2666
- // array of events
2667
- if (Array.isArray(event)) {
2668
- for (let i = 0, l = event.length; i < l; i++) {
2669
- vm.$off(event[i], fn);
2670
- }
2671
- return vm
2672
- }
2673
- // specific event
2674
- const cbs = vm._events[event];
2675
- if (!cbs) {
2676
- return vm
2677
- }
2678
- if (!fn) {
2679
- vm._events[event] = null;
2680
- return vm
2638
+ let ret, i, l, keys, key;
2639
+ if (Array.isArray(val) || typeof val === 'string') {
2640
+ ret = new Array(val.length);
2641
+ for (i = 0, l = val.length; i < l; i++) {
2642
+ ret[i] = render(val[i], i);
2681
2643
  }
2682
- // specific handler
2683
- let cb;
2684
- let i = cbs.length;
2685
- while (i--) {
2686
- cb = cbs[i];
2687
- if (cb === fn || cb.fn === fn) {
2688
- cbs.splice(i, 1);
2689
- break
2690
- }
2644
+ } else if (typeof val === 'number') {
2645
+ ret = new Array(val);
2646
+ for (i = 0; i < val; i++) {
2647
+ ret[i] = render(i + 1, i);
2691
2648
  }
2692
- return vm
2693
- };
2694
-
2695
- Vue.prototype.$emit = function (event) {
2696
- const vm = this;
2697
- {
2698
- const lowerCaseEvent = event.toLowerCase();
2699
- if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
2700
- tip(
2701
- `Event "${lowerCaseEvent}" is emitted in component ` +
2702
- `${formatComponentName(vm)} but the handler is registered for "${event}". ` +
2703
- `Note that HTML attributes are case-insensitive and you cannot use ` +
2704
- `v-on to listen to camelCase events when using in-DOM templates. ` +
2705
- `You should probably use "${hyphenate(event)}" instead of "${event}".`
2706
- );
2649
+ } else if (isObject(val)) {
2650
+ if (hasSymbol && val[Symbol.iterator]) {
2651
+ ret = [];
2652
+ const iterator = val[Symbol.iterator]();
2653
+ let result = iterator.next();
2654
+ while (!result.done) {
2655
+ ret.push(render(result.value, ret.length));
2656
+ result = iterator.next();
2707
2657
  }
2708
- }
2709
- let cbs = vm._events[event];
2710
- if (cbs) {
2711
- cbs = cbs.length > 1 ? toArray(cbs) : cbs;
2712
- const args = toArray(arguments, 1);
2713
- const info = `event handler for "${event}"`;
2714
- for (let i = 0, l = cbs.length; i < l; i++) {
2715
- invokeWithErrorHandling(cbs[i], vm, args, vm, info);
2658
+ } else {
2659
+ keys = Object.keys(val);
2660
+ ret = new Array(keys.length);
2661
+ for (i = 0, l = keys.length; i < l; i++) {
2662
+ key = keys[i];
2663
+ ret[i] = render(val[key], key, i);
2716
2664
  }
2717
2665
  }
2718
- return vm
2719
- };
2666
+ }
2667
+ if (!isDef(ret)) {
2668
+ ret = [];
2669
+ }
2670
+ (ret)._isVList = true;
2671
+ return ret
2720
2672
  }
2721
2673
 
2722
2674
  /* */
2723
2675
 
2724
-
2725
-
2726
2676
  /**
2727
- * Runtime helper for resolving raw children VNodes into a slot object.
2677
+ * Runtime helper for rendering <slot>
2728
2678
  */
2729
- function resolveSlots (
2730
- children,
2731
- context
2679
+ function renderSlot (
2680
+ name,
2681
+ fallback,
2682
+ props,
2683
+ bindObject
2732
2684
  ) {
2733
- if (!children || !children.length) {
2734
- return {}
2735
- }
2736
- const slots = {};
2737
- for (let i = 0, l = children.length; i < l; i++) {
2738
- const child = children[i];
2739
- const data = child.data;
2740
- // remove slot attribute if the node is resolved as a Vue slot node
2741
- if (data && data.attrs && data.attrs.slot) {
2742
- delete data.attrs.slot;
2743
- }
2744
- // named slots should only be respected if the vnode was rendered in the
2745
- // same context.
2746
- if ((child.context === context || child.fnContext === context) &&
2747
- data && data.slot != null
2748
- ) {
2749
- const name = data.slot;
2750
- const slot = (slots[name] || (slots[name] = []));
2751
- if (child.tag === 'template') {
2752
- slot.push.apply(slot, child.children || []);
2753
- } else {
2754
- slot.push(child);
2685
+ const scopedSlotFn = this.$scopedSlots[name];
2686
+ let nodes;
2687
+ if (scopedSlotFn) { // scoped slot
2688
+ props = props || {};
2689
+ if (bindObject) {
2690
+ if (!isObject(bindObject)) {
2691
+ warn(
2692
+ 'slot v-bind without argument expects an Object',
2693
+ this
2694
+ );
2755
2695
  }
2756
- } else {
2757
- (slots.default || (slots.default = [])).push(child);
2696
+ props = extend(extend({}, bindObject), props);
2758
2697
  }
2698
+ nodes = scopedSlotFn(props) || fallback;
2699
+ } else {
2700
+ nodes = this.$slots[name] || fallback;
2759
2701
  }
2760
- // ignore slots that contains only whitespace
2761
- for (const name in slots) {
2762
- if (slots[name].every(isWhitespace)) {
2763
- delete slots[name];
2764
- }
2702
+
2703
+ const target = props && props.slot;
2704
+ if (target) {
2705
+ return this.$createElement('template', { slot: target }, nodes)
2706
+ } else {
2707
+ return nodes
2765
2708
  }
2766
- return slots
2767
2709
  }
2768
2710
 
2769
- function isWhitespace (node) {
2770
- return (node.isComment && !node.asyncFactory) || node.text === ' '
2771
- }
2711
+ /* */
2772
2712
 
2773
- function resolveScopedSlots (
2774
- fns, // see flow/vnode
2775
- hasDynamicKeys,
2776
- res
2777
- ) {
2778
- res = res || { $stable: !hasDynamicKeys };
2779
- for (let i = 0; i < fns.length; i++) {
2780
- const slot = fns[i];
2781
- if (Array.isArray(slot)) {
2782
- resolveScopedSlots(slot, hasDynamicKeys, res);
2783
- } else if (slot) {
2784
- res[slot.key] = slot.fn;
2785
- }
2786
- }
2787
- return res
2713
+ /**
2714
+ * Runtime helper for resolving filters
2715
+ */
2716
+ function resolveFilter (id) {
2717
+ return resolveAsset(this.$options, 'filters', id, true) || identity
2788
2718
  }
2789
2719
 
2790
2720
  /* */
2791
2721
 
2792
- let activeInstance = null;
2793
- let isUpdatingChildComponent = false;
2794
-
2795
- function setActiveInstance(vm) {
2796
- const prevActiveInstance = activeInstance;
2797
- activeInstance = vm;
2798
- return () => {
2799
- activeInstance = prevActiveInstance;
2722
+ function isKeyNotMatch (expect, actual) {
2723
+ if (Array.isArray(expect)) {
2724
+ return expect.indexOf(actual) === -1
2725
+ } else {
2726
+ return expect !== actual
2800
2727
  }
2801
2728
  }
2802
2729
 
2803
- function initLifecycle (vm) {
2804
- const options = vm.$options;
2805
-
2806
- // locate first non-abstract parent
2807
- let parent = options.parent;
2808
- if (parent && !options.abstract) {
2809
- while (parent.$options.abstract && parent.$parent) {
2810
- parent = parent.$parent;
2811
- }
2812
- parent.$children.push(vm);
2730
+ /**
2731
+ * Runtime helper for checking keyCodes from config.
2732
+ * exposed as Vue.prototype._k
2733
+ * passing in eventKeyName as last argument separately for backwards compat
2734
+ */
2735
+ function checkKeyCodes (
2736
+ eventKeyCode,
2737
+ key,
2738
+ builtInKeyCode,
2739
+ eventKeyName,
2740
+ builtInKeyName
2741
+ ) {
2742
+ const mappedKeyCode = config.keyCodes[key] || builtInKeyCode;
2743
+ if (builtInKeyName && eventKeyName && !config.keyCodes[key]) {
2744
+ return isKeyNotMatch(builtInKeyName, eventKeyName)
2745
+ } else if (mappedKeyCode) {
2746
+ return isKeyNotMatch(mappedKeyCode, eventKeyCode)
2747
+ } else if (eventKeyName) {
2748
+ return hyphenate(eventKeyName) !== key
2813
2749
  }
2750
+ }
2814
2751
 
2815
- vm.$parent = parent;
2816
- vm.$root = parent ? parent.$root : vm;
2752
+ /* */
2817
2753
 
2818
- vm.$children = [];
2819
- vm.$refs = {};
2754
+ /**
2755
+ * Runtime helper for merging v-bind="object" into a VNode's data.
2756
+ */
2757
+ function bindObjectProps (
2758
+ data,
2759
+ tag,
2760
+ value,
2761
+ asProp,
2762
+ isSync
2763
+ ) {
2764
+ if (value) {
2765
+ if (!isObject(value)) {
2766
+ warn(
2767
+ 'v-bind without argument expects an Object or Array value',
2768
+ this
2769
+ );
2770
+ } else {
2771
+ if (Array.isArray(value)) {
2772
+ value = toObject(value);
2773
+ }
2774
+ let hash;
2775
+ for (const key in value) {
2776
+ if (
2777
+ key === 'class' ||
2778
+ key === 'style' ||
2779
+ isReservedAttribute(key)
2780
+ ) {
2781
+ hash = data;
2782
+ } else {
2783
+ const type = data.attrs && data.attrs.type;
2784
+ hash = asProp || config.mustUseProp(tag, type, key)
2785
+ ? data.domProps || (data.domProps = {})
2786
+ : data.attrs || (data.attrs = {});
2787
+ }
2788
+ const camelizedKey = camelize(key);
2789
+ if (!(key in hash) && !(camelizedKey in hash)) {
2790
+ hash[key] = value[key];
2820
2791
 
2821
- vm._watcher = null;
2822
- vm._inactive = null;
2823
- vm._directInactive = false;
2824
- vm._isMounted = false;
2825
- vm._isDestroyed = false;
2826
- vm._isBeingDestroyed = false;
2792
+ if (isSync) {
2793
+ const on = data.on || (data.on = {});
2794
+ on[`update:${camelizedKey}`] = function ($event) {
2795
+ value[key] = $event;
2796
+ };
2797
+ }
2798
+ }
2799
+ }
2800
+ }
2801
+ }
2802
+ return data
2827
2803
  }
2828
2804
 
2829
- function lifecycleMixin (Vue) {
2830
- Vue.prototype._update = function (vnode, hydrating) {
2831
- const vm = this;
2832
- const prevEl = vm.$el;
2833
- const prevVnode = vm._vnode;
2834
- const restoreActiveInstance = setActiveInstance(vm);
2835
- vm._vnode = vnode;
2836
- // Vue.prototype.__patch__ is injected in entry points
2837
- // based on the rendering backend used.
2838
- if (!prevVnode) {
2839
- // initial render
2840
- vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */);
2841
- } else {
2842
- // updates
2843
- vm.$el = vm.__patch__(prevVnode, vnode);
2844
- }
2845
- restoreActiveInstance();
2846
- // update __vue__ reference
2847
- if (prevEl) {
2848
- prevEl.__vue__ = null;
2849
- }
2850
- if (vm.$el) {
2851
- vm.$el.__vue__ = vm;
2852
- }
2853
- // if parent is an HOC, update its $el as well
2854
- if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
2855
- vm.$parent.$el = vm.$el;
2856
- }
2857
- // updated hook is called by the scheduler to ensure that children are
2858
- // updated in a parent's updated hook.
2859
- };
2805
+ /* */
2860
2806
 
2861
- Vue.prototype.$forceUpdate = function () {
2862
- const vm = this;
2863
- if (vm._watcher) {
2864
- vm._watcher.update();
2865
- }
2866
- };
2807
+ /**
2808
+ * Runtime helper for rendering static trees.
2809
+ */
2810
+ function renderStatic (
2811
+ index,
2812
+ isInFor
2813
+ ) {
2814
+ const cached = this._staticTrees || (this._staticTrees = []);
2815
+ let tree = cached[index];
2816
+ // if has already-rendered static tree and not inside v-for,
2817
+ // we can reuse the same tree.
2818
+ if (tree && !isInFor) {
2819
+ return tree
2820
+ }
2821
+ // otherwise, render a fresh tree.
2822
+ tree = cached[index] = this.$options.staticRenderFns[index].call(
2823
+ this._renderProxy,
2824
+ null,
2825
+ this // for render fns generated for functional component templates
2826
+ );
2827
+ markStatic(tree, `__static__${index}`, false);
2828
+ return tree
2829
+ }
2867
2830
 
2868
- Vue.prototype.$destroy = function () {
2869
- const vm = this;
2870
- if (vm._isBeingDestroyed) {
2871
- return
2872
- }
2873
- callHook(vm, 'beforeDestroy');
2874
- vm._isBeingDestroyed = true;
2875
- // remove self from parent
2876
- const parent = vm.$parent;
2877
- if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
2878
- remove(parent.$children, vm);
2879
- }
2880
- // teardown watchers
2881
- if (vm._watcher) {
2882
- vm._watcher.teardown();
2883
- }
2884
- let i = vm._watchers.length;
2885
- while (i--) {
2886
- vm._watchers[i].teardown();
2887
- }
2888
- // remove reference from data ob
2889
- // frozen object may not have observer.
2890
- if (vm._data.__ob__) {
2891
- vm._data.__ob__.vmCount--;
2892
- }
2893
- // call the last hook...
2894
- vm._isDestroyed = true;
2895
- // invoke destroy hooks on current rendered tree
2896
- vm.__patch__(vm._vnode, null);
2897
- // fire destroyed hook
2898
- callHook(vm, 'destroyed');
2899
- // turn off all instance listeners.
2900
- vm.$off();
2901
- // remove __vue__ reference
2902
- if (vm.$el) {
2903
- vm.$el.__vue__ = null;
2904
- }
2905
- // release circular reference (#6759)
2906
- if (vm.$vnode) {
2907
- vm.$vnode.parent = null;
2908
- }
2909
- };
2831
+ /**
2832
+ * Runtime helper for v-once.
2833
+ * Effectively it means marking the node as static with a unique key.
2834
+ */
2835
+ function markOnce (
2836
+ tree,
2837
+ index,
2838
+ key
2839
+ ) {
2840
+ markStatic(tree, `__once__${index}${key ? `_${key}` : ``}`, true);
2841
+ return tree
2910
2842
  }
2911
2843
 
2912
- function mountComponent (
2913
- vm,
2914
- el,
2915
- hydrating
2844
+ function markStatic (
2845
+ tree,
2846
+ key,
2847
+ isOnce
2916
2848
  ) {
2917
- vm.$el = el;
2918
- if (!vm.$options.render) {
2919
- vm.$options.render = createEmptyVNode;
2920
- {
2921
- /* istanbul ignore if */
2922
- if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||
2923
- vm.$options.el || el) {
2924
- warn(
2925
- 'You are using the runtime-only build of Vue where the template ' +
2926
- 'compiler is not available. Either pre-compile the templates into ' +
2927
- 'render functions, or use the compiler-included build.',
2928
- vm
2929
- );
2930
- } else {
2931
- warn(
2932
- 'Failed to mount component: template or render function not defined.',
2933
- vm
2934
- );
2849
+ if (Array.isArray(tree)) {
2850
+ for (let i = 0; i < tree.length; i++) {
2851
+ if (tree[i] && typeof tree[i] !== 'string') {
2852
+ markStaticNode(tree[i], `${key}_${i}`, isOnce);
2935
2853
  }
2936
2854
  }
2855
+ } else {
2856
+ markStaticNode(tree, key, isOnce);
2937
2857
  }
2938
- callHook(vm, 'beforeMount');
2858
+ }
2939
2859
 
2940
- let updateComponent;
2941
- /* istanbul ignore if */
2942
- if (config.performance && mark) {
2943
- updateComponent = () => {
2944
- const name = vm._name;
2945
- const id = vm._uid;
2946
- const startTag = `vue-perf-start:${id}`;
2947
- const endTag = `vue-perf-end:${id}`;
2860
+ function markStaticNode (node, key, isOnce) {
2861
+ node.isStatic = true;
2862
+ node.key = key;
2863
+ node.isOnce = isOnce;
2864
+ }
2948
2865
 
2949
- mark(startTag);
2950
- const vnode = vm._render();
2951
- mark(endTag);
2952
- measure(`vue ${name} render`, startTag, endTag);
2866
+ /* */
2953
2867
 
2954
- mark(startTag);
2955
- vm._update(vnode, hydrating);
2956
- mark(endTag);
2957
- measure(`vue ${name} patch`, startTag, endTag);
2958
- };
2959
- } else {
2960
- updateComponent = () => {
2961
- vm._update(vm._render(), hydrating);
2962
- };
2868
+ function bindObjectListeners (data, value) {
2869
+ if (value) {
2870
+ if (!isPlainObject(value)) {
2871
+ warn(
2872
+ 'v-on without argument expects an Object value',
2873
+ this
2874
+ );
2875
+ } else {
2876
+ const on = data.on = data.on ? extend({}, data.on) : {};
2877
+ for (const key in value) {
2878
+ const existing = on[key];
2879
+ const ours = value[key];
2880
+ on[key] = existing ? [].concat(existing, ours) : ours;
2881
+ }
2882
+ }
2963
2883
  }
2884
+ return data
2885
+ }
2964
2886
 
2965
- // we set this to vm._watcher inside the watcher's constructor
2966
- // since the watcher's initial patch may call $forceUpdate (e.g. inside child
2967
- // component's mounted hook), which relies on vm._watcher being already defined
2968
- new Watcher(vm, updateComponent, noop, {
2969
- before () {
2970
- if (vm._isMounted && !vm._isDestroyed) {
2971
- callHook(vm, 'beforeUpdate');
2887
+ /* */
2888
+
2889
+ function resolveScopedSlots (
2890
+ fns, // see flow/vnode
2891
+ hasDynamicKeys,
2892
+ res
2893
+ ) {
2894
+ res = res || { $stable: !hasDynamicKeys };
2895
+ for (let i = 0; i < fns.length; i++) {
2896
+ const slot = fns[i];
2897
+ if (Array.isArray(slot)) {
2898
+ resolveScopedSlots(slot, hasDynamicKeys, res);
2899
+ } else if (slot) {
2900
+ // marker for reverse proxying v-slot without scope on this.$slots
2901
+ if (slot.proxy) {
2902
+ slot.fn.proxy = true;
2972
2903
  }
2904
+ res[slot.key] = slot.fn;
2973
2905
  }
2974
- }, true /* isRenderWatcher */);
2975
- hydrating = false;
2906
+ }
2907
+ return res
2908
+ }
2976
2909
 
2977
- // manually mounted instance, call mounted on self
2978
- // mounted is called for render-created child components in its inserted hook
2979
- if (vm.$vnode == null) {
2980
- vm._isMounted = true;
2981
- callHook(vm, 'mounted');
2910
+ /* */
2911
+
2912
+ function bindDynamicKeys (baseObj, values) {
2913
+ for (let i = 0; i < values.length; i += 2) {
2914
+ const key = values[i];
2915
+ if (typeof key === 'string' && key) {
2916
+ baseObj[values[i]] = values[i + 1];
2917
+ } else if (key !== '' && key !== null) {
2918
+ // null is a speical value for explicitly removing a binding
2919
+ warn(
2920
+ `Invalid value for dynamic directive argument (expected string or null): ${key}`,
2921
+ this
2922
+ );
2923
+ }
2982
2924
  }
2983
- return vm
2925
+ return baseObj
2984
2926
  }
2985
2927
 
2986
- function updateChildComponent (
2987
- vm,
2988
- propsData,
2989
- listeners,
2990
- parentVnode,
2991
- renderChildren
2928
+ // helper to dynamically append modifier runtime markers to event names.
2929
+ // ensure only append when value is already string, otherwise it will be cast
2930
+ // to string and cause the type check to miss.
2931
+ function prependModifier (value, symbol) {
2932
+ return typeof value === 'string' ? symbol + value : value
2933
+ }
2934
+
2935
+ /* */
2936
+
2937
+ function installRenderHelpers (target) {
2938
+ target._o = markOnce;
2939
+ target._n = toNumber;
2940
+ target._s = toString;
2941
+ target._l = renderList;
2942
+ target._t = renderSlot;
2943
+ target._q = looseEqual;
2944
+ target._i = looseIndexOf;
2945
+ target._m = renderStatic;
2946
+ target._f = resolveFilter;
2947
+ target._k = checkKeyCodes;
2948
+ target._b = bindObjectProps;
2949
+ target._v = createTextVNode;
2950
+ target._e = createEmptyVNode;
2951
+ target._u = resolveScopedSlots;
2952
+ target._g = bindObjectListeners;
2953
+ target._d = bindDynamicKeys;
2954
+ target._p = prependModifier;
2955
+ }
2956
+
2957
+ /* */
2958
+
2959
+ function FunctionalRenderContext (
2960
+ data,
2961
+ props,
2962
+ children,
2963
+ parent,
2964
+ Ctor
2992
2965
  ) {
2993
- {
2994
- isUpdatingChildComponent = true;
2966
+ const options = Ctor.options;
2967
+ // ensure the createElement function in functional components
2968
+ // gets a unique context - this is necessary for correct named slot check
2969
+ let contextVm;
2970
+ if (hasOwn(parent, '_uid')) {
2971
+ contextVm = Object.create(parent);
2972
+ // $flow-disable-line
2973
+ contextVm._original = parent;
2974
+ } else {
2975
+ // the context vm passed in is a functional context as well.
2976
+ // in this case we want to make sure we are able to get a hold to the
2977
+ // real context instance.
2978
+ contextVm = parent;
2979
+ // $flow-disable-line
2980
+ parent = parent._original;
2995
2981
  }
2982
+ const isCompiled = isTrue(options._compiled);
2983
+ const needNormalization = !isCompiled;
2996
2984
 
2997
- // determine whether component has slot children
2998
- // we need to do this before overwriting $options._renderChildren.
2985
+ this.data = data;
2986
+ this.props = props;
2987
+ this.children = children;
2988
+ this.parent = parent;
2989
+ this.listeners = data.on || emptyObject;
2990
+ this.injections = resolveInject(options.inject, parent);
2991
+ this.slots = () => {
2992
+ if (!this.$slots) {
2993
+ normalizeScopedSlots(
2994
+ data.scopedSlots,
2995
+ this.$slots = resolveSlots(children, parent)
2996
+ );
2997
+ }
2998
+ return this.$slots
2999
+ };
2999
3000
 
3000
- // check if there are dynamic scopedSlots (hand-written or compiled but with
3001
- // dynamic slot names). Static scoped slots compiled from template has the
3002
- // "$stable" marker.
3003
- const hasDynamicScopedSlot = !!(
3004
- (parentVnode.data.scopedSlots && !parentVnode.data.scopedSlots.$stable) ||
3005
- (vm.$scopedSlots !== emptyObject && !vm.$scopedSlots.$stable)
3006
- );
3007
- // Any static slot children from the parent may have changed during parent's
3008
- // update. Dynamic scoped slots may also have changed. In such cases, a forced
3009
- // update is necessary to ensure correctness.
3010
- const needsForceUpdate = !!(
3011
- renderChildren || // has new static slots
3012
- vm.$options._renderChildren || // has old static slots
3013
- hasDynamicScopedSlot
3014
- );
3001
+ Object.defineProperty(this, 'scopedSlots', ({
3002
+ enumerable: true,
3003
+ get () {
3004
+ return normalizeScopedSlots(data.scopedSlots, this.slots())
3005
+ }
3006
+ }));
3015
3007
 
3016
- vm.$options._parentVnode = parentVnode;
3017
- vm.$vnode = parentVnode; // update vm's placeholder node without re-render
3008
+ // support for compiled functional template
3009
+ if (isCompiled) {
3010
+ // exposing $options for renderStatic()
3011
+ this.$options = options;
3012
+ // pre-resolve slots for renderSlot()
3013
+ this.$slots = this.slots();
3014
+ this.$scopedSlots = normalizeScopedSlots(data.scopedSlots, this.$slots);
3015
+ }
3018
3016
 
3019
- if (vm._vnode) { // update child tree's parent
3020
- vm._vnode.parent = parentVnode;
3017
+ if (options._scopeId) {
3018
+ this._c = (a, b, c, d) => {
3019
+ const vnode = createElement(contextVm, a, b, c, d, needNormalization);
3020
+ if (vnode && !Array.isArray(vnode)) {
3021
+ vnode.fnScopeId = options._scopeId;
3022
+ vnode.fnContext = parent;
3023
+ }
3024
+ return vnode
3025
+ };
3026
+ } else {
3027
+ this._c = (a, b, c, d) => createElement(contextVm, a, b, c, d, needNormalization);
3021
3028
  }
3022
- vm.$options._renderChildren = renderChildren;
3029
+ }
3023
3030
 
3024
- // update $attrs and $listeners hash
3025
- // these are also reactive so they may trigger child update if the child
3026
- // used them during render
3027
- vm.$attrs = parentVnode.data.attrs || emptyObject;
3028
- vm.$listeners = listeners || emptyObject;
3031
+ installRenderHelpers(FunctionalRenderContext.prototype);
3029
3032
 
3030
- // update props
3031
- if (propsData && vm.$options.props) {
3032
- toggleObserving(false);
3033
- const props = vm._props;
3034
- const propKeys = vm.$options._propKeys || [];
3035
- for (let i = 0; i < propKeys.length; i++) {
3036
- const key = propKeys[i];
3037
- const propOptions = vm.$options.props; // wtf flow?
3038
- props[key] = validateProp(key, propOptions, propsData, vm);
3033
+ function createFunctionalComponent (
3034
+ Ctor,
3035
+ propsData,
3036
+ data,
3037
+ contextVm,
3038
+ children
3039
+ ) {
3040
+ const options = Ctor.options;
3041
+ const props = {};
3042
+ const propOptions = options.props;
3043
+ if (isDef(propOptions)) {
3044
+ for (const key in propOptions) {
3045
+ props[key] = validateProp(key, propOptions, propsData || emptyObject);
3039
3046
  }
3040
- toggleObserving(true);
3041
- // keep a copy of raw propsData
3042
- vm.$options.propsData = propsData;
3047
+ } else {
3048
+ if (isDef(data.attrs)) mergeProps(props, data.attrs);
3049
+ if (isDef(data.props)) mergeProps(props, data.props);
3043
3050
  }
3044
3051
 
3045
- // update listeners
3046
- listeners = listeners || emptyObject;
3047
- const oldListeners = vm.$options._parentListeners;
3048
- vm.$options._parentListeners = listeners;
3049
- updateComponentListeners(vm, listeners, oldListeners);
3052
+ const renderContext = new FunctionalRenderContext(
3053
+ data,
3054
+ props,
3055
+ children,
3056
+ contextVm,
3057
+ Ctor
3058
+ );
3050
3059
 
3051
- // resolve slots + force update if has children
3052
- if (needsForceUpdate) {
3053
- vm.$slots = resolveSlots(renderChildren, parentVnode.context);
3054
- vm.$forceUpdate();
3060
+ const vnode = options.render.call(null, renderContext._c, renderContext);
3061
+
3062
+ if (vnode instanceof VNode) {
3063
+ return cloneAndMarkFunctionalResult(vnode, data, renderContext.parent, options, renderContext)
3064
+ } else if (Array.isArray(vnode)) {
3065
+ const vnodes = normalizeChildren(vnode) || [];
3066
+ const res = new Array(vnodes.length);
3067
+ for (let i = 0; i < vnodes.length; i++) {
3068
+ res[i] = cloneAndMarkFunctionalResult(vnodes[i], data, renderContext.parent, options, renderContext);
3069
+ }
3070
+ return res
3055
3071
  }
3072
+ }
3056
3073
 
3074
+ function cloneAndMarkFunctionalResult (vnode, data, contextVm, options, renderContext) {
3075
+ // #7817 clone node before setting fnContext, otherwise if the node is reused
3076
+ // (e.g. it was from a cached normal slot) the fnContext causes named slots
3077
+ // that should not be matched to match.
3078
+ const clone = cloneVNode(vnode);
3079
+ clone.fnContext = contextVm;
3080
+ clone.fnOptions = options;
3057
3081
  {
3058
- isUpdatingChildComponent = false;
3082
+ (clone.devtoolsMeta = clone.devtoolsMeta || {}).renderContext = renderContext;
3059
3083
  }
3084
+ if (data.slot) {
3085
+ (clone.data || (clone.data = {})).slot = data.slot;
3086
+ }
3087
+ return clone
3060
3088
  }
3061
3089
 
3062
- function isInInactiveTree (vm) {
3063
- while (vm && (vm = vm.$parent)) {
3064
- if (vm._inactive) return true
3090
+ function mergeProps (to, from) {
3091
+ for (const key in from) {
3092
+ to[camelize(key)] = from[key];
3065
3093
  }
3066
- return false
3067
3094
  }
3068
3095
 
3069
- function activateChildComponent (vm, direct) {
3070
- if (direct) {
3071
- vm._directInactive = false;
3072
- if (isInInactiveTree(vm)) {
3073
- return
3074
- }
3075
- } else if (vm._directInactive) {
3076
- return
3077
- }
3078
- if (vm._inactive || vm._inactive === null) {
3079
- vm._inactive = false;
3080
- for (let i = 0; i < vm.$children.length; i++) {
3081
- activateChildComponent(vm.$children[i]);
3096
+ /* */
3097
+
3098
+ /* */
3099
+
3100
+ /* */
3101
+
3102
+ /* */
3103
+
3104
+ // inline hooks to be invoked on component VNodes during patch
3105
+ const componentVNodeHooks = {
3106
+ init (vnode, hydrating) {
3107
+ if (
3108
+ vnode.componentInstance &&
3109
+ !vnode.componentInstance._isDestroyed &&
3110
+ vnode.data.keepAlive
3111
+ ) {
3112
+ // kept-alive components, treat as a patch
3113
+ const mountedNode = vnode; // work around flow
3114
+ componentVNodeHooks.prepatch(mountedNode, mountedNode);
3115
+ } else {
3116
+ const child = vnode.componentInstance = createComponentInstanceForVnode(
3117
+ vnode,
3118
+ activeInstance
3119
+ );
3120
+ child.$mount(hydrating ? vnode.elm : undefined, hydrating);
3082
3121
  }
3083
- callHook(vm, 'activated');
3084
- }
3085
- }
3122
+ },
3086
3123
 
3087
- function deactivateChildComponent (vm, direct) {
3088
- if (direct) {
3089
- vm._directInactive = true;
3090
- if (isInInactiveTree(vm)) {
3091
- return
3124
+ prepatch (oldVnode, vnode) {
3125
+ const options = vnode.componentOptions;
3126
+ const child = vnode.componentInstance = oldVnode.componentInstance;
3127
+ updateChildComponent(
3128
+ child,
3129
+ options.propsData, // updated props
3130
+ options.listeners, // updated listeners
3131
+ vnode, // new parent vnode
3132
+ options.children // new children
3133
+ );
3134
+ },
3135
+
3136
+ insert (vnode) {
3137
+ const { context, componentInstance } = vnode;
3138
+ if (!componentInstance._isMounted) {
3139
+ componentInstance._isMounted = true;
3140
+ callHook(componentInstance, 'mounted');
3092
3141
  }
3093
- }
3094
- if (!vm._inactive) {
3095
- vm._inactive = true;
3096
- for (let i = 0; i < vm.$children.length; i++) {
3097
- deactivateChildComponent(vm.$children[i]);
3142
+ if (vnode.data.keepAlive) {
3143
+ if (context._isMounted) {
3144
+ // vue-router#1212
3145
+ // During updates, a kept-alive component's child components may
3146
+ // change, so directly walking the tree here may call activated hooks
3147
+ // on incorrect children. Instead we push them into a queue which will
3148
+ // be processed after the whole patch process ended.
3149
+ queueActivatedComponent(componentInstance);
3150
+ } else {
3151
+ activateChildComponent(componentInstance, true /* direct */);
3152
+ }
3098
3153
  }
3099
- callHook(vm, 'deactivated');
3100
- }
3101
- }
3154
+ },
3102
3155
 
3103
- function callHook (vm, hook) {
3104
- // #7573 disable dep collection when invoking lifecycle hooks
3105
- pushTarget();
3106
- const handlers = vm.$options[hook];
3107
- const info = `${hook} hook`;
3108
- if (handlers) {
3109
- for (let i = 0, j = handlers.length; i < j; i++) {
3110
- invokeWithErrorHandling(handlers[i], vm, null, vm, info);
3156
+ destroy (vnode) {
3157
+ const { componentInstance } = vnode;
3158
+ if (!componentInstance._isDestroyed) {
3159
+ if (!vnode.data.keepAlive) {
3160
+ componentInstance.$destroy();
3161
+ } else {
3162
+ deactivateChildComponent(componentInstance, true /* direct */);
3163
+ }
3111
3164
  }
3112
3165
  }
3113
- if (vm._hasHookEvent) {
3114
- vm.$emit('hook:' + hook);
3166
+ };
3167
+
3168
+ const hooksToMerge = Object.keys(componentVNodeHooks);
3169
+
3170
+ function createComponent (
3171
+ Ctor,
3172
+ data,
3173
+ context,
3174
+ children,
3175
+ tag
3176
+ ) {
3177
+ if (isUndef(Ctor)) {
3178
+ return
3115
3179
  }
3116
- popTarget();
3117
- }
3118
3180
 
3119
- /* */
3181
+ const baseCtor = context.$options._base;
3120
3182
 
3121
- const MAX_UPDATE_COUNT = 100;
3183
+ // plain options object: turn it into a constructor
3184
+ if (isObject(Ctor)) {
3185
+ Ctor = baseCtor.extend(Ctor);
3186
+ }
3122
3187
 
3123
- const queue = [];
3124
- const activatedChildren = [];
3125
- let has = {};
3126
- let circular = {};
3127
- let waiting = false;
3128
- let flushing = false;
3129
- let index = 0;
3188
+ // if at this stage it's not a constructor or an async component factory,
3189
+ // reject.
3190
+ if (typeof Ctor !== 'function') {
3191
+ {
3192
+ warn(`Invalid Component definition: ${String(Ctor)}`, context);
3193
+ }
3194
+ return
3195
+ }
3130
3196
 
3131
- /**
3132
- * Reset the scheduler's state.
3133
- */
3134
- function resetSchedulerState () {
3135
- index = queue.length = activatedChildren.length = 0;
3136
- has = {};
3137
- {
3138
- circular = {};
3197
+ // async component
3198
+ let asyncFactory;
3199
+ if (isUndef(Ctor.cid)) {
3200
+ asyncFactory = Ctor;
3201
+ Ctor = resolveAsyncComponent(asyncFactory, baseCtor);
3202
+ if (Ctor === undefined) {
3203
+ // return a placeholder node for async component, which is rendered
3204
+ // as a comment node but preserves all the raw information for the node.
3205
+ // the information will be used for async server-rendering and hydration.
3206
+ return createAsyncPlaceholder(
3207
+ asyncFactory,
3208
+ data,
3209
+ context,
3210
+ children,
3211
+ tag
3212
+ )
3213
+ }
3139
3214
  }
3140
- waiting = flushing = false;
3141
- }
3142
3215
 
3143
- // Async edge case #6566 requires saving the timestamp when event listeners are
3144
- // attached. However, calling performance.now() has a perf overhead especially
3145
- // if the page has thousands of event listeners. Instead, we take a timestamp
3146
- // every time the scheduler flushes and use that for all event listeners
3147
- // attached during that flush.
3148
- let currentFlushTimestamp = 0;
3216
+ data = data || {};
3149
3217
 
3150
- // Async edge case fix requires storing an event listener's attach timestamp.
3151
- let getNow = Date.now;
3218
+ // resolve constructor options in case global mixins are applied after
3219
+ // component constructor creation
3220
+ resolveConstructorOptions(Ctor);
3152
3221
 
3153
- // Determine what event timestamp the browser is using. Annoyingly, the
3154
- // timestamp can either be hi-res ( relative to poge load) or low-res
3155
- // (relative to UNIX epoch), so in order to compare time we have to use the
3156
- // same timestamp type when saving the flush timestamp.
3157
- if (inBrowser && getNow() > document.createEvent('Event').timeStamp) {
3158
- // if the low-res timestamp which is bigger than the event timestamp
3159
- // (which is evaluated AFTER) it means the event is using a hi-res timestamp,
3160
- // and we need to use the hi-res version for event listeners as well.
3161
- getNow = () => performance.now();
3162
- }
3222
+ // transform component v-model data into props & events
3223
+ if (isDef(data.model)) {
3224
+ transformModel(Ctor.options, data);
3225
+ }
3163
3226
 
3164
- /**
3165
- * Flush both queues and run the watchers.
3166
- */
3167
- function flushSchedulerQueue () {
3168
- currentFlushTimestamp = getNow();
3169
- flushing = true;
3170
- let watcher, id;
3227
+ // extract props
3228
+ const propsData = extractPropsFromVNodeData(data, Ctor, tag);
3171
3229
 
3172
- // Sort queue before flush.
3173
- // This ensures that:
3174
- // 1. Components are updated from parent to child. (because parent is always
3175
- // created before the child)
3176
- // 2. A component's user watchers are run before its render watcher (because
3177
- // user watchers are created before the render watcher)
3178
- // 3. If a component is destroyed during a parent component's watcher run,
3179
- // its watchers can be skipped.
3180
- queue.sort((a, b) => a.id - b.id);
3230
+ // functional component
3231
+ if (isTrue(Ctor.options.functional)) {
3232
+ return createFunctionalComponent(Ctor, propsData, data, context, children)
3233
+ }
3181
3234
 
3182
- // do not cache length because more watchers might be pushed
3183
- // as we run existing watchers
3184
- for (index = 0; index < queue.length; index++) {
3185
- watcher = queue[index];
3186
- if (watcher.before) {
3187
- watcher.before();
3188
- }
3189
- id = watcher.id;
3190
- has[id] = null;
3191
- watcher.run();
3192
- // in dev build, check and stop circular updates.
3193
- if (has[id] != null) {
3194
- circular[id] = (circular[id] || 0) + 1;
3195
- if (circular[id] > MAX_UPDATE_COUNT) {
3196
- warn(
3197
- 'You may have an infinite update loop ' + (
3198
- watcher.user
3199
- ? `in watcher with expression "${watcher.expression}"`
3200
- : `in a component render function.`
3201
- ),
3202
- watcher.vm
3203
- );
3204
- break
3205
- }
3235
+ // extract listeners, since these needs to be treated as
3236
+ // child component listeners instead of DOM listeners
3237
+ const listeners = data.on;
3238
+ // replace with listeners with .native modifier
3239
+ // so it gets processed during parent component patch.
3240
+ data.on = data.nativeOn;
3241
+
3242
+ if (isTrue(Ctor.options.abstract)) {
3243
+ // abstract components do not keep anything
3244
+ // other than props & listeners & slot
3245
+
3246
+ // work around flow
3247
+ const slot = data.slot;
3248
+ data = {};
3249
+ if (slot) {
3250
+ data.slot = slot;
3206
3251
  }
3207
3252
  }
3208
3253
 
3209
- // keep copies of post queues before resetting state
3210
- const activatedQueue = activatedChildren.slice();
3211
- const updatedQueue = queue.slice();
3254
+ // install component management hooks onto the placeholder node
3255
+ installComponentHooks(data);
3212
3256
 
3213
- resetSchedulerState();
3257
+ // return a placeholder vnode
3258
+ const name = Ctor.options.name || tag;
3259
+ const vnode = new VNode(
3260
+ `vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
3261
+ data, undefined, undefined, undefined, context,
3262
+ { Ctor, propsData, listeners, tag, children },
3263
+ asyncFactory
3264
+ );
3214
3265
 
3215
- // call component updated and activated hooks
3216
- callActivatedHooks(activatedQueue);
3217
- callUpdatedHooks(updatedQueue);
3266
+ return vnode
3267
+ }
3218
3268
 
3219
- // devtool hook
3220
- /* istanbul ignore if */
3221
- if (devtools && config.devtools) {
3222
- devtools.emit('flush');
3269
+ function createComponentInstanceForVnode (
3270
+ vnode, // we know it's MountedComponentVNode but flow doesn't
3271
+ parent, // activeInstance in lifecycle state
3272
+ ) {
3273
+ const options = {
3274
+ _isComponent: true,
3275
+ _parentVnode: vnode,
3276
+ parent
3277
+ };
3278
+ // check inline-template render functions
3279
+ const inlineTemplate = vnode.data.inlineTemplate;
3280
+ if (isDef(inlineTemplate)) {
3281
+ options.render = inlineTemplate.render;
3282
+ options.staticRenderFns = inlineTemplate.staticRenderFns;
3223
3283
  }
3284
+ return new vnode.componentOptions.Ctor(options)
3224
3285
  }
3225
3286
 
3226
- function callUpdatedHooks (queue) {
3227
- let i = queue.length;
3228
- while (i--) {
3229
- const watcher = queue[i];
3230
- const vm = watcher.vm;
3231
- if (vm._watcher === watcher && vm._isMounted && !vm._isDestroyed) {
3232
- callHook(vm, 'updated');
3287
+ function installComponentHooks (data) {
3288
+ const hooks = data.hook || (data.hook = {});
3289
+ for (let i = 0; i < hooksToMerge.length; i++) {
3290
+ const key = hooksToMerge[i];
3291
+ const existing = hooks[key];
3292
+ const toMerge = componentVNodeHooks[key];
3293
+ if (existing !== toMerge && !(existing && existing._merged)) {
3294
+ hooks[key] = existing ? mergeHook$1(toMerge, existing) : toMerge;
3233
3295
  }
3234
3296
  }
3235
3297
  }
3236
3298
 
3237
- /**
3238
- * Queue a kept-alive component that was activated during patch.
3239
- * The queue will be processed after the entire tree has been patched.
3240
- */
3241
- function queueActivatedComponent (vm) {
3242
- // setting _inactive to false here so that a render function can
3243
- // rely on checking whether it's in an inactive tree (e.g. router-view)
3244
- vm._inactive = false;
3245
- activatedChildren.push(vm);
3246
- }
3247
-
3248
- function callActivatedHooks (queue) {
3249
- for (let i = 0; i < queue.length; i++) {
3250
- queue[i]._inactive = true;
3251
- activateChildComponent(queue[i], true /* true */);
3252
- }
3299
+ function mergeHook$1 (f1, f2) {
3300
+ const merged = (a, b) => {
3301
+ // flow complains about extra args which is why we use any
3302
+ f1(a, b);
3303
+ f2(a, b);
3304
+ };
3305
+ merged._merged = true;
3306
+ return merged
3253
3307
  }
3254
3308
 
3255
- /**
3256
- * Push a watcher into the watcher queue.
3257
- * Jobs with duplicate IDs will be skipped unless it's
3258
- * pushed when the queue is being flushed.
3259
- */
3260
- function queueWatcher (watcher) {
3261
- const id = watcher.id;
3262
- if (has[id] == null) {
3263
- has[id] = true;
3264
- if (!flushing) {
3265
- queue.push(watcher);
3266
- } else {
3267
- // if already flushing, splice the watcher based on its id
3268
- // if already past its id, it will be run next immediately.
3269
- let i = queue.length - 1;
3270
- while (i > index && queue[i].id > watcher.id) {
3271
- i--;
3272
- }
3273
- queue.splice(i + 1, 0, watcher);
3274
- }
3275
- // queue the flush
3276
- if (!waiting) {
3277
- waiting = true;
3278
-
3279
- if (!config.async) {
3280
- flushSchedulerQueue();
3281
- return
3282
- }
3283
- nextTick(flushSchedulerQueue);
3309
+ // transform component v-model info (value and callback) into
3310
+ // prop and event handler respectively.
3311
+ function transformModel (options, data) {
3312
+ const prop = (options.model && options.model.prop) || 'value';
3313
+ const event = (options.model && options.model.event) || 'input'
3314
+ ;(data.attrs || (data.attrs = {}))[prop] = data.model.value;
3315
+ const on = data.on || (data.on = {});
3316
+ const existing = on[event];
3317
+ const callback = data.model.callback;
3318
+ if (isDef(existing)) {
3319
+ if (
3320
+ Array.isArray(existing)
3321
+ ? existing.indexOf(callback) === -1
3322
+ : existing !== callback
3323
+ ) {
3324
+ on[event] = [callback].concat(existing);
3284
3325
  }
3326
+ } else {
3327
+ on[event] = callback;
3285
3328
  }
3286
3329
  }
3287
3330
 
3288
3331
  /* */
3289
3332
 
3333
+ const SIMPLE_NORMALIZE = 1;
3334
+ const ALWAYS_NORMALIZE = 2;
3290
3335
 
3336
+ // wrapper function for providing a more flexible interface
3337
+ // without getting yelled at by flow
3338
+ function createElement (
3339
+ context,
3340
+ tag,
3341
+ data,
3342
+ children,
3343
+ normalizationType,
3344
+ alwaysNormalize
3345
+ ) {
3346
+ if (Array.isArray(data) || isPrimitive(data)) {
3347
+ normalizationType = children;
3348
+ children = data;
3349
+ data = undefined;
3350
+ }
3351
+ if (isTrue(alwaysNormalize)) {
3352
+ normalizationType = ALWAYS_NORMALIZE;
3353
+ }
3354
+ return _createElement(context, tag, data, children, normalizationType)
3355
+ }
3291
3356
 
3292
- let uid$1 = 0;
3293
-
3294
- /**
3295
- * A watcher parses an expression, collects dependencies,
3296
- * and fires callback when the expression value changes.
3297
- * This is used for both the $watch() api and directives.
3298
- */
3299
- class Watcher {
3300
-
3301
-
3302
-
3303
-
3304
-
3305
-
3306
-
3307
-
3308
-
3309
-
3310
-
3311
-
3312
-
3313
-
3314
-
3315
-
3316
-
3317
-
3318
- constructor (
3319
- vm,
3320
- expOrFn,
3321
- cb,
3322
- options,
3323
- isRenderWatcher
3357
+ function _createElement (
3358
+ context,
3359
+ tag,
3360
+ data,
3361
+ children,
3362
+ normalizationType
3363
+ ) {
3364
+ if (isDef(data) && isDef((data).__ob__)) {
3365
+ warn(
3366
+ `Avoid using observed data object as vnode data: ${JSON.stringify(data)}\n` +
3367
+ 'Always create fresh vnode data objects in each render!',
3368
+ context
3369
+ );
3370
+ return createEmptyVNode()
3371
+ }
3372
+ // object syntax in v-bind
3373
+ if (isDef(data) && isDef(data.is)) {
3374
+ tag = data.is;
3375
+ }
3376
+ if (!tag) {
3377
+ // in case of component :is set to falsy value
3378
+ return createEmptyVNode()
3379
+ }
3380
+ // warn against non-primitive key
3381
+ if (isDef(data) && isDef(data.key) && !isPrimitive(data.key)
3324
3382
  ) {
3325
- this.vm = vm;
3326
- if (isRenderWatcher) {
3327
- vm._watcher = this;
3328
- }
3329
- vm._watchers.push(this);
3330
- // options
3331
- if (options) {
3332
- this.deep = !!options.deep;
3333
- this.user = !!options.user;
3334
- this.lazy = !!options.lazy;
3335
- this.sync = !!options.sync;
3336
- this.before = options.before;
3337
- } else {
3338
- this.deep = this.user = this.lazy = this.sync = false;
3383
+ {
3384
+ warn(
3385
+ 'Avoid using non-primitive value as key, ' +
3386
+ 'use string/number value instead.',
3387
+ context
3388
+ );
3339
3389
  }
3340
- this.cb = cb;
3341
- this.id = ++uid$1; // uid for batching
3342
- this.active = true;
3343
- this.dirty = this.lazy; // for lazy watchers
3344
- this.deps = [];
3345
- this.newDeps = [];
3346
- this.depIds = new _Set();
3347
- this.newDepIds = new _Set();
3348
- this.expression = expOrFn.toString();
3349
- // parse expression for getter
3350
- if (typeof expOrFn === 'function') {
3351
- this.getter = expOrFn;
3390
+ }
3391
+ // support single function children as default scoped slot
3392
+ if (Array.isArray(children) &&
3393
+ typeof children[0] === 'function'
3394
+ ) {
3395
+ data = data || {};
3396
+ data.scopedSlots = { default: children[0] };
3397
+ children.length = 0;
3398
+ }
3399
+ if (normalizationType === ALWAYS_NORMALIZE) {
3400
+ children = normalizeChildren(children);
3401
+ } else if (normalizationType === SIMPLE_NORMALIZE) {
3402
+ children = simpleNormalizeChildren(children);
3403
+ }
3404
+ let vnode, ns;
3405
+ if (typeof tag === 'string') {
3406
+ let Ctor;
3407
+ ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag);
3408
+ if (config.isReservedTag(tag)) {
3409
+ // platform built-in elements
3410
+ vnode = new VNode(
3411
+ config.parsePlatformTagName(tag), data, children,
3412
+ undefined, undefined, context
3413
+ );
3414
+ } else if ((!data || !data.pre) && isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {
3415
+ // component
3416
+ vnode = createComponent(Ctor, data, context, children, tag);
3352
3417
  } else {
3353
- this.getter = parsePath(expOrFn);
3354
- if (!this.getter) {
3355
- this.getter = noop;
3356
- warn(
3357
- `Failed watching path: "${expOrFn}" ` +
3358
- 'Watcher only accepts simple dot-delimited paths. ' +
3359
- 'For full control, use a function instead.',
3360
- vm
3361
- );
3362
- }
3418
+ // unknown or unlisted namespaced elements
3419
+ // check at runtime because it may get assigned a namespace when its
3420
+ // parent normalizes children
3421
+ vnode = new VNode(
3422
+ tag, data, children,
3423
+ undefined, undefined, context
3424
+ );
3363
3425
  }
3364
- this.value = this.lazy
3365
- ? undefined
3366
- : this.get();
3426
+ } else {
3427
+ // direct component options / constructor
3428
+ vnode = createComponent(tag, data, context, children);
3367
3429
  }
3368
-
3369
- /**
3370
- * Evaluate the getter, and re-collect dependencies.
3371
- */
3372
- get () {
3373
- pushTarget(this);
3374
- let value;
3375
- const vm = this.vm;
3376
- try {
3377
- value = this.getter.call(vm, vm);
3378
- } catch (e) {
3379
- if (this.user) {
3380
- handleError(e, vm, `getter for watcher "${this.expression}"`);
3381
- } else {
3382
- throw e
3383
- }
3384
- } finally {
3385
- // "touch" every property so they are all tracked as
3386
- // dependencies for deep watching
3387
- if (this.deep) {
3388
- traverse(value);
3389
- }
3390
- popTarget();
3391
- this.cleanupDeps();
3392
- }
3393
- return value
3430
+ if (Array.isArray(vnode)) {
3431
+ return vnode
3432
+ } else if (isDef(vnode)) {
3433
+ if (isDef(ns)) applyNS(vnode, ns);
3434
+ if (isDef(data)) registerDeepBindings(data);
3435
+ return vnode
3436
+ } else {
3437
+ return createEmptyVNode()
3394
3438
  }
3439
+ }
3395
3440
 
3396
- /**
3397
- * Add a dependency to this directive.
3398
- */
3399
- addDep (dep) {
3400
- const id = dep.id;
3401
- if (!this.newDepIds.has(id)) {
3402
- this.newDepIds.add(id);
3403
- this.newDeps.push(dep);
3404
- if (!this.depIds.has(id)) {
3405
- dep.addSub(this);
3406
- }
3407
- }
3441
+ function applyNS (vnode, ns, force) {
3442
+ vnode.ns = ns;
3443
+ if (vnode.tag === 'foreignObject') {
3444
+ // use default namespace inside foreignObject
3445
+ ns = undefined;
3446
+ force = true;
3408
3447
  }
3409
-
3410
- /**
3411
- * Clean up for dependency collection.
3412
- */
3413
- cleanupDeps () {
3414
- let i = this.deps.length;
3415
- while (i--) {
3416
- const dep = this.deps[i];
3417
- if (!this.newDepIds.has(dep.id)) {
3418
- dep.removeSub(this);
3448
+ if (isDef(vnode.children)) {
3449
+ for (let i = 0, l = vnode.children.length; i < l; i++) {
3450
+ const child = vnode.children[i];
3451
+ if (isDef(child.tag) && (
3452
+ isUndef(child.ns) || (isTrue(force) && child.tag !== 'svg'))) {
3453
+ applyNS(child, ns, force);
3419
3454
  }
3420
3455
  }
3421
- let tmp = this.depIds;
3422
- this.depIds = this.newDepIds;
3423
- this.newDepIds = tmp;
3424
- this.newDepIds.clear();
3425
- tmp = this.deps;
3426
- this.deps = this.newDeps;
3427
- this.newDeps = tmp;
3428
- this.newDeps.length = 0;
3429
3456
  }
3457
+ }
3430
3458
 
3431
- /**
3432
- * Subscriber interface.
3433
- * Will be called when a dependency changes.
3434
- */
3435
- update () {
3436
- /* istanbul ignore else */
3437
- if (this.lazy) {
3438
- this.dirty = true;
3439
- } else if (this.sync) {
3440
- this.run();
3441
- } else {
3442
- queueWatcher(this);
3443
- }
3459
+ // ref #5318
3460
+ // necessary to ensure parent re-render when deep bindings like :style and
3461
+ // :class are used on slot nodes
3462
+ function registerDeepBindings (data) {
3463
+ if (isObject(data.style)) {
3464
+ traverse(data.style);
3444
3465
  }
3445
-
3446
- /**
3447
- * Scheduler job interface.
3448
- * Will be called by the scheduler.
3449
- */
3450
- run () {
3451
- if (this.active) {
3452
- const value = this.get();
3453
- if (
3454
- value !== this.value ||
3455
- // Deep watchers and watchers on Object/Arrays should fire even
3456
- // when the value is the same, because the value may
3457
- // have mutated.
3458
- isObject(value) ||
3459
- this.deep
3460
- ) {
3461
- // set new value
3462
- const oldValue = this.value;
3463
- this.value = value;
3464
- if (this.user) {
3465
- try {
3466
- this.cb.call(this.vm, value, oldValue);
3467
- } catch (e) {
3468
- handleError(e, this.vm, `callback for watcher "${this.expression}"`);
3469
- }
3470
- } else {
3471
- this.cb.call(this.vm, value, oldValue);
3472
- }
3473
- }
3474
- }
3466
+ if (isObject(data.class)) {
3467
+ traverse(data.class);
3475
3468
  }
3469
+ }
3476
3470
 
3477
- /**
3478
- * Evaluate the value of the watcher.
3479
- * This only gets called for lazy watchers.
3480
- */
3481
- evaluate () {
3482
- this.value = this.get();
3483
- this.dirty = false;
3471
+ /* */
3472
+
3473
+ function initRender (vm) {
3474
+ vm._vnode = null; // the root of the child tree
3475
+ vm._staticTrees = null; // v-once cached trees
3476
+ const options = vm.$options;
3477
+ const parentVnode = vm.$vnode = options._parentVnode; // the placeholder node in parent tree
3478
+ const renderContext = parentVnode && parentVnode.context;
3479
+ vm.$slots = resolveSlots(options._renderChildren, renderContext);
3480
+ vm.$scopedSlots = emptyObject;
3481
+ // bind the createElement fn to this instance
3482
+ // so that we get proper render context inside it.
3483
+ // args order: tag, data, children, normalizationType, alwaysNormalize
3484
+ // internal version is used by render functions compiled from templates
3485
+ vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false);
3486
+ // normalization is always applied for the public version, used in
3487
+ // user-written render functions.
3488
+ vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true);
3489
+
3490
+ // $attrs & $listeners are exposed for easier HOC creation.
3491
+ // they need to be reactive so that HOCs using them are always updated
3492
+ const parentData = parentVnode && parentVnode.data;
3493
+
3494
+ /* istanbul ignore else */
3495
+ {
3496
+ defineReactive$$1(vm, '$attrs', parentData && parentData.attrs || emptyObject, () => {
3497
+ !isUpdatingChildComponent && warn(`$attrs is readonly.`, vm);
3498
+ }, true);
3499
+ defineReactive$$1(vm, '$listeners', options._parentListeners || emptyObject, () => {
3500
+ !isUpdatingChildComponent && warn(`$listeners is readonly.`, vm);
3501
+ }, true);
3484
3502
  }
3503
+ }
3485
3504
 
3486
- /**
3487
- * Depend on all deps collected by this watcher.
3488
- */
3489
- depend () {
3490
- let i = this.deps.length;
3491
- while (i--) {
3492
- this.deps[i].depend();
3505
+ let currentRenderingInstance = null;
3506
+
3507
+ function renderMixin (Vue) {
3508
+ // install runtime convenience helpers
3509
+ installRenderHelpers(Vue.prototype);
3510
+
3511
+ Vue.prototype.$nextTick = function (fn) {
3512
+ return nextTick(fn, this)
3513
+ };
3514
+
3515
+ Vue.prototype._render = function () {
3516
+ const vm = this;
3517
+ const { render, _parentVnode } = vm.$options;
3518
+
3519
+ if (_parentVnode) {
3520
+ vm.$scopedSlots = normalizeScopedSlots(
3521
+ _parentVnode.data.scopedSlots,
3522
+ vm.$slots,
3523
+ vm.$scopedSlots
3524
+ );
3493
3525
  }
3494
- }
3495
3526
 
3496
- /**
3497
- * Remove self from all dependencies' subscriber list.
3498
- */
3499
- teardown () {
3500
- if (this.active) {
3501
- // remove self from vm's watcher list
3502
- // this is a somewhat expensive operation so we skip it
3503
- // if the vm is being destroyed.
3504
- if (!this.vm._isBeingDestroyed) {
3505
- remove(this.vm._watchers, this);
3527
+ // set parent vnode. this allows render functions to have access
3528
+ // to the data on the placeholder node.
3529
+ vm.$vnode = _parentVnode;
3530
+ // render self
3531
+ let vnode;
3532
+ try {
3533
+ // There's no need to maintain a stack becaues all render fns are called
3534
+ // separately from one another. Nested component's render fns are called
3535
+ // when parent component is patched.
3536
+ currentRenderingInstance = vm;
3537
+ vnode = render.call(vm._renderProxy, vm.$createElement);
3538
+ } catch (e) {
3539
+ handleError(e, vm, `render`);
3540
+ // return error render result,
3541
+ // or previous vnode to prevent render error causing blank component
3542
+ /* istanbul ignore else */
3543
+ if (vm.$options.renderError) {
3544
+ try {
3545
+ vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e);
3546
+ } catch (e) {
3547
+ handleError(e, vm, `renderError`);
3548
+ vnode = vm._vnode;
3549
+ }
3550
+ } else {
3551
+ vnode = vm._vnode;
3506
3552
  }
3507
- let i = this.deps.length;
3508
- while (i--) {
3509
- this.deps[i].removeSub(this);
3553
+ } finally {
3554
+ currentRenderingInstance = null;
3555
+ }
3556
+ // if the returned array contains only a single node, allow it
3557
+ if (Array.isArray(vnode) && vnode.length === 1) {
3558
+ vnode = vnode[0];
3559
+ }
3560
+ // return empty vnode in case the render function errored out
3561
+ if (!(vnode instanceof VNode)) {
3562
+ if (Array.isArray(vnode)) {
3563
+ warn(
3564
+ 'Multiple root nodes returned from render function. Render function ' +
3565
+ 'should return a single root node.',
3566
+ vm
3567
+ );
3510
3568
  }
3511
- this.active = false;
3569
+ vnode = createEmptyVNode();
3512
3570
  }
3513
- }
3571
+ // set parent
3572
+ vnode.parent = _parentVnode;
3573
+ return vnode
3574
+ };
3514
3575
  }
3515
3576
 
3516
3577
  /* */
3517
3578
 
3518
- const sharedPropertyDefinition = {
3519
- enumerable: true,
3520
- configurable: true,
3521
- get: noop,
3522
- set: noop
3523
- };
3579
+ function ensureCtor (comp, base) {
3580
+ if (
3581
+ comp.__esModule ||
3582
+ (hasSymbol && comp[Symbol.toStringTag] === 'Module')
3583
+ ) {
3584
+ comp = comp.default;
3585
+ }
3586
+ return isObject(comp)
3587
+ ? base.extend(comp)
3588
+ : comp
3589
+ }
3524
3590
 
3525
- function proxy (target, sourceKey, key) {
3526
- sharedPropertyDefinition.get = function proxyGetter () {
3527
- return this[sourceKey][key]
3528
- };
3529
- sharedPropertyDefinition.set = function proxySetter (val) {
3530
- this[sourceKey][key] = val;
3531
- };
3532
- Object.defineProperty(target, key, sharedPropertyDefinition);
3591
+ function createAsyncPlaceholder (
3592
+ factory,
3593
+ data,
3594
+ context,
3595
+ children,
3596
+ tag
3597
+ ) {
3598
+ const node = createEmptyVNode();
3599
+ node.asyncFactory = factory;
3600
+ node.asyncMeta = { data, context, children, tag };
3601
+ return node
3533
3602
  }
3534
3603
 
3535
- function initState (vm) {
3536
- vm._watchers = [];
3537
- const opts = vm.$options;
3538
- if (opts.props) initProps(vm, opts.props);
3539
- if (opts.methods) initMethods(vm, opts.methods);
3540
- if (opts.data) {
3541
- initData(vm);
3542
- } else {
3543
- observe(vm._data = {}, true /* asRootData */);
3604
+ function resolveAsyncComponent (
3605
+ factory,
3606
+ baseCtor
3607
+ ) {
3608
+ if (isTrue(factory.error) && isDef(factory.errorComp)) {
3609
+ return factory.errorComp
3544
3610
  }
3545
- if (opts.computed) initComputed(vm, opts.computed);
3546
- if (opts.watch && opts.watch !== nativeWatch) {
3547
- initWatch(vm, opts.watch);
3611
+
3612
+ if (isDef(factory.resolved)) {
3613
+ return factory.resolved
3548
3614
  }
3549
- }
3550
3615
 
3551
- function initProps (vm, propsOptions) {
3552
- const propsData = vm.$options.propsData || {};
3553
- const props = vm._props = {};
3554
- // cache prop keys so that future props updates can iterate using Array
3555
- // instead of dynamic object key enumeration.
3556
- const keys = vm.$options._propKeys = [];
3557
- const isRoot = !vm.$parent;
3558
- // root instance props should be converted
3559
- if (!isRoot) {
3560
- toggleObserving(false);
3616
+ if (isTrue(factory.loading) && isDef(factory.loadingComp)) {
3617
+ return factory.loadingComp
3561
3618
  }
3562
- for (const key in propsOptions) {
3563
- keys.push(key);
3564
- const value = validateProp(key, propsOptions, propsData, vm);
3565
- /* istanbul ignore else */
3566
- {
3567
- const hyphenatedKey = hyphenate(key);
3568
- if (isReservedAttribute(hyphenatedKey) ||
3569
- config.isReservedAttr(hyphenatedKey)) {
3570
- warn(
3571
- `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`,
3572
- vm
3573
- );
3619
+
3620
+ const owner = currentRenderingInstance;
3621
+ if (isDef(factory.owners)) {
3622
+ // already pending
3623
+ factory.owners.push(owner);
3624
+ } else {
3625
+ const owners = factory.owners = [owner];
3626
+ let sync = true;
3627
+
3628
+ const forceRender = (renderCompleted) => {
3629
+ for (let i = 0, l = owners.length; i < l; i++) {
3630
+ (owners[i]).$forceUpdate();
3574
3631
  }
3575
- defineReactive$$1(props, key, value, () => {
3576
- if (!isRoot && !isUpdatingChildComponent) {
3577
- warn(
3578
- `Avoid mutating a prop directly since the value will be ` +
3579
- `overwritten whenever the parent component re-renders. ` +
3580
- `Instead, use a data or computed property based on the prop's ` +
3581
- `value. Prop being mutated: "${key}"`,
3582
- vm
3583
- );
3584
- }
3585
- });
3586
- }
3587
- // static props are already proxied on the component's prototype
3588
- // during Vue.extend(). We only need to proxy props defined at
3589
- // instantiation here.
3590
- if (!(key in vm)) {
3591
- proxy(vm, `_props`, key);
3592
- }
3593
- }
3594
- toggleObserving(true);
3595
- }
3596
3632
 
3597
- function initData (vm) {
3598
- let data = vm.$options.data;
3599
- data = vm._data = typeof data === 'function'
3600
- ? getData(data, vm)
3601
- : data || {};
3602
- if (!isPlainObject(data)) {
3603
- data = {};
3604
- warn(
3605
- 'data functions should return an object:\n' +
3606
- 'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
3607
- vm
3608
- );
3609
- }
3610
- // proxy data on instance
3611
- const keys = Object.keys(data);
3612
- const props = vm.$options.props;
3613
- const methods = vm.$options.methods;
3614
- let i = keys.length;
3615
- while (i--) {
3616
- const key = keys[i];
3617
- {
3618
- if (methods && hasOwn(methods, key)) {
3619
- warn(
3620
- `Method "${key}" has already been defined as a data property.`,
3621
- vm
3622
- );
3633
+ if (renderCompleted) {
3634
+ owners.length = 0;
3623
3635
  }
3624
- }
3625
- if (props && hasOwn(props, key)) {
3636
+ };
3637
+
3638
+ const resolve = once((res) => {
3639
+ // cache resolved
3640
+ factory.resolved = ensureCtor(res, baseCtor);
3641
+ // invoke callbacks only if this is not a synchronous resolve
3642
+ // (async resolves are shimmed as synchronous during SSR)
3643
+ if (!sync) {
3644
+ forceRender(true);
3645
+ } else {
3646
+ owners.length = 0;
3647
+ }
3648
+ });
3649
+
3650
+ const reject = once(reason => {
3626
3651
  warn(
3627
- `The data property "${key}" is already declared as a prop. ` +
3628
- `Use prop default value instead.`,
3629
- vm
3652
+ `Failed to resolve async component: ${String(factory)}` +
3653
+ (reason ? `\nReason: ${reason}` : '')
3630
3654
  );
3631
- } else if (!isReserved(key)) {
3632
- proxy(vm, `_data`, key);
3633
- }
3634
- }
3635
- // observe data
3636
- observe(data, true /* asRootData */);
3637
- }
3638
-
3639
- function getData (data, vm) {
3640
- // #7573 disable dep collection when invoking data getters
3641
- pushTarget();
3642
- try {
3643
- return data.call(vm, vm)
3644
- } catch (e) {
3645
- handleError(e, vm, `data()`);
3646
- return {}
3647
- } finally {
3648
- popTarget();
3649
- }
3650
- }
3655
+ if (isDef(factory.errorComp)) {
3656
+ factory.error = true;
3657
+ forceRender(true);
3658
+ }
3659
+ });
3651
3660
 
3652
- const computedWatcherOptions = { lazy: true };
3661
+ const res = factory(resolve, reject);
3653
3662
 
3654
- function initComputed (vm, computed) {
3655
- // $flow-disable-line
3656
- const watchers = vm._computedWatchers = Object.create(null);
3657
- // computed properties are just getters during SSR
3658
- const isSSR = isServerRendering();
3663
+ if (isObject(res)) {
3664
+ if (isPromise(res)) {
3665
+ // () => Promise
3666
+ if (isUndef(factory.resolved)) {
3667
+ res.then(resolve, reject);
3668
+ }
3669
+ } else if (isPromise(res.component)) {
3670
+ res.component.then(resolve, reject);
3659
3671
 
3660
- for (const key in computed) {
3661
- const userDef = computed[key];
3662
- const getter = typeof userDef === 'function' ? userDef : userDef.get;
3663
- if (getter == null) {
3664
- warn(
3665
- `Getter is missing for computed property "${key}".`,
3666
- vm
3667
- );
3668
- }
3672
+ if (isDef(res.error)) {
3673
+ factory.errorComp = ensureCtor(res.error, baseCtor);
3674
+ }
3669
3675
 
3670
- if (!isSSR) {
3671
- // create internal watcher for the computed property.
3672
- watchers[key] = new Watcher(
3673
- vm,
3674
- getter || noop,
3675
- noop,
3676
- computedWatcherOptions
3677
- );
3678
- }
3676
+ if (isDef(res.loading)) {
3677
+ factory.loadingComp = ensureCtor(res.loading, baseCtor);
3678
+ if (res.delay === 0) {
3679
+ factory.loading = true;
3680
+ } else {
3681
+ setTimeout(() => {
3682
+ if (isUndef(factory.resolved) && isUndef(factory.error)) {
3683
+ factory.loading = true;
3684
+ forceRender(false);
3685
+ }
3686
+ }, res.delay || 200);
3687
+ }
3688
+ }
3679
3689
 
3680
- // component-defined computed properties are already defined on the
3681
- // component prototype. We only need to define computed properties defined
3682
- // at instantiation here.
3683
- if (!(key in vm)) {
3684
- defineComputed(vm, key, userDef);
3685
- } else {
3686
- if (key in vm.$data) {
3687
- warn(`The computed property "${key}" is already defined in data.`, vm);
3688
- } else if (vm.$options.props && key in vm.$options.props) {
3689
- warn(`The computed property "${key}" is already defined as a prop.`, vm);
3690
+ if (isDef(res.timeout)) {
3691
+ setTimeout(() => {
3692
+ if (isUndef(factory.resolved)) {
3693
+ reject(
3694
+ `timeout (${res.timeout}ms)`
3695
+ );
3696
+ }
3697
+ }, res.timeout);
3698
+ }
3690
3699
  }
3691
3700
  }
3701
+
3702
+ sync = false;
3703
+ // return in case resolved synchronously
3704
+ return factory.loading
3705
+ ? factory.loadingComp
3706
+ : factory.resolved
3692
3707
  }
3693
3708
  }
3694
3709
 
3695
- function defineComputed (
3696
- target,
3697
- key,
3698
- userDef
3699
- ) {
3700
- const shouldCache = !isServerRendering();
3701
- if (typeof userDef === 'function') {
3702
- sharedPropertyDefinition.get = shouldCache
3703
- ? createComputedGetter(key)
3704
- : createGetterInvoker(userDef);
3705
- sharedPropertyDefinition.set = noop;
3706
- } else {
3707
- sharedPropertyDefinition.get = userDef.get
3708
- ? shouldCache && userDef.cache !== false
3709
- ? createComputedGetter(key)
3710
- : createGetterInvoker(userDef.get)
3711
- : noop;
3712
- sharedPropertyDefinition.set = userDef.set || noop;
3713
- }
3714
- if (sharedPropertyDefinition.set === noop) {
3715
- sharedPropertyDefinition.set = function () {
3716
- warn(
3717
- `Computed property "${key}" was assigned to but it has no setter.`,
3718
- this
3719
- );
3720
- };
3721
- }
3722
- Object.defineProperty(target, key, sharedPropertyDefinition);
3710
+ /* */
3711
+
3712
+ function isAsyncPlaceholder (node) {
3713
+ return node.isComment && node.asyncFactory
3723
3714
  }
3724
3715
 
3725
- function createComputedGetter (key) {
3726
- return function computedGetter () {
3727
- const watcher = this._computedWatchers && this._computedWatchers[key];
3728
- if (watcher) {
3729
- if (watcher.dirty) {
3730
- watcher.evaluate();
3731
- }
3732
- if (Dep.target) {
3733
- watcher.depend();
3716
+ /* */
3717
+
3718
+ function getFirstComponentChild (children) {
3719
+ if (Array.isArray(children)) {
3720
+ for (let i = 0; i < children.length; i++) {
3721
+ const c = children[i];
3722
+ if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
3723
+ return c
3734
3724
  }
3735
- return watcher.value
3736
3725
  }
3737
3726
  }
3738
3727
  }
3739
3728
 
3740
- function createGetterInvoker(fn) {
3741
- return function computedGetter () {
3742
- return fn.call(this, this)
3729
+ /* */
3730
+
3731
+ /* */
3732
+
3733
+ function initEvents (vm) {
3734
+ vm._events = Object.create(null);
3735
+ vm._hasHookEvent = false;
3736
+ // init parent attached events
3737
+ const listeners = vm.$options._parentListeners;
3738
+ if (listeners) {
3739
+ updateComponentListeners(vm, listeners);
3743
3740
  }
3744
3741
  }
3745
3742
 
3746
- function initMethods (vm, methods) {
3747
- const props = vm.$options.props;
3748
- for (const key in methods) {
3749
- {
3750
- if (typeof methods[key] !== 'function') {
3751
- warn(
3752
- `Method "${key}" has type "${typeof methods[key]}" in the component definition. ` +
3753
- `Did you reference the function correctly?`,
3754
- vm
3755
- );
3756
- }
3757
- if (props && hasOwn(props, key)) {
3758
- warn(
3759
- `Method "${key}" has already been defined as a prop.`,
3760
- vm
3761
- );
3762
- }
3763
- if ((key in vm) && isReserved(key)) {
3764
- warn(
3765
- `Method "${key}" conflicts with an existing Vue instance method. ` +
3766
- `Avoid defining component methods that start with _ or $.`
3767
- );
3768
- }
3769
- }
3770
- vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm);
3771
- }
3743
+ let target;
3744
+
3745
+ function add (event, fn) {
3746
+ target.$on(event, fn);
3772
3747
  }
3773
3748
 
3774
- function initWatch (vm, watch) {
3775
- for (const key in watch) {
3776
- const handler = watch[key];
3777
- if (Array.isArray(handler)) {
3778
- for (let i = 0; i < handler.length; i++) {
3779
- createWatcher(vm, key, handler[i]);
3780
- }
3781
- } else {
3782
- createWatcher(vm, key, handler);
3749
+ function remove$1 (event, fn) {
3750
+ target.$off(event, fn);
3751
+ }
3752
+
3753
+ function createOnceHandler (event, fn) {
3754
+ const _target = target;
3755
+ return function onceHandler () {
3756
+ const res = fn.apply(null, arguments);
3757
+ if (res !== null) {
3758
+ _target.$off(event, onceHandler);
3783
3759
  }
3784
3760
  }
3785
3761
  }
3786
3762
 
3787
- function createWatcher (
3763
+ function updateComponentListeners (
3788
3764
  vm,
3789
- expOrFn,
3790
- handler,
3791
- options
3765
+ listeners,
3766
+ oldListeners
3792
3767
  ) {
3793
- if (isPlainObject(handler)) {
3794
- options = handler;
3795
- handler = handler.handler;
3796
- }
3797
- if (typeof handler === 'string') {
3798
- handler = vm[handler];
3799
- }
3800
- return vm.$watch(expOrFn, handler, options)
3768
+ target = vm;
3769
+ updateListeners(listeners, oldListeners || {}, add, remove$1, createOnceHandler, vm);
3770
+ target = undefined;
3801
3771
  }
3802
3772
 
3803
- function stateMixin (Vue) {
3804
- // flow somehow has problems with directly declared definition object
3805
- // when using Object.defineProperty, so we have to procedurally build up
3806
- // the object here.
3807
- const dataDef = {};
3808
- dataDef.get = function () { return this._data };
3809
- const propsDef = {};
3810
- propsDef.get = function () { return this._props };
3811
- {
3812
- dataDef.set = function () {
3813
- warn(
3814
- 'Avoid replacing instance root $data. ' +
3815
- 'Use nested data properties instead.',
3816
- this
3817
- );
3818
- };
3819
- propsDef.set = function () {
3820
- warn(`$props is readonly.`, this);
3821
- };
3822
- }
3823
- Object.defineProperty(Vue.prototype, '$data', dataDef);
3824
- Object.defineProperty(Vue.prototype, '$props', propsDef);
3773
+ function eventsMixin (Vue) {
3774
+ const hookRE = /^hook:/;
3775
+ Vue.prototype.$on = function (event, fn) {
3776
+ const vm = this;
3777
+ if (Array.isArray(event)) {
3778
+ for (let i = 0, l = event.length; i < l; i++) {
3779
+ vm.$on(event[i], fn);
3780
+ }
3781
+ } else {
3782
+ (vm._events[event] || (vm._events[event] = [])).push(fn);
3783
+ // optimize hook:event cost by using a boolean flag marked at registration
3784
+ // instead of a hash lookup
3785
+ if (hookRE.test(event)) {
3786
+ vm._hasHookEvent = true;
3787
+ }
3788
+ }
3789
+ return vm
3790
+ };
3825
3791
 
3826
- Vue.prototype.$set = set;
3827
- Vue.prototype.$delete = del;
3792
+ Vue.prototype.$once = function (event, fn) {
3793
+ const vm = this;
3794
+ function on () {
3795
+ vm.$off(event, on);
3796
+ fn.apply(vm, arguments);
3797
+ }
3798
+ on.fn = fn;
3799
+ vm.$on(event, on);
3800
+ return vm
3801
+ };
3828
3802
 
3829
- Vue.prototype.$watch = function (
3830
- expOrFn,
3831
- cb,
3832
- options
3833
- ) {
3803
+ Vue.prototype.$off = function (event, fn) {
3834
3804
  const vm = this;
3835
- if (isPlainObject(cb)) {
3836
- return createWatcher(vm, expOrFn, cb, options)
3805
+ // all
3806
+ if (!arguments.length) {
3807
+ vm._events = Object.create(null);
3808
+ return vm
3837
3809
  }
3838
- options = options || {};
3839
- options.user = true;
3840
- const watcher = new Watcher(vm, expOrFn, cb, options);
3841
- if (options.immediate) {
3842
- try {
3843
- cb.call(vm, watcher.value);
3844
- } catch (error) {
3845
- handleError(error, vm, `callback for immediate watcher "${watcher.expression}"`);
3810
+ // array of events
3811
+ if (Array.isArray(event)) {
3812
+ for (let i = 0, l = event.length; i < l; i++) {
3813
+ vm.$off(event[i], fn);
3814
+ }
3815
+ return vm
3816
+ }
3817
+ // specific event
3818
+ const cbs = vm._events[event];
3819
+ if (!cbs) {
3820
+ return vm
3821
+ }
3822
+ if (!fn) {
3823
+ vm._events[event] = null;
3824
+ return vm
3825
+ }
3826
+ // specific handler
3827
+ let cb;
3828
+ let i = cbs.length;
3829
+ while (i--) {
3830
+ cb = cbs[i];
3831
+ if (cb === fn || cb.fn === fn) {
3832
+ cbs.splice(i, 1);
3833
+ break
3846
3834
  }
3847
3835
  }
3848
- return function unwatchFn () {
3849
- watcher.teardown();
3836
+ return vm
3837
+ };
3838
+
3839
+ Vue.prototype.$emit = function (event) {
3840
+ const vm = this;
3841
+ {
3842
+ const lowerCaseEvent = event.toLowerCase();
3843
+ if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
3844
+ tip(
3845
+ `Event "${lowerCaseEvent}" is emitted in component ` +
3846
+ `${formatComponentName(vm)} but the handler is registered for "${event}". ` +
3847
+ `Note that HTML attributes are case-insensitive and you cannot use ` +
3848
+ `v-on to listen to camelCase events when using in-DOM templates. ` +
3849
+ `You should probably use "${hyphenate(event)}" instead of "${event}".`
3850
+ );
3851
+ }
3852
+ }
3853
+ let cbs = vm._events[event];
3854
+ if (cbs) {
3855
+ cbs = cbs.length > 1 ? toArray(cbs) : cbs;
3856
+ const args = toArray(arguments, 1);
3857
+ const info = `event handler for "${event}"`;
3858
+ for (let i = 0, l = cbs.length; i < l; i++) {
3859
+ invokeWithErrorHandling(cbs[i], vm, args, vm, info);
3860
+ }
3850
3861
  }
3862
+ return vm
3851
3863
  };
3852
3864
  }
3853
3865
 
3854
3866
  /* */
3855
3867
 
3856
- function initProvide (vm) {
3857
- const provide = vm.$options.provide;
3858
- if (provide) {
3859
- vm._provided = typeof provide === 'function'
3860
- ? provide.call(vm)
3861
- : provide;
3862
- }
3863
- }
3868
+ let activeInstance = null;
3869
+ let isUpdatingChildComponent = false;
3864
3870
 
3865
- function initInjections (vm) {
3866
- const result = resolveInject(vm.$options.inject, vm);
3867
- if (result) {
3868
- toggleObserving(false);
3869
- Object.keys(result).forEach(key => {
3870
- /* istanbul ignore else */
3871
- {
3872
- defineReactive$$1(vm, key, result[key], () => {
3873
- warn(
3874
- `Avoid mutating an injected value directly since the changes will be ` +
3875
- `overwritten whenever the provided component re-renders. ` +
3876
- `injection being mutated: "${key}"`,
3877
- vm
3878
- );
3879
- });
3880
- }
3881
- });
3882
- toggleObserving(true);
3871
+ function setActiveInstance(vm) {
3872
+ const prevActiveInstance = activeInstance;
3873
+ activeInstance = vm;
3874
+ return () => {
3875
+ activeInstance = prevActiveInstance;
3883
3876
  }
3884
3877
  }
3885
3878
 
3886
- function resolveInject (inject, vm) {
3887
- if (inject) {
3888
- // inject is :any because flow is not smart enough to figure out cached
3889
- const result = Object.create(null);
3890
- const keys = hasSymbol
3891
- ? Reflect.ownKeys(inject)
3892
- : Object.keys(inject);
3879
+ function initLifecycle (vm) {
3880
+ const options = vm.$options;
3893
3881
 
3894
- for (let i = 0; i < keys.length; i++) {
3895
- const key = keys[i];
3896
- // #6574 in case the inject object is observed...
3897
- if (key === '__ob__') continue
3898
- const provideKey = inject[key].from;
3899
- let source = vm;
3900
- while (source) {
3901
- if (source._provided && hasOwn(source._provided, provideKey)) {
3902
- result[key] = source._provided[provideKey];
3903
- break
3904
- }
3905
- source = source.$parent;
3906
- }
3907
- if (!source) {
3908
- if ('default' in inject[key]) {
3909
- const provideDefault = inject[key].default;
3910
- result[key] = typeof provideDefault === 'function'
3911
- ? provideDefault.call(vm)
3912
- : provideDefault;
3913
- } else {
3914
- warn(`Injection "${key}" not found`, vm);
3915
- }
3916
- }
3882
+ // locate first non-abstract parent
3883
+ let parent = options.parent;
3884
+ if (parent && !options.abstract) {
3885
+ while (parent.$options.abstract && parent.$parent) {
3886
+ parent = parent.$parent;
3917
3887
  }
3918
- return result
3888
+ parent.$children.push(vm);
3919
3889
  }
3920
- }
3921
3890
 
3922
- /* */
3891
+ vm.$parent = parent;
3892
+ vm.$root = parent ? parent.$root : vm;
3923
3893
 
3924
- function normalizeScopedSlots (
3925
- slots,
3926
- normalSlots
3927
- ) {
3928
- let res;
3929
- if (!slots) {
3930
- res = {};
3931
- } else if (slots._normalized) {
3932
- return slots
3933
- } else {
3934
- res = {};
3935
- for (const key in slots) {
3936
- if (slots[key] && key[0] !== '$') {
3937
- res[key] = normalizeScopedSlot(normalSlots, key, slots[key]);
3938
- }
3939
- }
3940
- }
3941
- // expose normal slots on scopedSlots
3942
- for (const key in normalSlots) {
3943
- if (!(key in res)) {
3944
- res[key] = proxyNormalSlot(normalSlots, key);
3945
- }
3946
- }
3947
- res._normalized = true;
3948
- res.$stable = slots ? slots.$stable : true;
3949
- return res
3950
- }
3894
+ vm.$children = [];
3895
+ vm.$refs = {};
3951
3896
 
3952
- function normalizeScopedSlot(normalSlots, key, fn) {
3953
- const normalized = (scope = {}) => {
3954
- const res = fn(scope);
3955
- return res && typeof res === 'object' && !Array.isArray(res)
3956
- ? [res] // single vnode
3957
- : normalizeChildren(res)
3958
- };
3959
- // proxy scoped slots on normal $slots
3960
- if (!hasOwn(normalSlots, key)) {
3961
- Object.defineProperty(normalSlots, key, {
3962
- get: normalized
3963
- });
3964
- }
3965
- return normalized
3897
+ vm._watcher = null;
3898
+ vm._inactive = null;
3899
+ vm._directInactive = false;
3900
+ vm._isMounted = false;
3901
+ vm._isDestroyed = false;
3902
+ vm._isBeingDestroyed = false;
3966
3903
  }
3967
3904
 
3968
- function proxyNormalSlot(slots, key) {
3969
- return () => slots[key]
3970
- }
3905
+ function lifecycleMixin (Vue) {
3906
+ Vue.prototype._update = function (vnode, hydrating) {
3907
+ const vm = this;
3908
+ const prevEl = vm.$el;
3909
+ const prevVnode = vm._vnode;
3910
+ const restoreActiveInstance = setActiveInstance(vm);
3911
+ vm._vnode = vnode;
3912
+ // Vue.prototype.__patch__ is injected in entry points
3913
+ // based on the rendering backend used.
3914
+ if (!prevVnode) {
3915
+ // initial render
3916
+ vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */);
3917
+ } else {
3918
+ // updates
3919
+ vm.$el = vm.__patch__(prevVnode, vnode);
3920
+ }
3921
+ restoreActiveInstance();
3922
+ // update __vue__ reference
3923
+ if (prevEl) {
3924
+ prevEl.__vue__ = null;
3925
+ }
3926
+ if (vm.$el) {
3927
+ vm.$el.__vue__ = vm;
3928
+ }
3929
+ // if parent is an HOC, update its $el as well
3930
+ if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
3931
+ vm.$parent.$el = vm.$el;
3932
+ }
3933
+ // updated hook is called by the scheduler to ensure that children are
3934
+ // updated in a parent's updated hook.
3935
+ };
3971
3936
 
3972
- /* */
3937
+ Vue.prototype.$forceUpdate = function () {
3938
+ const vm = this;
3939
+ if (vm._watcher) {
3940
+ vm._watcher.update();
3941
+ }
3942
+ };
3973
3943
 
3974
- /**
3975
- * Runtime helper for rendering v-for lists.
3976
- */
3977
- function renderList (
3978
- val,
3979
- render
3980
- ) {
3981
- let ret, i, l, keys, key;
3982
- if (Array.isArray(val) || typeof val === 'string') {
3983
- ret = new Array(val.length);
3984
- for (i = 0, l = val.length; i < l; i++) {
3985
- ret[i] = render(val[i], i);
3944
+ Vue.prototype.$destroy = function () {
3945
+ const vm = this;
3946
+ if (vm._isBeingDestroyed) {
3947
+ return
3986
3948
  }
3987
- } else if (typeof val === 'number') {
3988
- ret = new Array(val);
3989
- for (i = 0; i < val; i++) {
3990
- ret[i] = render(i + 1, i);
3949
+ callHook(vm, 'beforeDestroy');
3950
+ vm._isBeingDestroyed = true;
3951
+ // remove self from parent
3952
+ const parent = vm.$parent;
3953
+ if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
3954
+ remove(parent.$children, vm);
3991
3955
  }
3992
- } else if (isObject(val)) {
3993
- if (hasSymbol && val[Symbol.iterator]) {
3994
- ret = [];
3995
- const iterator = val[Symbol.iterator]();
3996
- let result = iterator.next();
3997
- while (!result.done) {
3998
- ret.push(render(result.value, ret.length));
3999
- result = iterator.next();
4000
- }
4001
- } else {
4002
- keys = Object.keys(val);
4003
- ret = new Array(keys.length);
4004
- for (i = 0, l = keys.length; i < l; i++) {
4005
- key = keys[i];
4006
- ret[i] = render(val[key], key, i);
4007
- }
3956
+ // teardown watchers
3957
+ if (vm._watcher) {
3958
+ vm._watcher.teardown();
4008
3959
  }
4009
- }
4010
- if (!isDef(ret)) {
4011
- ret = [];
4012
- }
4013
- (ret)._isVList = true;
4014
- return ret
3960
+ let i = vm._watchers.length;
3961
+ while (i--) {
3962
+ vm._watchers[i].teardown();
3963
+ }
3964
+ // remove reference from data ob
3965
+ // frozen object may not have observer.
3966
+ if (vm._data.__ob__) {
3967
+ vm._data.__ob__.vmCount--;
3968
+ }
3969
+ // call the last hook...
3970
+ vm._isDestroyed = true;
3971
+ // invoke destroy hooks on current rendered tree
3972
+ vm.__patch__(vm._vnode, null);
3973
+ // fire destroyed hook
3974
+ callHook(vm, 'destroyed');
3975
+ // turn off all instance listeners.
3976
+ vm.$off();
3977
+ // remove __vue__ reference
3978
+ if (vm.$el) {
3979
+ vm.$el.__vue__ = null;
3980
+ }
3981
+ // release circular reference (#6759)
3982
+ if (vm.$vnode) {
3983
+ vm.$vnode.parent = null;
3984
+ }
3985
+ };
4015
3986
  }
4016
3987
 
4017
- /* */
4018
-
4019
- /**
4020
- * Runtime helper for rendering <slot>
4021
- */
4022
- function renderSlot (
4023
- name,
4024
- fallback,
4025
- props,
4026
- bindObject
3988
+ function mountComponent (
3989
+ vm,
3990
+ el,
3991
+ hydrating
4027
3992
  ) {
4028
- const scopedSlotFn = this.$scopedSlots[name];
4029
- let nodes;
4030
- if (scopedSlotFn) { // scoped slot
4031
- props = props || {};
4032
- if (bindObject) {
4033
- if (!isObject(bindObject)) {
3993
+ vm.$el = el;
3994
+ if (!vm.$options.render) {
3995
+ vm.$options.render = createEmptyVNode;
3996
+ {
3997
+ /* istanbul ignore if */
3998
+ if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||
3999
+ vm.$options.el || el) {
4034
4000
  warn(
4035
- 'slot v-bind without argument expects an Object',
4036
- this
4001
+ 'You are using the runtime-only build of Vue where the template ' +
4002
+ 'compiler is not available. Either pre-compile the templates into ' +
4003
+ 'render functions, or use the compiler-included build.',
4004
+ vm
4005
+ );
4006
+ } else {
4007
+ warn(
4008
+ 'Failed to mount component: template or render function not defined.',
4009
+ vm
4037
4010
  );
4038
4011
  }
4039
- props = extend(extend({}, bindObject), props);
4040
4012
  }
4041
- nodes = scopedSlotFn(props) || fallback;
4042
- } else {
4043
- nodes = this.$slots[name] || fallback;
4044
4013
  }
4014
+ callHook(vm, 'beforeMount');
4045
4015
 
4046
- const target = props && props.slot;
4047
- if (target) {
4048
- return this.$createElement('template', { slot: target }, nodes)
4049
- } else {
4050
- return nodes
4051
- }
4052
- }
4016
+ let updateComponent;
4017
+ /* istanbul ignore if */
4018
+ if (config.performance && mark) {
4019
+ updateComponent = () => {
4020
+ const name = vm._name;
4021
+ const id = vm._uid;
4022
+ const startTag = `vue-perf-start:${id}`;
4023
+ const endTag = `vue-perf-end:${id}`;
4053
4024
 
4054
- /* */
4025
+ mark(startTag);
4026
+ const vnode = vm._render();
4027
+ mark(endTag);
4028
+ measure(`vue ${name} render`, startTag, endTag);
4055
4029
 
4056
- /**
4057
- * Runtime helper for resolving filters
4058
- */
4059
- function resolveFilter (id) {
4060
- return resolveAsset(this.$options, 'filters', id, true) || identity
4061
- }
4030
+ mark(startTag);
4031
+ vm._update(vnode, hydrating);
4032
+ mark(endTag);
4033
+ measure(`vue ${name} patch`, startTag, endTag);
4034
+ };
4035
+ } else {
4036
+ updateComponent = () => {
4037
+ vm._update(vm._render(), hydrating);
4038
+ };
4039
+ }
4062
4040
 
4063
- /* */
4041
+ // we set this to vm._watcher inside the watcher's constructor
4042
+ // since the watcher's initial patch may call $forceUpdate (e.g. inside child
4043
+ // component's mounted hook), which relies on vm._watcher being already defined
4044
+ new Watcher(vm, updateComponent, noop, {
4045
+ before () {
4046
+ if (vm._isMounted && !vm._isDestroyed) {
4047
+ callHook(vm, 'beforeUpdate');
4048
+ }
4049
+ }
4050
+ }, true /* isRenderWatcher */);
4051
+ hydrating = false;
4064
4052
 
4065
- function isKeyNotMatch (expect, actual) {
4066
- if (Array.isArray(expect)) {
4067
- return expect.indexOf(actual) === -1
4068
- } else {
4069
- return expect !== actual
4053
+ // manually mounted instance, call mounted on self
4054
+ // mounted is called for render-created child components in its inserted hook
4055
+ if (vm.$vnode == null) {
4056
+ vm._isMounted = true;
4057
+ callHook(vm, 'mounted');
4070
4058
  }
4059
+ return vm
4071
4060
  }
4072
4061
 
4073
- /**
4074
- * Runtime helper for checking keyCodes from config.
4075
- * exposed as Vue.prototype._k
4076
- * passing in eventKeyName as last argument separately for backwards compat
4077
- */
4078
- function checkKeyCodes (
4079
- eventKeyCode,
4080
- key,
4081
- builtInKeyCode,
4082
- eventKeyName,
4083
- builtInKeyName
4062
+ function updateChildComponent (
4063
+ vm,
4064
+ propsData,
4065
+ listeners,
4066
+ parentVnode,
4067
+ renderChildren
4084
4068
  ) {
4085
- const mappedKeyCode = config.keyCodes[key] || builtInKeyCode;
4086
- if (builtInKeyName && eventKeyName && !config.keyCodes[key]) {
4087
- return isKeyNotMatch(builtInKeyName, eventKeyName)
4088
- } else if (mappedKeyCode) {
4089
- return isKeyNotMatch(mappedKeyCode, eventKeyCode)
4090
- } else if (eventKeyName) {
4091
- return hyphenate(eventKeyName) !== key
4069
+ {
4070
+ isUpdatingChildComponent = true;
4092
4071
  }
4093
- }
4094
4072
 
4095
- /* */
4073
+ // determine whether component has slot children
4074
+ // we need to do this before overwriting $options._renderChildren.
4096
4075
 
4097
- /**
4098
- * Runtime helper for merging v-bind="object" into a VNode's data.
4099
- */
4100
- function bindObjectProps (
4101
- data,
4102
- tag,
4103
- value,
4104
- asProp,
4105
- isSync
4106
- ) {
4107
- if (value) {
4108
- if (!isObject(value)) {
4109
- warn(
4110
- 'v-bind without argument expects an Object or Array value',
4111
- this
4112
- );
4113
- } else {
4114
- if (Array.isArray(value)) {
4115
- value = toObject(value);
4116
- }
4117
- let hash;
4118
- for (const key in value) {
4119
- if (
4120
- key === 'class' ||
4121
- key === 'style' ||
4122
- isReservedAttribute(key)
4123
- ) {
4124
- hash = data;
4125
- } else {
4126
- const type = data.attrs && data.attrs.type;
4127
- hash = asProp || config.mustUseProp(tag, type, key)
4128
- ? data.domProps || (data.domProps = {})
4129
- : data.attrs || (data.attrs = {});
4130
- }
4131
- const camelizedKey = camelize(key);
4132
- if (!(key in hash) && !(camelizedKey in hash)) {
4133
- hash[key] = value[key];
4076
+ // check if there are dynamic scopedSlots (hand-written or compiled but with
4077
+ // dynamic slot names). Static scoped slots compiled from template has the
4078
+ // "$stable" marker.
4079
+ const hasDynamicScopedSlot = !!(
4080
+ (parentVnode.data.scopedSlots && !parentVnode.data.scopedSlots.$stable) ||
4081
+ (vm.$scopedSlots !== emptyObject && !vm.$scopedSlots.$stable)
4082
+ );
4134
4083
 
4135
- if (isSync) {
4136
- const on = data.on || (data.on = {});
4137
- on[`update:${camelizedKey}`] = function ($event) {
4138
- value[key] = $event;
4139
- };
4140
- }
4141
- }
4142
- }
4143
- }
4084
+ // Any static slot children from the parent may have changed during parent's
4085
+ // update. Dynamic scoped slots may also have changed. In such cases, a forced
4086
+ // update is necessary to ensure correctness.
4087
+ const needsForceUpdate = !!(
4088
+ renderChildren || // has new static slots
4089
+ vm.$options._renderChildren || // has old static slots
4090
+ hasDynamicScopedSlot
4091
+ );
4092
+
4093
+ vm.$options._parentVnode = parentVnode;
4094
+ vm.$vnode = parentVnode; // update vm's placeholder node without re-render
4095
+
4096
+ if (vm._vnode) { // update child tree's parent
4097
+ vm._vnode.parent = parentVnode;
4144
4098
  }
4145
- return data
4146
- }
4099
+ vm.$options._renderChildren = renderChildren;
4147
4100
 
4148
- /* */
4101
+ // update $attrs and $listeners hash
4102
+ // these are also reactive so they may trigger child update if the child
4103
+ // used them during render
4104
+ vm.$attrs = parentVnode.data.attrs || emptyObject;
4105
+ vm.$listeners = listeners || emptyObject;
4149
4106
 
4150
- /**
4151
- * Runtime helper for rendering static trees.
4152
- */
4153
- function renderStatic (
4154
- index,
4155
- isInFor
4156
- ) {
4157
- const cached = this._staticTrees || (this._staticTrees = []);
4158
- let tree = cached[index];
4159
- // if has already-rendered static tree and not inside v-for,
4160
- // we can reuse the same tree.
4161
- if (tree && !isInFor) {
4162
- return tree
4107
+ // update props
4108
+ if (propsData && vm.$options.props) {
4109
+ toggleObserving(false);
4110
+ const props = vm._props;
4111
+ const propKeys = vm.$options._propKeys || [];
4112
+ for (let i = 0; i < propKeys.length; i++) {
4113
+ const key = propKeys[i];
4114
+ const propOptions = vm.$options.props; // wtf flow?
4115
+ props[key] = validateProp(key, propOptions, propsData, vm);
4116
+ }
4117
+ toggleObserving(true);
4118
+ // keep a copy of raw propsData
4119
+ vm.$options.propsData = propsData;
4120
+ }
4121
+
4122
+ // update listeners
4123
+ listeners = listeners || emptyObject;
4124
+ const oldListeners = vm.$options._parentListeners;
4125
+ vm.$options._parentListeners = listeners;
4126
+ updateComponentListeners(vm, listeners, oldListeners);
4127
+
4128
+ // resolve slots + force update if has children
4129
+ if (needsForceUpdate) {
4130
+ vm.$slots = resolveSlots(renderChildren, parentVnode.context);
4131
+ vm.$forceUpdate();
4132
+ }
4133
+
4134
+ {
4135
+ isUpdatingChildComponent = false;
4163
4136
  }
4164
- // otherwise, render a fresh tree.
4165
- tree = cached[index] = this.$options.staticRenderFns[index].call(
4166
- this._renderProxy,
4167
- null,
4168
- this // for render fns generated for functional component templates
4169
- );
4170
- markStatic(tree, `__static__${index}`, false);
4171
- return tree
4172
4137
  }
4173
4138
 
4174
- /**
4175
- * Runtime helper for v-once.
4176
- * Effectively it means marking the node as static with a unique key.
4177
- */
4178
- function markOnce (
4179
- tree,
4180
- index,
4181
- key
4182
- ) {
4183
- markStatic(tree, `__once__${index}${key ? `_${key}` : ``}`, true);
4184
- return tree
4139
+ function isInInactiveTree (vm) {
4140
+ while (vm && (vm = vm.$parent)) {
4141
+ if (vm._inactive) return true
4142
+ }
4143
+ return false
4185
4144
  }
4186
4145
 
4187
- function markStatic (
4188
- tree,
4189
- key,
4190
- isOnce
4191
- ) {
4192
- if (Array.isArray(tree)) {
4193
- for (let i = 0; i < tree.length; i++) {
4194
- if (tree[i] && typeof tree[i] !== 'string') {
4195
- markStaticNode(tree[i], `${key}_${i}`, isOnce);
4196
- }
4146
+ function activateChildComponent (vm, direct) {
4147
+ if (direct) {
4148
+ vm._directInactive = false;
4149
+ if (isInInactiveTree(vm)) {
4150
+ return
4197
4151
  }
4198
- } else {
4199
- markStaticNode(tree, key, isOnce);
4152
+ } else if (vm._directInactive) {
4153
+ return
4154
+ }
4155
+ if (vm._inactive || vm._inactive === null) {
4156
+ vm._inactive = false;
4157
+ for (let i = 0; i < vm.$children.length; i++) {
4158
+ activateChildComponent(vm.$children[i]);
4159
+ }
4160
+ callHook(vm, 'activated');
4200
4161
  }
4201
4162
  }
4202
4163
 
4203
- function markStaticNode (node, key, isOnce) {
4204
- node.isStatic = true;
4205
- node.key = key;
4206
- node.isOnce = isOnce;
4164
+ function deactivateChildComponent (vm, direct) {
4165
+ if (direct) {
4166
+ vm._directInactive = true;
4167
+ if (isInInactiveTree(vm)) {
4168
+ return
4169
+ }
4170
+ }
4171
+ if (!vm._inactive) {
4172
+ vm._inactive = true;
4173
+ for (let i = 0; i < vm.$children.length; i++) {
4174
+ deactivateChildComponent(vm.$children[i]);
4175
+ }
4176
+ callHook(vm, 'deactivated');
4177
+ }
4207
4178
  }
4208
4179
 
4209
- /* */
4210
-
4211
- function bindObjectListeners (data, value) {
4212
- if (value) {
4213
- if (!isPlainObject(value)) {
4214
- warn(
4215
- 'v-on without argument expects an Object value',
4216
- this
4217
- );
4218
- } else {
4219
- const on = data.on = data.on ? extend({}, data.on) : {};
4220
- for (const key in value) {
4221
- const existing = on[key];
4222
- const ours = value[key];
4223
- on[key] = existing ? [].concat(existing, ours) : ours;
4224
- }
4180
+ function callHook (vm, hook) {
4181
+ // #7573 disable dep collection when invoking lifecycle hooks
4182
+ pushTarget();
4183
+ const handlers = vm.$options[hook];
4184
+ const info = `${hook} hook`;
4185
+ if (handlers) {
4186
+ for (let i = 0, j = handlers.length; i < j; i++) {
4187
+ invokeWithErrorHandling(handlers[i], vm, null, vm, info);
4225
4188
  }
4226
4189
  }
4227
- return data
4190
+ if (vm._hasHookEvent) {
4191
+ vm.$emit('hook:' + hook);
4192
+ }
4193
+ popTarget();
4228
4194
  }
4229
4195
 
4230
4196
  /* */
4231
4197
 
4232
- function bindDynamicKeys (baseObj, values) {
4233
- for (let i = 0; i < values.length; i += 2) {
4234
- const key = values[i];
4235
- if (typeof key === 'string' && key) {
4236
- baseObj[values[i]] = values[i + 1];
4237
- } else if (key !== '' && key !== null) {
4238
- // null is a speical value for explicitly removing a binding
4239
- warn(
4240
- `Invalid value for dynamic directive argument (expected string or null): ${key}`,
4241
- this
4242
- );
4243
- }
4198
+ const MAX_UPDATE_COUNT = 100;
4199
+
4200
+ const queue = [];
4201
+ const activatedChildren = [];
4202
+ let has = {};
4203
+ let circular = {};
4204
+ let waiting = false;
4205
+ let flushing = false;
4206
+ let index = 0;
4207
+
4208
+ /**
4209
+ * Reset the scheduler's state.
4210
+ */
4211
+ function resetSchedulerState () {
4212
+ index = queue.length = activatedChildren.length = 0;
4213
+ has = {};
4214
+ {
4215
+ circular = {};
4244
4216
  }
4245
- return baseObj
4217
+ waiting = flushing = false;
4246
4218
  }
4247
4219
 
4248
- // helper to dynamically append modifier runtime markers to event names.
4249
- // ensure only append when value is already string, otherwise it will be cast
4250
- // to string and cause the type check to miss.
4251
- function prependModifier (value, symbol) {
4252
- return typeof value === 'string' ? symbol + value : value
4253
- }
4220
+ // Async edge case #6566 requires saving the timestamp when event listeners are
4221
+ // attached. However, calling performance.now() has a perf overhead especially
4222
+ // if the page has thousands of event listeners. Instead, we take a timestamp
4223
+ // every time the scheduler flushes and use that for all event listeners
4224
+ // attached during that flush.
4225
+ let currentFlushTimestamp = 0;
4254
4226
 
4255
- /* */
4227
+ // Async edge case fix requires storing an event listener's attach timestamp.
4228
+ let getNow = Date.now;
4256
4229
 
4257
- function installRenderHelpers (target) {
4258
- target._o = markOnce;
4259
- target._n = toNumber;
4260
- target._s = toString;
4261
- target._l = renderList;
4262
- target._t = renderSlot;
4263
- target._q = looseEqual;
4264
- target._i = looseIndexOf;
4265
- target._m = renderStatic;
4266
- target._f = resolveFilter;
4267
- target._k = checkKeyCodes;
4268
- target._b = bindObjectProps;
4269
- target._v = createTextVNode;
4270
- target._e = createEmptyVNode;
4271
- target._u = resolveScopedSlots;
4272
- target._g = bindObjectListeners;
4273
- target._d = bindDynamicKeys;
4274
- target._p = prependModifier;
4230
+ // Determine what event timestamp the browser is using. Annoyingly, the
4231
+ // timestamp can either be hi-res (relative to page load) or low-res
4232
+ // (relative to UNIX epoch), so in order to compare time we have to use the
4233
+ // same timestamp type when saving the flush timestamp.
4234
+ if (inBrowser && getNow() > document.createEvent('Event').timeStamp) {
4235
+ // if the low-res timestamp which is bigger than the event timestamp
4236
+ // (which is evaluated AFTER) it means the event is using a hi-res timestamp,
4237
+ // and we need to use the hi-res version for event listeners as well.
4238
+ getNow = () => performance.now();
4275
4239
  }
4276
4240
 
4277
- /* */
4278
-
4279
- function FunctionalRenderContext (
4280
- data,
4281
- props,
4282
- children,
4283
- parent,
4284
- Ctor
4285
- ) {
4286
- const options = Ctor.options;
4287
- // ensure the createElement function in functional components
4288
- // gets a unique context - this is necessary for correct named slot check
4289
- let contextVm;
4290
- if (hasOwn(parent, '_uid')) {
4291
- contextVm = Object.create(parent);
4292
- // $flow-disable-line
4293
- contextVm._original = parent;
4294
- } else {
4295
- // the context vm passed in is a functional context as well.
4296
- // in this case we want to make sure we are able to get a hold to the
4297
- // real context instance.
4298
- contextVm = parent;
4299
- // $flow-disable-line
4300
- parent = parent._original;
4301
- }
4302
- const isCompiled = isTrue(options._compiled);
4303
- const needNormalization = !isCompiled;
4241
+ /**
4242
+ * Flush both queues and run the watchers.
4243
+ */
4244
+ function flushSchedulerQueue () {
4245
+ currentFlushTimestamp = getNow();
4246
+ flushing = true;
4247
+ let watcher, id;
4304
4248
 
4305
- this.data = data;
4306
- this.props = props;
4307
- this.children = children;
4308
- this.parent = parent;
4309
- this.listeners = data.on || emptyObject;
4310
- this.injections = resolveInject(options.inject, parent);
4311
- this.slots = () => resolveSlots(children, parent);
4249
+ // Sort queue before flush.
4250
+ // This ensures that:
4251
+ // 1. Components are updated from parent to child. (because parent is always
4252
+ // created before the child)
4253
+ // 2. A component's user watchers are run before its render watcher (because
4254
+ // user watchers are created before the render watcher)
4255
+ // 3. If a component is destroyed during a parent component's watcher run,
4256
+ // its watchers can be skipped.
4257
+ queue.sort((a, b) => a.id - b.id);
4312
4258
 
4313
- Object.defineProperty(this, 'scopedSlots', ({
4314
- enumerable: true,
4315
- get () {
4316
- return normalizeScopedSlots(data.scopedSlots, this.slots())
4259
+ // do not cache length because more watchers might be pushed
4260
+ // as we run existing watchers
4261
+ for (index = 0; index < queue.length; index++) {
4262
+ watcher = queue[index];
4263
+ if (watcher.before) {
4264
+ watcher.before();
4317
4265
  }
4318
- }));
4319
-
4320
- // support for compiled functional template
4321
- if (isCompiled) {
4322
- // exposing $options for renderStatic()
4323
- this.$options = options;
4324
- // pre-resolve slots for renderSlot()
4325
- this.$slots = this.slots();
4326
- this.$scopedSlots = normalizeScopedSlots(data.scopedSlots, this.$slots);
4327
- }
4328
-
4329
- if (options._scopeId) {
4330
- this._c = (a, b, c, d) => {
4331
- const vnode = createElement(contextVm, a, b, c, d, needNormalization);
4332
- if (vnode && !Array.isArray(vnode)) {
4333
- vnode.fnScopeId = options._scopeId;
4334
- vnode.fnContext = parent;
4266
+ id = watcher.id;
4267
+ has[id] = null;
4268
+ watcher.run();
4269
+ // in dev build, check and stop circular updates.
4270
+ if (has[id] != null) {
4271
+ circular[id] = (circular[id] || 0) + 1;
4272
+ if (circular[id] > MAX_UPDATE_COUNT) {
4273
+ warn(
4274
+ 'You may have an infinite update loop ' + (
4275
+ watcher.user
4276
+ ? `in watcher with expression "${watcher.expression}"`
4277
+ : `in a component render function.`
4278
+ ),
4279
+ watcher.vm
4280
+ );
4281
+ break
4335
4282
  }
4336
- return vnode
4337
- };
4338
- } else {
4339
- this._c = (a, b, c, d) => createElement(contextVm, a, b, c, d, needNormalization);
4283
+ }
4340
4284
  }
4341
- }
4342
4285
 
4343
- installRenderHelpers(FunctionalRenderContext.prototype);
4286
+ // keep copies of post queues before resetting state
4287
+ const activatedQueue = activatedChildren.slice();
4288
+ const updatedQueue = queue.slice();
4344
4289
 
4345
- function createFunctionalComponent (
4346
- Ctor,
4347
- propsData,
4348
- data,
4349
- contextVm,
4350
- children
4351
- ) {
4352
- const options = Ctor.options;
4353
- const props = {};
4354
- const propOptions = options.props;
4355
- if (isDef(propOptions)) {
4356
- for (const key in propOptions) {
4357
- props[key] = validateProp(key, propOptions, propsData || emptyObject);
4358
- }
4359
- } else {
4360
- if (isDef(data.attrs)) mergeProps(props, data.attrs);
4361
- if (isDef(data.props)) mergeProps(props, data.props);
4362
- }
4290
+ resetSchedulerState();
4363
4291
 
4364
- const renderContext = new FunctionalRenderContext(
4365
- data,
4366
- props,
4367
- children,
4368
- contextVm,
4369
- Ctor
4370
- );
4292
+ // call component updated and activated hooks
4293
+ callActivatedHooks(activatedQueue);
4294
+ callUpdatedHooks(updatedQueue);
4371
4295
 
4372
- const vnode = options.render.call(null, renderContext._c, renderContext);
4296
+ // devtool hook
4297
+ /* istanbul ignore if */
4298
+ if (devtools && config.devtools) {
4299
+ devtools.emit('flush');
4300
+ }
4301
+ }
4373
4302
 
4374
- if (vnode instanceof VNode) {
4375
- return cloneAndMarkFunctionalResult(vnode, data, renderContext.parent, options, renderContext)
4376
- } else if (Array.isArray(vnode)) {
4377
- const vnodes = normalizeChildren(vnode) || [];
4378
- const res = new Array(vnodes.length);
4379
- for (let i = 0; i < vnodes.length; i++) {
4380
- res[i] = cloneAndMarkFunctionalResult(vnodes[i], data, renderContext.parent, options, renderContext);
4303
+ function callUpdatedHooks (queue) {
4304
+ let i = queue.length;
4305
+ while (i--) {
4306
+ const watcher = queue[i];
4307
+ const vm = watcher.vm;
4308
+ if (vm._watcher === watcher && vm._isMounted && !vm._isDestroyed) {
4309
+ callHook(vm, 'updated');
4381
4310
  }
4382
- return res
4383
4311
  }
4384
4312
  }
4385
4313
 
4386
- function cloneAndMarkFunctionalResult (vnode, data, contextVm, options, renderContext) {
4387
- // #7817 clone node before setting fnContext, otherwise if the node is reused
4388
- // (e.g. it was from a cached normal slot) the fnContext causes named slots
4389
- // that should not be matched to match.
4390
- const clone = cloneVNode(vnode);
4391
- clone.fnContext = contextVm;
4392
- clone.fnOptions = options;
4393
- {
4394
- (clone.devtoolsMeta = clone.devtoolsMeta || {}).renderContext = renderContext;
4395
- }
4396
- if (data.slot) {
4397
- (clone.data || (clone.data = {})).slot = data.slot;
4398
- }
4399
- return clone
4314
+ /**
4315
+ * Queue a kept-alive component that was activated during patch.
4316
+ * The queue will be processed after the entire tree has been patched.
4317
+ */
4318
+ function queueActivatedComponent (vm) {
4319
+ // setting _inactive to false here so that a render function can
4320
+ // rely on checking whether it's in an inactive tree (e.g. router-view)
4321
+ vm._inactive = false;
4322
+ activatedChildren.push(vm);
4400
4323
  }
4401
4324
 
4402
- function mergeProps (to, from) {
4403
- for (const key in from) {
4404
- to[camelize(key)] = from[key];
4325
+ function callActivatedHooks (queue) {
4326
+ for (let i = 0; i < queue.length; i++) {
4327
+ queue[i]._inactive = true;
4328
+ activateChildComponent(queue[i], true /* true */);
4405
4329
  }
4406
4330
  }
4407
4331
 
4408
- /* */
4332
+ /**
4333
+ * Push a watcher into the watcher queue.
4334
+ * Jobs with duplicate IDs will be skipped unless it's
4335
+ * pushed when the queue is being flushed.
4336
+ */
4337
+ function queueWatcher (watcher) {
4338
+ const id = watcher.id;
4339
+ if (has[id] == null) {
4340
+ has[id] = true;
4341
+ if (!flushing) {
4342
+ queue.push(watcher);
4343
+ } else {
4344
+ // if already flushing, splice the watcher based on its id
4345
+ // if already past its id, it will be run next immediately.
4346
+ let i = queue.length - 1;
4347
+ while (i > index && queue[i].id > watcher.id) {
4348
+ i--;
4349
+ }
4350
+ queue.splice(i + 1, 0, watcher);
4351
+ }
4352
+ // queue the flush
4353
+ if (!waiting) {
4354
+ waiting = true;
4409
4355
 
4410
- /* */
4356
+ if (!config.async) {
4357
+ flushSchedulerQueue();
4358
+ return
4359
+ }
4360
+ nextTick(flushSchedulerQueue);
4361
+ }
4362
+ }
4363
+ }
4411
4364
 
4412
4365
  /* */
4413
4366
 
4414
- /* */
4415
4367
 
4416
- // inline hooks to be invoked on component VNodes during patch
4417
- const componentVNodeHooks = {
4418
- init (vnode, hydrating) {
4419
- if (
4420
- vnode.componentInstance &&
4421
- !vnode.componentInstance._isDestroyed &&
4422
- vnode.data.keepAlive
4423
- ) {
4424
- // kept-alive components, treat as a patch
4425
- const mountedNode = vnode; // work around flow
4426
- componentVNodeHooks.prepatch(mountedNode, mountedNode);
4427
- } else {
4428
- const child = vnode.componentInstance = createComponentInstanceForVnode(
4429
- vnode,
4430
- activeInstance
4431
- );
4432
- child.$mount(hydrating ? vnode.elm : undefined, hydrating);
4433
- }
4434
- },
4435
4368
 
4436
- prepatch (oldVnode, vnode) {
4437
- const options = vnode.componentOptions;
4438
- const child = vnode.componentInstance = oldVnode.componentInstance;
4439
- updateChildComponent(
4440
- child,
4441
- options.propsData, // updated props
4442
- options.listeners, // updated listeners
4443
- vnode, // new parent vnode
4444
- options.children // new children
4445
- );
4446
- },
4369
+ let uid$2 = 0;
4447
4370
 
4448
- insert (vnode) {
4449
- const { context, componentInstance } = vnode;
4450
- if (!componentInstance._isMounted) {
4451
- componentInstance._isMounted = true;
4452
- callHook(componentInstance, 'mounted');
4371
+ /**
4372
+ * A watcher parses an expression, collects dependencies,
4373
+ * and fires callback when the expression value changes.
4374
+ * This is used for both the $watch() api and directives.
4375
+ */
4376
+ class Watcher {
4377
+
4378
+
4379
+
4380
+
4381
+
4382
+
4383
+
4384
+
4385
+
4386
+
4387
+
4388
+
4389
+
4390
+
4391
+
4392
+
4393
+
4394
+
4395
+ constructor (
4396
+ vm,
4397
+ expOrFn,
4398
+ cb,
4399
+ options,
4400
+ isRenderWatcher
4401
+ ) {
4402
+ this.vm = vm;
4403
+ if (isRenderWatcher) {
4404
+ vm._watcher = this;
4453
4405
  }
4454
- if (vnode.data.keepAlive) {
4455
- if (context._isMounted) {
4456
- // vue-router#1212
4457
- // During updates, a kept-alive component's child components may
4458
- // change, so directly walking the tree here may call activated hooks
4459
- // on incorrect children. Instead we push them into a queue which will
4460
- // be processed after the whole patch process ended.
4461
- queueActivatedComponent(componentInstance);
4462
- } else {
4463
- activateChildComponent(componentInstance, true /* direct */);
4406
+ vm._watchers.push(this);
4407
+ // options
4408
+ if (options) {
4409
+ this.deep = !!options.deep;
4410
+ this.user = !!options.user;
4411
+ this.lazy = !!options.lazy;
4412
+ this.sync = !!options.sync;
4413
+ this.before = options.before;
4414
+ } else {
4415
+ this.deep = this.user = this.lazy = this.sync = false;
4416
+ }
4417
+ this.cb = cb;
4418
+ this.id = ++uid$2; // uid for batching
4419
+ this.active = true;
4420
+ this.dirty = this.lazy; // for lazy watchers
4421
+ this.deps = [];
4422
+ this.newDeps = [];
4423
+ this.depIds = new _Set();
4424
+ this.newDepIds = new _Set();
4425
+ this.expression = expOrFn.toString();
4426
+ // parse expression for getter
4427
+ if (typeof expOrFn === 'function') {
4428
+ this.getter = expOrFn;
4429
+ } else {
4430
+ this.getter = parsePath(expOrFn);
4431
+ if (!this.getter) {
4432
+ this.getter = noop;
4433
+ warn(
4434
+ `Failed watching path: "${expOrFn}" ` +
4435
+ 'Watcher only accepts simple dot-delimited paths. ' +
4436
+ 'For full control, use a function instead.',
4437
+ vm
4438
+ );
4464
4439
  }
4465
4440
  }
4466
- },
4441
+ this.value = this.lazy
4442
+ ? undefined
4443
+ : this.get();
4444
+ }
4467
4445
 
4468
- destroy (vnode) {
4469
- const { componentInstance } = vnode;
4470
- if (!componentInstance._isDestroyed) {
4471
- if (!vnode.data.keepAlive) {
4472
- componentInstance.$destroy();
4446
+ /**
4447
+ * Evaluate the getter, and re-collect dependencies.
4448
+ */
4449
+ get () {
4450
+ pushTarget(this);
4451
+ let value;
4452
+ const vm = this.vm;
4453
+ try {
4454
+ value = this.getter.call(vm, vm);
4455
+ } catch (e) {
4456
+ if (this.user) {
4457
+ handleError(e, vm, `getter for watcher "${this.expression}"`);
4473
4458
  } else {
4474
- deactivateChildComponent(componentInstance, true /* direct */);
4459
+ throw e
4460
+ }
4461
+ } finally {
4462
+ // "touch" every property so they are all tracked as
4463
+ // dependencies for deep watching
4464
+ if (this.deep) {
4465
+ traverse(value);
4475
4466
  }
4467
+ popTarget();
4468
+ this.cleanupDeps();
4476
4469
  }
4477
- }
4478
- };
4479
-
4480
- const hooksToMerge = Object.keys(componentVNodeHooks);
4481
-
4482
- function createComponent (
4483
- Ctor,
4484
- data,
4485
- context,
4486
- children,
4487
- tag
4488
- ) {
4489
- if (isUndef(Ctor)) {
4490
- return
4491
- }
4492
-
4493
- const baseCtor = context.$options._base;
4494
-
4495
- // plain options object: turn it into a constructor
4496
- if (isObject(Ctor)) {
4497
- Ctor = baseCtor.extend(Ctor);
4470
+ return value
4498
4471
  }
4499
4472
 
4500
- // if at this stage it's not a constructor or an async component factory,
4501
- // reject.
4502
- if (typeof Ctor !== 'function') {
4503
- {
4504
- warn(`Invalid Component definition: ${String(Ctor)}`, context);
4473
+ /**
4474
+ * Add a dependency to this directive.
4475
+ */
4476
+ addDep (dep) {
4477
+ const id = dep.id;
4478
+ if (!this.newDepIds.has(id)) {
4479
+ this.newDepIds.add(id);
4480
+ this.newDeps.push(dep);
4481
+ if (!this.depIds.has(id)) {
4482
+ dep.addSub(this);
4483
+ }
4505
4484
  }
4506
- return
4507
4485
  }
4508
4486
 
4509
- // async component
4510
- let asyncFactory;
4511
- if (isUndef(Ctor.cid)) {
4512
- asyncFactory = Ctor;
4513
- Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context);
4514
- if (Ctor === undefined) {
4515
- // return a placeholder node for async component, which is rendered
4516
- // as a comment node but preserves all the raw information for the node.
4517
- // the information will be used for async server-rendering and hydration.
4518
- return createAsyncPlaceholder(
4519
- asyncFactory,
4520
- data,
4521
- context,
4522
- children,
4523
- tag
4524
- )
4487
+ /**
4488
+ * Clean up for dependency collection.
4489
+ */
4490
+ cleanupDeps () {
4491
+ let i = this.deps.length;
4492
+ while (i--) {
4493
+ const dep = this.deps[i];
4494
+ if (!this.newDepIds.has(dep.id)) {
4495
+ dep.removeSub(this);
4496
+ }
4525
4497
  }
4498
+ let tmp = this.depIds;
4499
+ this.depIds = this.newDepIds;
4500
+ this.newDepIds = tmp;
4501
+ this.newDepIds.clear();
4502
+ tmp = this.deps;
4503
+ this.deps = this.newDeps;
4504
+ this.newDeps = tmp;
4505
+ this.newDeps.length = 0;
4526
4506
  }
4527
4507
 
4528
- data = data || {};
4529
-
4530
- // resolve constructor options in case global mixins are applied after
4531
- // component constructor creation
4532
- resolveConstructorOptions(Ctor);
4533
-
4534
- // transform component v-model data into props & events
4535
- if (isDef(data.model)) {
4536
- transformModel(Ctor.options, data);
4537
- }
4538
-
4539
- // extract props
4540
- const propsData = extractPropsFromVNodeData(data, Ctor, tag);
4541
-
4542
- // functional component
4543
- if (isTrue(Ctor.options.functional)) {
4544
- return createFunctionalComponent(Ctor, propsData, data, context, children)
4508
+ /**
4509
+ * Subscriber interface.
4510
+ * Will be called when a dependency changes.
4511
+ */
4512
+ update () {
4513
+ /* istanbul ignore else */
4514
+ if (this.lazy) {
4515
+ this.dirty = true;
4516
+ } else if (this.sync) {
4517
+ this.run();
4518
+ } else {
4519
+ queueWatcher(this);
4520
+ }
4545
4521
  }
4546
4522
 
4547
- // extract listeners, since these needs to be treated as
4548
- // child component listeners instead of DOM listeners
4549
- const listeners = data.on;
4550
- // replace with listeners with .native modifier
4551
- // so it gets processed during parent component patch.
4552
- data.on = data.nativeOn;
4553
-
4554
- if (isTrue(Ctor.options.abstract)) {
4555
- // abstract components do not keep anything
4556
- // other than props & listeners & slot
4557
-
4558
- // work around flow
4559
- const slot = data.slot;
4560
- data = {};
4561
- if (slot) {
4562
- data.slot = slot;
4523
+ /**
4524
+ * Scheduler job interface.
4525
+ * Will be called by the scheduler.
4526
+ */
4527
+ run () {
4528
+ if (this.active) {
4529
+ const value = this.get();
4530
+ if (
4531
+ value !== this.value ||
4532
+ // Deep watchers and watchers on Object/Arrays should fire even
4533
+ // when the value is the same, because the value may
4534
+ // have mutated.
4535
+ isObject(value) ||
4536
+ this.deep
4537
+ ) {
4538
+ // set new value
4539
+ const oldValue = this.value;
4540
+ this.value = value;
4541
+ if (this.user) {
4542
+ try {
4543
+ this.cb.call(this.vm, value, oldValue);
4544
+ } catch (e) {
4545
+ handleError(e, this.vm, `callback for watcher "${this.expression}"`);
4546
+ }
4547
+ } else {
4548
+ this.cb.call(this.vm, value, oldValue);
4549
+ }
4550
+ }
4563
4551
  }
4564
4552
  }
4565
4553
 
4566
- // install component management hooks onto the placeholder node
4567
- installComponentHooks(data);
4568
-
4569
- // return a placeholder vnode
4570
- const name = Ctor.options.name || tag;
4571
- const vnode = new VNode(
4572
- `vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
4573
- data, undefined, undefined, undefined, context,
4574
- { Ctor, propsData, listeners, tag, children },
4575
- asyncFactory
4576
- );
4577
-
4578
- return vnode
4579
- }
4580
-
4581
- function createComponentInstanceForVnode (
4582
- vnode, // we know it's MountedComponentVNode but flow doesn't
4583
- parent, // activeInstance in lifecycle state
4584
- ) {
4585
- const options = {
4586
- _isComponent: true,
4587
- _parentVnode: vnode,
4588
- parent
4589
- };
4590
- // check inline-template render functions
4591
- const inlineTemplate = vnode.data.inlineTemplate;
4592
- if (isDef(inlineTemplate)) {
4593
- options.render = inlineTemplate.render;
4594
- options.staticRenderFns = inlineTemplate.staticRenderFns;
4554
+ /**
4555
+ * Evaluate the value of the watcher.
4556
+ * This only gets called for lazy watchers.
4557
+ */
4558
+ evaluate () {
4559
+ this.value = this.get();
4560
+ this.dirty = false;
4595
4561
  }
4596
- return new vnode.componentOptions.Ctor(options)
4597
- }
4598
4562
 
4599
- function installComponentHooks (data) {
4600
- const hooks = data.hook || (data.hook = {});
4601
- for (let i = 0; i < hooksToMerge.length; i++) {
4602
- const key = hooksToMerge[i];
4603
- const existing = hooks[key];
4604
- const toMerge = componentVNodeHooks[key];
4605
- if (existing !== toMerge && !(existing && existing._merged)) {
4606
- hooks[key] = existing ? mergeHook$1(toMerge, existing) : toMerge;
4563
+ /**
4564
+ * Depend on all deps collected by this watcher.
4565
+ */
4566
+ depend () {
4567
+ let i = this.deps.length;
4568
+ while (i--) {
4569
+ this.deps[i].depend();
4607
4570
  }
4608
4571
  }
4609
- }
4610
-
4611
- function mergeHook$1 (f1, f2) {
4612
- const merged = (a, b) => {
4613
- // flow complains about extra args which is why we use any
4614
- f1(a, b);
4615
- f2(a, b);
4616
- };
4617
- merged._merged = true;
4618
- return merged
4619
- }
4620
4572
 
4621
- // transform component v-model info (value and callback) into
4622
- // prop and event handler respectively.
4623
- function transformModel (options, data) {
4624
- const prop = (options.model && options.model.prop) || 'value';
4625
- const event = (options.model && options.model.event) || 'input'
4626
- ;(data.attrs || (data.attrs = {}))[prop] = data.model.value;
4627
- const on = data.on || (data.on = {});
4628
- const existing = on[event];
4629
- const callback = data.model.callback;
4630
- if (isDef(existing)) {
4631
- if (
4632
- Array.isArray(existing)
4633
- ? existing.indexOf(callback) === -1
4634
- : existing !== callback
4635
- ) {
4636
- on[event] = [callback].concat(existing);
4573
+ /**
4574
+ * Remove self from all dependencies' subscriber list.
4575
+ */
4576
+ teardown () {
4577
+ if (this.active) {
4578
+ // remove self from vm's watcher list
4579
+ // this is a somewhat expensive operation so we skip it
4580
+ // if the vm is being destroyed.
4581
+ if (!this.vm._isBeingDestroyed) {
4582
+ remove(this.vm._watchers, this);
4583
+ }
4584
+ let i = this.deps.length;
4585
+ while (i--) {
4586
+ this.deps[i].removeSub(this);
4587
+ }
4588
+ this.active = false;
4637
4589
  }
4638
- } else {
4639
- on[event] = callback;
4640
4590
  }
4641
4591
  }
4642
4592
 
4643
4593
  /* */
4644
4594
 
4645
- const SIMPLE_NORMALIZE = 1;
4646
- const ALWAYS_NORMALIZE = 2;
4595
+ const sharedPropertyDefinition = {
4596
+ enumerable: true,
4597
+ configurable: true,
4598
+ get: noop,
4599
+ set: noop
4600
+ };
4647
4601
 
4648
- // wrapper function for providing a more flexible interface
4649
- // without getting yelled at by flow
4650
- function createElement (
4651
- context,
4652
- tag,
4653
- data,
4654
- children,
4655
- normalizationType,
4656
- alwaysNormalize
4657
- ) {
4658
- if (Array.isArray(data) || isPrimitive(data)) {
4659
- normalizationType = children;
4660
- children = data;
4661
- data = undefined;
4602
+ function proxy (target, sourceKey, key) {
4603
+ sharedPropertyDefinition.get = function proxyGetter () {
4604
+ return this[sourceKey][key]
4605
+ };
4606
+ sharedPropertyDefinition.set = function proxySetter (val) {
4607
+ this[sourceKey][key] = val;
4608
+ };
4609
+ Object.defineProperty(target, key, sharedPropertyDefinition);
4610
+ }
4611
+
4612
+ function initState (vm) {
4613
+ vm._watchers = [];
4614
+ const opts = vm.$options;
4615
+ if (opts.props) initProps(vm, opts.props);
4616
+ if (opts.methods) initMethods(vm, opts.methods);
4617
+ if (opts.data) {
4618
+ initData(vm);
4619
+ } else {
4620
+ observe(vm._data = {}, true /* asRootData */);
4662
4621
  }
4663
- if (isTrue(alwaysNormalize)) {
4664
- normalizationType = ALWAYS_NORMALIZE;
4622
+ if (opts.computed) initComputed(vm, opts.computed);
4623
+ if (opts.watch && opts.watch !== nativeWatch) {
4624
+ initWatch(vm, opts.watch);
4665
4625
  }
4666
- return _createElement(context, tag, data, children, normalizationType)
4667
4626
  }
4668
4627
 
4669
- function _createElement (
4670
- context,
4671
- tag,
4672
- data,
4673
- children,
4674
- normalizationType
4675
- ) {
4676
- if (isDef(data) && isDef((data).__ob__)) {
4677
- warn(
4678
- `Avoid using observed data object as vnode data: ${JSON.stringify(data)}\n` +
4679
- 'Always create fresh vnode data objects in each render!',
4680
- context
4681
- );
4682
- return createEmptyVNode()
4628
+ function initProps (vm, propsOptions) {
4629
+ const propsData = vm.$options.propsData || {};
4630
+ const props = vm._props = {};
4631
+ // cache prop keys so that future props updates can iterate using Array
4632
+ // instead of dynamic object key enumeration.
4633
+ const keys = vm.$options._propKeys = [];
4634
+ const isRoot = !vm.$parent;
4635
+ // root instance props should be converted
4636
+ if (!isRoot) {
4637
+ toggleObserving(false);
4683
4638
  }
4684
- // object syntax in v-bind
4685
- if (isDef(data) && isDef(data.is)) {
4686
- tag = data.is;
4639
+ for (const key in propsOptions) {
4640
+ keys.push(key);
4641
+ const value = validateProp(key, propsOptions, propsData, vm);
4642
+ /* istanbul ignore else */
4643
+ {
4644
+ const hyphenatedKey = hyphenate(key);
4645
+ if (isReservedAttribute(hyphenatedKey) ||
4646
+ config.isReservedAttr(hyphenatedKey)) {
4647
+ warn(
4648
+ `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`,
4649
+ vm
4650
+ );
4651
+ }
4652
+ defineReactive$$1(props, key, value, () => {
4653
+ if (!isRoot && !isUpdatingChildComponent) {
4654
+ warn(
4655
+ `Avoid mutating a prop directly since the value will be ` +
4656
+ `overwritten whenever the parent component re-renders. ` +
4657
+ `Instead, use a data or computed property based on the prop's ` +
4658
+ `value. Prop being mutated: "${key}"`,
4659
+ vm
4660
+ );
4661
+ }
4662
+ });
4663
+ }
4664
+ // static props are already proxied on the component's prototype
4665
+ // during Vue.extend(). We only need to proxy props defined at
4666
+ // instantiation here.
4667
+ if (!(key in vm)) {
4668
+ proxy(vm, `_props`, key);
4669
+ }
4687
4670
  }
4688
- if (!tag) {
4689
- // in case of component :is set to falsy value
4690
- return createEmptyVNode()
4671
+ toggleObserving(true);
4672
+ }
4673
+
4674
+ function initData (vm) {
4675
+ let data = vm.$options.data;
4676
+ data = vm._data = typeof data === 'function'
4677
+ ? getData(data, vm)
4678
+ : data || {};
4679
+ if (!isPlainObject(data)) {
4680
+ data = {};
4681
+ warn(
4682
+ 'data functions should return an object:\n' +
4683
+ 'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
4684
+ vm
4685
+ );
4691
4686
  }
4692
- // warn against non-primitive key
4693
- if (isDef(data) && isDef(data.key) && !isPrimitive(data.key)
4694
- ) {
4687
+ // proxy data on instance
4688
+ const keys = Object.keys(data);
4689
+ const props = vm.$options.props;
4690
+ const methods = vm.$options.methods;
4691
+ let i = keys.length;
4692
+ while (i--) {
4693
+ const key = keys[i];
4695
4694
  {
4695
+ if (methods && hasOwn(methods, key)) {
4696
+ warn(
4697
+ `Method "${key}" has already been defined as a data property.`,
4698
+ vm
4699
+ );
4700
+ }
4701
+ }
4702
+ if (props && hasOwn(props, key)) {
4696
4703
  warn(
4697
- 'Avoid using non-primitive value as key, ' +
4698
- 'use string/number value instead.',
4699
- context
4704
+ `The data property "${key}" is already declared as a prop. ` +
4705
+ `Use prop default value instead.`,
4706
+ vm
4700
4707
  );
4708
+ } else if (!isReserved(key)) {
4709
+ proxy(vm, `_data`, key);
4701
4710
  }
4702
4711
  }
4703
- // support single function children as default scoped slot
4704
- if (Array.isArray(children) &&
4705
- typeof children[0] === 'function'
4706
- ) {
4707
- data = data || {};
4708
- data.scopedSlots = { default: children[0] };
4709
- children.length = 0;
4710
- }
4711
- if (normalizationType === ALWAYS_NORMALIZE) {
4712
- children = normalizeChildren(children);
4713
- } else if (normalizationType === SIMPLE_NORMALIZE) {
4714
- children = simpleNormalizeChildren(children);
4712
+ // observe data
4713
+ observe(data, true /* asRootData */);
4714
+ }
4715
+
4716
+ function getData (data, vm) {
4717
+ // #7573 disable dep collection when invoking data getters
4718
+ pushTarget();
4719
+ try {
4720
+ return data.call(vm, vm)
4721
+ } catch (e) {
4722
+ handleError(e, vm, `data()`);
4723
+ return {}
4724
+ } finally {
4725
+ popTarget();
4715
4726
  }
4716
- let vnode, ns;
4717
- if (typeof tag === 'string') {
4718
- let Ctor;
4719
- ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag);
4720
- if (config.isReservedTag(tag)) {
4721
- // platform built-in elements
4722
- vnode = new VNode(
4723
- config.parsePlatformTagName(tag), data, children,
4724
- undefined, undefined, context
4727
+ }
4728
+
4729
+ const computedWatcherOptions = { lazy: true };
4730
+
4731
+ function initComputed (vm, computed) {
4732
+ // $flow-disable-line
4733
+ const watchers = vm._computedWatchers = Object.create(null);
4734
+ // computed properties are just getters during SSR
4735
+ const isSSR = isServerRendering();
4736
+
4737
+ for (const key in computed) {
4738
+ const userDef = computed[key];
4739
+ const getter = typeof userDef === 'function' ? userDef : userDef.get;
4740
+ if (getter == null) {
4741
+ warn(
4742
+ `Getter is missing for computed property "${key}".`,
4743
+ vm
4725
4744
  );
4726
- } else if ((!data || !data.pre) && isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {
4727
- // component
4728
- vnode = createComponent(Ctor, data, context, children, tag);
4745
+ }
4746
+
4747
+ if (!isSSR) {
4748
+ // create internal watcher for the computed property.
4749
+ watchers[key] = new Watcher(
4750
+ vm,
4751
+ getter || noop,
4752
+ noop,
4753
+ computedWatcherOptions
4754
+ );
4755
+ }
4756
+
4757
+ // component-defined computed properties are already defined on the
4758
+ // component prototype. We only need to define computed properties defined
4759
+ // at instantiation here.
4760
+ if (!(key in vm)) {
4761
+ defineComputed(vm, key, userDef);
4729
4762
  } else {
4730
- // unknown or unlisted namespaced elements
4731
- // check at runtime because it may get assigned a namespace when its
4732
- // parent normalizes children
4733
- vnode = new VNode(
4734
- tag, data, children,
4735
- undefined, undefined, context
4763
+ if (key in vm.$data) {
4764
+ warn(`The computed property "${key}" is already defined in data.`, vm);
4765
+ } else if (vm.$options.props && key in vm.$options.props) {
4766
+ warn(`The computed property "${key}" is already defined as a prop.`, vm);
4767
+ }
4768
+ }
4769
+ }
4770
+ }
4771
+
4772
+ function defineComputed (
4773
+ target,
4774
+ key,
4775
+ userDef
4776
+ ) {
4777
+ const shouldCache = !isServerRendering();
4778
+ if (typeof userDef === 'function') {
4779
+ sharedPropertyDefinition.get = shouldCache
4780
+ ? createComputedGetter(key)
4781
+ : createGetterInvoker(userDef);
4782
+ sharedPropertyDefinition.set = noop;
4783
+ } else {
4784
+ sharedPropertyDefinition.get = userDef.get
4785
+ ? shouldCache && userDef.cache !== false
4786
+ ? createComputedGetter(key)
4787
+ : createGetterInvoker(userDef.get)
4788
+ : noop;
4789
+ sharedPropertyDefinition.set = userDef.set || noop;
4790
+ }
4791
+ if (sharedPropertyDefinition.set === noop) {
4792
+ sharedPropertyDefinition.set = function () {
4793
+ warn(
4794
+ `Computed property "${key}" was assigned to but it has no setter.`,
4795
+ this
4736
4796
  );
4797
+ };
4798
+ }
4799
+ Object.defineProperty(target, key, sharedPropertyDefinition);
4800
+ }
4801
+
4802
+ function createComputedGetter (key) {
4803
+ return function computedGetter () {
4804
+ const watcher = this._computedWatchers && this._computedWatchers[key];
4805
+ if (watcher) {
4806
+ if (watcher.dirty) {
4807
+ watcher.evaluate();
4808
+ }
4809
+ if (Dep.target) {
4810
+ watcher.depend();
4811
+ }
4812
+ return watcher.value
4737
4813
  }
4738
- } else {
4739
- // direct component options / constructor
4740
- vnode = createComponent(tag, data, context, children);
4741
4814
  }
4742
- if (Array.isArray(vnode)) {
4743
- return vnode
4744
- } else if (isDef(vnode)) {
4745
- if (isDef(ns)) applyNS(vnode, ns);
4746
- if (isDef(data)) registerDeepBindings(data);
4747
- return vnode
4748
- } else {
4749
- return createEmptyVNode()
4815
+ }
4816
+
4817
+ function createGetterInvoker(fn) {
4818
+ return function computedGetter () {
4819
+ return fn.call(this, this)
4750
4820
  }
4751
4821
  }
4752
4822
 
4753
- function applyNS (vnode, ns, force) {
4754
- vnode.ns = ns;
4755
- if (vnode.tag === 'foreignObject') {
4756
- // use default namespace inside foreignObject
4757
- ns = undefined;
4758
- force = true;
4823
+ function initMethods (vm, methods) {
4824
+ const props = vm.$options.props;
4825
+ for (const key in methods) {
4826
+ {
4827
+ if (typeof methods[key] !== 'function') {
4828
+ warn(
4829
+ `Method "${key}" has type "${typeof methods[key]}" in the component definition. ` +
4830
+ `Did you reference the function correctly?`,
4831
+ vm
4832
+ );
4833
+ }
4834
+ if (props && hasOwn(props, key)) {
4835
+ warn(
4836
+ `Method "${key}" has already been defined as a prop.`,
4837
+ vm
4838
+ );
4839
+ }
4840
+ if ((key in vm) && isReserved(key)) {
4841
+ warn(
4842
+ `Method "${key}" conflicts with an existing Vue instance method. ` +
4843
+ `Avoid defining component methods that start with _ or $.`
4844
+ );
4845
+ }
4846
+ }
4847
+ vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm);
4759
4848
  }
4760
- if (isDef(vnode.children)) {
4761
- for (let i = 0, l = vnode.children.length; i < l; i++) {
4762
- const child = vnode.children[i];
4763
- if (isDef(child.tag) && (
4764
- isUndef(child.ns) || (isTrue(force) && child.tag !== 'svg'))) {
4765
- applyNS(child, ns, force);
4849
+ }
4850
+
4851
+ function initWatch (vm, watch) {
4852
+ for (const key in watch) {
4853
+ const handler = watch[key];
4854
+ if (Array.isArray(handler)) {
4855
+ for (let i = 0; i < handler.length; i++) {
4856
+ createWatcher(vm, key, handler[i]);
4766
4857
  }
4858
+ } else {
4859
+ createWatcher(vm, key, handler);
4767
4860
  }
4768
4861
  }
4769
4862
  }
4770
4863
 
4771
- // ref #5318
4772
- // necessary to ensure parent re-render when deep bindings like :style and
4773
- // :class are used on slot nodes
4774
- function registerDeepBindings (data) {
4775
- if (isObject(data.style)) {
4776
- traverse(data.style);
4864
+ function createWatcher (
4865
+ vm,
4866
+ expOrFn,
4867
+ handler,
4868
+ options
4869
+ ) {
4870
+ if (isPlainObject(handler)) {
4871
+ options = handler;
4872
+ handler = handler.handler;
4777
4873
  }
4778
- if (isObject(data.class)) {
4779
- traverse(data.class);
4874
+ if (typeof handler === 'string') {
4875
+ handler = vm[handler];
4780
4876
  }
4877
+ return vm.$watch(expOrFn, handler, options)
4781
4878
  }
4782
4879
 
4783
- /* */
4784
-
4785
- function initRender (vm) {
4786
- vm._vnode = null; // the root of the child tree
4787
- vm._staticTrees = null; // v-once cached trees
4788
- const options = vm.$options;
4789
- const parentVnode = vm.$vnode = options._parentVnode; // the placeholder node in parent tree
4790
- const renderContext = parentVnode && parentVnode.context;
4791
- vm.$slots = resolveSlots(options._renderChildren, renderContext);
4792
- vm.$scopedSlots = emptyObject;
4793
- // bind the createElement fn to this instance
4794
- // so that we get proper render context inside it.
4795
- // args order: tag, data, children, normalizationType, alwaysNormalize
4796
- // internal version is used by render functions compiled from templates
4797
- vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false);
4798
- // normalization is always applied for the public version, used in
4799
- // user-written render functions.
4800
- vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true);
4801
-
4802
- // $attrs & $listeners are exposed for easier HOC creation.
4803
- // they need to be reactive so that HOCs using them are always updated
4804
- const parentData = parentVnode && parentVnode.data;
4805
-
4806
- /* istanbul ignore else */
4880
+ function stateMixin (Vue) {
4881
+ // flow somehow has problems with directly declared definition object
4882
+ // when using Object.defineProperty, so we have to procedurally build up
4883
+ // the object here.
4884
+ const dataDef = {};
4885
+ dataDef.get = function () { return this._data };
4886
+ const propsDef = {};
4887
+ propsDef.get = function () { return this._props };
4807
4888
  {
4808
- defineReactive$$1(vm, '$attrs', parentData && parentData.attrs || emptyObject, () => {
4809
- !isUpdatingChildComponent && warn(`$attrs is readonly.`, vm);
4810
- }, true);
4811
- defineReactive$$1(vm, '$listeners', options._parentListeners || emptyObject, () => {
4812
- !isUpdatingChildComponent && warn(`$listeners is readonly.`, vm);
4813
- }, true);
4889
+ dataDef.set = function () {
4890
+ warn(
4891
+ 'Avoid replacing instance root $data. ' +
4892
+ 'Use nested data properties instead.',
4893
+ this
4894
+ );
4895
+ };
4896
+ propsDef.set = function () {
4897
+ warn(`$props is readonly.`, this);
4898
+ };
4814
4899
  }
4815
- }
4816
-
4817
- function renderMixin (Vue) {
4818
- // install runtime convenience helpers
4819
- installRenderHelpers(Vue.prototype);
4900
+ Object.defineProperty(Vue.prototype, '$data', dataDef);
4901
+ Object.defineProperty(Vue.prototype, '$props', propsDef);
4820
4902
 
4821
- Vue.prototype.$nextTick = function (fn) {
4822
- return nextTick(fn, this)
4823
- };
4903
+ Vue.prototype.$set = set;
4904
+ Vue.prototype.$delete = del;
4824
4905
 
4825
- Vue.prototype._render = function () {
4906
+ Vue.prototype.$watch = function (
4907
+ expOrFn,
4908
+ cb,
4909
+ options
4910
+ ) {
4826
4911
  const vm = this;
4827
- const { render, _parentVnode } = vm.$options;
4828
-
4829
- if (_parentVnode) {
4830
- vm.$scopedSlots = normalizeScopedSlots(
4831
- _parentVnode.data.scopedSlots,
4832
- vm.$slots
4833
- );
4912
+ if (isPlainObject(cb)) {
4913
+ return createWatcher(vm, expOrFn, cb, options)
4834
4914
  }
4835
-
4836
- // set parent vnode. this allows render functions to have access
4837
- // to the data on the placeholder node.
4838
- vm.$vnode = _parentVnode;
4839
- // render self
4840
- let vnode;
4841
- try {
4842
- vnode = render.call(vm._renderProxy, vm.$createElement);
4843
- } catch (e) {
4844
- handleError(e, vm, `render`);
4845
- // return error render result,
4846
- // or previous vnode to prevent render error causing blank component
4847
- /* istanbul ignore else */
4848
- if (vm.$options.renderError) {
4849
- try {
4850
- vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e);
4851
- } catch (e) {
4852
- handleError(e, vm, `renderError`);
4853
- vnode = vm._vnode;
4854
- }
4855
- } else {
4856
- vnode = vm._vnode;
4915
+ options = options || {};
4916
+ options.user = true;
4917
+ const watcher = new Watcher(vm, expOrFn, cb, options);
4918
+ if (options.immediate) {
4919
+ try {
4920
+ cb.call(vm, watcher.value);
4921
+ } catch (error) {
4922
+ handleError(error, vm, `callback for immediate watcher "${watcher.expression}"`);
4857
4923
  }
4858
4924
  }
4859
- // if the returned array contains only a single node, allow it
4860
- if (Array.isArray(vnode) && vnode.length === 1) {
4861
- vnode = vnode[0];
4862
- }
4863
- // return empty vnode in case the render function errored out
4864
- if (!(vnode instanceof VNode)) {
4865
- if (Array.isArray(vnode)) {
4866
- warn(
4867
- 'Multiple root nodes returned from render function. Render function ' +
4868
- 'should return a single root node.',
4869
- vm
4870
- );
4871
- }
4872
- vnode = createEmptyVNode();
4925
+ return function unwatchFn () {
4926
+ watcher.teardown();
4873
4927
  }
4874
- // set parent
4875
- vnode.parent = _parentVnode;
4876
- return vnode
4877
4928
  };
4878
4929
  }
4879
4930
 
@@ -5359,7 +5410,7 @@ Object.defineProperty(Vue, 'FunctionalRenderContext', {
5359
5410
  value: FunctionalRenderContext
5360
5411
  });
5361
5412
 
5362
- Vue.version = '2.6.2';
5413
+ Vue.version = '2.6.6';
5363
5414
 
5364
5415
  /* */
5365
5416
 
@@ -7415,6 +7466,11 @@ function createOnceHandler$1 (event, handler, capture) {
7415
7466
  }
7416
7467
  }
7417
7468
 
7469
+ // #9446: Firefox <= 53 (in particular, ESR 52) has incorrect Event.timeStamp
7470
+ // implementation and does not fire microtasks in between event propagation, so
7471
+ // safe to exclude.
7472
+ const useMicrotaskFix = isUsingMicroTask && !(isFF && Number(isFF[1]) <= 53);
7473
+
7418
7474
  function add$1 (
7419
7475
  name,
7420
7476
  handler,
@@ -7427,11 +7483,24 @@ function add$1 (
7427
7483
  // the solution is simple: we save the timestamp when a handler is attached,
7428
7484
  // and the handler would only fire if the event passed to it was fired
7429
7485
  // AFTER it was attached.
7430
- if (isUsingMicroTask) {
7486
+ if (useMicrotaskFix) {
7431
7487
  const attachedTimestamp = currentFlushTimestamp;
7432
7488
  const original = handler;
7433
7489
  handler = original._wrapper = function (e) {
7434
- if (e.timeStamp >= attachedTimestamp) {
7490
+ if (
7491
+ // no bubbling, should always fire.
7492
+ // this is just a safety net in case event.timeStamp is unreliable in
7493
+ // certain weird environments...
7494
+ e.target === e.currentTarget ||
7495
+ // event is fired after handler attachment
7496
+ e.timeStamp >= attachedTimestamp ||
7497
+ // #9462 bail for iOS 9 bug: event.timeStamp is 0 after history.pushState
7498
+ e.timeStamp === 0 ||
7499
+ // #9448 bail if event is fired in another document in a multi-page
7500
+ // electron/nw.js app, since event.timeStamp will be using a different
7501
+ // starting reference
7502
+ e.target.ownerDocument !== document
7503
+ ) {
7435
7504
  return original.apply(this, arguments)
7436
7505
  }
7437
7506
  };
@@ -9437,6 +9506,8 @@ const invalidAttributeRE = /[\s"'<>\/=]/;
9437
9506
 
9438
9507
  const decodeHTMLCached = cached(he.decode);
9439
9508
 
9509
+ const emptySlotScopeToken = `_empty_`;
9510
+
9440
9511
  // configurable state
9441
9512
  let warn$2;
9442
9513
  let delimiters;
@@ -10047,7 +10118,7 @@ function processSlotContent (el) {
10047
10118
  const { name, dynamic } = getSlotName(slotBinding);
10048
10119
  el.slotTarget = name;
10049
10120
  el.slotTargetDynamic = dynamic;
10050
- el.slotScope = slotBinding.value || `_`; // force it into a scoped slot for perf
10121
+ el.slotScope = slotBinding.value || emptySlotScopeToken; // force it into a scoped slot for perf
10051
10122
  }
10052
10123
  } else {
10053
10124
  // v-slot on component, denotes default slot
@@ -10080,8 +10151,13 @@ function processSlotContent (el) {
10080
10151
  const slotContainer = slots[name] = createASTElement('template', [], el);
10081
10152
  slotContainer.slotTarget = name;
10082
10153
  slotContainer.slotTargetDynamic = dynamic;
10083
- slotContainer.children = el.children.filter(c => !(c).slotScope);
10084
- slotContainer.slotScope = slotBinding.value || `_`;
10154
+ slotContainer.children = el.children.filter((c) => {
10155
+ if (!c.slotScope) {
10156
+ c.parent = slotContainer;
10157
+ return true
10158
+ }
10159
+ });
10160
+ slotContainer.slotScope = slotBinding.value || emptySlotScopeToken;
10085
10161
  // remove children as they are returned from scopedSlots now
10086
10162
  el.children = [];
10087
10163
  // mark el non-plain so data gets generated
@@ -10730,7 +10806,13 @@ function genHandler (handler) {
10730
10806
  }
10731
10807
 
10732
10808
  function genKeyFilter (keys) {
10733
- return `if(('keyCode' in $event)&&${keys.map(genFilterCode).join('&&')})return null;`
10809
+ return (
10810
+ // make sure the key filters only apply to KeyboardEvents
10811
+ // #9441: can't use 'keyCode' in $event because Chrome autofill fires fake
10812
+ // key events that do not have keyCode property...
10813
+ `if(!$event.type.indexOf('key')&&` +
10814
+ `${keys.map(genFilterCode).join('&&')})return null;`
10815
+ )
10734
10816
  }
10735
10817
 
10736
10818
  function genFilterCode (key) {
@@ -11040,7 +11122,7 @@ function genData$2 (el, state) {
11040
11122
  }
11041
11123
  // scoped slots
11042
11124
  if (el.scopedSlots) {
11043
- data += `${genScopedSlots(el.scopedSlots, state)},`;
11125
+ data += `${genScopedSlots(el, el.scopedSlots, state)},`;
11044
11126
  }
11045
11127
  // component v-model
11046
11128
  if (el.model) {
@@ -11127,18 +11209,51 @@ function genInlineTemplate (el, state) {
11127
11209
  }
11128
11210
 
11129
11211
  function genScopedSlots (
11212
+ el,
11130
11213
  slots,
11131
11214
  state
11132
11215
  ) {
11133
- const hasDynamicKeys = Object.keys(slots).some(key => {
11216
+ // by default scoped slots are considered "stable", this allows child
11217
+ // components with only scoped slots to skip forced updates from parent.
11218
+ // but in some cases we have to bail-out of this optimization
11219
+ // for example if the slot contains dynamic names, has v-if or v-for on them...
11220
+ let needsForceUpdate = Object.keys(slots).some(key => {
11134
11221
  const slot = slots[key];
11135
- return slot.slotTargetDynamic || slot.if || slot.for
11222
+ return (
11223
+ slot.slotTargetDynamic ||
11224
+ slot.if ||
11225
+ slot.for ||
11226
+ containsSlotChild(slot) // is passing down slot from parent which may be dynamic
11227
+ )
11136
11228
  });
11229
+ // OR when it is inside another scoped slot (the reactivity is disconnected)
11230
+ // #9438
11231
+ if (!needsForceUpdate) {
11232
+ let parent = el.parent;
11233
+ while (parent) {
11234
+ if (parent.slotScope && parent.slotScope !== emptySlotScopeToken) {
11235
+ needsForceUpdate = true;
11236
+ break
11237
+ }
11238
+ parent = parent.parent;
11239
+ }
11240
+ }
11241
+
11137
11242
  return `scopedSlots:_u([${
11138
11243
  Object.keys(slots).map(key => {
11139
11244
  return genScopedSlot(slots[key], state)
11140
11245
  }).join(',')
11141
- }]${hasDynamicKeys ? `,true` : ``})`
11246
+ }]${needsForceUpdate ? `,true` : ``})`
11247
+ }
11248
+
11249
+ function containsSlotChild (el) {
11250
+ if (el.type === 1) {
11251
+ if (el.tag === 'slot') {
11252
+ return true
11253
+ }
11254
+ return el.children.some(containsSlotChild)
11255
+ }
11256
+ return false
11142
11257
  }
11143
11258
 
11144
11259
  function genScopedSlot (
@@ -11152,14 +11267,19 @@ function genScopedSlot (
11152
11267
  if (el.for && !el.forProcessed) {
11153
11268
  return genFor(el, state, genScopedSlot)
11154
11269
  }
11155
- const fn = `function(${String(el.slotScope)}){` +
11270
+ const slotScope = el.slotScope === emptySlotScopeToken
11271
+ ? ``
11272
+ : String(el.slotScope);
11273
+ const fn = `function(${slotScope}){` +
11156
11274
  `return ${el.tag === 'template'
11157
11275
  ? el.if && isLegacySyntax
11158
11276
  ? `(${el.if})?${genChildren(el, state) || 'undefined'}:undefined`
11159
11277
  : genChildren(el, state) || 'undefined'
11160
11278
  : genElement(el, state)
11161
11279
  }}`;
11162
- return `{key:${el.slotTarget || `"default"`},fn:${fn}}`
11280
+ // reverse proxy v-slot without scope on this.$slots
11281
+ const reverseProxy = slotScope ? `` : `,proxy:true`;
11282
+ return `{key:${el.slotTarget || `"default"`},fn:${fn}${reverseProxy}}`
11163
11283
  }
11164
11284
 
11165
11285
  function genChildren (
@@ -11249,7 +11369,14 @@ function genSlot (el, state) {
11249
11369
  const slotName = el.slotName || '"default"';
11250
11370
  const children = genChildren(el, state);
11251
11371
  let res = `_t(${slotName}${children ? `,${children}` : ''}`;
11252
- const attrs = el.attrs && `{${el.attrs.map(a => `${camelize(a.name)}:${a.value}`).join(',')}}`;
11372
+ const attrs = el.attrs || el.dynamicAttrs
11373
+ ? genProps((el.attrs || []).concat(el.dynamicAttrs || []).map(attr => ({
11374
+ // slot props are camelized
11375
+ name: camelize(attr.name),
11376
+ value: attr.value,
11377
+ dynamic: attr.dynamic
11378
+ })))
11379
+ : null;
11253
11380
  const bind$$1 = el.attrsMap['v-bind'];
11254
11381
  if ((attrs || bind$$1) && !children) {
11255
11382
  res += `,null`;