mirror of https://github.com/vuejs/core.git
fix(runtime-core): support `getCurrentInstance` across mutiple builds of Vue
This commit is contained in:
parent
f597dc69e7
commit
8d2d5bf48a
|
@ -56,7 +56,8 @@ import {
|
||||||
makeMap,
|
makeMap,
|
||||||
isPromise,
|
isPromise,
|
||||||
ShapeFlags,
|
ShapeFlags,
|
||||||
extend
|
extend,
|
||||||
|
getGlobalThis
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { SuspenseBoundary } from './components/Suspense'
|
import { SuspenseBoundary } from './components/Suspense'
|
||||||
import { CompilerOptions } from '@vue/compiler-core'
|
import { CompilerOptions } from '@vue/compiler-core'
|
||||||
|
@ -565,14 +566,73 @@ export let currentInstance: ComponentInternalInstance | null = null
|
||||||
export const getCurrentInstance: () => ComponentInternalInstance | null = () =>
|
export const getCurrentInstance: () => ComponentInternalInstance | null = () =>
|
||||||
currentInstance || currentRenderingInstance
|
currentInstance || currentRenderingInstance
|
||||||
|
|
||||||
|
type GlobalInstanceSetter = ((
|
||||||
|
instance: ComponentInternalInstance | null
|
||||||
|
) => void) & { version?: string }
|
||||||
|
|
||||||
|
let globalCurrentInstanceSetters: GlobalInstanceSetter[]
|
||||||
|
let internalSetCurrentInstance: GlobalInstanceSetter
|
||||||
|
let hasWarnedDuplicatedVue = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following makes getCurrentInstance() usage across multiple copies of Vue
|
||||||
|
* work. Some cases of how this can happen are summarized in #7590. In principle
|
||||||
|
* the duplication should be avoided, but in practice there are often cases
|
||||||
|
* where the user is unable to resolve on their own, especially in complicated
|
||||||
|
* SSR setups.
|
||||||
|
*
|
||||||
|
* Note this fix is technically incomplete, as we still rely on other singletons
|
||||||
|
* for effectScope and global reactive dependency maps. However, it does make
|
||||||
|
* some of the most common cases work. It also warns if the duplication is
|
||||||
|
* found during browser execution.
|
||||||
|
*/
|
||||||
|
if (__SSR__) {
|
||||||
|
const settersKey = '__VUE_INSTANCE_SETTERS__'
|
||||||
|
if (!(globalCurrentInstanceSetters = getGlobalThis()[settersKey])) {
|
||||||
|
globalCurrentInstanceSetters = getGlobalThis()[settersKey] = []
|
||||||
|
}
|
||||||
|
globalCurrentInstanceSetters.push(i => (currentInstance = i))
|
||||||
|
|
||||||
|
if (__DEV__) {
|
||||||
|
globalCurrentInstanceSetters[
|
||||||
|
globalCurrentInstanceSetters.length - 1
|
||||||
|
].version = __VERSION__
|
||||||
|
}
|
||||||
|
|
||||||
|
internalSetCurrentInstance = instance => {
|
||||||
|
if (globalCurrentInstanceSetters.length > 1) {
|
||||||
|
// eslint-disable-next-line no-restricted-globals
|
||||||
|
if (__DEV__ && !hasWarnedDuplicatedVue && typeof window !== 'undefined') {
|
||||||
|
warn(
|
||||||
|
`Mixed usage of duplicated Vue runtimes detected: ${globalCurrentInstanceSetters
|
||||||
|
.map(fn => fn.version)
|
||||||
|
.join(', ')}.\n` +
|
||||||
|
`This likely means there are multiple versions of Vue ` +
|
||||||
|
`duplicated in your dependency tree, and could lead to errors. ` +
|
||||||
|
`To avoid this warning, ensure that the all imports of Vue are resolving to ` +
|
||||||
|
`the same location on disk.`
|
||||||
|
)
|
||||||
|
hasWarnedDuplicatedVue = true
|
||||||
|
}
|
||||||
|
globalCurrentInstanceSetters.forEach(s => s(instance))
|
||||||
|
} else {
|
||||||
|
globalCurrentInstanceSetters[0](instance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
internalSetCurrentInstance = i => {
|
||||||
|
currentInstance = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const setCurrentInstance = (instance: ComponentInternalInstance) => {
|
export const setCurrentInstance = (instance: ComponentInternalInstance) => {
|
||||||
currentInstance = instance
|
internalSetCurrentInstance(instance)
|
||||||
instance.scope.on()
|
instance.scope.on()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const unsetCurrentInstance = () => {
|
export const unsetCurrentInstance = () => {
|
||||||
currentInstance && currentInstance.scope.off()
|
currentInstance && currentInstance.scope.off()
|
||||||
currentInstance = null
|
internalSetCurrentInstance(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
const isBuiltInTag = /*#__PURE__*/ makeMap('slot,component')
|
const isBuiltInTag = /*#__PURE__*/ makeMap('slot,component')
|
||||||
|
|
Loading…
Reference in New Issue