vue 2.6.6 → 2.6.10

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.
Files changed (37) hide show
  1. package/README.md +24 -19
  2. package/dist/README.md +1 -1
  3. package/dist/vue.common.dev.js +169 -80
  4. package/dist/vue.common.prod.js +2 -2
  5. package/dist/vue.esm.browser.js +167 -76
  6. package/dist/vue.esm.browser.min.js +2 -2
  7. package/dist/vue.esm.js +169 -80
  8. package/dist/vue.js +169 -80
  9. package/dist/vue.min.js +2 -2
  10. package/dist/vue.runtime.common.dev.js +121 -62
  11. package/dist/vue.runtime.common.prod.js +2 -2
  12. package/dist/vue.runtime.esm.js +121 -62
  13. package/dist/vue.runtime.js +121 -62
  14. package/dist/vue.runtime.min.js +2 -2
  15. package/package.json +2 -2
  16. package/src/compiler/codeframe.js +7 -5
  17. package/src/compiler/codegen/events.js +1 -1
  18. package/src/compiler/codegen/index.js +38 -9
  19. package/src/compiler/parser/html-parser.js +3 -3
  20. package/src/compiler/parser/index.js +4 -3
  21. package/src/core/instance/lifecycle.js +5 -2
  22. package/src/core/instance/render-helpers/bind-object-props.js +5 -3
  23. package/src/core/instance/render-helpers/resolve-scoped-slots.js +7 -2
  24. package/src/core/observer/scheduler.js +17 -6
  25. package/src/core/util/error.js +24 -13
  26. package/src/core/util/lang.js +2 -2
  27. package/src/core/util/options.js +2 -2
  28. package/src/core/vdom/helpers/normalize-scoped-slots.js +14 -5
  29. package/src/core/vdom/helpers/resolve-async-component.js +25 -8
  30. package/src/platforms/web/runtime/modules/dom-props.js +15 -12
  31. package/src/platforms/web/runtime/modules/events.js +4 -2
  32. package/src/platforms/web/runtime/modules/transition.js +1 -1
  33. package/src/server/template-renderer/create-async-file-mapper.js +2 -2
  34. package/src/server/write.js +1 -1
  35. package/types/options.d.ts +3 -3
  36. package/types/vnode.d.ts +6 -2
  37. package/types/vue.d.ts +3 -3
@@ -8,7 +8,8 @@ import {
8
8
  warn,
9
9
  nextTick,
10
10
  devtools,
11
- inBrowser
11
+ inBrowser,
12
+ isIE
12
13
  } from '../util/index'
13
14
 
14
15
  export const MAX_UPDATE_COUNT = 100
@@ -47,11 +48,21 @@ let getNow: () => number = Date.now
47
48
  // timestamp can either be hi-res (relative to page load) or low-res
48
49
  // (relative to UNIX epoch), so in order to compare time we have to use the
49
50
  // same timestamp type when saving the flush timestamp.
