| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- import {
- type ComponentOptions,
- type ConcreteComponent,
- currentInstance,
- getComponentName,
- } from '../component'
- import { currentRenderingInstance } from '../componentRenderContext'
- import type { Directive } from '../directives'
- import { camelize, capitalize, isString } from '@vue/shared'
- import { warn } from '../warning'
- import type { VNodeTypes } from '../vnode'
- export const COMPONENTS = 'components'
- export const DIRECTIVES = 'directives'
- export const FILTERS = 'filters'
- export type AssetTypes = typeof COMPONENTS | typeof DIRECTIVES | typeof FILTERS
- /**
- * @private
- */
- export function resolveComponent(
- name: string,
- maybeSelfReference?: boolean,
- ): ConcreteComponent | string {
- return resolveAsset(COMPONENTS, name, true, maybeSelfReference) || name
- }
- export const NULL_DYNAMIC_COMPONENT = Symbol.for('v-ndc')
- /**
- * @private
- */
- export function resolveDynamicComponent(component: unknown): VNodeTypes {
- if (isString(component)) {
- return resolveAsset(COMPONENTS, component, false) || component
- } else {
- // invalid types will fallthrough to createVNode and raise warning
- return (component || NULL_DYNAMIC_COMPONENT) as any
- }
- }
- /**
- * @private
- */
- export function resolveDirective(name: string): Directive | undefined {
- return resolveAsset(DIRECTIVES, name)
- }
- /**
- * v2 compat only
- * @internal
- */
- export function resolveFilter(name: string): Function | undefined {
- return resolveAsset(FILTERS, name)
- }
- /**
- * @private
- * overload 1: components
- */
- function resolveAsset(
- type: typeof COMPONENTS,
- name: string,
- warnMissing?: boolean,
- maybeSelfReference?: boolean,
- ): ConcreteComponent | undefined
- // overload 2: directives
- function resolveAsset(
- type: typeof DIRECTIVES,
- name: string,
- ): Directive | undefined
- // implementation
- // overload 3: filters (compat only)
- function resolveAsset(type: typeof FILTERS, name: string): Function | undefined
- // implementation
- function resolveAsset(
- type: AssetTypes,
- name: string,
- warnMissing = true,
- maybeSelfReference = false,
- ) {
- const instance = currentRenderingInstance || currentInstance
- if (instance) {
- const Component = instance.type
- // explicit self name has highest priority
- if (type === COMPONENTS) {
- const selfName = getComponentName(
- Component,
- false /* do not include inferred name to avoid breaking existing code */,
- )
- if (
- selfName &&
- (selfName === name ||
- selfName === camelize(name) ||
- selfName === capitalize(camelize(name)))
- ) {
- return Component
- }
- }
- const res =
- // local registration
- // check instance[type] first which is resolved for options API
- resolve(instance[type] || (Component as ComponentOptions)[type], name) ||
- // global registration
- resolve(instance.appContext[type], name)
- if (!res && maybeSelfReference) {
- // fallback to implicit self-reference
- return Component
- }
- if (__DEV__ && warnMissing && !res) {
- const extra =
- type === COMPONENTS
- ? `\nIf this is a native custom element, make sure to exclude it from ` +
- `component resolution via compilerOptions.isCustomElement.`
- : ``
- warn(`Failed to resolve ${type.slice(0, -1)}: ${name}${extra}`)
- }
- return res
- } else if (__DEV__) {
- warn(
- `resolve${capitalize(type.slice(0, -1))} ` +
- `can only be used in render() or setup().`,
- )
- }
- }
- function resolve(registry: Record<string, any> | undefined, name: string) {
- return (
- registry &&
- (registry[name] ||
- registry[camelize(name)] ||
- registry[capitalize(camelize(name))])
- )
- }
|