@@ -56,7 +56,8 @@ import {
5656 makeMap ,
5757 isPromise ,
5858 ShapeFlags ,
59- extend
59+ extend ,
60+ getGlobalThis
6061} from '@vue/shared'
6162import { SuspenseBoundary } from './components/Suspense'
6263import { CompilerOptions } from '@vue/compiler-core'
@@ -565,14 +566,73 @@ export let currentInstance: ComponentInternalInstance | null = null
565566export const getCurrentInstance : ( ) => ComponentInternalInstance | null = ( ) =>
566567 currentInstance || currentRenderingInstance
567568
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+
568628export const setCurrentInstance = ( instance : ComponentInternalInstance ) => {
569- currentInstance = instance
629+ internalSetCurrentInstance ( instance )
570630 instance . scope . on ( )
571631}
572632
573633export const unsetCurrentInstance = ( ) => {
574634 currentInstance && currentInstance . scope . off ( )
575- currentInstance = null
635+ internalSetCurrentInstance ( null )
576636}
577637
578638const isBuiltInTag = /*#__PURE__*/ makeMap ( 'slot,component' )
0 commit comments