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.
@@ -44,7 +44,7 @@ export let currentFlushTimestamp = 0
44
44
  let getNow: () => number = Date.now
45
45
 
46
46
  // Determine what event timestamp the browser is using. Annoyingly, the
47
- // timestamp can either be hi-res ( relative to poge load) or low-res
47
+ // timestamp can either be hi-res (relative to page load) or low-res
48
48
  // (relative to UNIX epoch), so in order to compare time we have to use the
49
49
  // same timestamp type when saving the flush timestamp.
50
50
  if (inBrowser && getNow() > document.createEvent('Event').timeStamp) {
@@ -15,6 +15,7 @@ export const isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform ===
15
15
  export const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios')
16
16
  export const isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge
17
17
  export const isPhantomJS = UA && /phantomjs/.test(UA)
18
+ export const isFF = UA && UA.match(/firefox\/(\d+)/)
18
19
 
19
20
  // Firefox has a "watch" function on Object.prototype...
20
21
  export const nativeWatch = ({}).watch
@@ -49,7 +49,11 @@ function globalHandleError (err, vm, info) {
49
49
  try {
50
50
  return config.errorHandler.call(null, err, vm, info)
51
51
  } catch (e) {
52
- logError(e, null, 'config.errorHandler')
52
+ // if the user intentionally throws the original error in the handler,
53
+ // do not log it twice
54
+ if (e !== err) {
55
+ logError(e, null, 'config.errorHandler')
56
+ }
53
57
  }
54
58
  }
55
59
  logError(err, vm, info)
@@ -129,7 +129,7 @@ export function createComponent (
129
129
  let asyncFactory
130
130
  if (isUndef(Ctor.cid)) {
131
131
  asyncFactory = Ctor
132
- Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context)
132
+ Ctor = resolveAsyncComponent(asyncFactory, baseCtor)
133
133
  if (Ctor === undefined) {
134
134
  // return a placeholder node for async component, which is rendered
135
135
  // as a comment node but preserves all the raw information for the node.
@@ -49,7 +49,15 @@ export function FunctionalRenderContext (
49
49
  this.parent = parent
50
50
  this.listeners = data.on || emptyObject
51
51
  this.injections = resolveInject(options.inject, parent)
52
- this.slots = () => resolveSlots(children, parent)
52
+ this.slots = () => {
53
+ if (!this.$slots) {
54
+ normalizeScopedSlots(
55
+ data.scopedSlots,
56
+ this.$slots = resolveSlots(children, parent)
57
+ )
58
+ }
59
+ return this.$slots
60
+ }
53
61
 
54
62
  Object.defineProperty(this, 'scopedSlots', ({
55
63
  enumerable: true,
@@ -1,17 +1,29 @@
1
1
  /* @flow */
2
2
 
3
- import { hasOwn } from 'shared/util'
3
+ import { def } from 'core/util/lang'
4
4
  import { normalizeChildren } from 'core/vdom/helpers/normalize-children'
5
+ import { emptyObject } from 'shared/util'
5
6
 
6
7
  export function normalizeScopedSlots (
7
8
  slots: { [key: string]: Function } | void,
8
- normalSlots: { [key: string]: Array<VNode> }
9
+ normalSlots: { [key: string]: Array<VNode> },
10
+ prevSlots?: { [key: string]: Function } | void
9
11
  ): any {
10
12
  let res
11
13
  if (!slots) {
12
14
  res = {}
13
15
  } else if (slots._normalized) {
14
- return slots
16
+ // fast path 1: child component re-render only, parent did not change
17
+ return slots._normalized
18
+ } else if (
19
+ slots.$stable &&
20
+ prevSlots &&
21
+ prevSlots !== emptyObject &&
22
+ Object.keys(normalSlots).length === 0
23
+ ) {
24
+ // fast path 2: stable scoped slots w/ no normal slots to proxy,
25
+ // only need to normalize once
26
+ return prevSlots
15
27
  } else {
16
28
  res = {}
17
29
  for (const key in slots) {
@@ -26,22 +38,33 @@ export function normalizeScopedSlots (
26
38
  res[key] = proxyNormalSlot(normalSlots, key)
27
39
  }
28
40
  }
29
- res._normalized = true
30
- res.$stable = slots ? slots.$stable : true
41
+ // avoriaz seems to mock a non-extensible $scopedSlots object
42
+ // and when that is passed down this would cause an error
43
+ if (slots && Object.isExtensible(slots)) {
44
+ (slots: any)._normalized = res
45
+ }
46
+ def(res, '$stable', slots ? !!slots.$stable : true)
31
47
  return res
32
48
  }
33
49
 
34
50
  function normalizeScopedSlot(normalSlots, key, fn) {
35
- const normalized = (scope = {}) => {
36
- const res = fn(scope)
37
- return res && typeof res === 'object' && !Array.isArray(res)
51
+ const normalized = function () {
52
+ let res = arguments.length ? fn.apply(null, arguments) : fn({})
53
+ res = res && typeof res === 'object' && !Array.isArray(res)
38
54
  ? [res] // single vnode
39
55
  : normalizeChildren(res)
56
+ return res && res.length === 0
57
+ ? undefined
58
+ : res
40
59
  }
41
- // proxy scoped slots on normal $slots
42
- if (!hasOwn(normalSlots, key)) {
60
+ // this is a slot using the new v-slot syntax without scope. although it is
61
+ // compiled as a scoped slot, render fn users would expect it to be present
62
+ // on this.$slots because the usage is semantically a normal slot.
63
+ if (fn.proxy) {
43
64
  Object.defineProperty(normalSlots, key, {
44
- get: normalized
65
+ get: normalized,
66
+ enumerable: true,
67
+ configurable: true
45
68
  })
46
69
  }
47
70
  return normalized
@@ -12,6 +12,7 @@ import {
12
12
  } from 'core/util/index'
13
13
 
14
14
  import { createEmptyVNode } from 'core/vdom/vnode'
15
+ import { currentRenderingInstance } from 'core/instance/render'
15
16
 
16
17
  function ensureCtor (comp: any, base) {
17
18
  if (
@@ -40,8 +41,7 @@ export function createAsyncPlaceholder (
40
41
 
41
42
  export function resolveAsyncComponent (
42
43
  factory: Function,
43
- baseCtor: Class<Component>,
44
- context: Component
44
+ baseCtor: Class<Component>
45
45
  ): Class<Component> | void {
46
46
  if (isTrue(factory.error) && isDef(factory.errorComp)) {
47
47
  return factory.errorComp
@@ -55,20 +55,21 @@ export function resolveAsyncComponent (
55
55
  return factory.loadingComp
56
56
  }
57
57
 
58
- if (isDef(factory.contexts)) {
58
+ const owner = currentRenderingInstance
59
+ if (isDef(factory.owners)) {
59
60
  // already pending
60
- factory.contexts.push(context)
61
+ factory.owners.push(owner)
61
62
  } else {
62
- const contexts = factory.contexts = [context]
63
+ const owners = factory.owners = [owner]
63
64
  let sync = true
64
65
 
65
66
  const forceRender = (renderCompleted: boolean) => {
66
- for (let i = 0, l = contexts.length; i < l; i++) {
67
- contexts[i].$forceUpdate()
67
+ for (let i = 0, l = owners.length; i < l; i++) {
68
+ (owners[i]: any).$forceUpdate()
68
69
  }
69
70
 
70
71
  if (renderCompleted) {
71
- contexts.length = 0
72
+ owners.length = 0
72
73
  }
73
74
  }
74
75
 
@@ -80,7 +81,7 @@ export function resolveAsyncComponent (
80
81
  if (!sync) {
81
82
  forceRender(true)
82
83
  } else {
83
- contexts.length = 0
84
+ owners.length = 0
84
85
  }
85
86
  })
86
87
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { isDef, isUndef } from 'shared/util'
4
4
  import { updateListeners } from 'core/vdom/helpers/index'
5
- import { isIE, supportsPassive, isUsingMicroTask } from 'core/util/index'
5
+ import { isIE, isFF, supportsPassive, isUsingMicroTask } from 'core/util/index'
6
6
  import { RANGE_TOKEN, CHECKBOX_RADIO_TOKEN } from 'web/compiler/directives/model'
7
7
  import { currentFlushTimestamp } from 'core/observer/scheduler'
8
8
 
@@ -39,6 +39,11 @@ function createOnceHandler (event, handler, capture) {
39
39
  }
40
40
  }
41
41
 
42
+ // #9446: Firefox <= 53 (in particular, ESR 52) has incorrect Event.timeStamp
43
+ // implementation and does not fire microtasks in between event propagation, so
44
+ // safe to exclude.
45
+ const useMicrotaskFix = isUsingMicroTask && !(isFF && Number(isFF[1]) <= 53)
46
+
42
47
  function add (
43
48
  name: string,
44
49
  handler: Function,
@@ -51,11 +56,24 @@ function add (
51
56
  // the solution is simple: we save the timestamp when a handler is attached,
52
57
  // and the handler would only fire if the event passed to it was fired
53
58
  // AFTER it was attached.
54
- if (isUsingMicroTask) {
59
+ if (useMicrotaskFix) {
55
60
  const attachedTimestamp = currentFlushTimestamp
56
61
  const original = handler
57
62
  handler = original._wrapper = function (e) {
58
- if (e.timeStamp >= attachedTimestamp) {
63
+ if (
64
+ // no bubbling, should always fire.
65
+ // this is just a safety net in case event.timeStamp is unreliable in
66
+ // certain weird environments...
67
+ e.target === e.currentTarget ||
68
+ // event is fired after handler attachment
69
+ e.timeStamp >= attachedTimestamp ||
70
+ // #9462 bail for iOS 9 bug: event.timeStamp is 0 after history.pushState
71
+ e.timeStamp === 0 ||
72
+ // #9448 bail if event is fired in another document in a multi-page
73
+ // electron/nw.js app, since event.timeStamp will be using a different
74
+ // starting reference
75
+ e.target.ownerDocument !== document
76
+ ) {
59
77
  return original.apply(this, arguments)
60
78
  }
61
79
  }
package/types/vue.d.ts CHANGED
@@ -122,6 +122,7 @@ export interface VueConstructor<V extends Vue = Vue> {
122
122
  observable<T>(obj: T): T;
123
123
 
124
124
  config: VueConfiguration;
125
+ version: string;
125
126
  }
126
127
 
127
128
  export const Vue: VueConstructor;