@@ -56,7 +56,8 @@ import {
56
56
makeMap ,
57
57
isPromise ,
58
58
ShapeFlags ,
59
- extend
59
+ extend ,
60
+ getGlobalThis
60
61
} from '@vue/shared'
61
62
import { SuspenseBoundary } from './components/Suspense'
62
63
import { CompilerOptions } from '@vue/compiler-core'
@@ -565,14 +566,73 @@ export let currentInstance: ComponentInternalInstance | null = null
565
566
export const getCurrentInstance : ( ) => ComponentInternalInstance | null = ( ) =>
566
567
currentInstance || currentRenderingInstance
567
568
569
+ type GlobalInstanceSetter = ( (
570
+ instance : ComponentInternalInstance | null
571
+ ) => void ) & { version ?: string }
572
+
573
+ let globalCurrentInstanceSetters : GlobalInstanceSetter [ ]
574
+ let internalSetCurrentInstance : GlobalInstanceSetter
575
+ let hasWarnedDuplicatedVue = false
576
+
577
+ /**
578
+ * The following makes getCurrentInstance() usage across multiple copies of Vue
579
+ * work. Some cases of how this can happen are summarized in #7590. In principle
580
+ * the duplication should be avoided, but in practice there are often cases
581
+ * where the user is unable to resolve on their own, especially in complicated
582
+ * SSR setups.
583
+ *
584
+ * Note this fix is technically incomplete, as we still rely on other singletons
585
+ * for effectScope and global reactive dependency maps. However, it does make
586
+ * some of the most common cases work. It also warns if the duplication is
587
+ * found during browser execution.
588
+ */
589
+ if ( __SSR__ ) {
590
+ const settersKey = '__VUE_INSTANCE_SETTERS__'
591
+ if ( ! ( globalCurrentInstanceSetters = getGlobalThis ( ) [ settersKey ] ) ) {
592
+ globalCurrentInstanceSetters = getGlobalThis ( ) [ settersKey ] = [ ]
593
+ }
594
+ globalCurrentInstanceSetters . push ( i => ( currentInstance = i ) )
595
+
596
+ if ( __DEV__ ) {
597
+ globalCurrentInstanceSetters [
598
+ globalCurrentInstanceSetters . length - 1
599
+ ] . version = __VERSION__
600
+ }
601
+
602
+ internalSetCurrentInstance = instance => {
603
+ if ( globalCurrentInstanceSetters . length > 1 ) {
604
+ // eslint-disable-next-line no-restricted-globals
605
+ if ( __DEV__ && ! hasWarnedDuplicatedVue && typeof window !== 'undefined' ) {
606
+ warn (
607
+ `Mixed usage of duplicated Vue runtimes detected: ${ globalCurrentInstanceSetters
608
+ . map ( fn => fn . version )
609
+ . join ( ', ' ) } .\n` +
610
+ `This likely means there are multiple versions of Vue ` +
611
+ `duplicated in your dependency tree, and could lead to errors. ` +
612
+ `To avoid this warning, ensure that the all imports of Vue are resolving to ` +
613
+ `the same location on disk.`
614
+ )
615
+ hasWarnedDuplicatedVue = true
616
+ }
617
+ globalCurrentInstanceSetters . forEach ( s => s ( instance ) )
618
+ } else {
619
+ globalCurrentInstanceSetters [ 0 ] ( instance )
620
+ }
621
+ }
622
+ } else {
623
+ internalSetCurrentInstance = i => {
624
+ currentInstance = i
625
+ }
626
+ }
627
+
568
628
export const setCurrentInstance = ( instance : ComponentInternalInstance ) => {
569
- currentInstance = instance
629
+ internalSetCurrentInstance ( instance )
570
630
instance . scope . on ( )
571
631
}
572
632
573
633
export const unsetCurrentInstance = ( ) => {
574
634
currentInstance && currentInstance . scope . off ( )
575
- currentInstance = null
635
+ internalSetCurrentInstance ( null )
576
636
}
577
637
578
638
const isBuiltInTag = /*#__PURE__*/ makeMap ( 'slot,component' )
0 commit comments