| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364 |
- import { type VNode, type VNodeChild, isVNode } from './vnode'
- import {
- EffectScope,
- type ReactiveEffect,
- TrackOpTypes,
- isRef,
- markRaw,
- proxyRefs,
- setActiveSub,
- shallowReadonly,
- track,
- } from '@vue/reactivity'
- import {
- type ComponentPublicInstance,
- type ComponentPublicInstanceConstructor,
- PublicInstanceProxyHandlers,
- RuntimeCompiledPublicInstanceProxyHandlers,
- createDevRenderContext,
- exposePropsOnRenderContext,
- exposeSetupStateOnRenderContext,
- publicPropertiesMap,
- } from './componentPublicInstance'
- import {
- type ComponentPropsOptions,
- type NormalizedPropsOptions,
- initProps,
- normalizePropsOptions,
- } from './componentProps'
- import {
- type InternalSlots,
- type Slots,
- type SlotsType,
- type UnwrapSlotsType,
- initSlots,
- } from './componentSlots'
- import { warn } from './warning'
- import { ErrorCodes, callWithErrorHandling, handleError } from './errorHandling'
- import {
- type AppConfig,
- type AppContext,
- type GenericAppContext,
- createAppContext,
- } from './apiCreateApp'
- import { type Directive, validateDirectiveName } from './directives'
- import {
- type ComponentOptions,
- type ComputedOptions,
- type MergedComponentOptions,
- type MethodOptions,
- applyOptions,
- resolveMergedOptions,
- } from './componentOptions'
- import {
- type EmitFn,
- type EmitsOptions,
- type EmitsToProps,
- type ObjectEmitsOptions,
- type ShortEmitsToObject,
- emit,
- normalizeEmitsOptions,
- } from './componentEmits'
- import {
- EMPTY_OBJ,
- type IfAny,
- NOOP,
- ShapeFlags,
- extend,
- isArray,
- isBuiltInTag,
- isFunction,
- isObject,
- isPromise,
- } from '@vue/shared'
- import type { SuspenseBoundary } from './components/Suspense'
- import type { CompilerOptions } from '@vue/compiler-core'
- import { markAttrsAccessed } from './componentRenderUtils'
- import { endMeasure, startMeasure } from './profiling'
- import { convertLegacyRenderFn } from './compat/renderFn'
- import {
- type CompatConfig,
- globalCompatConfig,
- validateCompatConfig,
- } from './compat/compatConfig'
- import type { SchedulerJob } from './scheduler'
- import type { LifecycleHooks } from './enums'
- // Augment GlobalComponents
- import type { TeleportProps } from './components/Teleport'
- import type { SuspenseProps } from './components/Suspense'
- import type { KeepAliveProps } from './components/KeepAlive'
- import type { BaseTransitionProps } from './components/BaseTransition'
- import type { DefineComponent } from './apiDefineComponent'
- import { markAsyncBoundary } from './helpers/useId'
- import { isAsyncWrapper } from './apiAsyncComponent'
- import type { RendererElement } from './renderer'
- import {
- setCurrentInstance,
- setInSSRSetupState,
- } from './componentCurrentInstance'
- export * from './componentCurrentInstance'
- export type Data = Record<string, unknown>
- /**
- * Public utility type for extracting the instance type of a component.
- * Works with all valid component definition types. This is intended to replace
- * the usage of `InstanceType<typeof Comp>` which only works for
- * constructor-based component definition types.
- *
- * @example
- * ```ts
- * const MyComp = { ... }
- * declare const instance: ComponentInstance<typeof MyComp>
- * ```
- */
- export type ComponentInstance<T> = T extends { new (): ComponentPublicInstance }
- ? InstanceType<T>
- : T extends FunctionalComponent<infer Props, infer Emits>
- ? ComponentPublicInstance<Props, {}, {}, {}, {}, ShortEmitsToObject<Emits>>
- : T extends Component<
- infer PropsOrInstance,
- infer RawBindings,
- infer D,
- infer C,
- infer M
- >
- ? PropsOrInstance extends { $props: unknown }
- ? // T is returned by `defineComponent()`
- PropsOrInstance
- : // NOTE we override Props/RawBindings/D to make sure is not `unknown`
- ComponentPublicInstance<
- unknown extends PropsOrInstance ? {} : PropsOrInstance,
- unknown extends RawBindings ? {} : RawBindings,
- unknown extends D ? {} : D,
- C,
- M
- >
- : never // not a vue Component
- /**
- * For extending allowed non-declared props on components in TSX
- */
- export interface ComponentCustomProps {}
- /**
- * For globally defined Directives
- * Here is an example of adding a directive `VTooltip` as global directive:
- *
- * @example
- * ```ts
- * import VTooltip from 'v-tooltip'
- *
- * declare module '@vue/runtime-core' {
- * interface GlobalDirectives {
- * VTooltip
- * }
- * }
- * ```
- */
- export interface GlobalDirectives {}
- /**
- * For globally defined Components
- * Here is an example of adding a component `RouterView` as global component:
- *
- * @example
- * ```ts
- * import { RouterView } from 'vue-router'
- *
- * declare module '@vue/runtime-core' {
- * interface GlobalComponents {
- * RouterView
- * }
- * }
- * ```
- */
- export interface GlobalComponents {
- Teleport: DefineComponent<TeleportProps>
- Suspense: DefineComponent<SuspenseProps>
- KeepAlive: DefineComponent<KeepAliveProps>
- BaseTransition: DefineComponent<BaseTransitionProps>
- }
- /**
- * Default allowed non-declared props on component in TSX
- */
- export interface AllowedComponentProps {
- class?: unknown
- style?: unknown
- }
- // Note: can't mark this whole interface internal because some public interfaces
- // extend it.
- export interface ComponentInternalOptions {
- /**
- * indicates vapor component
- */
- __vapor?: boolean
- /**
- * indicates keep-alive component
- */
- __isKeepAlive?: boolean
- /**
- * @internal
- */
- __scopeId?: string
- /**
- * @internal
- */
- __cssModules?: Data
- /**
- * @internal
- */
- __hmrId?: string
- /**
- * Compat build only, for bailing out of certain compatibility behavior
- */
- __isBuiltIn?: boolean
- /**
- * This one should be exposed so that devtools can make use of it
- */
- __file?: string
- /**
- * name inferred from filename
- */
- __name?: string
- }
- export interface AsyncComponentInternalOptions<
- R = ConcreteComponent,
- I = ComponentInternalInstance,
- > {
- /**
- * marker for AsyncComponentWrapper
- * @internal
- */
- __asyncLoader?: () => Promise<R>
- /**
- * the inner component resolved by the AsyncComponentWrapper
- * @internal
- */
- __asyncResolved?: R
- /**
- * Exposed for lazy hydration
- * @internal
- */
- __asyncHydrate?: (el: Element, instance: I, hydrate: () => void) => void
- }
- export interface FunctionalComponent<
- P = {},
- E extends EmitsOptions | Record<string, any[]> = {},
- S extends Record<string, any> = any,
- EE extends EmitsOptions = ShortEmitsToObject<E>,
- > extends ComponentInternalOptions {
- // use of any here is intentional so it can be a valid JSX Element constructor
- (
- props: P & EmitsToProps<EE>,
- ctx: Omit<SetupContext<EE, IfAny<S, {}, SlotsType<S>>>, 'expose'>,
- ): any
- props?: ComponentPropsOptions<P>
- emits?: EE | (keyof EE)[]
- slots?: IfAny<S, Slots, SlotsType<S>>
- inheritAttrs?: boolean
- displayName?: string
- compatConfig?: CompatConfig
- }
- export interface ClassComponent {
- new (...args: any[]): ComponentPublicInstance<any, any, any, any, any>
- __vccOpts: ComponentOptions
- }
- /**
- * Type used where a function accepts both vdom and vapor components.
- */
- export type GenericComponent = (
- | {
- name?: string
- }
- | ((() => any) & { displayName?: string })
- ) &
- ComponentInternalOptions
- /**
- * Concrete component type matches its actual value: it's either an options
- * object, or a function. Use this where the code expects to work with actual
- * values, e.g. checking if its a function or not. This is mostly for internal
- * implementation code.
- */
- export type ConcreteComponent<
- Props = {},
- RawBindings = any,
- D = any,
- C extends ComputedOptions = ComputedOptions,
- M extends MethodOptions = MethodOptions,
- E extends EmitsOptions | Record<string, any[]> = {},
- S extends Record<string, any> = any,
- > =
- | ComponentOptions<Props, RawBindings, D, C, M>
- | FunctionalComponent<Props, E, S>
- /**
- * A type used in public APIs where a component type is expected.
- * The constructor type is an artificial type returned by defineComponent().
- */
- export type Component<
- PropsOrInstance = any,
- RawBindings = any,
- D = any,
- C extends ComputedOptions = ComputedOptions,
- M extends MethodOptions = MethodOptions,
- E extends EmitsOptions | Record<string, any[]> = {},
- S extends Record<string, any> = any,
- > =
- | ConcreteComponent<PropsOrInstance, RawBindings, D, C, M, E, S>
- | ComponentPublicInstanceConstructor<PropsOrInstance>
- export type { ComponentOptions }
- export type LifecycleHook<TFn = Function> = (TFn & SchedulerJob)[] | null
- // use `E extends any` to force evaluating type to fix #2362
- export type SetupContext<
- E = EmitsOptions,
- S extends SlotsType = {},
- > = E extends any
- ? {
- attrs: Data
- slots: UnwrapSlotsType<S>
- emit: EmitFn<E>
- expose: <Exposed extends Record<string, any> = Record<string, any>>(
- exposed?: Exposed,
- ) => void
- }
- : never
- /**
- * @internal
- */
- export type InternalRenderFunction = {
- (
- ctx: ComponentPublicInstance,
- cache: ComponentInternalInstance['renderCache'],
- // for compiler-optimized bindings
- $props: ComponentInternalInstance['props'],
- $setup: ComponentInternalInstance['setupState'],
- $data: ComponentInternalInstance['data'],
- $options: ComponentInternalInstance['ctx'],
- ): VNodeChild
- _rc?: boolean // isRuntimeCompiled
- // __COMPAT__ only
- _compatChecked?: boolean // v3 and already checked for v2 compat
- _compatWrapped?: boolean // is wrapped for v2 compat
- }
- /**
- * Base component instance interface that is shared between vdom mode and vapor
- * mode, so that we can have a mixed instance tree and reuse core logic that
- * operate on both.
- */
- export interface GenericComponentInstance {
- vapor?: boolean
- uid: number
- type: GenericComponent
- root: GenericComponentInstance | null
- parent: GenericComponentInstance | null
- appContext: GenericAppContext
- /**
- * Object containing values this component provides for its descendants
- * @internal
- */
- provides: Data
- /**
- * Tracking reactive effects (e.g. watchers) associated with this component
- * so that they can be automatically stopped on component unmount
- * @internal
- */
- scope: EffectScope
- /**
- * render function will have different types between vdom and vapor
- */
- render?: Function | null
- /**
- * SSR render function
- * (they are the same between vdom and vapor components.)
- * @internal
- */
- ssrRender?: Function | null
- // state
- props: Data
- attrs: Data
- refs: Data
- emit: EmitFn
- /**
- * used for keeping track of .once event handlers on components
- * @internal
- */
- emitted: Record<string, boolean> | null
- /**
- * used for caching the value returned from props default factory functions to
- * avoid unnecessary watcher trigger
- * @internal
- */
- propsDefaults: Data | null
- /**
- * used for getting the keys of a component's raw props, vapor only
- * @internal
- */
- rawKeys?: () => string[]
- // exposed properties via expose()
- exposed: Record<string, any> | null
- exposeProxy: Record<string, any> | null
- /**
- * setup related
- * @internal
- */
- setupState?: Data
- /**
- * devtools access to additional info
- * @internal
- */
- devtoolsRawSetupState?: any
- // lifecycle
- isMounted: boolean
- 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
- * @internal
- */
- propsOptions?: NormalizedPropsOptions
- /**
- * resolved emits options
- * @internal
- */
- emitsOptions?: ObjectEmitsOptions | null
- /**
- * Public instance proxy, vdom only
- */
- proxy?: any
- /**
- * suspense related
- * @internal
- */
- suspense: SuspenseBoundary | null
- /**
- * suspense pending batch id
- * @internal
- */
- suspenseId: number
- /**
- * @internal
- */
- asyncDep: Promise<any> | null
- /**
- * @internal
- */
- asyncResolved: boolean
- /**
- * `updateTeleportCssVars`
- * For updating css vars on contained teleports
- * @internal
- */
- ut?: (vars?: Record<string, string>) => void
- /**
- * dev only. For style v-bind hydration mismatch checks
- * @internal
- */
- getCssVars?: () => Record<string, string>
- // 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>>
- /**
- * @internal vapor only
- */
- hmrRerender?: () => void
- /**
- * @internal vapor only
- */
- hmrReload?: (newComp: any) => void
- // these only exist on vdom instances
- vnode?: VNode
- subTree?: VNode
- /**
- * Custom Element instance (if component is created by defineCustomElement)
- * @internal
- */
- ce?: ComponentCustomElementInterface
- /**
- * is custom element? (kept only for compatibility)
- * @internal
- */
- isCE?: boolean
- /**
- * custom element specific HMR method
- * @internal
- */
- ceReload?: (newStyles?: string[]) => void
- }
- /**
- * We expose a subset of properties on the internal instance as they are
- * useful for advanced external libraries and tools.
- */
- export interface ComponentInternalInstance extends GenericComponentInstance {
- vapor?: never
- uid: number
- type: ConcreteComponent
- parent: GenericComponentInstance | null
- root: GenericComponentInstance
- appContext: AppContext
- /**
- * Vnode representing this component in its parent's vdom tree
- */
- vnode: VNode
- /**
- * The pending new vnode from parent updates
- * @internal
- */
- next: VNode | null
- /**
- * Root vnode of this component's own vdom tree
- */
- subTree: VNode
- /**
- * Render effect instance
- */
- effect: ReactiveEffect
- /**
- * Force update render effect
- */
- update: () => void
- /**
- * Render effect job to be passed to scheduler (checks if dirty)
- */
- job: SchedulerJob
- /**
- * The render function that returns vdom tree.
- * @internal
- */
- render: InternalRenderFunction | null
- /**
- * cache for proxy access type to avoid hasOwnProperty calls
- * @internal
- */
- accessCache: Data | null
- /**
- * cache for render function values that rely on _ctx but won't need updates
- * after initialized (e.g. inline handlers)
- * @internal
- */
- renderCache: (Function | VNode | undefined)[]
- /**
- * Resolved component registry, only for components with mixins or extends
- * @internal
- */
- components: Record<string, ConcreteComponent> | null
- /**
- * Resolved directive registry, only for components with mixins or extends
- * @internal
- */
- directives: Record<string, Directive> | null
- /**
- * Resolved filters registry, v2 compat only
- * @internal
- */
- filters?: Record<string, Function>
- /**
- * resolved props options
- * @internal
- */
- propsOptions: NormalizedPropsOptions
- /**
- * resolved emits options
- * @internal
- */
- emitsOptions: ObjectEmitsOptions | null
- /**
- * resolved inheritAttrs options
- * @internal
- */
- inheritAttrs?: boolean
- // the rest are only for stateful components ---------------------------------
- /**
- * setup related
- * @internal
- */
- setupState: Data
- /**
- * @internal
- */
- setupContext?: SetupContext | null
- // main proxy that serves as the public instance (`this`)
- proxy: ComponentPublicInstance | null
- data: Data // options API only
- emit: EmitFn
- slots: InternalSlots
- exposeProxy: Record<string, any> | null
- /**
- * alternative proxy used only for runtime-compiled render functions using
- * `with` block
- * @internal
- */
- withProxy: ComponentPublicInstance | null
- /**
- * This is the target for the public instance proxy. It also holds properties
- * injected by user options (computed, methods etc.) and user-attached
- * custom properties (via `this.x = ...`)
- * @internal
- */
- ctx: Data
- /**
- * suspense pending batch id
- * @internal
- */
- suspenseId: number
- /**
- * @internal
- */
- asyncDep: Promise<any> | null
- /**
- * @internal
- */
- asyncResolved: boolean
- /**
- * For caching bound $forceUpdate on public proxy access
- * @internal
- */
- f?: () => void
- /**
- * For caching bound $nextTick on public proxy access
- * @internal
- */
- n?: () => Promise<void>
- /**
- * v2 compat only, for caching mutated $options
- * @internal
- */
- resolvedOptions?: MergedComponentOptions
- }
- const emptyAppContext = createAppContext()
- let uid = 0
- /**
- * @internal for vapor
- */
- export function nextUid(): number {
- return uid++
- }
- export function createComponentInstance(
- vnode: VNode,
- parent: ComponentInternalInstance | null,
- suspense: SuspenseBoundary | null,
- ): ComponentInternalInstance {
- const type = vnode.type as ConcreteComponent
- // 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,
- root: null!, // to be immediately set
- next: null,
- subTree: null!, // will be set synchronously right after creation
- effect: null!,
- update: null!, // will be set synchronously right after creation
- job: null!,
- scope: new EffectScope(true /* detached */),
- render: null,
- proxy: null,
- exposed: null,
- exposeProxy: null,
- withProxy: null,
- provides: parent ? parent.provides : Object.create(appContext.provides),
- ids: parent ? parent.ids : ['', 0, 0],
- accessCache: null!,
- renderCache: [],
- // local resolved assets
- components: null,
- directives: null,
- // resolved props and emits options
- propsOptions: normalizePropsOptions(type, appContext),
- emitsOptions: normalizeEmitsOptions(type, appContext),
- // emit
- emit: null!, // to be set immediately
- emitted: null,
- // props default value
- propsDefaults: null,
- // inheritAttrs
- inheritAttrs: type.inheritAttrs,
- // state
- ctx: EMPTY_OBJ,
- data: EMPTY_OBJ,
- props: EMPTY_OBJ,
- attrs: EMPTY_OBJ,
- slots: EMPTY_OBJ,
- refs: EMPTY_OBJ,
- setupState: EMPTY_OBJ,
- setupContext: null,
- // suspense related
- suspense,
- suspenseId: suspense ? suspense.pendingId : 0,
- asyncDep: null,
- asyncResolved: false,
- // lifecycle hooks
- // not using enums here because it results in computed properties
- isMounted: false,
- isUnmounted: false,
- isDeactivated: false,
- bc: null,
- c: null,
- bm: null,
- m: null,
- bu: null,
- u: null,
- um: null,
- bum: null,
- da: null,
- a: null,
- rtg: null,
- rtc: null,
- ec: null,
- sp: null,
- }
- if (__DEV__) {
- instance.ctx = createDevRenderContext(instance)
- } else {
- instance.ctx = { _: instance }
- }
- instance.root = parent ? parent.root : instance
- instance.emit = emit.bind(null, instance)
- // apply custom element special handling
- if (vnode.ce) {
- vnode.ce(instance)
- }
- return instance
- }
- /**
- * @internal
- */
- export function validateComponentName(
- name: string,
- { isNativeTag }: AppConfig,
- ): void {
- if (isBuiltInTag(name) || isNativeTag(name)) {
- warn(
- 'Do not use built-in or reserved HTML elements as component id: ' + name,
- )
- }
- }
- export function isStatefulComponent(
- instance: ComponentInternalInstance,
- ): number {
- return instance.vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT
- }
- export function setupComponent(
- instance: ComponentInternalInstance,
- isSSR = false,
- optimized = false,
- ): Promise<void> | undefined {
- isSSR && setInSSRSetupState(isSSR)
- const { props, children, vi } = instance.vnode
- const isStateful = isStatefulComponent(instance)
- if (vi) {
- // Vapor interop override - use Vapor props/attrs proxy
- vi(instance)
- } else {
- initProps(instance, props, isStateful, isSSR)
- initSlots(instance, children, optimized || isSSR)
- }
- const setupResult = isStateful
- ? setupStatefulComponent(instance, isSSR)
- : undefined
- isSSR && setInSSRSetupState(false)
- return setupResult
- }
- function setupStatefulComponent(
- instance: ComponentInternalInstance,
- isSSR: boolean,
- ) {
- const Component = instance.type as ComponentOptions
- if (__DEV__) {
- if (Component.name) {
- validateComponentName(Component.name, instance.appContext.config)
- }
- if (Component.components) {
- const names = Object.keys(Component.components)
- for (let i = 0; i < names.length; i++) {
- validateComponentName(names[i], instance.appContext.config)
- }
- }
- if (Component.directives) {
- const names = Object.keys(Component.directives)
- for (let i = 0; i < names.length; i++) {
- validateDirectiveName(names[i])
- }
- }
- if (Component.compilerOptions && isRuntimeOnly()) {
- warn(
- `"compilerOptions" is only supported when using a build of Vue that ` +
- `includes the runtime compiler. Since you are using a runtime-only ` +
- `build, the options should be passed via your build tool config instead.`,
- )
- }
- }
- // 0. create render proxy property access cache
- instance.accessCache = Object.create(null)
- // 1. create public instance / render proxy
- instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers)
- if (__DEV__) {
- exposePropsOnRenderContext(instance)
- }
- // 2. call setup()
- const { setup } = Component
- if (setup) {
- const prevSub = setActiveSub()
- const setupContext = (instance.setupContext =
- setup.length > 1 ? createSetupContext(instance) : null)
- const prev = setCurrentInstance(instance)
- const setupResult = callWithErrorHandling(
- setup,
- instance,
- ErrorCodes.SETUP_FUNCTION,
- [
- __DEV__ ? shallowReadonly(instance.props) : instance.props,
- setupContext,
- ],
- )
- const isAsyncSetup = isPromise(setupResult)
- setActiveSub(prevSub)
- setCurrentInstance(...prev)
- if ((isAsyncSetup || instance.sp) && !isAsyncWrapper(instance)) {
- // async setup / serverPrefetch, mark as async boundary for useId()
- markAsyncBoundary(instance)
- }
- if (isAsyncSetup) {
- const unsetCurrentInstance = (): void => {
- setCurrentInstance(null, undefined)
- }
- setupResult.then(unsetCurrentInstance, unsetCurrentInstance)
- if (isSSR) {
- // return the promise so server-renderer can wait on it
- return setupResult
- .then((resolvedResult: unknown) => {
- handleSetupResult(instance, resolvedResult, isSSR)
- })
- .catch(e => {
- handleError(e, instance, ErrorCodes.SETUP_FUNCTION)
- })
- } else if (__FEATURE_SUSPENSE__) {
- // async setup returned Promise.
- // bail here and wait for re-entry.
- instance.asyncDep = setupResult
- if (__DEV__ && !instance.suspense) {
- const name = formatComponentName(instance, Component)
- warn(
- `Component <${name}>: setup function returned a promise, but no ` +
- `<Suspense> boundary was found in the parent component tree. ` +
- `A component with async setup() must be nested in a <Suspense> ` +
- `in order to be rendered.`,
- )
- }
- } else if (__DEV__) {
- warn(
- `setup() returned a Promise, but the version of Vue you are using ` +
- `does not support it yet.`,
- )
- }
- } else {
- handleSetupResult(instance, setupResult, isSSR)
- }
- } else {
- finishComponentSetup(instance, isSSR)
- }
- }
- export function handleSetupResult(
- instance: ComponentInternalInstance,
- setupResult: unknown,
- isSSR: boolean,
- ): void {
- if (isFunction(setupResult)) {
- // setup returned an inline render function
- if (__SSR__ && (instance.type as ComponentOptions).__ssrInlineRender) {
- // when the function's name is `ssrRender` (compiled by SFC inline mode),
- // set it as ssrRender instead.
- instance.ssrRender = setupResult
- } else {
- instance.render = setupResult as InternalRenderFunction
- }
- } else if (isObject(setupResult)) {
- if (__DEV__ && isVNode(setupResult)) {
- warn(
- `setup() should not return VNodes directly - ` +
- `return a render function instead.`,
- )
- }
- // setup returned bindings.
- // assuming a render function compiled from template is present.
- if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
- instance.devtoolsRawSetupState = setupResult
- }
- instance.setupState = proxyRefs(setupResult)
- if (__DEV__) {
- exposeSetupStateOnRenderContext(instance)
- }
- } else if (__DEV__ && setupResult !== undefined) {
- warn(
- `setup() should return an object. Received: ${
- setupResult === null ? 'null' : typeof setupResult
- }`,
- )
- }
- finishComponentSetup(instance, isSSR)
- }
- type CompileFunction = (
- template: string | object,
- options?: CompilerOptions,
- ) => InternalRenderFunction
- let compile: CompileFunction | undefined
- let installWithProxy: (i: ComponentInternalInstance) => void
- /**
- * For runtime-dom to register the compiler.
- * Note the exported method uses any to avoid d.ts relying on the compiler types.
- */
- export function registerRuntimeCompiler(_compile: any): void {
- compile = _compile
- installWithProxy = i => {
- if (i.render!._rc) {
- i.withProxy = new Proxy(i.ctx, RuntimeCompiledPublicInstanceProxyHandlers)
- }
- }
- }
- // dev only
- export const isRuntimeOnly = (): boolean => !compile
- export function finishComponentSetup(
- instance: ComponentInternalInstance,
- isSSR: boolean,
- skipOptions?: boolean,
- ): void {
- const Component = instance.type as ComponentOptions
- if (__COMPAT__) {
- convertLegacyRenderFn(instance)
- if (__DEV__ && Component.compatConfig) {
- validateCompatConfig(Component.compatConfig)
- }
- }
- // template / render function normalization
- // could be already set when returned from setup()
- if (!instance.render) {
- // only do on-the-fly compile if not in SSR - SSR on-the-fly compilation
- // is done by server-renderer
- if (!isSSR && compile && !Component.render) {
- const template =
- (__COMPAT__ &&
- instance.vnode.props &&
- instance.vnode.props['inline-template']) ||
- Component.template ||
- (__FEATURE_OPTIONS_API__ && resolveMergedOptions(instance).template)
- if (template) {
- if (__DEV__) {
- startMeasure(instance, `compile`)
- }
- const { isCustomElement, compilerOptions } = instance.appContext.config
- const { delimiters, compilerOptions: componentCompilerOptions } =
- Component
- const finalCompilerOptions: CompilerOptions = extend(
- extend(
- {
- isCustomElement,
- delimiters,
- },
- compilerOptions,
- ),
- componentCompilerOptions,
- )
- if (__COMPAT__) {
- // pass runtime compat config into the compiler
- finalCompilerOptions.compatConfig = Object.create(globalCompatConfig)
- if (Component.compatConfig) {
- // @ts-expect-error types are not compatible
- extend(finalCompilerOptions.compatConfig, Component.compatConfig)
- }
- }
- Component.render = compile(template, finalCompilerOptions)
- if (__DEV__) {
- endMeasure(instance, `compile`)
- }
- }
- }
- instance.render = (Component.render || NOOP) as InternalRenderFunction
- // for runtime-compiled render functions using `with` blocks, the render
- // proxy used needs a different `has` handler which is more performant and
- // also only allows a whitelist of globals to fallthrough.
- if (installWithProxy) {
- installWithProxy(instance)
- }
- }
- // support for 2.x options
- if (__FEATURE_OPTIONS_API__ && !(__COMPAT__ && skipOptions)) {
- const prevInstance = setCurrentInstance(instance)
- const prevSub = setActiveSub()
- try {
- applyOptions(instance)
- } finally {
- setActiveSub(prevSub)
- setCurrentInstance(...prevInstance)
- }
- }
- // warn missing template/render
- // the runtime compilation of template in SSR is done by server-render
- if (__DEV__ && !Component.render && instance.render === NOOP && !isSSR) {
- if (!compile && Component.template) {
- /* v8 ignore start */
- warn(
- `Component provided template option but ` +
- `runtime compilation is not supported in this build of Vue.` +
- (__ESM_BUNDLER__
- ? ` Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".`
- : __ESM_BROWSER__
- ? ` Use "vue.esm-browser.js" instead.`
- : __GLOBAL__
- ? ` Use "vue.global.js" instead.`
- : ``) /* should not happen */,
- )
- /* v8 ignore stop */
- } else {
- warn(`Component is missing template or render function: `, Component)
- }
- }
- }
- const attrsProxyHandlers = __DEV__
- ? {
- get(target: Data, key: string) {
- markAttrsAccessed()
- track(target, TrackOpTypes.GET, '')
- return target[key]
- },
- set() {
- warn(`setupContext.attrs is readonly.`)
- return false
- },
- deleteProperty() {
- warn(`setupContext.attrs is readonly.`)
- return false
- },
- }
- : {
- get(target: Data, key: string) {
- track(target, TrackOpTypes.GET, '')
- return target[key]
- },
- }
- /**
- * Dev-only
- */
- function getSlotsProxy(instance: ComponentInternalInstance): Slots {
- return new Proxy(instance.slots, {
- get(target, key: string) {
- track(instance, TrackOpTypes.GET, '$slots')
- return target[key]
- },
- })
- }
- export function createSetupContext(
- instance: ComponentInternalInstance,
- ): SetupContext {
- if (__DEV__) {
- // We use getters in dev in case libs like test-utils overwrite instance
- // properties (overwrites should not be done in prod)
- let attrsProxy: Data
- let slotsProxy: Slots
- return Object.freeze({
- get attrs() {
- return (
- attrsProxy ||
- (attrsProxy = new Proxy(instance.attrs, attrsProxyHandlers))
- )
- },
- get slots() {
- return slotsProxy || (slotsProxy = getSlotsProxy(instance))
- },
- get emit() {
- return (event: string, ...args: any[]) => instance.emit(event, ...args)
- },
- expose: exposed => expose(instance, exposed as any),
- })
- } else {
- return {
- attrs: new Proxy(instance.attrs, attrsProxyHandlers),
- slots: instance.slots,
- emit: instance.emit,
- expose: exposed => expose(instance, exposed as any),
- }
- }
- }
- /**
- * @internal
- */
- export function expose(
- instance: GenericComponentInstance,
- exposed: Record<string, any>,
- ): void {
- if (__DEV__) {
- if (instance.exposed) {
- warn(`expose() should be called only once per setup().`)
- }
- if (exposed != null) {
- let exposedType: string = typeof exposed
- if (exposedType === 'object') {
- if (isArray(exposed)) {
- exposedType = 'array'
- } else if (isRef(exposed)) {
- exposedType = 'ref'
- }
- }
- if (exposedType !== 'object') {
- warn(
- `expose() should be passed a plain object, received ${exposedType}.`,
- )
- }
- }
- }
- instance.exposed = exposed || {}
- }
- export function getComponentPublicInstance(
- instance: GenericComponentInstance,
- ): ComponentPublicInstance | ComponentInternalInstance['exposed'] | null {
- if (instance.exposed) {
- return (
- instance.exposeProxy ||
- (instance.exposeProxy = new Proxy(proxyRefs(markRaw(instance.exposed)), {
- get(target, key: string) {
- if (key in target) {
- return target[key]
- } else if (key in publicPropertiesMap) {
- return publicPropertiesMap[key](
- instance as ComponentInternalInstance,
- )
- }
- },
- has(target, key: string) {
- return key in target || key in publicPropertiesMap
- },
- }))
- )
- } else {
- return instance.proxy
- }
- }
- const classifyRE = /(?:^|[-_])\w/g
- const classify = (str: string): string =>
- str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, '')
- export function getComponentName(
- Component: GenericComponent,
- includeInferred = true,
- ): string | false | undefined {
- return isFunction(Component)
- ? Component.displayName || Component.name
- : Component.name || (includeInferred && Component.__name)
- }
- export function formatComponentName(
- instance: GenericComponentInstance | null,
- Component: GenericComponent,
- isRoot = false,
- ): string {
- let name = getComponentName(Component)
- if (!name && Component.__file) {
- const match = Component.__file.match(/([^/\\]+)\.\w+$/)
- if (match) {
- name = match[1]
- }
- }
- if (!name && instance) {
- // try to infer the name based on reverse resolution
- const inferFromRegistry = (
- registry: Record<string, any> | undefined | null,
- ) => {
- for (const key in registry) {
- if (registry[key] === Component) {
- return key
- }
- }
- }
- name =
- inferFromRegistry((instance as ComponentInternalInstance).components) ||
- (instance.parent &&
- inferFromRegistry(
- (instance.parent.type as ComponentOptions).components,
- )) ||
- inferFromRegistry(instance.appContext.components)
- }
- return name ? classify(name) : isRoot ? `App` : `Anonymous`
- }
- export function isClassComponent(value: unknown): value is ClassComponent {
- return isFunction(value) && '__vccOpts' in value
- }
- export interface ComponentCustomElementInterface {
- /**
- * @internal
- */
- _injectChildStyle(type: ConcreteComponent): void
- /**
- * @internal
- */
- _removeChildStyle(type: ConcreteComponent): void
- /**
- * @internal
- */
- _setProp(
- key: string,
- val: any,
- shouldReflect?: boolean,
- shouldUpdate?: boolean,
- ): void
- /**
- * @internal
- */
- _beginPatch(): void
- /**
- * @internal
- */
- _endPatch(): void
- /**
- * @internal attached by the nested Teleport when shadowRoot is false.
- */
- _teleportTargets?: Set<RendererElement>
- }
|