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,
|
||||
isPromise,
|
||||
ShapeFlags,
|
||||
extend
|
||||
extend,
|
||||
getGlobalThis
|
||||
} from '@vue/shared'
|
||||
import { SuspenseBoundary } from './components/Suspense'
|
||||
import { CompilerOptions } from '@vue/compiler-core'
|
||||
|
@ -565,14 +566,73 @@ export let currentInstance: ComponentInternalInstance | null = null
|
|||
export const getCurrentInstance: () => ComponentInternalInstance | null = () =>
|
||||
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) => {
|
||||
currentInstance = instance
|
||||
internalSetCurrentInstance(instance)
|
||||
instance.scope.on()
|
||||
}
|
||||
|
||||
export const unsetCurrentInstance = () => {
|
||||
currentInstance && currentInstance.scope.off()
|
||||
currentInstance = null
|
||||
internalSetCurrentInstance(null)
|
||||
}
|
||||
|
||||
const isBuiltInTag = /*#__PURE__*/ makeMap('slot,component')
|
||||
|
|
Loading…
Reference in New Issue