import { isFunction } from '@vue/shared'
-import { currentInstance } from './component'
-import { currentRenderingInstance } from './componentRenderContext'
+import { getCurrentGenericInstance } from './component'
import { currentApp } from './apiCreateApp'
import { warn } from './warning'
key: K,
value: K extends InjectionKey<infer V> ? V : T,
): void {
+ const currentInstance = getCurrentGenericInstance()
if (!currentInstance) {
if (__DEV__) {
warn(`provide() can only be used inside setup().`)
) {
// fallback to `currentRenderingInstance` so that this can be called in
// a functional component
- const instance = currentInstance || currentRenderingInstance
+ const instance = getCurrentGenericInstance()
// also support looking up from app-level provides w/ `app.runWithContext()`
if (instance || currentApp) {
? currentApp._context.provides
: instance
? instance.parent == null
- ? instance.vnode.appContext && instance.vnode.appContext.provides
+ ? instance.appContext && instance.appContext.provides
: instance.parent.provides
: undefined
* user. One example is `useRoute()` in `vue-router`.
*/
export function hasInjectionContext(): boolean {
- return !!(currentInstance || currentRenderingInstance || currentApp)
+ return !!(getCurrentGenericInstance() || currentApp)
}
import {
- type ComponentInternalInstance,
+ type GenericComponentInstance,
currentInstance,
isInSSRComponentSetup,
setCurrentInstance,
export function injectHook(
type: LifecycleHooks,
hook: Function & { __weh?: Function },
- target: ComponentInternalInstance | null = currentInstance,
+ target: GenericComponentInstance | null = currentInstance,
prepend: boolean = false,
): Function | undefined {
if (target) {
<T extends Function = () => any>(lifecycle: LifecycleHooks) =>
(
hook: T,
- target: ComponentInternalInstance | null = currentInstance,
+ target: GenericComponentInstance | null = currentInstance,
): void => {
// post-create lifecycle registrations are noops during SSR (except for serverPrefetch)
if (
}
type CreateHook<T = any> = (
hook: T,
- target?: ComponentInternalInstance | null,
+ target?: GenericComponentInstance | null,
) => void
export const onBeforeMount: CreateHook = createHook(LifecycleHooks.BEFORE_MOUNT)
export function onErrorCaptured<TError = Error>(
hook: ErrorCapturedHook<TError>,
- target: ComponentInternalInstance | null = currentInstance,
+ target: GenericComponentInstance | null = currentInstance,
): void {
injectHook(LifecycleHooks.ERROR_CAPTURED, hook, target)
}
* operate on both.
*/
export interface GenericComponentInstance {
+ vapor?: boolean
uid: number
type: GenericComponent
parent: GenericComponentInstance | null
// the following are for error handling logic only
proxy?: any
+
+ // lifecycle
+ /**
+ * @internal
+ */
+ [LifecycleHooks.BEFORE_CREATE]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.CREATED]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.BEFORE_MOUNT]?: LifecycleHook
/**
* @internal
*/
- [LifecycleHooks.ERROR_CAPTURED]: LifecycleHook
+ [LifecycleHooks.MOUNTED]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.BEFORE_UPDATE]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.UPDATED]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.BEFORE_UNMOUNT]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.UNMOUNTED]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.RENDER_TRACKED]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.RENDER_TRIGGERED]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.ACTIVATED]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.DEACTIVATED]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.ERROR_CAPTURED]?: LifecycleHook
+ /**
+ * @internal
+ */
+ [LifecycleHooks.SERVER_PREFETCH]?: LifecycleHook<() => Promise<unknown>>
}
/**
* useful for advanced external libraries and tools.
*/
export interface ComponentInternalInstance extends GenericComponentInstance {
+ vapor?: never
uid: number
type: ConcreteComponent
parent: ComponentInternalInstance | null
*/
asyncResolved: boolean
- // lifecycle
- /**
- * @internal
- */
- [LifecycleHooks.BEFORE_CREATE]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.CREATED]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.BEFORE_MOUNT]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.MOUNTED]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.BEFORE_UPDATE]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.UPDATED]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.BEFORE_UNMOUNT]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.UNMOUNTED]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.RENDER_TRACKED]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.RENDER_TRIGGERED]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.ACTIVATED]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.DEACTIVATED]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.ERROR_CAPTURED]: LifecycleHook
- /**
- * @internal
- */
- [LifecycleHooks.SERVER_PREFETCH]: LifecycleHook<() => Promise<unknown>>
-
/**
* For caching bound $forceUpdate on public proxy access
* @internal
import { getGlobalThis } from '@vue/shared'
-import type { ComponentInternalInstance } from './component'
+import type {
+ ComponentInternalInstance,
+ GenericComponentInstance,
+} from './component'
import { currentRenderingInstance } from './componentRenderContext'
-export let currentInstance: ComponentInternalInstance | null = null
+/**
+ * @internal
+ */
+export let currentInstance: GenericComponentInstance | null = null
+
+/**
+ * @internal
+ */
+export const getCurrentGenericInstance: () => GenericComponentInstance | null =
+ () => currentInstance || currentRenderingInstance
export const getCurrentInstance: () => ComponentInternalInstance | null = () =>
- currentInstance || currentRenderingInstance
+ currentInstance && !currentInstance.vapor
+ ? (currentInstance as ComponentInternalInstance)
+ : currentRenderingInstance
export let isInSSRComponentSetup = false
export let setInSSRSetupState: (state: boolean) => void
let internalSetCurrentInstance: (
- instance: ComponentInternalInstance | null,
+ instance: GenericComponentInstance | null,
) => void
/**
}
}
-export const setCurrentInstance = (instance: ComponentInternalInstance) => {
+/**
+ * @internal
+ */
+export const setCurrentInstance = (instance: GenericComponentInstance) => {
const prev = currentInstance
internalSetCurrentInstance(instance)
instance.scope.on()
type Data,
type InternalRenderFunction,
type SetupContext,
- currentInstance,
+ getCurrentInstance,
} from './component'
import {
type LooseRequired,
const options: WatchOptions = {}
if (__COMPAT__) {
- const instance =
- currentInstance && getCurrentScope() === currentInstance.scope
- ? currentInstance
- : null
+ const cur = getCurrentInstance()
+ const instance = cur && getCurrentScope() === cur.scope ? cur : null
const newValue = getter()
if (
type ComponentOptions,
type ConcreteComponent,
type SetupContext,
- currentInstance,
getComponentName,
getCurrentInstance,
} from '../component'
function registerKeepAliveHook(
hook: Function & { __wdc?: Function },
type: LifecycleHooks,
- target: ComponentInternalInstance | null = currentInstance,
+ target: ComponentInternalInstance | null = getCurrentInstance(),
) {
// cache the deactivate branch check wrapper for injected hooks so the same
// hook can be properly deduped by the scheduler. "__wdc" stands for "with
type AppMountFn,
type AppUnmountFn,
} from './apiCreateApp'
+export { currentInstance, setCurrentInstance } from './componentCurrentInstance'
type LifecycleHook,
type NormalizedPropsOptions,
type ObjectEmitsOptions,
+ currentInstance,
nextUid,
popWarningContext,
pushWarningContext,
+ setCurrentInstance,
warn,
} from '@vue/runtime-dom'
import { type Block, isBlock } from './block'
import { renderEffect } from './renderEffect'
import { emit, normalizeEmitsOptions } from './componentEmits'
+export { currentInstance } from '@vue/runtime-dom'
+
export type VaporComponent = FunctionalVaporComponent | ObjectVaporComponent
export type VaporSetupFn = (
): VaporComponentInstance {
// check if we are the single root of the parent
// if yes, inject parent attrs as dynamic props source
- if (isSingleRoot && currentInstance && currentInstance.hasFallthrough) {
+ if (
+ isSingleRoot &&
+ isVaporComponent(currentInstance) &&
+ currentInstance.hasFallthrough
+ ) {
const attrs = currentInstance.attrs
if (rawProps) {
;(rawProps.$ || (rawProps.$ = [])).push(() => attrs)
}
const instance = new VaporComponentInstance(component, rawProps)
+ const resetCurrentInstance = setCurrentInstance(instance)
pauseTracking()
- let prevInstance = currentInstance
- currentInstance = instance
- instance.scope.on()
-
if (__DEV__) {
pushWarningContext(instance)
}
if (__DEV__) {
popWarningContext()
}
-
- instance.scope.off()
- currentInstance = prevInstance
resetTracking()
+ resetCurrentInstance()
+
return instance
}
-export let currentInstance: VaporComponentInstance | null = null
-
const emptyContext: GenericAppContext = {
app: null as any,
config: {},
}
export class VaporComponentInstance implements GenericComponentInstance {
+ vapor: true
uid: number
type: VaporComponent
parent: GenericComponentInstance | null
hasFallthrough: boolean
+ // lifecycle hooks
isMounted: boolean
isUnmounted: boolean
isDeactivated: boolean
- // LifecycleHooks.ERROR_CAPTURED
- ec: LifecycleHook
+
+ bc?: LifecycleHook // LifecycleHooks.BEFORE_CREATE
+ c?: LifecycleHook // LifecycleHooks.CREATED
+ bm?: LifecycleHook // LifecycleHooks.BEFORE_MOUNT
+ m?: LifecycleHook // LifecycleHooks.MOUNTED
+ bu?: LifecycleHook // LifecycleHooks.BEFORE_UPDATE
+ u?: LifecycleHook // LifecycleHooks.UPDATED
+ um?: LifecycleHook // LifecycleHooks.BEFORE_UNMOUNT
+ bum?: LifecycleHook // LifecycleHooks.UNMOUNTED
+ da?: LifecycleHook // LifecycleHooks.DEACTIVATED
+ a?: LifecycleHook // LifecycleHooks.ACTIVATED
+ rtg?: LifecycleHook // LifecycleHooks.RENDER_TRACKED
+ rtc?: LifecycleHook // LifecycleHooks.RENDER_TRIGGERED
+ ec?: LifecycleHook // LifecycleHooks.ERROR_CAPTURED
+ sp?: LifecycleHook<() => Promise<unknown>> // LifecycleHooks.SERVER_PREFETCH
// dev only
setupState?: Record<string, any>
emitsOptions?: ObjectEmitsOptions | null
constructor(comp: VaporComponent, rawProps?: RawProps) {
+ this.vapor = true
this.uid = nextUid()
this.type = comp
- this.parent = currentInstance
+ this.parent = currentInstance // TODO when inside
this.appContext = currentInstance
? currentInstance.appContext
: emptyContext
this.block = null! // to be set
this.scope = new EffectScope(true)
- this.rawProps = rawProps
- this.provides = this.refs = EMPTY_OBJ
+ this.provides = currentInstance
+ ? currentInstance.provides
+ : Object.create(this.appContext.provides)
+ this.refs = EMPTY_OBJ
this.emitted = this.ec = this.exposed = this.propsDefaults = null
this.isMounted = this.isUnmounted = this.isDeactivated = false
// init props
const target = rawProps || EMPTY_OBJ
const handlers = getPropsProxyHandlers(comp, this)
+ this.rawProps = rawProps
this.props = comp.props ? new Proxy(target, handlers[0]!) : {}
this.attrs = new Proxy(target, handlers[1])
this.hasFallthrough = hasFallthroughAttrs(comp, rawProps)
import { ReactiveEffect } from '@vue/reactivity'
-import { type SchedulerJob, queueJob } from '@vue/runtime-dom'
-import { currentInstance } from './component'
+import { type SchedulerJob, currentInstance, queueJob } from '@vue/runtime-dom'
export function renderEffect(fn: () => void): void {
const updateFn = () => {