vue 2.6.4 → 2.6.8

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.
@@ -4,25 +4,33 @@ import config from '../config'
4
4
  import { warn } from './debug'
5
5
  import { inBrowser, inWeex } from './env'
6
6
  import { isPromise } from 'shared/util'
7
+ import { pushTarget, popTarget } from '../observer/dep'
7
8
 
8
9
  export function handleError (err: Error, vm: any, info: string) {
9
- if (vm) {
10
- let cur = vm
11
- while ((cur = cur.$parent)) {
12
- const hooks = cur.$options.errorCaptured
13
- if (hooks) {
14
- for (let i = 0; i < hooks.length; i++) {
15
- try {
16
- const capture = hooks[i].call(cur, err, vm, info) === false
17
- if (capture) return
18
- } catch (e) {
19
- globalHandleError(e, cur, 'errorCaptured hook')
10
+ // Deactivate deps tracking while processing error handler to avoid possible infinite rendering.
11
+ // See: https://github.com/vuejs/vuex/issues/1505
12
+ pushTarget()
13
+ try {
14
+ if (vm) {
15
+ let cur = vm
16
+ while ((cur = cur.$parent)) {
17
+ const hooks = cur.$options.errorCaptured
18
+ if (hooks) {
19
+ for (let i = 0; i < hooks.length; i++) {
20
+ try {
21
+ const capture = hooks[i].call(cur, err, vm, info) === false
22
+ if (capture) return
23
+ } catch (e) {
24
+ globalHandleError(e, cur, 'errorCaptured hook')
25
+ }
20
26
  }
21
27
  }
22
28
  }
23
29
  }
30
+ globalHandleError(err, vm, info)
31
+ } finally {
32
+ popTarget()
24
33
  }
25
- globalHandleError(err, vm, info)
26
34
  }
27
35
 
28
36
  export function invokeWithErrorHandling (
@@ -36,7 +44,9 @@ export function invokeWithErrorHandling (
36
44
  try {
37
45
  res = args ? handler.apply(context, args) : handler.call(context)
38
46
  if (res && !res._isVue && isPromise(res)) {
39
- res.catch(e => handleError(e, vm, info + ` (Promise/async)`))
47
+ // issue #9511
48
+ // reassign to res to avoid catch triggering multiple times when nested calls
49
+ res = res.catch(e => handleError(e, vm, info + ` (Promise/async)`))
40
50
  }
41
51
  } catch (e) {
42
52
  handleError(e, vm, info)
@@ -5,7 +5,7 @@
5
5
  * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname
6
6
  * skipping \u10000-\uEFFFF due to it freezing up PhantomJS
7
7
  */
8
- export const unicodeLetters = 'a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD'
8
+ export const unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/
9
9
 
10
10
  /**
11
11
  * Check if a string starts with $ or _
@@ -30,7 +30,7 @@ export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
30
30
  /**
31
31
  * Parse simple path.
32
32
  */
33
- const bailRE = new RegExp(`[^${unicodeLetters}.$_\\d]`)
33
+ const bailRE = new RegExp(`[^${unicodeRegExp.source}.$_\\d]`)
34
34
  export function parsePath (path: string): any {
35
35
  if (bailRE.test(path)) {
36
36
  return
@@ -3,7 +3,7 @@
3
3
  import config from '../config'
4
4
  import { warn } from './debug'
5
5
  import { set } from '../observer/index'
6
- import { unicodeLetters } from './lang'
6
+ import { unicodeRegExp } from './lang'
7
7
  import { nativeWatch, hasSymbol } from './env'
8
8
 
9
9
  import {
@@ -277,7 +277,7 @@ function checkComponents (options: Object) {
277
277
  }
278
278
 
279
279
  export function validateComponentName (name: string) {
280
- if (!new RegExp(`^[a-zA-Z][\\-\\.0-9_${unicodeLetters}]*$`).test(name)) {
280
+ if (!new RegExp(`^[a-zA-Z][\\-\\.0-9_${unicodeRegExp.source}]*$`).test(name)) {
281
281
  warn(
282
282
  'Invalid component name: "' + name + '". Component names ' +
283
283
  'should conform to valid custom element name in html5 specification.'
@@ -10,13 +10,22 @@ export function normalizeScopedSlots (
10
10
  prevSlots?: { [key: string]: Function } | void
11
11
  ): any {
12
12
  let res
13
+ const isStable = slots ? !!slots.$stable : true
14
+ const key = slots && slots.$key
13
15
  if (!slots) {
14
16
  res = {}
15
17
  } else if (slots._normalized) {
16
18
  // fast path 1: child component re-render only, parent did not change
17
19
  return slots._normalized
18
- } else if (slots.$stable && prevSlots && prevSlots !== emptyObject) {
19
- // fast path 2: stable scoped slots, only need to normalize once
20
+ } else if (
21
+ isStable &&
22
+ prevSlots &&
23
+ prevSlots !== emptyObject &&
24
+ key === prevSlots.$key &&
25
+ Object.keys(normalSlots).length === 0
26
+ ) {
27
+ // fast path 2: stable scoped slots w/ no normal slots to proxy,
28
+ // only need to normalize once
20
29
  return prevSlots
21
30
  } else {
22
31
  res = {}
@@ -37,13 +46,14 @@ export function normalizeScopedSlots (
37
46
  if (slots && Object.isExtensible(slots)) {
38
47
  (slots: any)._normalized = res
39
48
  }
40
- def(res, '$stable', slots ? !!slots.$stable : true)
49
+ def(res, '$stable', isStable)
50
+ def(res, '$key', key)
41
51
  return res
42
52
  }
43
53
 
44
54
  function normalizeScopedSlot(normalSlots, key, fn) {
45
- const normalized = scope => {
46
- let res = fn(scope || {})
55
+ const normalized = function () {
56
+ let res = arguments.length ? fn.apply(null, arguments) : fn({})
47
57
  res = res && typeof res === 'object' && !Array.isArray(res)
48
58
  ? [res] // single vnode
49
59
  : normalizeChildren(res)
@@ -8,7 +8,8 @@ import {
8
8
  isTrue,
9
9
  isObject,
10
10
  hasSymbol,
11
- isPromise
11
+ isPromise,
12
+ remove
12
13
  } from 'core/util/index'
13
14
 
14
15
  import { createEmptyVNode } from 'core/vdom/vnode'
@@ -51,18 +52,22 @@ export function resolveAsyncComponent (
51
52
  return factory.resolved
52
53
  }
53
54
 
55
+ const owner = currentRenderingInstance
56
+ if (isDef(factory.owners) && factory.owners.indexOf(owner) === -1) {
57
+ // already pending
58
+ factory.owners.push(owner)
59
+ }
60
+
54
61
  if (isTrue(factory.loading) && isDef(factory.loadingComp)) {
55
62
  return factory.loadingComp
56
63
  }
57
64
 
58
- const owner = currentRenderingInstance
59
- if (isDef(factory.owners)) {
60
- // already pending
61
- factory.owners.push(owner)
62
- } else {
65
+ if (!isDef(factory.owners)) {
63
66
  const owners = factory.owners = [owner]
64
67
  let sync = true
65
68
 
69
+ ;(owner: any).$on('hook:destroyed', () => remove(owners, owner))
70
+
66
71
  const forceRender = (renderCompleted: boolean) => {
67
72
  for (let i = 0, l = owners.length; i < l; i++) {
68
73
  (owners[i]: any).$forceUpdate()
@@ -38,15 +38,7 @@ function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
38
38
  }
39
39
  }
40
40
 
41
- // skip the update if old and new VDOM state is the same.
42
- // the only exception is `value` where the DOM value may be temporarily
43
- // out of sync with VDOM state due to focus, composition and modifiers.
44
- // This also covers #4521 by skipping the unnecesarry `checked` update.
45
- if (key !== 'value' && cur === oldProps[key]) {
46
- continue
47
- }
48
-
49
- if (key === 'value') {
41
+ if (key === 'value' && elm.tagName !== 'PROGRESS') {
50
42
  // store value as _value as well since
51
43
  // non-string values will be stringified
52
44
  elm._value = cur
@@ -66,8 +58,18 @@ function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
66
58
  while (svg.firstChild) {
67
59
  elm.appendChild(svg.firstChild)
68
60
  }
69
- } else {
70
- elm[key] = cur
61
+ } else if (
62
+ // skip the update if old and new VDOM state is the same.
63
+ // `value` is handled separately because the DOM value may be temporarily
64
+ // out of sync with VDOM state due to focus, composition and modifiers.
65
+ // This #4521 by skipping the unnecesarry `checked` update.
66
+ cur !== oldProps[key]
67
+ ) {
68
+ // some property updates can throw
69
+ // e.g. `value` on <progress> w/ non-finite value
70
+ try {
71
+ elm[key] = cur
72
+ } catch (e) {}
71
73
  }
72
74
  }
73
75
  }
@@ -61,9 +61,17 @@ function add (
61
61
  const original = handler
62
62
  handler = original._wrapper = function (e) {
63
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
64
69
  e.timeStamp >= attachedTimestamp ||
70
+ // #9462 bail for iOS 9 bug: event.timeStamp is 0 after history.pushState
71
+ e.timeStamp === 0 ||
65
72
  // #9448 bail if event is fired in another document in a multi-page
66
- // electron/nw.js app
73
+ // electron/nw.js app, since event.timeStamp will be using a different
74
+ // starting reference
67
75
  e.target.ownerDocument !== document
68
76
  ) {
69
77
  return original.apply(this, arguments)
@@ -1,6 +1,6 @@
1
1
  /* @flow */
2
2
 
3
- const MAX_STACK_DEPTH = 900
3
+ const MAX_STACK_DEPTH = 800
4
4
  const noop = _ => _
5
5
 
6
6
  const defer = typeof process !== 'undefined' && process.nextTick
package/types/vnode.d.ts CHANGED
@@ -1,7 +1,11 @@
1
1
  import { Vue } from "./vue";
2
2
 
3
+ export type ScopedSlot = (props: any) => ScopedSlotReturnValue;
4
+ type ScopedSlotReturnValue = VNode | string | boolean | null | undefined | ScopedSlotReturnArray;
5
+ interface ScopedSlotReturnArray extends Array<ScopedSlotReturnValue> {}
6
+
3
7
  // Scoped slots are guaranteed to return Array of VNodes starting in 2.6
4
- export type ScopedSlot = (props: any) => ScopedSlotChildren;
8
+ export type NormalizedScopedSlot = (props: any) => ScopedSlotChildren;
5
9
  export type ScopedSlotChildren = VNode[] | undefined;
6
10
 
7
11
  // Relaxed type compatible with $createElement
package/types/vue.d.ts CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  ThisTypedComponentOptionsWithRecordProps,
13
13
  WatchOptions,
14
14
  } from "./options";
15
- import { VNode, VNodeData, VNodeChildren, ScopedSlot } from "./vnode";
15
+ import { VNode, VNodeData, VNodeChildren, ScopedSlot, NormalizedScopedSlot } from "./vnode";
16
16
  import { PluginFunction, PluginObject } from "./plugin";
17
17
 
18
18
  export interface CreateElement {
@@ -28,7 +28,7 @@ export interface Vue {
28
28
  readonly $children: Vue[];
29
29
  readonly $refs: { [key: string]: Vue | Element | Vue[] | Element[] };
30
30
  readonly $slots: { [key: string]: VNode[] | undefined };
31
- readonly $scopedSlots: { [key: string]: ScopedSlot | undefined };
31
+ readonly $scopedSlots: { [key: string]: NormalizedScopedSlot | undefined };
32
32
  readonly $isServer: boolean;
33
33
  readonly $data: Record<string, any>;
34
34
  readonly $props: Record<string, any>;
@@ -89,7 +89,7 @@ export interface VueConstructor<V extends Vue = Vue> {
89
89
  extend<Props>(definition: FunctionalComponentOptions<Props, RecordPropsDefinition<Props>>): ExtendedVue<V, {}, {}, {}, Props>;
90
90
  extend(options?: ComponentOptions<V>): ExtendedVue<V, {}, {}, {}, {}>;
91
91
 
92
- nextTick(callback: () => void, context?: any[]): void;
92
+ nextTick<T>(callback: (this: T) => void, context?: T): void;
93
93
  nextTick(): Promise<void>
94
94
  set<T>(object: object, key: string | number, value: T): T;
95
95
  set<T>(array: T[], key: number, value: T): T;