1
- import { reactive } from '@vue/reactivity'
2
- import { isFunction } from '@vue/shared'
1
+ import {
2
+ isReactive ,
3
+ reactive ,
4
+ track ,
5
+ TrackOpTypes ,
6
+ trigger ,
7
+ TriggerOpTypes
8
+ } from '@vue/reactivity'
9
+ import {
10
+ isFunction ,
11
+ extend ,
12
+ NOOP ,
13
+ EMPTY_OBJ ,
14
+ isArray ,
15
+ isObject
16
+ } from '@vue/shared'
3
17
import { warn } from '../warning'
4
18
import { cloneVNode , createVNode } from '../vnode'
5
19
import { RootRenderFunction } from '../renderer'
@@ -20,7 +34,7 @@ import {
20
34
isRuntimeOnly ,
21
35
setupComponent
22
36
} from '../component'
23
- import { RenderFunction } from '../componentOptions'
37
+ import { RenderFunction , mergeOptions } from '../componentOptions'
24
38
import { ComponentPublicInstance } from '../componentPublicInstance'
25
39
import { devtoolsInitApp } from '../devtools'
26
40
import { Directive } from '../directives'
@@ -129,17 +143,14 @@ export function createCompatVue(
129
143
isCopyingConfig = false
130
144
131
145
// copy prototype augmentations as config.globalProperties
132
- const isPrototypeEnabled = isCompatEnabled (
133
- DeprecationTypes . GLOBAL_PROTOTYPE ,
134
- null
135
- )
146
+ if ( isCompatEnabled ( DeprecationTypes . GLOBAL_PROTOTYPE , null ) ) {
147
+ app . config . globalProperties = Ctor . prototype
148
+ }
136
149
let hasPrototypeAugmentations = false
137
150
for ( const key in Ctor . prototype ) {
138
151
if ( key !== 'constructor' ) {
139
152
hasPrototypeAugmentations = true
140
- }
141
- if ( isPrototypeEnabled ) {
142
- app . config . globalProperties [ key ] = Ctor . prototype [ key ]
153
+ break
143
154
}
144
155
}
145
156
if ( __DEV__ && hasPrototypeAugmentations ) {
@@ -228,6 +239,21 @@ export function createCompatVue(
228
239
// TODO compiler warning for filters (maybe behavior compat?)
229
240
} ) as any
230
241
242
+ // internal utils - these are technically internal but some plugins use it.
243
+ const util = {
244
+ warn : __DEV__ ? warn : NOOP ,
245
+ extend,
246
+ mergeOptions : ( parent : any , child : any , vm ?: ComponentPublicInstance ) =>
247
+ mergeOptions ( parent , child , vm && vm . $ ) ,
248
+ defineReactive
249
+ }
250
+ Object . defineProperty ( Vue , 'util' , {
251
+ get ( ) {
252
+ assertCompatEnabled ( DeprecationTypes . GLOBAL_UTIL , null )
253
+ return util
254
+ }
255
+ } )
256
+
231
257
Vue . configureCompat = configureCompat
232
258
233
259
return Vue
@@ -358,3 +384,67 @@ export function installCompatMount(
358
384
return instance . proxy !
359
385
}
360
386
}
387
+
388
+ const methodsToPatch = [
389
+ 'push' ,
390
+ 'pop' ,
391
+ 'shift' ,
392
+ 'unshift' ,
393
+ 'splice' ,
394
+ 'sort' ,
395
+ 'reverse'
396
+ ]
397
+
398
+ const patched = new WeakSet < object > ( )
399
+
400
+ function defineReactive ( obj : any , key : string , val : any ) {
401
+ // it's possible for the orignial object to be mutated after being defined
402
+ // and expecting reactivity... we are covering it here because this seems to
403
+ // be a bit more common.
404
+ if ( isObject ( val ) && ! isReactive ( val ) && ! patched . has ( val ) ) {
405
+ const reactiveVal = reactive ( val )
406
+ if ( isArray ( val ) ) {
407
+ methodsToPatch . forEach ( m => {
408
+ // @ts -ignore
409
+ val [ m ] = ( ...args : any [ ] ) => {
410
+ // @ts -ignore
411
+ Array . prototype [ m ] . call ( reactiveVal , ...args )
412
+ }
413
+ } )
414
+ } else {
415
+ Object . keys ( val ) . forEach ( key => {
416
+ defineReactiveSimple ( val , key , val [ key ] )
417
+ } )
418
+ }
419
+ }
420
+
421
+ const i = obj . $
422
+ if ( i && obj === i . proxy ) {
423
+ // Vue instance, add it to data
424
+ if ( i . data === EMPTY_OBJ ) {
425
+ i . data = reactive ( { } )
426
+ }
427
+ i . data [ key ] = val
428
+ i . accessCache = Object . create ( null )
429
+ } else if ( isReactive ( obj ) ) {
430
+ obj [ key ] = val
431
+ } else {
432
+ defineReactiveSimple ( obj , key , val )
433
+ }
434
+ }
435
+
436
+ function defineReactiveSimple ( obj : any , key : string , val : any ) {
437
+ val = isObject ( val ) ? reactive ( val ) : val
438
+ Object . defineProperty ( obj , key , {
439
+ enumerable : true ,
440
+ configurable : true ,
441
+ get ( ) {
442
+ track ( obj , TrackOpTypes . GET , key )
443
+ return val
444
+ } ,
445
+ set ( newVal ) {
446
+ val = isObject ( newVal ) ? reactive ( newVal ) : newVal
447
+ trigger ( obj , TriggerOpTypes . SET , key , newVal )
448
+ }
449
+ } )
450
+ }
0 commit comments