| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- import { getGlobalThis } from '@vue/shared'
- import type {
- ComponentInternalInstance,
- GenericComponentInstance,
- } from './component'
- import { currentRenderingInstance } from './componentRenderContext'
- import { type EffectScope, setCurrentScope } from '@vue/reactivity'
- import { warn } from './warning'
- /**
- * @internal
- */
- export let currentInstance: GenericComponentInstance | null = null
- /**
- * @internal
- */
- export const getCurrentGenericInstance: () => GenericComponentInstance | null =
- () => currentInstance || currentRenderingInstance
- export const getCurrentInstance: () => ComponentInternalInstance | null = () =>
- currentInstance && !currentInstance.vapor
- ? (currentInstance as ComponentInternalInstance)
- : currentRenderingInstance
- export let isInSSRComponentSetup = false
- export let setInSSRSetupState: (state: boolean) => void
- /**
- * @internal
- */
- export let simpleSetCurrentInstance: (
- instance: GenericComponentInstance | null,
- ) => void
- /**
- * 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__) {
- type Setter = (v: any) => void
- const g = getGlobalThis()
- const registerGlobalSetter = (key: string, setter: Setter) => {
- let setters: Setter[]
- if (!(setters = g[key])) setters = g[key] = []
- setters.push(setter)
- return (v: any) => {
- if (setters.length > 1) setters.forEach(set => set(v))
- else setters[0](v)
- }
- }
- simpleSetCurrentInstance = registerGlobalSetter(
- `__VUE_INSTANCE_SETTERS__`,
- v => (currentInstance = v),
- )
- // also make `isInSSRComponentSetup` sharable across copies of Vue.
- // this is needed in the SFC playground when SSRing async components, since
- // we have to load both the runtime and the server-renderer from CDNs, they
- // contain duplicated copies of Vue runtime code.
- setInSSRSetupState = registerGlobalSetter(
- `__VUE_SSR_SETTERS__`,
- v => (isInSSRComponentSetup = v),
- )
- } else {
- simpleSetCurrentInstance = i => {
- currentInstance = i
- }
- setInSSRSetupState = v => {
- isInSSRComponentSetup = v
- }
- }
- export const setCurrentInstance = (
- instance: GenericComponentInstance | null,
- scope: EffectScope | undefined = instance !== null
- ? instance.scope
- : undefined,
- ): [GenericComponentInstance | null, EffectScope | undefined] => {
- try {
- return [currentInstance, setCurrentScope(scope)]
- } finally {
- simpleSetCurrentInstance(instance)
- }
- }
- const internalOptions = ['ce', 'type'] as const
- /**
- * @internal
- */
- export const useInstanceOption = <K extends (typeof internalOptions)[number]>(
- key: K,
- silent = false,
- ): {
- hasInstance: boolean
- value: GenericComponentInstance[K] | undefined
- } => {
- const instance = getCurrentGenericInstance()
- if (!instance) {
- if (__DEV__ && !silent) {
- warn(`useInstanceOption called without an active component instance.`)
- }
- return { hasInstance: false, value: undefined }
- }
- if (!internalOptions.includes(key)) {
- if (__DEV__) {
- warn(
- `useInstanceOption only accepts ` +
- ` ${internalOptions.map(k => `'${k}'`).join(', ')} as key, got '${key}'.`,
- )
- }
- return { hasInstance: true, value: undefined }
- }
- return { hasInstance: true, value: instance[key] }
- }
|