vue 2.7.4 → 2.7.7

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 (36) hide show
  1. package/dist/vue.common.dev.js +2693 -2657
  2. package/dist/vue.common.prod.js +3 -3
  3. package/dist/vue.esm.browser.js +2693 -2657
  4. package/dist/vue.esm.browser.min.js +3 -3
  5. package/dist/vue.esm.js +3813 -3776
  6. package/dist/vue.js +3781 -3744
  7. package/dist/vue.min.js +3 -3
  8. package/dist/vue.runtime.common.dev.js +2930 -2895
  9. package/dist/vue.runtime.common.prod.js +3 -3
  10. package/dist/vue.runtime.esm.js +2942 -2906
  11. package/dist/vue.runtime.js +2660 -2624
  12. package/dist/vue.runtime.min.js +3 -3
  13. package/dist/vue.runtime.mjs +1 -0
  14. package/package.json +2 -2
  15. package/packages/compiler-sfc/dist/compiler-sfc.js +1033 -1026
  16. package/packages/compiler-sfc/package.json +1 -1
  17. package/src/compiler/codegen/index.ts +3 -2
  18. package/src/core/components/keep-alive.ts +5 -4
  19. package/src/core/global-api/extend.ts +3 -1
  20. package/src/core/instance/init.ts +1 -1
  21. package/src/core/instance/inject.ts +10 -5
  22. package/src/core/instance/lifecycle.ts +8 -3
  23. package/src/core/instance/render.ts +8 -2
  24. package/src/core/observer/scheduler.ts +10 -1
  25. package/src/core/observer/traverse.ts +3 -0
  26. package/src/core/observer/watcher.ts +2 -0
  27. package/src/core/util/debug.ts +2 -1
  28. package/src/core/vdom/create-component.ts +5 -1
  29. package/src/platforms/web/runtime/components/transition-group.ts +2 -1
  30. package/src/v3/apiInject.ts +17 -12
  31. package/src/v3/apiWatch.ts +5 -7
  32. package/src/v3/reactivity/ref.ts +11 -2
  33. package/types/options.d.ts +2 -0
  34. package/types/v3-component-public-instance.d.ts +15 -15
  35. package/types/v3-setup-context.d.ts +1 -0
  36. package/types/vue.d.ts +27 -11
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue/compiler-sfc",
3
- "version": "2.7.4",
3
+ "version": "2.7.7",
4
4
  "description": "compiler-sfc for Vue 2",
5
5
  "main": "dist/compiler-sfc.js",
6
6
  "types": "dist/compiler-sfc.d.ts",