50
- if (inBrowser && getNow() > document.createEvent('Event').timeStamp) {
51
- // if the low-res timestamp which is bigger than the event timestamp
52
- // (which is evaluated AFTER) it means the event is using a hi-res timestamp,
53
- // and we need to use the hi-res version for event listeners as well.
54
- getNow = () => performance.now()
51
+ // All IE versions use low-res event timestamps, and have problematic clock
52
+ // implementations (#9632)
53
+ if (inBrowser && !isIE) {
54
+ const performance = window.performance
55
+ if (
56
+ performance &&
57
+ typeof performance.now === 'function' &&
58
+ getNow() > document.createEvent('Event').timeStamp
59
+ ) {
60
+ // if the event timestamp, although evaluated AFTER the Date.now(), is
61
+ // smaller than it, it means the event is using a hi-res timestamp,
62
+ // and we need to use the hi-res version for event listener timestamps as
63
+ // well.
64
+ getNow = () => performance.now()
65
+ }
55
66
  }
56
67
 
57
68
  /**
@@ -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 (
@@ -35,8 +43,11 @@ export function invokeWithErrorHandling (
35
43
  let res
36
44
  try {
37
45
  res = args ? handler.apply(context, args) : handler.call(context)
38
- if (res && !res._isVue && isPromise(res)) {
46
+ if (res && !res._isVue && isPromise(res) && !res._handled) {
39
47
  res.catch(e => handleError(e, vm, info + ` (Promise/async)`))
48
+ // issue #9511
49
+ // avoid catch triggering multiple times when nested calls
50
+ res._handled = true
40
51
  }
41
52
  } catch (e) {
42
53
  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,16 +10,21 @@ export function normalizeScopedSlots (
10
10
  prevSlots?: { [key: string]: Function } | void
11
11
  ): any {
12
12
  let res
13
+ const hasNormalSlots = Object.keys(normalSlots).length > 0
14
+ const isStable = slots ? !!slots.$stable : !hasNormalSlots
15
+ const key = slots && slots.$key
13
16
  if (!slots) {
14
17
  res = {}
15
18
  } else if (slots._normalized) {
16
19
  // fast path 1: child component re-render only, parent did not change
17
20
  return slots._normalized
18
21
  } else if (
19
- slots.$stable &&
22
+ isStable &&
20
23
  prevSlots &&
21
24
  prevSlots !== emptyObject &&
22
- Object.keys(normalSlots).length === 0
25
+ key === prevSlots.$key &&
26
+ !hasNormalSlots &&
27
+ !prevSlots.$hasNormal
23
28
  ) {
24
29
  // fast path 2: stable scoped slots w/ no normal slots to proxy,
25
30
  // only need to normalize once
@@ -43,7 +48,9 @@ export function normalizeScopedSlots (
43
48
  if (slots && Object.isExtensible(slots)) {
44
49
  (slots: any)._normalized = res
45
50
  }
46
- def(res, '$stable', slots ? !!slots.$stable : true)
51
+ def(res, '$stable', isStable)
52
+ def(res, '$key', key)
53
+ def(res, '$hasNormal', hasNormalSlots)
47
54
  return res
48
55
  }
49
56
 
@@ -53,8 +60,10 @@ function normalizeScopedSlot(normalSlots, key, fn) {
53
60
  res = res && typeof res === 'object' && !Array.isArray(res)
54
61
  ? [res] // single vnode
55
62
  : normalizeChildren(res)
56
- return res && res.length === 0
57
- ? undefined
63
+ return res && (
64
+ res.length === 0 ||
65
+ (res.length === 1 && res[0].isComment) // #9658
66
+ ) ? undefined
58
67
  : res
59
68
  }
60
69
  // this is a slot using the new v-slot syntax without scope. although it is
@@ -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,17 +52,23 @@ export function resolveAsyncComponent (
51
52
  return factory.resolved
52
53
  }
53
54
 
55
+ const owner = currentRenderingInstance
56
+ if (owner && 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 (owner && !isDef(factory.owners)) {
63
66
  const owners = factory.owners = [owner]
64
67
  let sync = true
68
+ let timerLoading = null
69
+ let timerTimeout = null
70
+
71
+ ;(owner: any).$on('hook:destroyed', () => remove(owners, owner))
65
72
 
66
73
  const forceRender = (renderCompleted: boolean) => {
67
74
  for (let i = 0, l = owners.length; i < l; i++) {
@@ -70,6 +77,14 @@ export function resolveAsyncComponent (
70
77
 
71
78
  if (renderCompleted) {
72
79
  owners.length = 0
80
+ if (timerLoading !== null) {
81
+ clearTimeout(timerLoading)
82
+ timerLoading = null
83
+ }
84
+ if (timerTimeout !== null) {
85
+ clearTimeout(timerTimeout)
86
+ timerTimeout = null
87
+ }
73
88
  }
74
89
  }
75
90
 
@@ -116,7 +131,8 @@ export function resolveAsyncComponent (
116
131
  if (res.delay === 0) {
117
132
  factory.loading = true
118
133
  } else {
119
- setTimeout(() => {
134
+ timerLoading = setTimeout(() => {
135
+ timerLoading = null
120
136
  if (isUndef(factory.resolved) && isUndef(factory.error)) {
121
137
  factory.loading = true
122
138
  forceRender(false)
@@ -126,7 +142,8 @@ export function resolveAsyncComponent (
126
142
  }
127
143
 
128
144
  if (isDef(res.timeout)) {
129
- setTimeout(() => {
145
+ timerTimeout = setTimeout(() => {
146
+ timerTimeout = null
130
147
  if (isUndef(factory.resolved)) {
131
148
  reject(
132
149
  process.env.NODE_ENV !== 'production'
@@ -19,10 +19,11 @@ function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
19
19
  }
20
20
 
21
21
  for (key in oldProps) {
22
- if (isUndef(props[key])) {
22
+ if (!(key in props)) {
23
23
  elm[key] = ''
24
24
  }
25
25
  }
26
+
26
27
  for (key in props) {
27
28
  cur = props[key]
28
29
  // ignore children if the node has textContent or innerHTML,
@@ -38,15 +39,7 @@ function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
38
39
  }
39
40
  }
40
41
 
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') {
42
+ if (key === 'value' && elm.tagName !== 'PROGRESS') {
50
43
  // store value as _value as well since
51
44
  // non-string values will be stringified
52
45
  elm._value = cur
@@ -66,8 +59,18 @@ function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
66
59
  while (svg.firstChild) {
67
60
  elm.appendChild(svg.firstChild)
68
61
  }
69
- } else {
70
- elm[key] = cur
62
+ } else if (
63
+ // skip the update if old and new VDOM state is the same.
64
+ // `value` is handled separately because the DOM value may be temporarily
65
+ // out of sync with VDOM state due to focus, composition and modifiers.
66
+ // This #4521 by skipping the unnecesarry `checked` update.
67
+ cur !== oldProps[key]
68
+ ) {
69
+ // some property updates can throw
70
+ // e.g. `value` on <progress> w/ non-finite value
71
+ try {
72
+ elm[key] = cur
73
+ } catch (e) {}
71
74
  }
72
75
  }
73
76
  }
@@ -67,8 +67,10 @@ function add (
67
67
  e.target === e.currentTarget ||
68
68
  // event is fired after handler attachment
69
69
  e.timeStamp >= attachedTimestamp ||
70
- // #9462 bail for iOS 9 bug: event.timeStamp is 0 after history.pushState
71
- e.timeStamp === 0 ||
70
+ // bail for environments that have buggy event.timeStamp implementations
71
+ // #9462 iOS 9 bug: event.timeStamp is 0 after history.pushState
72
+ // #9681 QtWebEngine event.timeStamp is negative value
73
+ e.timeStamp <= 0 ||
72
74
  // #9448 bail if event is fired in another document in a multi-page
73
75
  // electron/nw.js app, since event.timeStamp will be using a different
74
76
  // starting reference
@@ -66,8 +66,8 @@ export function enter (vnode: VNodeWithData, toggleDisplay: ?() => void) {
66
66
  let context = activeInstance
67
67
  let transitionNode = activeInstance.$vnode
68
68
  while (transitionNode && transitionNode.parent) {
69
- transitionNode = transitionNode.parent
70
69
  context = transitionNode.context
70
+ transitionNode = transitionNode.parent
71
71
  }
72
72
 
73
73
  const isAppear = !context._isMounted || !vnode.isRootInsert
@@ -43,8 +43,8 @@ function mapIdToFile (id, clientManifest) {
43
43
  if (fileIndices) {
44
44
  fileIndices.forEach(index => {
45
45
  const file = clientManifest.all[index]
46
- // only include async files or non-js assets
47
- if (clientManifest.async.indexOf(file) > -1 || !(/\.js($|\?)/.test(file))) {
46
+ // only include async files or non-js, non-css assets
47
+ if (clientManifest.async.indexOf(file) > -1 || !(/\.(js|css)($|\?)/.test(file))) {
48
48
  files.push(file)
49
49
  }
50
50
  })
@@ -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
@@ -1,5 +1,5 @@
1
1
  import { Vue, CreateElement, CombinedVueInstance } from "./vue";
2
- import { VNode, VNodeData, VNodeDirective, ScopedSlot } from "./vnode";
2
+ import { VNode, VNodeData, VNodeDirective, NormalizedScopedSlot } from "./vnode";
3
3
 
4
4
  type Constructor = {
5
5
  new (...args: any[]): any;
@@ -140,11 +140,11 @@ export interface RenderContext<Props=DefaultProps> {
140
140
  data: VNodeData;
141
141
  parent: Vue;
142
142
  listeners: { [key: string]: Function | Function[] };
143
- scopedSlots: { [key: string]: ScopedSlot };
143
+ scopedSlots: { [key: string]: NormalizedScopedSlot };
144
144
  injections: any
145
145
  }
146
146
 
147
- export type Prop<T> = { (): T } | { new(...args: any[]): T & object }
147
+ export type Prop<T> = { (): T } | { new(...args: any[]): T & object } | { new(...args: string[]): Function }
148
148
 
149
149
  export type PropType<T> = Prop<T> | Prop<T>[];
150
150
 
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
@@ -44,7 +48,7 @@ export interface VNodeData {
44
48
  staticClass?: string;
45
49
  class?: any;
46
50
  staticStyle?: { [key: string]: any };
47
- style?: object[] | object;
51
+ style?: string | object[] | object;
48
52
  props?: { [key: string]: any };
49
53
  attrs?: { [key: string]: any };
50
54
  domProps?: { [key: string]: any };
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, 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;