diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 9efb657e9c5..da6d51c1bb2 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -24,7 +24,7 @@ import { Slots, initSlots, InternalSlots } from './componentSlots' import { warn } from './warning' import { ErrorCodes, callWithErrorHandling } from './errorHandling' import { AppContext, createAppContext, AppConfig } from './apiCreateApp' -import { Directive, validateDirectiveName } from './directives' +import { validateDirectiveName } from './directives' import { applyOptions, ComponentOptions } from './componentOptions' import { EmitsOptions, @@ -223,17 +223,6 @@ export interface ComponentInternalInstance { */ renderCache: (Function | VNode)[] - /** - * Asset hashes that prototypally inherits app-level asset hashes for fast - * resolution - * @internal - */ - components: Record - /** - * @internal - */ - directives: Record - // the rest are only for stateful components --------------------------------- // main proxy that serves as the public instance (`this`) @@ -354,15 +343,17 @@ export function createComponentInstance( parent: ComponentInternalInstance | null, suspense: SuspenseBoundary | null ) { + const type = vnode.type as Component // inherit parent app context - or - if root, adopt from root vnode const appContext = (parent ? parent.appContext : vnode.appContext) || emptyAppContext + const instance: ComponentInternalInstance = { uid: uid++, vnode, + type, parent, appContext, - type: vnode.type as Component, root: null!, // to be immediately set next: null, subTree: null!, // will be set synchronously right after creation @@ -385,10 +376,6 @@ export function createComponentInstance( setupState: EMPTY_OBJ, setupContext: null, - // per-instance asset storage (mutable during options resolution) - components: Object.create(appContext.components), - directives: Object.create(appContext.directives), - // suspense related suspense, asyncDep: null, @@ -727,14 +714,18 @@ export function formatComponentName( } if (!name && instance && instance.parent) { - // try to infer the name based on local resolution - const registry = instance.parent.components - for (const key in registry) { - if (registry[key] === Component) { - name = key - break + // try to infer the name based on reverse resolution + const inferFromRegistry = (registry: Record | undefined) => { + for (const key in registry) { + if (registry[key] === Component) { + return key + } } } + name = + inferFromRegistry( + (instance.parent.type as ComponentOptions).components + ) || inferFromRegistry(instance.appContext.components) } return name ? classify(name) : isRoot ? `App` : `Anonymous` diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 948ceafc538..247ea946d47 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -381,9 +381,6 @@ export function applyOptions( watch: watchOptions, provide: provideOptions, inject: injectOptions, - // assets - components, - directives, // lifecycle beforeMount, mounted, @@ -570,14 +567,6 @@ export function applyOptions( } } - // asset options - if (components) { - extend(instance.components, components) - } - if (directives) { - extend(instance.directives, directives) - } - // lifecycle options if (!asMixin) { callSyncHook('created', options, publicThis, globalMixins) diff --git a/packages/runtime-core/src/helpers/resolveAssets.ts b/packages/runtime-core/src/helpers/resolveAssets.ts index 03a83337b97..3272317dfb9 100644 --- a/packages/runtime-core/src/helpers/resolveAssets.ts +++ b/packages/runtime-core/src/helpers/resolveAssets.ts @@ -1,5 +1,10 @@ import { currentRenderingInstance } from '../componentRenderUtils' -import { currentInstance, Component, FunctionalComponent } from '../component' +import { + currentInstance, + Component, + FunctionalComponent, + ComponentOptions +} from '../component' import { Directive } from '../directives' import { camelize, capitalize, isString } from '@vue/shared' import { warn } from '../warning' @@ -58,24 +63,27 @@ function resolveAsset( ) { const instance = currentRenderingInstance || currentInstance if (instance) { - let camelized, capitalized - const registry = instance[type] - let res = - registry[name] || - registry[(camelized = camelize(name))] || - registry[(capitalized = capitalize(camelized))] - if (!res && type === COMPONENTS) { - const self = instance.type - const selfName = (self as FunctionalComponent).displayName || self.name + const Component = instance.type + + // self name has highest priority + if (type === COMPONENTS) { + const selfName = + (Component as FunctionalComponent).displayName || Component.name if ( selfName && (selfName === name || - selfName === camelized || - selfName === capitalized) + selfName === camelize(name) || + selfName === capitalize(camelize(name))) ) { - res = self + return Component } } + + const res = + // local registration + resolve((Component as ComponentOptions)[type], name) || + // global registration + resolve(instance.appContext[type], name) if (__DEV__ && warnMissing && !res) { warn(`Failed to resolve ${type.slice(0, -1)}: ${name}`) } @@ -87,3 +95,12 @@ function resolveAsset( ) } } + +function resolve(registry: Record | undefined, name: string) { + return ( + registry && + (registry[name] || + registry[camelize(name)] || + registry[capitalize(camelize(name))]) + ) +}