@@ -95,14 +95,15 @@ export function genElement(el: ASTElement, state: CodegenState): string {
95
95
  code = genComponent(el.component, el, state)
96
96
  } else {
97
97
  let data
98
- if (!el.plain || (el.pre && state.maybeComponent(el))) {
98
+ const maybeComponent = state.maybeComponent(el)
99
+ if (!el.plain || (el.pre && maybeComponent)) {
99
100
  data = genData(el, state)
100
101
  }
101
102
 
102
103
  let tag: string | undefined
103
104
  // check if this is a component in <script setup>
104
105
  const bindings = state.options.bindings
105
- if (bindings && bindings.__isScriptSetup !== false) {
106
+ if (maybeComponent && bindings && bindings.__isScriptSetup !== false) {
106
107
  tag =
107
108
  checkBindingType(bindings, el.tag) ||
108
109
  checkBindingType(bindings, camelize(el.tag)) ||
@@ -3,6 +3,7 @@ import { getFirstComponentChild } from 'core/vdom/helpers/index'
3
3
  import type VNode from 'core/vdom/vnode'
4
4
  import type { VNodeComponentOptions } from 'types/vnode'
5
5
  import type { Component } from 'types/component'
6
+ import { getComponentName } from '../vdom/create-component'
6
7
 
7
8
  type CacheEntry = {
8
9
  name?: string
@@ -12,8 +13,8 @@ type CacheEntry = {
12
13
 
13
14
  type CacheEntryMap = Record<string, CacheEntry | null>
14
15
 
15
- function getComponentName(opts?: VNodeComponentOptions): string | null {
16
- return opts && (opts.Ctor.options.name || opts.tag)
16
+ function _getComponentName(opts?: VNodeComponentOptions): string | null {
17
+ return opts && (getComponentName(opts.Ctor.options as any) || opts.tag)
17
18
  }
18
19
 
19
20
  function matches(
@@ -81,7 +82,7 @@ export default {
81
82
  if (vnodeToCache) {
82
83
  const { tag, componentInstance, componentOptions } = vnodeToCache
83
84
  cache[keyToCache] = {
84
- name: getComponentName(componentOptions),
85
+ name: _getComponentName(componentOptions),
85
86
  tag,
86
87
  componentInstance
87
88
  }
@@ -126,7 +127,7 @@ export default {
126
127
  const componentOptions = vnode && vnode.componentOptions
127
128
  if (componentOptions) {
128
129
  // check pattern
129
- const name = getComponentName(componentOptions)
130
+ const name = _getComponentName(componentOptions)
130
131
  const { include, exclude } = this
131
132
  if (
132
133
  // not included
@@ -3,6 +3,7 @@ import type { Component } from 'types/component'
3
3
  import type { GlobalAPI } from 'types/global-api'
4
4
  import { defineComputed, proxy } from '../instance/state'
5
5
  import { extend, mergeOptions, validateComponentName } from '../util/index'
6
+ import { getComponentName } from '../vdom/create-component'
6
7
 
7
8
  export function initExtend(Vue: GlobalAPI) {
8
9
  /**
@@ -25,7 +26,8 @@ export function initExtend(Vue: GlobalAPI) {
25
26
  return cachedCtors[SuperId]
26
27
  }
27
28
 
28
- const name = extendOptions.name || Super.options.name
29
+ const name =
30
+ getComponentName(extendOptions) || getComponentName(Super.options)
29
31
  if (__DEV__ && name) {
30
32
  validateComponentName(name)
31
33
  }
@@ -58,7 +58,7 @@ export function initMixin(Vue: typeof Component) {
58
58
  initLifecycle(vm)
59
59
  initEvents(vm)
60
60
  initRender(vm)
61
- callHook(vm, 'beforeCreate')
61
+ callHook(vm, 'beforeCreate', undefined, false /* setContext */)
62
62
  initInjections(vm) // resolve injections before data/props
63
63
  initState(vm)
64
64
  initProvide(vm) // resolve provide after data/props
@@ -1,8 +1,7 @@
1
1
  import { warn, hasSymbol, isFunction, isObject } from '../util/index'
2
2
  import { defineReactive, toggleObserving } from '../observer/index'
3
3
  import type { Component } from 'types/component'
4
- import { provide } from 'v3/apiInject'
5
- import { setCurrentInstance } from '../../v3/currentInstance'
4
+ import { resolveProvided } from 'v3/apiInject'
6
5
 
7
6
  export function initProvide(vm: Component) {
8
7
  const provideOption = vm.$options.provide
@@ -13,12 +12,18 @@ export function initProvide(vm: Component) {
13
12
  if (!isObject(provided)) {
14
13
  return
15
14
  }
15
+ const source = resolveProvided(vm)
16
+ // IE9 doesn't support Object.getOwnPropertyDescriptors so we have to
17
+ // iterate the keys ourselves.
16
18
  const keys = hasSymbol ? Reflect.ownKeys(provided) : Object.keys(provided)
17
- setCurrentInstance(vm)
18
19
  for (let i = 0; i < keys.length; i++) {
19
- provide(keys[i], provided[keys[i]])
20
+ const key = keys[i]
21
+ Object.defineProperty(
22
+ source,
23
+ key,
24
+ Object.getOwnPropertyDescriptor(provided, key)!
25
+ )
20
26
  }
21
- setCurrentInstance()
22
27
  }
23
28
  }
24
29
 
@@ -375,11 +375,16 @@ export function deactivateChildComponent(vm: Component, direct?: boolean) {
375
375
  }
376
376
  }
377
377
 
378
- export function callHook(vm: Component, hook: string, args?: any[]) {
378
+ export function callHook(
379
+ vm: Component,
380
+ hook: string,
381
+ args?: any[],
382
+ setContext = true
383
+ ) {
379
384
  // #7573 disable dep collection when invoking lifecycle hooks
380
385
  pushTarget()
381
386
  const prev = currentInstance
382
- setCurrentInstance(vm)
387
+ setContext && setCurrentInstance(vm)
383
388
  const handlers = vm.$options[hook]
384
389
  const info = `${hook} hook`
385
390
  if (handlers) {
@@ -390,6 +395,6 @@ export function callHook(vm: Component, hook: string, args?: any[]) {
390
395
  if (vm._hasHookEvent) {
391
396
  vm.$emit('hook:' + hook)
392
397
  }
393
- setCurrentInstance(prev)
398
+ setContext && setCurrentInstance(prev)
394
399
  popTarget()
395
400
  }
@@ -25,7 +25,13 @@ export function initRender(vm: Component) {
25
25
  const parentVnode = (vm.$vnode = options._parentVnode!) // the placeholder node in parent tree
26
26
  const renderContext = parentVnode && (parentVnode.context as Component)
27
27
  vm.$slots = resolveSlots(options._renderChildren, renderContext)
28
- vm.$scopedSlots = emptyObject
28
+ vm.$scopedSlots = parentVnode
29
+ ? normalizeScopedSlots(
30
+ vm.$parent!,
31
+ parentVnode.data!.scopedSlots,
32
+ vm.$slots
33
+ )
34
+ : emptyObject
29
35
  // bind the createElement fn to this instance
30
36
  // so that we get proper render context inside it.
31
37
  // args order: tag, data, children, normalizationType, alwaysNormalize
@@ -98,7 +104,7 @@ export function renderMixin(Vue: typeof Component) {
98
104
  const vm: Component = this
99
105
  const { render, _parentVnode } = vm.$options
100
106
 
101
- if (_parentVnode) {
107
+ if (_parentVnode && vm._isMounted) {
102
108
  vm.$scopedSlots = normalizeScopedSlots(
103
109
  vm.$parent!,
104
110
  _parentVnode.data!.scopedSlots,
@@ -59,6 +59,15 @@ if (inBrowser && !isIE) {
59
59
  }
60
60
  }
61
61
 
62
+ const sortCompareFn = (a: Watcher, b: Watcher): number => {
63
+ if (a.post) {
64
+ if (!b.post) return 1
65
+ } else if (b.post) {
66
+ return -1
67
+ }
68
+ return a.id - b.id
69
+ }
70
+
62
71
  /**
63
72
  * Flush both queues and run the watchers.
64
73
  */
@@ -75,7 +84,7 @@ function flushSchedulerQueue() {
75
84
  // user watchers are created before the render watcher)
76
85
  // 3. If a component is destroyed during a parent component's watcher run,
77
86
  // its watchers can be skipped.
78
- queue.sort((a, b) => a.id - b.id)
87
+ queue.sort(sortCompareFn)
79
88
 
80
89
  // do not cache length because more watchers might be pushed
81
90
  // as we run existing watchers
@@ -1,6 +1,7 @@
1
1
  import { _Set as Set, isObject, isArray } from '../util/index'
2
2
  import type { SimpleSet } from '../util/index'
3
3
  import VNode from '../vdom/vnode'
4
+ import { isRef } from '../../v3'
4
5
 
5
6
  const seenObjects = new Set()
6
7
 
@@ -35,6 +36,8 @@ function _traverse(val: any, seen: SimpleSet) {
35
36
  if (isA) {
36
37
  i = val.length
37
38
  while (i--) _traverse(val[i], seen)
39
+ } else if (isRef(val)) {
40
+ _traverse(val.value, seen)
38
41
  } else {
39
42
  keys = Object.keys(val)
40
43
  i = keys.length
@@ -58,6 +58,7 @@ export default class Watcher implements DepTarget {
58
58
  noRecurse?: boolean
59
59
  getter: Function
60
60
  value: any
61
+ post: boolean
61
62
 
62
63
  // dev only
63
64
  onTrack?: ((event: DebuggerEvent) => void) | undefined
@@ -93,6 +94,7 @@ export default class Watcher implements DepTarget {
93
94
  this.cb = cb
94
95
  this.id = ++uid // uid for batching
95
96
  this.active = true
97
+ this.post = false
96
98
  this.dirty = this.lazy // for lazy watchers
97
99
  this.deps = []
98
100
  this.newDeps = []
@@ -2,6 +2,7 @@ import config from '../config'
2
2
  import { noop, isArray, isFunction } from 'shared/util'
3
3
  import type { Component } from 'types/component'
4
4
  import { currentInstance } from 'v3/currentInstance'
5
+ import { getComponentName } from '../vdom/create-component'
5
6
 
6
7
  export let warn: (msg: string, vm?: Component | null) => void = noop
7
8
  export let tip = noop
@@ -40,7 +41,7 @@ if (__DEV__) {
40
41
  : vm._isVue
41
42
  ? vm.$options || (vm.constructor as any).options
42
43
  : vm
43
- let name = options.name || options._componentTag
44
+ let name = getComponentName(options)
44
45
  const file = options.__file
45
46
  if (!name && file) {
46
47
  const match = file.match(/([^/\\]+)\.vue$/)
@@ -28,6 +28,10 @@ import type {
28
28
  import type { Component } from 'types/component'
29
29
  import type { ComponentOptions, InternalComponentOptions } from 'types/options'
30
30
 
31
+ export function getComponentName(options: ComponentOptions) {
32
+ return options.name || options.__name || options._componentTag
33
+ }
34
+
31
35
  // inline hooks to be invoked on component VNodes during patch
32
36
  const componentVNodeHooks = {
33
37
  init(vnode: VNodeWithData, hydrating: boolean): boolean | void {
@@ -188,7 +192,7 @@ export function createComponent(
188
192
 
189
193
  // return a placeholder vnode
190
194
  // @ts-expect-error
191
- const name = Ctor.options.name || tag
195
+ const name = getComponentName(Ctor.options) || tag
192
196
  const vnode = new VNode(
193
197
  // @ts-expect-error
194
198
  `vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
@@ -23,6 +23,7 @@ import {
23
23
  } from 'web/runtime/transition-util'
24
24
  import VNode from 'core/vdom/vnode'
25
25
  import { VNodeWithData } from 'types/vnode'
26
+ import { getComponentName } from 'core/vdom/create-component'
26
27
 
27
28
  const props = extend(
28
29
  {
@@ -72,7 +73,7 @@ export default {
72
73
  } else if (__DEV__) {
73
74
  const opts = c.componentOptions
74
75
  const name: string = opts
75
- ? opts.Ctor.options.name || opts.tag || ''
76
+ ? getComponentName(opts.Ctor.options as any) || opts.tag || ''
76
77
  : c.tag
77
78
  warn(`<transition-group> children must be keyed: <${name}>`)
78
79
  }
@@ -1,5 +1,6 @@
1
1
  import { isFunction, warn } from 'core/util'
2
2
  import { currentInstance } from './currentInstance'
3
+ import type { Component } from 'types/component'
3
4
 
4
5
  export interface InjectionKey<T> extends Symbol {}
5
6
 
@@ -9,19 +10,23 @@ export function provide<T>(key: InjectionKey<T> | string | number, value: T) {
9
10
  warn(`provide() can only be used inside setup().`)
10
11
  }
11
12
  } else {
12
- let provides = currentInstance._provided
13
- // by default an instance inherits its parent's provides object
14
- // but when it needs to provide values of its own, it creates its
15
- // own provides object using parent provides object as prototype.
16
- // this way in `inject` we can simply look up injections from direct
17
- // parent and let the prototype chain do the work.
18
- const parentProvides =
19
- currentInstance.$parent && currentInstance.$parent._provided
20
- if (parentProvides === provides) {
21
- provides = currentInstance._provided = Object.create(parentProvides)
22
- }
23
13
  // TS doesn't allow symbol as index type
24
- provides[key as string] = value
14
+ resolveProvided(currentInstance)[key as string] = value
15
+ }
16
+ }
17
+
18
+ export function resolveProvided(vm: Component): Record<string, any> {
19
+ // by default an instance inherits its parent's provides object
20
+ // but when it needs to provide values of its own, it creates its
21
+ // own provides object using parent provides object as prototype.
22
+ // this way in `inject` we can simply look up injections from direct
23
+ // parent and let the prototype chain do the work.
24
+ const existing = vm._provided
25
+ const parentProvides = vm.$parent && vm.$parent._provided
26
+ if (parentProvides === existing) {
27
+ return (vm._provided = Object.create(parentProvides))
28
+ } else {
29
+ return existing
25
30
  }
26
31
  }
27
32
 
@@ -196,12 +196,10 @@ function doWatch(
196
196
  getter = () => source.value
197
197
  forceTrigger = isShallow(source)
198
198
  } else if (isReactive(source)) {
199
- getter = isArray(source)
200
- ? () => {
201
- ;(source as any).__ob__.dep.depend()
202
- return source
203
- }
204
- : () => source
199
+ getter = () => {
200
+ ;(source as any).__ob__.dep.depend()
201
+ return source
202
+ }
205
203
  deep = true
206
204
  } else if (isArray(source)) {
207
205
  isMultiSource = true
@@ -315,7 +313,7 @@ function doWatch(
315
313
  if (flush === 'sync') {
316
314
  watcher.update = watcher.run
317
315
  } else if (flush === 'post') {
318
- watcher.id = Infinity
316
+ watcher.post = true
319
317
  watcher.update = () => queueWatcher(watcher)
320
318
  } else {
321
319
  // pre
@@ -68,7 +68,7 @@ function createRef(rawValue: unknown, shallow: boolean) {
68
68
  }
69
69
  const ref: any = {}
70
70
  def(ref, RefFlag, true)
71
- def(ref, ReactiveFlags.IS_SHALLOW, true)
71
+ def(ref, ReactiveFlags.IS_SHALLOW, shallow)
72
72
  def(
73
73
  ref,
74
74
  'dep',
@@ -119,7 +119,16 @@ export function proxyWithRefUnwrap(
119
119
  Object.defineProperty(target, key, {
120
120
  enumerable: true,
121
121
  configurable: true,
122
- get: () => unref(source[key]),
122
+ get: () => {
123
+ const val = source[key]
124
+ if (isRef(val)) {
125
+ return val.value
126
+ } else {
127
+ const ob = val && val.__ob__
128
+ if (ob) ob.dep.depend()
129
+ return val
130
+ }
131
+ },
123
132
  set: value => {
124
133
  const oldValue = source[key]
125
134
  if (isRef(oldValue) && !isRef(value)) {
@@ -219,6 +219,8 @@ export interface ComponentOptions<
219
219
  parent?: Vue
220
220
  mixins?: (ComponentOptions<Vue> | typeof Vue)[]
221
221
  name?: string
222
+ // for SFC auto name inference w/ ts-loader check
223
+ __name?: string
222
224
  // TODO: support properly inferred 'extends'
223
225
  extends?: ComponentOptions<Vue> | typeof Vue
224
226
  delimiters?: [string, string]
@@ -5,7 +5,7 @@ import {
5
5
  } from './v3-generated'
6
6
  import { UnionToIntersection } from './common'
7
7
 
8
- import { Vue, Vue2Instance, VueConstructor } from './vue'
8
+ import { Vue, VueConstructor } from './vue'
9
9
  import {
10
10
  ComputedOptions,
11
11
  MethodOptions,
@@ -13,8 +13,7 @@ import {
13
13
  ComponentOptionsMixin,
14
14
  ComponentOptionsBase
15
15
  } from './v3-component-options'
16
- import { EmitFn, EmitsOptions, Slots } from './v3-setup-context'
17
- import { VNode } from './vnode'
16
+ import { EmitFn, EmitsOptions } from './v3-setup-context'
18
17
 
19
18
  /**
20
19
  * Custom properties added to component instances in any way and can be accessed through `this`
@@ -173,18 +172,19 @@ interface Vue3Instance<
173
172
  Defaults,
174
173
  MakeDefaultsOptional,
175
174
  Options
176
- > extends Vue2Instance {
177
- $data: D
178
- readonly $props: Readonly<
179
- MakeDefaultsOptional extends true
180
- ? Partial<Defaults> & Omit<P & PublicProps, keyof Defaults>
181
- : P & PublicProps
182
- >
183
- readonly $root: ComponentPublicInstance | null
184
- readonly $parent: ComponentPublicInstance | null
185
- readonly $emit: EmitFn<E>
186
- readonly $options: Options & MergedComponentOptionsOverride
187
- }
175
+ > extends Vue<
176
+ D,
177
+ Readonly<
178
+ MakeDefaultsOptional extends true
179
+ ? Partial<Defaults> & Omit<P & PublicProps, keyof Defaults>
180
+ : P & PublicProps
181
+ >,
182
+ ComponentPublicInstance | null,
183
+ ComponentPublicInstance,
184
+ ComponentPublicInstance[],
185
+ Options & MergedComponentOptionsOverride,
186
+ EmitFn<E>
187
+ > {}
188
188
 
189
189
  type MergedHook<T = () => void> = T | T[]
190
190
 
@@ -33,4 +33,5 @@ export interface SetupContext<E extends EmitsOptions = {}> {
33
33
  attrs: Data
34
34
  slots: Slots
35
35
  emit: EmitFn<E>
36
+ expose(exposed?: Record<string, any>): void
36
37
  }
package/types/vue.d.ts CHANGED
@@ -14,6 +14,7 @@ import { VNode, VNodeData, VNodeChildren, NormalizedScopedSlot } from './vnode'
14
14
  import { PluginFunction, PluginObject } from './plugin'
15
15
  import { DefineComponent } from './v3-define-component'
16
16
  import { nextTick } from './v3-generated'
17
+ import { ComponentPublicInstance } from './v3-component-public-instance'
17
18
 
18
19
  export interface CreateElement {
19
20
  (
@@ -35,20 +36,35 @@ export interface CreateElement {
35
36
  ): VNode
36
37
  }
37
38
 
38
- export interface Vue extends Vue2Instance {
39
- readonly $data: Record<string, any>
40
- readonly $props: Record<string, any>
41
- readonly $parent: Vue
42
- readonly $root: Vue
43
- readonly $children: Vue[]
44
- readonly $options: ComponentOptions<Vue>
45
- $emit(event: string, ...args: any[]): this
46
- }
39
+ type NeverFallback<T, D> = [T] extends [never] ? D : T
40
+
41
+ export interface Vue<
42
+ Data = Record<string, any>,
43
+ Props = Record<string, any>,
44
+ Parent = never,
45
+ Root = never,
46
+ Children = never,
47
+ Options = never,
48
+ Emit = (event: string, ...args: any[]) => Vue
49
+ > {
50
+ // properties with different types in defineComponent()
51
+ readonly $data: Data
52
+ readonly $props: Props
53
+ readonly $parent: NeverFallback<Parent, Vue>
54
+ readonly $root: NeverFallback<Root, Vue>
55
+ readonly $children: NeverFallback<Children, Vue[]>
56
+ readonly $options: NeverFallback<Options, ComponentOptions<Vue>>
57
+ $emit: Emit
47
58
 
48
- export interface Vue2Instance {
59
+ // Vue 2 only or shared
49
60
  readonly $el: Element
50
61
  readonly $refs: {
51
- [key: string]: Vue | Element | (Vue | Element)[] | undefined
62
+ [key: string]:
63
+ | Vue
64
+ | Element
65
+ | ComponentPublicInstance
66
+ | (Vue | Element | ComponentPublicInstance)[]
67
+ | undefined
52
68
  }
53
69
  readonly $slots: { [key: string]: VNode[] | undefined }
54
70
  readonly $scopedSlots: { [key: string]: NormalizedScopedSlot | undefined }