diff --git a/packages/runtime-core/__tests__/directives.spec.ts b/packages/runtime-core/__tests__/directives.spec.ts index 8d9982548..96ca009e1 100644 --- a/packages/runtime-core/__tests__/directives.spec.ts +++ b/packages/runtime-core/__tests__/directives.spec.ts @@ -11,7 +11,7 @@ import { withDirectives, } from '@vue/runtime-test' import { - type ComponentInternalInstance, + type GenericComponentInstance, currentInstance, } from '../src/component' @@ -111,7 +111,7 @@ describe('directives', () => { unmounted, } - let _instance: ComponentInternalInstance | null = null + let _instance: GenericComponentInstance | null = null let _vnode: VNode | null = null let _prevVnode: VNode | null = null const Comp = { @@ -171,7 +171,7 @@ describe('directives', () => { expect(prevVNode).toBe(_prevVnode) }) as DirectiveHook) - let _instance: ComponentInternalInstance | null = null + let _instance: GenericComponentInstance | null = null let _vnode: VNode | null = null let _prevVnode: VNode | null = null const Comp = { @@ -300,7 +300,7 @@ describe('directives', () => { unmounted, } - let _instance: ComponentInternalInstance | null = null + let _instance: GenericComponentInstance | null = null let _vnode: VNode | null = null let _prevVnode: VNode | null = null diff --git a/packages/runtime-core/__tests__/vnode.spec.ts b/packages/runtime-core/__tests__/vnode.spec.ts index 6355607d7..b4d42d478 100644 --- a/packages/runtime-core/__tests__/vnode.spec.ts +++ b/packages/runtime-core/__tests__/vnode.spec.ts @@ -13,7 +13,7 @@ import { transformVNodeArgs, } from '../src/vnode' import { PatchFlags, ShapeFlags } from '@vue/shared' -import type { Data } from '@vue/runtime-shared' +import type { Data } from '../src/component' import { h, isReactive, reactive, ref, setBlockTracking, withCtx } from '../src' import { createApp, nodeOps, serializeInner } from '@vue/runtime-test' import { setCurrentRenderingInstance } from '../src/componentRenderContext' diff --git a/packages/runtime-core/src/apiAsyncComponent.ts b/packages/runtime-core/src/apiAsyncComponent.ts index 199b451f6..d7abb25fe 100644 --- a/packages/runtime-core/src/apiAsyncComponent.ts +++ b/packages/runtime-core/src/apiAsyncComponent.ts @@ -143,7 +143,7 @@ export function defineAsyncComponent< }, setup() { - const instance = currentInstance! + const instance = currentInstance as ComponentInternalInstance markAsyncBoundary(instance) // already resolved diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index f963ad81f..c7424abc7 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -382,6 +382,14 @@ export interface GenericComponentInstance { isUnmounted: boolean isDeactivated: boolean + /** + * for tracking useId() + * first element is the current boundary prefix + * second number is the index of the useId call within that boundary + * @internal + */ + ids: [string, number, number] + // for vapor the following two are dev only /** * resolved props options @@ -394,8 +402,15 @@ export interface GenericComponentInstance { */ emitsOptions?: ObjectEmitsOptions | null - // the following are for error handling logic only + /** + * Public instance proxy, vdom only + */ proxy?: any + /** + * suspense related + * @internal + */ + suspense: SuspenseBoundary | null // lifecycle /** @@ -497,13 +512,6 @@ export interface ComponentInternalInstance extends GenericComponentInstance { * @internal */ render: InternalRenderFunction | null - /** - * for tracking useId() - * first element is the current boundary prefix - * second number is the index of the useId call within that boundary - * @internal - */ - ids: [string, number, number] /** * cache for proxy access type to avoid hasOwnProperty calls * @internal @@ -600,11 +608,6 @@ export interface ComponentInternalInstance extends GenericComponentInstance { * @internal */ ctx: Data - /** - * suspense related - * @internal - */ - suspense: SuspenseBoundary | null /** * suspense pending batch id * @internal diff --git a/packages/runtime-core/src/componentSlots.ts b/packages/runtime-core/src/componentSlots.ts index 8f8392f1c..34aaa39df 100644 --- a/packages/runtime-core/src/componentSlots.ts +++ b/packages/runtime-core/src/componentSlots.ts @@ -1,4 +1,4 @@ -import { type ComponentInternalInstance, currentInstance } from './component' +import { type ComponentInternalInstance, getCurrentInstance } from './component' import { type VNode, type VNodeChild, @@ -94,16 +94,15 @@ const normalizeSlot = ( return rawSlot as Slot } const normalized = withCtx((...args: any[]) => { - if ( - __DEV__ && - currentInstance && - (!ctx || ctx.root === currentInstance.root) - ) { - warn( - `Slot "${key}" invoked outside of the render function: ` + - `this will not track dependencies used in the slot. ` + - `Invoke the slot function inside the render function instead.`, - ) + if (__DEV__) { + const currentInstance = getCurrentInstance() + if (currentInstance && (!ctx || ctx.root === currentInstance.root)) { + warn( + `Slot "${key}" invoked outside of the render function: ` + + `this will not track dependencies used in the slot. ` + + `Invoke the slot function inside the render function instead.`, + ) + } } return normalizeSlotValue(rawSlot(...args)) }, ctx) as Slot diff --git a/packages/runtime-core/src/helpers/resolveAssets.ts b/packages/runtime-core/src/helpers/resolveAssets.ts index aa6532c28..910fab334 100644 --- a/packages/runtime-core/src/helpers/resolveAssets.ts +++ b/packages/runtime-core/src/helpers/resolveAssets.ts @@ -1,4 +1,5 @@ import { + type ComponentInternalInstance, type ComponentOptions, type ConcreteComponent, currentInstance, @@ -103,8 +104,13 @@ function resolveAsset( const res = // local registration // check instance[type] first which is resolved for options API - resolve(instance[type] || (Component as ComponentOptions)[type], name) || + resolve( + (instance as ComponentInternalInstance)[type] || + (Component as ComponentOptions)[type], + name, + ) || // global registration + // @ts-expect-error filters only exist in compat mode resolve(instance.appContext[type], name) if (!res && maybeSelfReference) { diff --git a/packages/runtime-core/src/helpers/useId.ts b/packages/runtime-core/src/helpers/useId.ts index 4b51e0dda..0fcc1e435 100644 --- a/packages/runtime-core/src/helpers/useId.ts +++ b/packages/runtime-core/src/helpers/useId.ts @@ -1,11 +1,11 @@ import { - type ComponentInternalInstance, - getCurrentInstance, + type GenericComponentInstance, + getCurrentGenericInstance, } from '../component' import { warn } from '../warning' export function useId(): string { - const i = getCurrentInstance() + const i = getCurrentGenericInstance() if (i) { return (i.appContext.config.idPrefix || 'v') + '-' + i.ids[0] + i.ids[1]++ } else if (__DEV__) { @@ -23,6 +23,6 @@ export function useId(): string { * - components with async setup() * - components with serverPrefetch */ -export function markAsyncBoundary(instance: ComponentInternalInstance): void { +export function markAsyncBoundary(instance: GenericComponentInstance): void { instance.ids = [instance.ids[0] + instance.ids[2]++ + '-', 0, 0] } diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index e869a4586..9f4e3e2e4 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -2587,7 +2587,7 @@ function locateNonHydratedAsyncRoot( } } -export function invalidateMount(hooks: LifecycleHook): void { +export function invalidateMount(hooks: LifecycleHook | undefined): void { if (hooks) { for (let i = 0; i < hooks.length; i++) hooks[i].flags! |= SchedulerJobFlags.DISPOSED diff --git a/packages/runtime-vapor/src/component.ts b/packages/runtime-vapor/src/component.ts index af42304c2..aeaa07164 100644 --- a/packages/runtime-vapor/src/component.ts +++ b/packages/runtime-vapor/src/component.ts @@ -9,6 +9,7 @@ import { type LifecycleHook, type NormalizedPropsOptions, type ObjectEmitsOptions, + type SuspenseBoundary, currentInstance, nextUid, popWarningContext, @@ -121,6 +122,7 @@ export function createComponent( ) instance.block = [] } else { + instance.setupState = setupResult instance.block = component.render.call(null, setupResult) } } else { @@ -178,6 +180,10 @@ export class VaporComponentInstance implements GenericComponentInstance { refs: Record // for provide / inject provides: Record + // for useId + ids: [string, number, number] + // for suspense + suspense: SuspenseBoundary | null hasFallthrough: boolean @@ -211,7 +217,7 @@ export class VaporComponentInstance implements GenericComponentInstance { this.vapor = true this.uid = nextUid() this.type = comp - this.parent = currentInstance // TODO when inside + this.parent = currentInstance // TODO proper parent source when inside vdom instance this.appContext = currentInstance ? currentInstance.appContext : emptyContext @@ -223,7 +229,8 @@ export class VaporComponentInstance implements GenericComponentInstance { ? currentInstance.provides : Object.create(this.appContext.provides) this.refs = EMPTY_OBJ - this.emitted = this.ec = this.exposed = this.propsDefaults = null + this.ids = currentInstance ? currentInstance.ids : ['', 0, 0] + this.emitted = this.exposed = this.propsDefaults = this.suspense = null this.isMounted = this.isUnmounted = this.isUpdating =