component.ts 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364
  1. import { type VNode, type VNodeChild, isVNode } from './vnode'
  2. import {
  3. EffectScope,
  4. type ReactiveEffect,
  5. TrackOpTypes,
  6. isRef,
  7. markRaw,
  8. proxyRefs,
  9. setActiveSub,
  10. shallowReadonly,
  11. track,
  12. } from '@vue/reactivity'
  13. import {
  14. type ComponentPublicInstance,
  15. type ComponentPublicInstanceConstructor,
  16. PublicInstanceProxyHandlers,
  17. RuntimeCompiledPublicInstanceProxyHandlers,
  18. createDevRenderContext,
  19. exposePropsOnRenderContext,
  20. exposeSetupStateOnRenderContext,
  21. publicPropertiesMap,
  22. } from './componentPublicInstance'
  23. import {
  24. type ComponentPropsOptions,
  25. type NormalizedPropsOptions,
  26. initProps,
  27. normalizePropsOptions,
  28. } from './componentProps'
  29. import {
  30. type InternalSlots,
  31. type Slots,
  32. type SlotsType,
  33. type UnwrapSlotsType,
  34. initSlots,
  35. } from './componentSlots'
  36. import { warn } from './warning'
  37. import { ErrorCodes, callWithErrorHandling, handleError } from './errorHandling'
  38. import {
  39. type AppConfig,
  40. type AppContext,
  41. type GenericAppContext,
  42. createAppContext,
  43. } from './apiCreateApp'
  44. import { type Directive, validateDirectiveName } from './directives'
  45. import {
  46. type ComponentOptions,
  47. type ComputedOptions,
  48. type MergedComponentOptions,
  49. type MethodOptions,
  50. applyOptions,
  51. resolveMergedOptions,
  52. } from './componentOptions'
  53. import {
  54. type EmitFn,
  55. type EmitsOptions,
  56. type EmitsToProps,
  57. type ObjectEmitsOptions,
  58. type ShortEmitsToObject,
  59. emit,
  60. normalizeEmitsOptions,
  61. } from './componentEmits'
  62. import {
  63. EMPTY_OBJ,
  64. type IfAny,
  65. NOOP,
  66. ShapeFlags,
  67. extend,
  68. isArray,
  69. isBuiltInTag,
  70. isFunction,
  71. isObject,
  72. isPromise,
  73. } from '@vue/shared'
  74. import type { SuspenseBoundary } from './components/Suspense'
  75. import type { CompilerOptions } from '@vue/compiler-core'
  76. import { markAttrsAccessed } from './componentRenderUtils'
  77. import { endMeasure, startMeasure } from './profiling'
  78. import { convertLegacyRenderFn } from './compat/renderFn'
  79. import {
  80. type CompatConfig,
  81. globalCompatConfig,
  82. validateCompatConfig,
  83. } from './compat/compatConfig'
  84. import type { SchedulerJob } from './scheduler'
  85. import type { LifecycleHooks } from './enums'
  86. // Augment GlobalComponents
  87. import type { TeleportProps } from './components/Teleport'
  88. import type { SuspenseProps } from './components/Suspense'
  89. import type { KeepAliveProps } from './components/KeepAlive'
  90. import type { BaseTransitionProps } from './components/BaseTransition'
  91. import type { DefineComponent } from './apiDefineComponent'
  92. import { markAsyncBoundary } from './helpers/useId'
  93. import { isAsyncWrapper } from './apiAsyncComponent'
  94. import type { RendererElement } from './renderer'
  95. import {
  96. setCurrentInstance,
  97. setInSSRSetupState,
  98. } from './componentCurrentInstance'
  99. export * from './componentCurrentInstance'
  100. export type Data = Record<string, unknown>
  101. /**
  102. * Public utility type for extracting the instance type of a component.
  103. * Works with all valid component definition types. This is intended to replace
  104. * the usage of `InstanceType<typeof Comp>` which only works for
  105. * constructor-based component definition types.
  106. *
  107. * @example
  108. * ```ts
  109. * const MyComp = { ... }
  110. * declare const instance: ComponentInstance<typeof MyComp>
  111. * ```
  112. */
  113. export type ComponentInstance<T> = T extends { new (): ComponentPublicInstance }
  114. ? InstanceType<T>
  115. : T extends FunctionalComponent<infer Props, infer Emits>
  116. ? ComponentPublicInstance<Props, {}, {}, {}, {}, ShortEmitsToObject<Emits>>
  117. : T extends Component<
  118. infer PropsOrInstance,
  119. infer RawBindings,
  120. infer D,
  121. infer C,
  122. infer M
  123. >
  124. ? PropsOrInstance extends { $props: unknown }
  125. ? // T is returned by `defineComponent()`
  126. PropsOrInstance
  127. : // NOTE we override Props/RawBindings/D to make sure is not `unknown`
  128. ComponentPublicInstance<
  129. unknown extends PropsOrInstance ? {} : PropsOrInstance,
  130. unknown extends RawBindings ? {} : RawBindings,
  131. unknown extends D ? {} : D,
  132. C,
  133. M
  134. >
  135. : never // not a vue Component
  136. /**
  137. * For extending allowed non-declared props on components in TSX
  138. */
  139. export interface ComponentCustomProps {}
  140. /**
  141. * For globally defined Directives
  142. * Here is an example of adding a directive `VTooltip` as global directive:
  143. *
  144. * @example
  145. * ```ts
  146. * import VTooltip from 'v-tooltip'
  147. *
  148. * declare module '@vue/runtime-core' {
  149. * interface GlobalDirectives {
  150. * VTooltip
  151. * }
  152. * }
  153. * ```
  154. */
  155. export interface GlobalDirectives {}
  156. /**
  157. * For globally defined Components
  158. * Here is an example of adding a component `RouterView` as global component:
  159. *
  160. * @example
  161. * ```ts
  162. * import { RouterView } from 'vue-router'
  163. *
  164. * declare module '@vue/runtime-core' {
  165. * interface GlobalComponents {
  166. * RouterView
  167. * }
  168. * }
  169. * ```
  170. */
  171. export interface GlobalComponents {
  172. Teleport: DefineComponent<TeleportProps>
  173. Suspense: DefineComponent<SuspenseProps>
  174. KeepAlive: DefineComponent<KeepAliveProps>
  175. BaseTransition: DefineComponent<BaseTransitionProps>
  176. }
  177. /**
  178. * Default allowed non-declared props on component in TSX
  179. */
  180. export interface AllowedComponentProps {
  181. class?: unknown
  182. style?: unknown
  183. }
  184. // Note: can't mark this whole interface internal because some public interfaces
  185. // extend it.
  186. export interface ComponentInternalOptions {
  187. /**
  188. * indicates vapor component
  189. */
  190. __vapor?: boolean
  191. /**
  192. * indicates keep-alive component
  193. */
  194. __isKeepAlive?: boolean
  195. /**
  196. * @internal
  197. */
  198. __scopeId?: string
  199. /**
  200. * @internal
  201. */
  202. __cssModules?: Data
  203. /**
  204. * @internal
  205. */
  206. __hmrId?: string
  207. /**
  208. * Compat build only, for bailing out of certain compatibility behavior
  209. */
  210. __isBuiltIn?: boolean
  211. /**
  212. * This one should be exposed so that devtools can make use of it
  213. */
  214. __file?: string
  215. /**
  216. * name inferred from filename
  217. */
  218. __name?: string
  219. }
  220. export interface AsyncComponentInternalOptions<
  221. R = ConcreteComponent,
  222. I = ComponentInternalInstance,
  223. > {
  224. /**
  225. * marker for AsyncComponentWrapper
  226. * @internal
  227. */
  228. __asyncLoader?: () => Promise<R>
  229. /**
  230. * the inner component resolved by the AsyncComponentWrapper
  231. * @internal
  232. */
  233. __asyncResolved?: R
  234. /**
  235. * Exposed for lazy hydration
  236. * @internal
  237. */
  238. __asyncHydrate?: (el: Element, instance: I, hydrate: () => void) => void
  239. }
  240. export interface FunctionalComponent<
  241. P = {},
  242. E extends EmitsOptions | Record<string, any[]> = {},
  243. S extends Record<string, any> = any,
  244. EE extends EmitsOptions = ShortEmitsToObject<E>,
  245. > extends ComponentInternalOptions {
  246. // use of any here is intentional so it can be a valid JSX Element constructor
  247. (
  248. props: P & EmitsToProps<EE>,
  249. ctx: Omit<SetupContext<EE, IfAny<S, {}, SlotsType<S>>>, 'expose'>,
  250. ): any
  251. props?: ComponentPropsOptions<P>
  252. emits?: EE | (keyof EE)[]
  253. slots?: IfAny<S, Slots, SlotsType<S>>
  254. inheritAttrs?: boolean
  255. displayName?: string
  256. compatConfig?: CompatConfig
  257. }
  258. export interface ClassComponent {
  259. new (...args: any[]): ComponentPublicInstance<any, any, any, any, any>
  260. __vccOpts: ComponentOptions
  261. }
  262. /**
  263. * Type used where a function accepts both vdom and vapor components.
  264. */
  265. export type GenericComponent = (
  266. | {
  267. name?: string
  268. }
  269. | ((() => any) & { displayName?: string })
  270. ) &
  271. ComponentInternalOptions
  272. /**
  273. * Concrete component type matches its actual value: it's either an options
  274. * object, or a function. Use this where the code expects to work with actual
  275. * values, e.g. checking if its a function or not. This is mostly for internal
  276. * implementation code.
  277. */
  278. export type ConcreteComponent<
  279. Props = {},
  280. RawBindings = any,
  281. D = any,
  282. C extends ComputedOptions = ComputedOptions,
  283. M extends MethodOptions = MethodOptions,
  284. E extends EmitsOptions | Record<string, any[]> = {},
  285. S extends Record<string, any> = any,
  286. > =
  287. | ComponentOptions<Props, RawBindings, D, C, M>
  288. | FunctionalComponent<Props, E, S>
  289. /**
  290. * A type used in public APIs where a component type is expected.
  291. * The constructor type is an artificial type returned by defineComponent().
  292. */
  293. export type Component<
  294. PropsOrInstance = any,
  295. RawBindings = any,
  296. D = any,
  297. C extends ComputedOptions = ComputedOptions,
  298. M extends MethodOptions = MethodOptions,
  299. E extends EmitsOptions | Record<string, any[]> = {},
  300. S extends Record<string, any> = any,
  301. > =
  302. | ConcreteComponent<PropsOrInstance, RawBindings, D, C, M, E, S>
  303. | ComponentPublicInstanceConstructor<PropsOrInstance>
  304. export type { ComponentOptions }
  305. export type LifecycleHook<TFn = Function> = (TFn & SchedulerJob)[] | null
  306. // use `E extends any` to force evaluating type to fix #2362
  307. export type SetupContext<
  308. E = EmitsOptions,
  309. S extends SlotsType = {},
  310. > = E extends any
  311. ? {
  312. attrs: Data
  313. slots: UnwrapSlotsType<S>
  314. emit: EmitFn<E>
  315. expose: <Exposed extends Record<string, any> = Record<string, any>>(
  316. exposed?: Exposed,
  317. ) => void
  318. }
  319. : never
  320. /**
  321. * @internal
  322. */
  323. export type InternalRenderFunction = {
  324. (
  325. ctx: ComponentPublicInstance,
  326. cache: ComponentInternalInstance['renderCache'],
  327. // for compiler-optimized bindings
  328. $props: ComponentInternalInstance['props'],
  329. $setup: ComponentInternalInstance['setupState'],
  330. $data: ComponentInternalInstance['data'],
  331. $options: ComponentInternalInstance['ctx'],
  332. ): VNodeChild
  333. _rc?: boolean // isRuntimeCompiled
  334. // __COMPAT__ only
  335. _compatChecked?: boolean // v3 and already checked for v2 compat
  336. _compatWrapped?: boolean // is wrapped for v2 compat
  337. }
  338. /**
  339. * Base component instance interface that is shared between vdom mode and vapor
  340. * mode, so that we can have a mixed instance tree and reuse core logic that
  341. * operate on both.
  342. */
  343. export interface GenericComponentInstance {
  344. vapor?: boolean
  345. uid: number
  346. type: GenericComponent
  347. root: GenericComponentInstance | null
  348. parent: GenericComponentInstance | null
  349. appContext: GenericAppContext
  350. /**
  351. * Object containing values this component provides for its descendants
  352. * @internal
  353. */
  354. provides: Data
  355. /**
  356. * Tracking reactive effects (e.g. watchers) associated with this component
  357. * so that they can be automatically stopped on component unmount
  358. * @internal
  359. */
  360. scope: EffectScope
  361. /**
  362. * render function will have different types between vdom and vapor
  363. */
  364. render?: Function | null
  365. /**
  366. * SSR render function
  367. * (they are the same between vdom and vapor components.)
  368. * @internal
  369. */
  370. ssrRender?: Function | null
  371. // state
  372. props: Data
  373. attrs: Data
  374. refs: Data
  375. emit: EmitFn
  376. /**
  377. * used for keeping track of .once event handlers on components
  378. * @internal
  379. */
  380. emitted: Record<string, boolean> | null
  381. /**
  382. * used for caching the value returned from props default factory functions to
  383. * avoid unnecessary watcher trigger
  384. * @internal
  385. */
  386. propsDefaults: Data | null
  387. /**
  388. * used for getting the keys of a component's raw props, vapor only
  389. * @internal
  390. */
  391. rawKeys?: () => string[]
  392. // exposed properties via expose()
  393. exposed: Record<string, any> | null
  394. exposeProxy: Record<string, any> | null
  395. /**
  396. * setup related
  397. * @internal
  398. */
  399. setupState?: Data
  400. /**
  401. * devtools access to additional info
  402. * @internal
  403. */
  404. devtoolsRawSetupState?: any
  405. // lifecycle
  406. isMounted: boolean
  407. isUnmounted: boolean
  408. isDeactivated: boolean
  409. /**
  410. * for tracking useId()
  411. * first element is the current boundary prefix
  412. * second number is the index of the useId call within that boundary
  413. * @internal
  414. */
  415. ids: [string, number, number]
  416. // for vapor the following two are dev only
  417. /**
  418. * resolved props options
  419. * @internal
  420. */
  421. propsOptions?: NormalizedPropsOptions
  422. /**
  423. * resolved emits options
  424. * @internal
  425. */
  426. emitsOptions?: ObjectEmitsOptions | null
  427. /**
  428. * Public instance proxy, vdom only
  429. */
  430. proxy?: any
  431. /**
  432. * suspense related
  433. * @internal
  434. */
  435. suspense: SuspenseBoundary | null
  436. /**
  437. * suspense pending batch id
  438. * @internal
  439. */
  440. suspenseId: number
  441. /**
  442. * @internal
  443. */
  444. asyncDep: Promise<any> | null
  445. /**
  446. * @internal
  447. */
  448. asyncResolved: boolean
  449. /**
  450. * `updateTeleportCssVars`
  451. * For updating css vars on contained teleports
  452. * @internal
  453. */
  454. ut?: (vars?: Record<string, string>) => void
  455. /**
  456. * dev only. For style v-bind hydration mismatch checks
  457. * @internal
  458. */
  459. getCssVars?: () => Record<string, string>
  460. // lifecycle
  461. /**
  462. * @internal
  463. */
  464. [LifecycleHooks.BEFORE_CREATE]?: LifecycleHook
  465. /**
  466. * @internal
  467. */
  468. [LifecycleHooks.CREATED]?: LifecycleHook
  469. /**
  470. * @internal
  471. */
  472. [LifecycleHooks.BEFORE_MOUNT]?: LifecycleHook
  473. /**
  474. * @internal
  475. */
  476. [LifecycleHooks.MOUNTED]?: LifecycleHook
  477. /**
  478. * @internal
  479. */
  480. [LifecycleHooks.BEFORE_UPDATE]?: LifecycleHook
  481. /**
  482. * @internal
  483. */
  484. [LifecycleHooks.UPDATED]?: LifecycleHook
  485. /**
  486. * @internal
  487. */
  488. [LifecycleHooks.BEFORE_UNMOUNT]?: LifecycleHook
  489. /**
  490. * @internal
  491. */
  492. [LifecycleHooks.UNMOUNTED]?: LifecycleHook
  493. /**
  494. * @internal
  495. */
  496. [LifecycleHooks.RENDER_TRACKED]?: LifecycleHook
  497. /**
  498. * @internal
  499. */
  500. [LifecycleHooks.RENDER_TRIGGERED]?: LifecycleHook
  501. /**
  502. * @internal
  503. */
  504. [LifecycleHooks.ACTIVATED]?: LifecycleHook
  505. /**
  506. * @internal
  507. */
  508. [LifecycleHooks.DEACTIVATED]?: LifecycleHook
  509. /**
  510. * @internal
  511. */
  512. [LifecycleHooks.ERROR_CAPTURED]?: LifecycleHook
  513. /**
  514. * @internal
  515. */
  516. [LifecycleHooks.SERVER_PREFETCH]?: LifecycleHook<() => Promise<unknown>>
  517. /**
  518. * @internal vapor only
  519. */
  520. hmrRerender?: () => void
  521. /**
  522. * @internal vapor only
  523. */
  524. hmrReload?: (newComp: any) => void
  525. // these only exist on vdom instances
  526. vnode?: VNode
  527. subTree?: VNode
  528. /**
  529. * Custom Element instance (if component is created by defineCustomElement)
  530. * @internal
  531. */
  532. ce?: ComponentCustomElementInterface
  533. /**
  534. * is custom element? (kept only for compatibility)
  535. * @internal
  536. */
  537. isCE?: boolean
  538. /**
  539. * custom element specific HMR method
  540. * @internal
  541. */
  542. ceReload?: (newStyles?: string[]) => void
  543. }
  544. /**
  545. * We expose a subset of properties on the internal instance as they are
  546. * useful for advanced external libraries and tools.
  547. */
  548. export interface ComponentInternalInstance extends GenericComponentInstance {
  549. vapor?: never
  550. uid: number
  551. type: ConcreteComponent
  552. parent: GenericComponentInstance | null
  553. root: GenericComponentInstance
  554. appContext: AppContext
  555. /**
  556. * Vnode representing this component in its parent's vdom tree
  557. */
  558. vnode: VNode
  559. /**
  560. * The pending new vnode from parent updates
  561. * @internal
  562. */
  563. next: VNode | null
  564. /**
  565. * Root vnode of this component's own vdom tree
  566. */
  567. subTree: VNode
  568. /**
  569. * Render effect instance
  570. */
  571. effect: ReactiveEffect
  572. /**
  573. * Force update render effect
  574. */
  575. update: () => void
  576. /**
  577. * Render effect job to be passed to scheduler (checks if dirty)
  578. */
  579. job: SchedulerJob
  580. /**
  581. * The render function that returns vdom tree.
  582. * @internal
  583. */
  584. render: InternalRenderFunction | null
  585. /**
  586. * cache for proxy access type to avoid hasOwnProperty calls
  587. * @internal
  588. */
  589. accessCache: Data | null
  590. /**
  591. * cache for render function values that rely on _ctx but won't need updates
  592. * after initialized (e.g. inline handlers)
  593. * @internal
  594. */
  595. renderCache: (Function | VNode | undefined)[]
  596. /**
  597. * Resolved component registry, only for components with mixins or extends
  598. * @internal
  599. */
  600. components: Record<string, ConcreteComponent> | null
  601. /**
  602. * Resolved directive registry, only for components with mixins or extends
  603. * @internal
  604. */
  605. directives: Record<string, Directive> | null
  606. /**
  607. * Resolved filters registry, v2 compat only
  608. * @internal
  609. */
  610. filters?: Record<string, Function>
  611. /**
  612. * resolved props options
  613. * @internal
  614. */
  615. propsOptions: NormalizedPropsOptions
  616. /**
  617. * resolved emits options
  618. * @internal
  619. */
  620. emitsOptions: ObjectEmitsOptions | null
  621. /**
  622. * resolved inheritAttrs options
  623. * @internal
  624. */
  625. inheritAttrs?: boolean
  626. // the rest are only for stateful components ---------------------------------
  627. /**
  628. * setup related
  629. * @internal
  630. */
  631. setupState: Data
  632. /**
  633. * @internal
  634. */
  635. setupContext?: SetupContext | null
  636. // main proxy that serves as the public instance (`this`)
  637. proxy: ComponentPublicInstance | null
  638. data: Data // options API only
  639. emit: EmitFn
  640. slots: InternalSlots
  641. exposeProxy: Record<string, any> | null
  642. /**
  643. * alternative proxy used only for runtime-compiled render functions using
  644. * `with` block
  645. * @internal
  646. */
  647. withProxy: ComponentPublicInstance | null
  648. /**
  649. * This is the target for the public instance proxy. It also holds properties
  650. * injected by user options (computed, methods etc.) and user-attached
  651. * custom properties (via `this.x = ...`)
  652. * @internal
  653. */
  654. ctx: Data
  655. /**
  656. * suspense pending batch id
  657. * @internal
  658. */
  659. suspenseId: number
  660. /**
  661. * @internal
  662. */
  663. asyncDep: Promise<any> | null
  664. /**
  665. * @internal
  666. */
  667. asyncResolved: boolean
  668. /**
  669. * For caching bound $forceUpdate on public proxy access
  670. * @internal
  671. */
  672. f?: () => void
  673. /**
  674. * For caching bound $nextTick on public proxy access
  675. * @internal
  676. */
  677. n?: () => Promise<void>
  678. /**
  679. * v2 compat only, for caching mutated $options
  680. * @internal
  681. */
  682. resolvedOptions?: MergedComponentOptions
  683. }
  684. const emptyAppContext = createAppContext()
  685. let uid = 0
  686. /**
  687. * @internal for vapor
  688. */
  689. export function nextUid(): number {
  690. return uid++
  691. }
  692. export function createComponentInstance(
  693. vnode: VNode,
  694. parent: ComponentInternalInstance | null,
  695. suspense: SuspenseBoundary | null,
  696. ): ComponentInternalInstance {
  697. const type = vnode.type as ConcreteComponent
  698. // inherit parent app context - or - if root, adopt from root vnode
  699. const appContext =
  700. (parent ? parent.appContext : vnode.appContext) || emptyAppContext
  701. const instance: ComponentInternalInstance = {
  702. uid: uid++,
  703. vnode,
  704. type,
  705. parent,
  706. appContext,
  707. root: null!, // to be immediately set
  708. next: null,
  709. subTree: null!, // will be set synchronously right after creation
  710. effect: null!,
  711. update: null!, // will be set synchronously right after creation
  712. job: null!,
  713. scope: new EffectScope(true /* detached */),
  714. render: null,
  715. proxy: null,
  716. exposed: null,
  717. exposeProxy: null,
  718. withProxy: null,
  719. provides: parent ? parent.provides : Object.create(appContext.provides),
  720. ids: parent ? parent.ids : ['', 0, 0],
  721. accessCache: null!,
  722. renderCache: [],
  723. // local resolved assets
  724. components: null,
  725. directives: null,
  726. // resolved props and emits options
  727. propsOptions: normalizePropsOptions(type, appContext),
  728. emitsOptions: normalizeEmitsOptions(type, appContext),
  729. // emit
  730. emit: null!, // to be set immediately
  731. emitted: null,
  732. // props default value
  733. propsDefaults: null,
  734. // inheritAttrs
  735. inheritAttrs: type.inheritAttrs,
  736. // state
  737. ctx: EMPTY_OBJ,
  738. data: EMPTY_OBJ,
  739. props: EMPTY_OBJ,
  740. attrs: EMPTY_OBJ,
  741. slots: EMPTY_OBJ,
  742. refs: EMPTY_OBJ,
  743. setupState: EMPTY_OBJ,
  744. setupContext: null,
  745. // suspense related
  746. suspense,
  747. suspenseId: suspense ? suspense.pendingId : 0,
  748. asyncDep: null,
  749. asyncResolved: false,
  750. // lifecycle hooks
  751. // not using enums here because it results in computed properties
  752. isMounted: false,
  753. isUnmounted: false,
  754. isDeactivated: false,
  755. bc: null,
  756. c: null,
  757. bm: null,
  758. m: null,
  759. bu: null,
  760. u: null,
  761. um: null,
  762. bum: null,
  763. da: null,
  764. a: null,
  765. rtg: null,
  766. rtc: null,
  767. ec: null,
  768. sp: null,
  769. }
  770. if (__DEV__) {
  771. instance.ctx = createDevRenderContext(instance)
  772. } else {
  773. instance.ctx = { _: instance }
  774. }
  775. instance.root = parent ? parent.root : instance
  776. instance.emit = emit.bind(null, instance)
  777. // apply custom element special handling
  778. if (vnode.ce) {
  779. vnode.ce(instance)
  780. }
  781. return instance
  782. }
  783. /**
  784. * @internal
  785. */
  786. export function validateComponentName(
  787. name: string,
  788. { isNativeTag }: AppConfig,
  789. ): void {
  790. if (isBuiltInTag(name) || isNativeTag(name)) {
  791. warn(
  792. 'Do not use built-in or reserved HTML elements as component id: ' + name,
  793. )
  794. }
  795. }
  796. export function isStatefulComponent(
  797. instance: ComponentInternalInstance,
  798. ): number {
  799. return instance.vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT
  800. }
  801. export function setupComponent(
  802. instance: ComponentInternalInstance,
  803. isSSR = false,
  804. optimized = false,
  805. ): Promise<void> | undefined {
  806. isSSR && setInSSRSetupState(isSSR)
  807. const { props, children, vi } = instance.vnode
  808. const isStateful = isStatefulComponent(instance)
  809. if (vi) {
  810. // Vapor interop override - use Vapor props/attrs proxy
  811. vi(instance)
  812. } else {
  813. initProps(instance, props, isStateful, isSSR)
  814. initSlots(instance, children, optimized || isSSR)
  815. }
  816. const setupResult = isStateful
  817. ? setupStatefulComponent(instance, isSSR)
  818. : undefined
  819. isSSR && setInSSRSetupState(false)
  820. return setupResult
  821. }
  822. function setupStatefulComponent(
  823. instance: ComponentInternalInstance,
  824. isSSR: boolean,
  825. ) {
  826. const Component = instance.type as ComponentOptions
  827. if (__DEV__) {
  828. if (Component.name) {
  829. validateComponentName(Component.name, instance.appContext.config)
  830. }
  831. if (Component.components) {
  832. const names = Object.keys(Component.components)
  833. for (let i = 0; i < names.length; i++) {
  834. validateComponentName(names[i], instance.appContext.config)
  835. }
  836. }
  837. if (Component.directives) {
  838. const names = Object.keys(Component.directives)
  839. for (let i = 0; i < names.length; i++) {
  840. validateDirectiveName(names[i])
  841. }
  842. }
  843. if (Component.compilerOptions && isRuntimeOnly()) {
  844. warn(
  845. `"compilerOptions" is only supported when using a build of Vue that ` +
  846. `includes the runtime compiler. Since you are using a runtime-only ` +
  847. `build, the options should be passed via your build tool config instead.`,
  848. )
  849. }
  850. }
  851. // 0. create render proxy property access cache
  852. instance.accessCache = Object.create(null)
  853. // 1. create public instance / render proxy
  854. instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers)
  855. if (__DEV__) {
  856. exposePropsOnRenderContext(instance)
  857. }
  858. // 2. call setup()
  859. const { setup } = Component
  860. if (setup) {
  861. const prevSub = setActiveSub()
  862. const setupContext = (instance.setupContext =
  863. setup.length > 1 ? createSetupContext(instance) : null)
  864. const prev = setCurrentInstance(instance)
  865. const setupResult = callWithErrorHandling(
  866. setup,
  867. instance,
  868. ErrorCodes.SETUP_FUNCTION,
  869. [
  870. __DEV__ ? shallowReadonly(instance.props) : instance.props,
  871. setupContext,
  872. ],
  873. )
  874. const isAsyncSetup = isPromise(setupResult)
  875. setActiveSub(prevSub)
  876. setCurrentInstance(...prev)
  877. if ((isAsyncSetup || instance.sp) && !isAsyncWrapper(instance)) {
  878. // async setup / serverPrefetch, mark as async boundary for useId()
  879. markAsyncBoundary(instance)
  880. }
  881. if (isAsyncSetup) {
  882. const unsetCurrentInstance = (): void => {
  883. setCurrentInstance(null, undefined)
  884. }
  885. setupResult.then(unsetCurrentInstance, unsetCurrentInstance)
  886. if (isSSR) {
  887. // return the promise so server-renderer can wait on it
  888. return setupResult
  889. .then((resolvedResult: unknown) => {
  890. handleSetupResult(instance, resolvedResult, isSSR)
  891. })
  892. .catch(e => {
  893. handleError(e, instance, ErrorCodes.SETUP_FUNCTION)
  894. })
  895. } else if (__FEATURE_SUSPENSE__) {
  896. // async setup returned Promise.
  897. // bail here and wait for re-entry.
  898. instance.asyncDep = setupResult
  899. if (__DEV__ && !instance.suspense) {
  900. const name = formatComponentName(instance, Component)
  901. warn(
  902. `Component <${name}>: setup function returned a promise, but no ` +
  903. `<Suspense> boundary was found in the parent component tree. ` +
  904. `A component with async setup() must be nested in a <Suspense> ` +
  905. `in order to be rendered.`,
  906. )
  907. }
  908. } else if (__DEV__) {
  909. warn(
  910. `setup() returned a Promise, but the version of Vue you are using ` +
  911. `does not support it yet.`,
  912. )
  913. }
  914. } else {
  915. handleSetupResult(instance, setupResult, isSSR)
  916. }
  917. } else {
  918. finishComponentSetup(instance, isSSR)
  919. }
  920. }
  921. export function handleSetupResult(
  922. instance: ComponentInternalInstance,
  923. setupResult: unknown,
  924. isSSR: boolean,
  925. ): void {
  926. if (isFunction(setupResult)) {
  927. // setup returned an inline render function
  928. if (__SSR__ && (instance.type as ComponentOptions).__ssrInlineRender) {
  929. // when the function's name is `ssrRender` (compiled by SFC inline mode),
  930. // set it as ssrRender instead.
  931. instance.ssrRender = setupResult
  932. } else {
  933. instance.render = setupResult as InternalRenderFunction
  934. }
  935. } else if (isObject(setupResult)) {
  936. if (__DEV__ && isVNode(setupResult)) {
  937. warn(
  938. `setup() should not return VNodes directly - ` +
  939. `return a render function instead.`,
  940. )
  941. }
  942. // setup returned bindings.
  943. // assuming a render function compiled from template is present.
  944. if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
  945. instance.devtoolsRawSetupState = setupResult
  946. }
  947. instance.setupState = proxyRefs(setupResult)
  948. if (__DEV__) {
  949. exposeSetupStateOnRenderContext(instance)
  950. }
  951. } else if (__DEV__ && setupResult !== undefined) {
  952. warn(
  953. `setup() should return an object. Received: ${
  954. setupResult === null ? 'null' : typeof setupResult
  955. }`,
  956. )
  957. }
  958. finishComponentSetup(instance, isSSR)
  959. }
  960. type CompileFunction = (
  961. template: string | object,
  962. options?: CompilerOptions,
  963. ) => InternalRenderFunction
  964. let compile: CompileFunction | undefined
  965. let installWithProxy: (i: ComponentInternalInstance) => void
  966. /**
  967. * For runtime-dom to register the compiler.
  968. * Note the exported method uses any to avoid d.ts relying on the compiler types.
  969. */
  970. export function registerRuntimeCompiler(_compile: any): void {
  971. compile = _compile
  972. installWithProxy = i => {
  973. if (i.render!._rc) {
  974. i.withProxy = new Proxy(i.ctx, RuntimeCompiledPublicInstanceProxyHandlers)
  975. }
  976. }
  977. }
  978. // dev only
  979. export const isRuntimeOnly = (): boolean => !compile
  980. export function finishComponentSetup(
  981. instance: ComponentInternalInstance,
  982. isSSR: boolean,
  983. skipOptions?: boolean,
  984. ): void {
  985. const Component = instance.type as ComponentOptions
  986. if (__COMPAT__) {
  987. convertLegacyRenderFn(instance)
  988. if (__DEV__ && Component.compatConfig) {
  989. validateCompatConfig(Component.compatConfig)
  990. }
  991. }
  992. // template / render function normalization
  993. // could be already set when returned from setup()
  994. if (!instance.render) {
  995. // only do on-the-fly compile if not in SSR - SSR on-the-fly compilation
  996. // is done by server-renderer
  997. if (!isSSR && compile && !Component.render) {
  998. const template =
  999. (__COMPAT__ &&
  1000. instance.vnode.props &&
  1001. instance.vnode.props['inline-template']) ||
  1002. Component.template ||
  1003. (__FEATURE_OPTIONS_API__ && resolveMergedOptions(instance).template)
  1004. if (template) {
  1005. if (__DEV__) {
  1006. startMeasure(instance, `compile`)
  1007. }
  1008. const { isCustomElement, compilerOptions } = instance.appContext.config
  1009. const { delimiters, compilerOptions: componentCompilerOptions } =
  1010. Component
  1011. const finalCompilerOptions: CompilerOptions = extend(
  1012. extend(
  1013. {
  1014. isCustomElement,
  1015. delimiters,
  1016. },
  1017. compilerOptions,
  1018. ),
  1019. componentCompilerOptions,
  1020. )
  1021. if (__COMPAT__) {
  1022. // pass runtime compat config into the compiler
  1023. finalCompilerOptions.compatConfig = Object.create(globalCompatConfig)
  1024. if (Component.compatConfig) {
  1025. // @ts-expect-error types are not compatible
  1026. extend(finalCompilerOptions.compatConfig, Component.compatConfig)
  1027. }
  1028. }
  1029. Component.render = compile(template, finalCompilerOptions)
  1030. if (__DEV__) {
  1031. endMeasure(instance, `compile`)
  1032. }
  1033. }
  1034. }
  1035. instance.render = (Component.render || NOOP) as InternalRenderFunction
  1036. // for runtime-compiled render functions using `with` blocks, the render
  1037. // proxy used needs a different `has` handler which is more performant and
  1038. // also only allows a whitelist of globals to fallthrough.
  1039. if (installWithProxy) {
  1040. installWithProxy(instance)
  1041. }
  1042. }
  1043. // support for 2.x options
  1044. if (__FEATURE_OPTIONS_API__ && !(__COMPAT__ && skipOptions)) {
  1045. const prevInstance = setCurrentInstance(instance)
  1046. const prevSub = setActiveSub()
  1047. try {
  1048. applyOptions(instance)
  1049. } finally {
  1050. setActiveSub(prevSub)
  1051. setCurrentInstance(...prevInstance)
  1052. }
  1053. }
  1054. // warn missing template/render
  1055. // the runtime compilation of template in SSR is done by server-render
  1056. if (__DEV__ && !Component.render && instance.render === NOOP && !isSSR) {
  1057. if (!compile && Component.template) {
  1058. /* v8 ignore start */
  1059. warn(
  1060. `Component provided template option but ` +
  1061. `runtime compilation is not supported in this build of Vue.` +
  1062. (__ESM_BUNDLER__
  1063. ? ` Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".`
  1064. : __ESM_BROWSER__
  1065. ? ` Use "vue.esm-browser.js" instead.`
  1066. : __GLOBAL__
  1067. ? ` Use "vue.global.js" instead.`
  1068. : ``) /* should not happen */,
  1069. )
  1070. /* v8 ignore stop */
  1071. } else {
  1072. warn(`Component is missing template or render function: `, Component)
  1073. }
  1074. }
  1075. }
  1076. const attrsProxyHandlers = __DEV__
  1077. ? {
  1078. get(target: Data, key: string) {
  1079. markAttrsAccessed()
  1080. track(target, TrackOpTypes.GET, '')
  1081. return target[key]
  1082. },
  1083. set() {
  1084. warn(`setupContext.attrs is readonly.`)
  1085. return false
  1086. },
  1087. deleteProperty() {
  1088. warn(`setupContext.attrs is readonly.`)
  1089. return false
  1090. },
  1091. }
  1092. : {
  1093. get(target: Data, key: string) {
  1094. track(target, TrackOpTypes.GET, '')
  1095. return target[key]
  1096. },
  1097. }
  1098. /**
  1099. * Dev-only
  1100. */
  1101. function getSlotsProxy(instance: ComponentInternalInstance): Slots {
  1102. return new Proxy(instance.slots, {
  1103. get(target, key: string) {
  1104. track(instance, TrackOpTypes.GET, '$slots')
  1105. return target[key]
  1106. },
  1107. })
  1108. }
  1109. export function createSetupContext(
  1110. instance: ComponentInternalInstance,
  1111. ): SetupContext {
  1112. if (__DEV__) {
  1113. // We use getters in dev in case libs like test-utils overwrite instance
  1114. // properties (overwrites should not be done in prod)
  1115. let attrsProxy: Data
  1116. let slotsProxy: Slots
  1117. return Object.freeze({
  1118. get attrs() {
  1119. return (
  1120. attrsProxy ||
  1121. (attrsProxy = new Proxy(instance.attrs, attrsProxyHandlers))
  1122. )
  1123. },
  1124. get slots() {
  1125. return slotsProxy || (slotsProxy = getSlotsProxy(instance))
  1126. },
  1127. get emit() {
  1128. return (event: string, ...args: any[]) => instance.emit(event, ...args)
  1129. },
  1130. expose: exposed => expose(instance, exposed as any),
  1131. })
  1132. } else {
  1133. return {
  1134. attrs: new Proxy(instance.attrs, attrsProxyHandlers),
  1135. slots: instance.slots,
  1136. emit: instance.emit,
  1137. expose: exposed => expose(instance, exposed as any),
  1138. }
  1139. }
  1140. }
  1141. /**
  1142. * @internal
  1143. */
  1144. export function expose(
  1145. instance: GenericComponentInstance,
  1146. exposed: Record<string, any>,
  1147. ): void {
  1148. if (__DEV__) {
  1149. if (instance.exposed) {
  1150. warn(`expose() should be called only once per setup().`)
  1151. }
  1152. if (exposed != null) {
  1153. let exposedType: string = typeof exposed
  1154. if (exposedType === 'object') {
  1155. if (isArray(exposed)) {
  1156. exposedType = 'array'
  1157. } else if (isRef(exposed)) {
  1158. exposedType = 'ref'
  1159. }
  1160. }
  1161. if (exposedType !== 'object') {
  1162. warn(
  1163. `expose() should be passed a plain object, received ${exposedType}.`,
  1164. )
  1165. }
  1166. }
  1167. }
  1168. instance.exposed = exposed || {}
  1169. }
  1170. export function getComponentPublicInstance(
  1171. instance: GenericComponentInstance,
  1172. ): ComponentPublicInstance | ComponentInternalInstance['exposed'] | null {
  1173. if (instance.exposed) {
  1174. return (
  1175. instance.exposeProxy ||
  1176. (instance.exposeProxy = new Proxy(proxyRefs(markRaw(instance.exposed)), {
  1177. get(target, key: string) {
  1178. if (key in target) {
  1179. return target[key]
  1180. } else if (key in publicPropertiesMap) {
  1181. return publicPropertiesMap[key](
  1182. instance as ComponentInternalInstance,
  1183. )
  1184. }
  1185. },
  1186. has(target, key: string) {
  1187. return key in target || key in publicPropertiesMap
  1188. },
  1189. }))
  1190. )
  1191. } else {
  1192. return instance.proxy
  1193. }
  1194. }
  1195. const classifyRE = /(?:^|[-_])\w/g
  1196. const classify = (str: string): string =>
  1197. str.replace(classifyRE, c => c.toUpperCase()).replace(/[-_]/g, '')
  1198. export function getComponentName(
  1199. Component: GenericComponent,
  1200. includeInferred = true,
  1201. ): string | false | undefined {
  1202. return isFunction(Component)
  1203. ? Component.displayName || Component.name
  1204. : Component.name || (includeInferred && Component.__name)
  1205. }
  1206. export function formatComponentName(
  1207. instance: GenericComponentInstance | null,
  1208. Component: GenericComponent,
  1209. isRoot = false,
  1210. ): string {
  1211. let name = getComponentName(Component)
  1212. if (!name && Component.__file) {
  1213. const match = Component.__file.match(/([^/\\]+)\.\w+$/)
  1214. if (match) {
  1215. name = match[1]
  1216. }
  1217. }
  1218. if (!name && instance) {
  1219. // try to infer the name based on reverse resolution
  1220. const inferFromRegistry = (
  1221. registry: Record<string, any> | undefined | null,
  1222. ) => {
  1223. for (const key in registry) {
  1224. if (registry[key] === Component) {
  1225. return key
  1226. }
  1227. }
  1228. }
  1229. name =
  1230. inferFromRegistry((instance as ComponentInternalInstance).components) ||
  1231. (instance.parent &&
  1232. inferFromRegistry(
  1233. (instance.parent.type as ComponentOptions).components,
  1234. )) ||
  1235. inferFromRegistry(instance.appContext.components)
  1236. }
  1237. return name ? classify(name) : isRoot ? `App` : `Anonymous`
  1238. }
  1239. export function isClassComponent(value: unknown): value is ClassComponent {
  1240. return isFunction(value) && '__vccOpts' in value
  1241. }
  1242. export interface ComponentCustomElementInterface {
  1243. /**
  1244. * @internal
  1245. */
  1246. _injectChildStyle(type: ConcreteComponent): void
  1247. /**
  1248. * @internal
  1249. */
  1250. _removeChildStyle(type: ConcreteComponent): void
  1251. /**
  1252. * @internal
  1253. */
  1254. _setProp(
  1255. key: string,
  1256. val: any,
  1257. shouldReflect?: boolean,
  1258. shouldUpdate?: boolean,
  1259. ): void
  1260. /**
  1261. * @internal
  1262. */
  1263. _beginPatch(): void
  1264. /**
  1265. * @internal
  1266. */
  1267. _endPatch(): void
  1268. /**
  1269. * @internal attached by the nested Teleport when shadowRoot is false.
  1270. */
  1271. _teleportTargets?: Set<RendererElement>
  1272. }