componentOptions.ts 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324
  1. import {
  2. type Component,
  3. type ComponentInternalInstance,
  4. type ComponentInternalOptions,
  5. type ConcreteComponent,
  6. type Data,
  7. type InternalRenderFunction,
  8. type SetupContext,
  9. currentInstance,
  10. } from './component'
  11. import {
  12. type LooseRequired,
  13. NOOP,
  14. type Prettify,
  15. extend,
  16. isArray,
  17. isFunction,
  18. isObject,
  19. isPromise,
  20. isString,
  21. } from '@vue/shared'
  22. import { type Ref, getCurrentScope, isRef, traverse } from '@vue/reactivity'
  23. import { computed } from './apiComputed'
  24. import {
  25. type WatchCallback,
  26. type WatchOptions,
  27. createPathGetter,
  28. watch,
  29. } from './apiWatch'
  30. import { inject, provide } from './apiInject'
  31. import {
  32. type DebuggerHook,
  33. type ErrorCapturedHook,
  34. onActivated,
  35. onBeforeMount,
  36. onBeforeUnmount,
  37. onBeforeUpdate,
  38. onDeactivated,
  39. onErrorCaptured,
  40. onMounted,
  41. onRenderTracked,
  42. onRenderTriggered,
  43. onServerPrefetch,
  44. onUnmounted,
  45. onUpdated,
  46. } from './apiLifecycle'
  47. import {
  48. type ComputedGetter,
  49. type WritableComputedOptions,
  50. reactive,
  51. } from '@vue/reactivity'
  52. import type {
  53. ComponentObjectPropsOptions,
  54. ComponentPropsOptions,
  55. ExtractDefaultPropTypes,
  56. ExtractPropTypes,
  57. } from './componentProps'
  58. import type {
  59. EmitsOptions,
  60. EmitsToProps,
  61. TypeEmitsToOptions,
  62. } from './componentEmits'
  63. import type { Directive } from './directives'
  64. import {
  65. type ComponentPublicInstance,
  66. type CreateComponentPublicInstanceWithMixins,
  67. type IntersectionMixin,
  68. type UnwrapMixinsType,
  69. isReservedPrefix,
  70. } from './componentPublicInstance'
  71. import { warn } from './warning'
  72. import type { VNodeChild } from './vnode'
  73. import { callWithAsyncErrorHandling } from './errorHandling'
  74. import { deepMergeData } from './compat/data'
  75. import { DeprecationTypes, checkCompatEnabled } from './compat/compatConfig'
  76. import {
  77. type CompatConfig,
  78. isCompatEnabled,
  79. softAssertCompatEnabled,
  80. } from './compat/compatConfig'
  81. import type { OptionMergeFunction } from './apiCreateApp'
  82. import { LifecycleHooks } from './enums'
  83. import type { SlotsType } from './componentSlots'
  84. import {
  85. type ComponentTypeEmits,
  86. normalizePropsOrEmits,
  87. } from './apiSetupHelpers'
  88. import { markAsyncBoundary } from './helpers/useId'
  89. /**
  90. * Interface for declaring custom options.
  91. *
  92. * @example
  93. * ```ts
  94. * declare module 'vue' {
  95. * interface ComponentCustomOptions {
  96. * beforeRouteUpdate?(
  97. * to: Route,
  98. * from: Route,
  99. * next: () => void
  100. * ): void
  101. * }
  102. * }
  103. * ```
  104. */
  105. export interface ComponentCustomOptions {}
  106. export type RenderFunction = () => VNodeChild
  107. export interface ComponentOptionsBase<
  108. Props,
  109. RawBindings,
  110. D,
  111. C extends ComputedOptions,
  112. M extends MethodOptions,
  113. Mixin extends ComponentOptionsMixin,
  114. Extends extends ComponentOptionsMixin,
  115. E extends EmitsOptions,
  116. EE extends string = string,
  117. Defaults = {},
  118. I extends ComponentInjectOptions = {},
  119. II extends string = string,
  120. S extends SlotsType = {},
  121. LC extends Record<string, Component> = {},
  122. Directives extends Record<string, Directive> = {},
  123. Exposed extends string = string,
  124. Provide extends ComponentProvideOptions = ComponentProvideOptions,
  125. > extends LegacyOptions<Props, D, C, M, Mixin, Extends, I, II, Provide>,
  126. ComponentInternalOptions,
  127. ComponentCustomOptions {
  128. setup?: (
  129. this: void,
  130. props: LooseRequired<
  131. Props &
  132. Prettify<
  133. UnwrapMixinsType<
  134. IntersectionMixin<Mixin> & IntersectionMixin<Extends>,
  135. 'P'
  136. >
  137. >
  138. >,
  139. ctx: SetupContext<E, S>,
  140. ) => Promise<RawBindings> | RawBindings | RenderFunction | void
  141. name?: string
  142. template?: string | object // can be a direct DOM node
  143. // Note: we are intentionally using the signature-less `Function` type here
  144. // since any type with signature will cause the whole inference to fail when
  145. // the return expression contains reference to `this`.
  146. // Luckily `render()` doesn't need any arguments nor does it care about return
  147. // type.
  148. render?: Function
  149. // NOTE: extending both LC and Record<string, Component> allows objects to be forced
  150. // to be of type Component, while still inferring LC generic
  151. components?: LC & Record<string, Component>
  152. // NOTE: extending both Directives and Record<string, Directive> allows objects to be forced
  153. // to be of type Directive, while still inferring Directives generic
  154. directives?: Directives & Record<string, Directive>
  155. inheritAttrs?: boolean
  156. emits?: (E | EE[]) & ThisType<void>
  157. slots?: S
  158. expose?: Exposed[]
  159. serverPrefetch?(): void | Promise<any>
  160. // Runtime compiler only -----------------------------------------------------
  161. compilerOptions?: RuntimeCompilerOptions
  162. // Internal ------------------------------------------------------------------
  163. /**
  164. * SSR only. This is produced by compiler-ssr and attached in compiler-sfc
  165. * not user facing, so the typing is lax and for test only.
  166. * @internal
  167. */
  168. ssrRender?: (
  169. ctx: any,
  170. push: (item: any) => void,
  171. parentInstance: ComponentInternalInstance,
  172. attrs: Data | undefined,
  173. // for compiler-optimized bindings
  174. $props: ComponentInternalInstance['props'],
  175. $setup: ComponentInternalInstance['setupState'],
  176. $data: ComponentInternalInstance['data'],
  177. $options: ComponentInternalInstance['ctx'],
  178. ) => void
  179. /**
  180. * Only generated by compiler-sfc to mark a ssr render function inlined and
  181. * returned from setup()
  182. * @internal
  183. */
  184. __ssrInlineRender?: boolean
  185. /**
  186. * marker for AsyncComponentWrapper
  187. * @internal
  188. */
  189. __asyncLoader?: () => Promise<ConcreteComponent>
  190. /**
  191. * the inner component resolved by the AsyncComponentWrapper
  192. * @internal
  193. */
  194. __asyncResolved?: ConcreteComponent
  195. /**
  196. * Exposed for lazy hydration
  197. * @internal
  198. */
  199. __asyncHydrate?: (
  200. el: Element,
  201. instance: ComponentInternalInstance,
  202. hydrate: () => void,
  203. ) => void
  204. // Type differentiators ------------------------------------------------------
  205. // Note these are internal but need to be exposed in d.ts for type inference
  206. // to work!
  207. // type-only differentiator to separate OptionWithoutProps from a constructor
  208. // type returned by defineComponent() or FunctionalComponent
  209. call?: (this: unknown, ...args: unknown[]) => never
  210. // type-only differentiators for built-in Vnode types
  211. __isFragment?: never
  212. __isTeleport?: never
  213. __isSuspense?: never
  214. __defaults?: Defaults
  215. }
  216. /**
  217. * Subset of compiler options that makes sense for the runtime.
  218. */
  219. export interface RuntimeCompilerOptions {
  220. isCustomElement?: (tag: string) => boolean
  221. whitespace?: 'preserve' | 'condense'
  222. comments?: boolean
  223. delimiters?: [string, string]
  224. }
  225. export type ComponentOptions<
  226. Props = {},
  227. RawBindings = any,
  228. D = any,
  229. C extends ComputedOptions = any,
  230. M extends MethodOptions = any,
  231. Mixin extends ComponentOptionsMixin = any,
  232. Extends extends ComponentOptionsMixin = any,
  233. E extends EmitsOptions = any,
  234. EE extends string = string,
  235. Defaults = {},
  236. I extends ComponentInjectOptions = {},
  237. II extends string = string,
  238. S extends SlotsType = {},
  239. LC extends Record<string, Component> = {},
  240. Directives extends Record<string, Directive> = {},
  241. Exposed extends string = string,
  242. Provide extends ComponentProvideOptions = ComponentProvideOptions,
  243. > = ComponentOptionsBase<
  244. Props,
  245. RawBindings,
  246. D,
  247. C,
  248. M,
  249. Mixin,
  250. Extends,
  251. E,
  252. EE,
  253. Defaults,
  254. I,
  255. II,
  256. S,
  257. LC,
  258. Directives,
  259. Exposed,
  260. Provide
  261. > &
  262. ThisType<
  263. CreateComponentPublicInstanceWithMixins<
  264. {},
  265. RawBindings,
  266. D,
  267. C,
  268. M,
  269. Mixin,
  270. Extends,
  271. E,
  272. Readonly<Props>,
  273. Defaults,
  274. false,
  275. I,
  276. S,
  277. LC,
  278. Directives
  279. >
  280. >
  281. export type ComponentOptionsMixin = ComponentOptionsBase<
  282. any,
  283. any,
  284. any,
  285. any,
  286. any,
  287. any,
  288. any,
  289. any,
  290. any,
  291. any,
  292. any,
  293. any,
  294. any,
  295. any,
  296. any,
  297. any,
  298. any
  299. >
  300. export type ComputedOptions = Record<
  301. string,
  302. ComputedGetter<any> | WritableComputedOptions<any>
  303. >
  304. export interface MethodOptions {
  305. [key: string]: Function
  306. }
  307. export type ExtractComputedReturns<T extends any> = {
  308. [key in keyof T]: T[key] extends { get: (...args: any[]) => infer TReturn }
  309. ? TReturn
  310. : T[key] extends (...args: any[]) => infer TReturn
  311. ? TReturn
  312. : never
  313. }
  314. export type ObjectWatchOptionItem = {
  315. handler: WatchCallback | string
  316. } & WatchOptions
  317. type WatchOptionItem = string | WatchCallback | ObjectWatchOptionItem
  318. type ComponentWatchOptionItem = WatchOptionItem | WatchOptionItem[]
  319. type ComponentWatchOptions = Record<string, ComponentWatchOptionItem>
  320. export type ComponentProvideOptions = ObjectProvideOptions | Function
  321. type ObjectProvideOptions = Record<string | symbol, unknown>
  322. export type ComponentInjectOptions = string[] | ObjectInjectOptions
  323. type ObjectInjectOptions = Record<
  324. string | symbol,
  325. string | symbol | { from?: string | symbol; default?: unknown }
  326. >
  327. export type InjectToObject<T extends ComponentInjectOptions> =
  328. T extends string[]
  329. ? {
  330. [K in T[number]]?: unknown
  331. }
  332. : T extends ObjectInjectOptions
  333. ? {
  334. [K in keyof T]?: unknown
  335. }
  336. : never
  337. interface LegacyOptions<
  338. Props,
  339. D,
  340. C extends ComputedOptions,
  341. M extends MethodOptions,
  342. Mixin extends ComponentOptionsMixin,
  343. Extends extends ComponentOptionsMixin,
  344. I extends ComponentInjectOptions,
  345. II extends string,
  346. Provide extends ComponentProvideOptions = ComponentProvideOptions,
  347. > {
  348. compatConfig?: CompatConfig
  349. // allow any custom options
  350. [key: string]: any
  351. // state
  352. // Limitation: we cannot expose RawBindings on the `this` context for data
  353. // since that leads to some sort of circular inference and breaks ThisType
  354. // for the entire component.
  355. data?: (
  356. this: CreateComponentPublicInstanceWithMixins<
  357. Props,
  358. {},
  359. {},
  360. {},
  361. MethodOptions,
  362. Mixin,
  363. Extends
  364. >,
  365. vm: CreateComponentPublicInstanceWithMixins<
  366. Props,
  367. {},
  368. {},
  369. {},
  370. MethodOptions,
  371. Mixin,
  372. Extends
  373. >,
  374. ) => D
  375. computed?: C
  376. methods?: M
  377. watch?: ComponentWatchOptions
  378. provide?: Provide
  379. inject?: I | II[]
  380. // assets
  381. filters?: Record<string, Function>
  382. // composition
  383. mixins?: Mixin[]
  384. extends?: Extends
  385. // lifecycle
  386. beforeCreate?(): any
  387. created?(): any
  388. beforeMount?(): any
  389. mounted?(): any
  390. beforeUpdate?(): any
  391. updated?(): any
  392. activated?(): any
  393. deactivated?(): any
  394. /** @deprecated use `beforeUnmount` instead */
  395. beforeDestroy?(): any
  396. beforeUnmount?(): any
  397. /** @deprecated use `unmounted` instead */
  398. destroyed?(): any
  399. unmounted?(): any
  400. renderTracked?: DebuggerHook
  401. renderTriggered?: DebuggerHook
  402. errorCaptured?: ErrorCapturedHook
  403. /**
  404. * runtime compile only
  405. * @deprecated use `compilerOptions.delimiters` instead.
  406. */
  407. delimiters?: [string, string]
  408. /**
  409. * #3468
  410. *
  411. * type-only, used to assist Mixin's type inference,
  412. * typescript will try to simplify the inferred `Mixin` type,
  413. * with the `__differentiator`, typescript won't be able to combine different mixins,
  414. * because the `__differentiator` will be different
  415. */
  416. __differentiator?: keyof D | keyof C | keyof M
  417. }
  418. type MergedHook<T = () => void> = T | T[]
  419. export type MergedComponentOptions = ComponentOptions &
  420. MergedComponentOptionsOverride
  421. export type MergedComponentOptionsOverride = {
  422. beforeCreate?: MergedHook
  423. created?: MergedHook
  424. beforeMount?: MergedHook
  425. mounted?: MergedHook
  426. beforeUpdate?: MergedHook
  427. updated?: MergedHook
  428. activated?: MergedHook
  429. deactivated?: MergedHook
  430. /** @deprecated use `beforeUnmount` instead */
  431. beforeDestroy?: MergedHook
  432. beforeUnmount?: MergedHook
  433. /** @deprecated use `unmounted` instead */
  434. destroyed?: MergedHook
  435. unmounted?: MergedHook
  436. renderTracked?: MergedHook<DebuggerHook>
  437. renderTriggered?: MergedHook<DebuggerHook>
  438. errorCaptured?: MergedHook<ErrorCapturedHook>
  439. }
  440. export type OptionTypesKeys = 'P' | 'B' | 'D' | 'C' | 'M' | 'Defaults'
  441. export type OptionTypesType<
  442. P = {},
  443. B = {},
  444. D = {},
  445. C extends ComputedOptions = {},
  446. M extends MethodOptions = {},
  447. Defaults = {},
  448. > = {
  449. P: P
  450. B: B
  451. D: D
  452. C: C
  453. M: M
  454. Defaults: Defaults
  455. }
  456. enum OptionTypes {
  457. PROPS = 'Props',
  458. DATA = 'Data',
  459. COMPUTED = 'Computed',
  460. METHODS = 'Methods',
  461. INJECT = 'Inject',
  462. }
  463. function createDuplicateChecker() {
  464. const cache = Object.create(null)
  465. return (type: OptionTypes, key: string) => {
  466. if (cache[key]) {
  467. warn(`${type} property "${key}" is already defined in ${cache[key]}.`)
  468. } else {
  469. cache[key] = type
  470. }
  471. }
  472. }
  473. export let shouldCacheAccess = true
  474. export function applyOptions(instance: ComponentInternalInstance): void {
  475. const options = resolveMergedOptions(instance)
  476. const publicThis = instance.proxy! as any
  477. const ctx = instance.ctx
  478. // do not cache property access on public proxy during state initialization
  479. shouldCacheAccess = false
  480. // call beforeCreate first before accessing other options since
  481. // the hook may mutate resolved options (#2791)
  482. if (options.beforeCreate) {
  483. callHook(options.beforeCreate, instance, LifecycleHooks.BEFORE_CREATE)
  484. }
  485. const {
  486. // state
  487. data: dataOptions,
  488. computed: computedOptions,
  489. methods,
  490. watch: watchOptions,
  491. provide: provideOptions,
  492. inject: injectOptions,
  493. // lifecycle
  494. created,
  495. beforeMount,
  496. mounted,
  497. beforeUpdate,
  498. updated,
  499. activated,
  500. deactivated,
  501. beforeDestroy,
  502. beforeUnmount,
  503. destroyed,
  504. unmounted,
  505. render,
  506. renderTracked,
  507. renderTriggered,
  508. errorCaptured,
  509. serverPrefetch,
  510. // public API
  511. expose,
  512. inheritAttrs,
  513. // assets
  514. components,
  515. directives,
  516. filters,
  517. } = options
  518. const checkDuplicateProperties = __DEV__ ? createDuplicateChecker() : null
  519. if (__DEV__) {
  520. const [propsOptions] = instance.propsOptions
  521. if (propsOptions) {
  522. for (const key in propsOptions) {
  523. checkDuplicateProperties!(OptionTypes.PROPS, key)
  524. }
  525. }
  526. }
  527. // options initialization order (to be consistent with Vue 2):
  528. // - props (already done outside of this function)
  529. // - inject
  530. // - methods
  531. // - data (deferred since it relies on `this` access)
  532. // - computed
  533. // - watch (deferred since it relies on `this` access)
  534. if (injectOptions) {
  535. resolveInjections(injectOptions, ctx, checkDuplicateProperties)
  536. }
  537. if (methods) {
  538. for (const key in methods) {
  539. const methodHandler = (methods as MethodOptions)[key]
  540. if (isFunction(methodHandler)) {
  541. // In dev mode, we use the `createRenderContext` function to define
  542. // methods to the proxy target, and those are read-only but
  543. // reconfigurable, so it needs to be redefined here
  544. if (__DEV__) {
  545. Object.defineProperty(ctx, key, {
  546. value: methodHandler.bind(publicThis),
  547. configurable: true,
  548. enumerable: true,
  549. writable: true,
  550. })
  551. } else {
  552. ctx[key] = methodHandler.bind(publicThis)
  553. }
  554. if (__DEV__) {
  555. checkDuplicateProperties!(OptionTypes.METHODS, key)
  556. }
  557. } else if (__DEV__) {
  558. warn(
  559. `Method "${key}" has type "${typeof methodHandler}" in the component definition. ` +
  560. `Did you reference the function correctly?`,
  561. )
  562. }
  563. }
  564. }
  565. if (dataOptions) {
  566. if (__DEV__ && !isFunction(dataOptions)) {
  567. warn(
  568. `The data option must be a function. ` +
  569. `Plain object usage is no longer supported.`,
  570. )
  571. }
  572. const data = dataOptions.call(publicThis, publicThis)
  573. if (__DEV__ && isPromise(data)) {
  574. warn(
  575. `data() returned a Promise - note data() cannot be async; If you ` +
  576. `intend to perform data fetching before component renders, use ` +
  577. `async setup() + <Suspense>.`,
  578. )
  579. }
  580. if (!isObject(data)) {
  581. __DEV__ && warn(`data() should return an object.`)
  582. } else {
  583. instance.data = reactive(data)
  584. if (__DEV__) {
  585. for (const key in data) {
  586. checkDuplicateProperties!(OptionTypes.DATA, key)
  587. // expose data on ctx during dev
  588. if (!isReservedPrefix(key[0])) {
  589. Object.defineProperty(ctx, key, {
  590. configurable: true,
  591. enumerable: true,
  592. get: () => data[key],
  593. set: NOOP,
  594. })
  595. }
  596. }
  597. }
  598. }
  599. }
  600. // state initialization complete at this point - start caching access
  601. shouldCacheAccess = true
  602. if (computedOptions) {
  603. for (const key in computedOptions) {
  604. const opt = (computedOptions as ComputedOptions)[key]
  605. const get = isFunction(opt)
  606. ? opt.bind(publicThis, publicThis)
  607. : isFunction(opt.get)
  608. ? opt.get.bind(publicThis, publicThis)
  609. : NOOP
  610. if (__DEV__ && get === NOOP) {
  611. warn(`Computed property "${key}" has no getter.`)
  612. }
  613. const set =
  614. !isFunction(opt) && isFunction(opt.set)
  615. ? opt.set.bind(publicThis)
  616. : __DEV__
  617. ? () => {
  618. warn(
  619. `Write operation failed: computed property "${key}" is readonly.`,
  620. )
  621. }
  622. : NOOP
  623. const c = computed({
  624. get,
  625. set,
  626. })
  627. Object.defineProperty(ctx, key, {
  628. enumerable: true,
  629. configurable: true,
  630. get: () => c.value,
  631. set: v => (c.value = v),
  632. })
  633. if (__DEV__) {
  634. checkDuplicateProperties!(OptionTypes.COMPUTED, key)
  635. }
  636. }
  637. }
  638. if (watchOptions) {
  639. for (const key in watchOptions) {
  640. createWatcher(watchOptions[key], ctx, publicThis, key)
  641. }
  642. }
  643. if (provideOptions) {
  644. const provides = isFunction(provideOptions)
  645. ? provideOptions.call(publicThis)
  646. : provideOptions
  647. Reflect.ownKeys(provides).forEach(key => {
  648. provide(key, provides[key])
  649. })
  650. }
  651. if (created) {
  652. callHook(created, instance, LifecycleHooks.CREATED)
  653. }
  654. function registerLifecycleHook(
  655. register: Function,
  656. hook?: Function | Function[],
  657. ) {
  658. if (isArray(hook)) {
  659. hook.forEach(_hook => register(_hook.bind(publicThis)))
  660. } else if (hook) {
  661. register(hook.bind(publicThis))
  662. }
  663. }
  664. registerLifecycleHook(onBeforeMount, beforeMount)
  665. registerLifecycleHook(onMounted, mounted)
  666. registerLifecycleHook(onBeforeUpdate, beforeUpdate)
  667. registerLifecycleHook(onUpdated, updated)
  668. registerLifecycleHook(onActivated, activated)
  669. registerLifecycleHook(onDeactivated, deactivated)
  670. registerLifecycleHook(onErrorCaptured, errorCaptured)
  671. registerLifecycleHook(onRenderTracked, renderTracked)
  672. registerLifecycleHook(onRenderTriggered, renderTriggered)
  673. registerLifecycleHook(onBeforeUnmount, beforeUnmount)
  674. registerLifecycleHook(onUnmounted, unmounted)
  675. registerLifecycleHook(onServerPrefetch, serverPrefetch)
  676. if (__COMPAT__) {
  677. if (
  678. beforeDestroy &&
  679. softAssertCompatEnabled(DeprecationTypes.OPTIONS_BEFORE_DESTROY, instance)
  680. ) {
  681. registerLifecycleHook(onBeforeUnmount, beforeDestroy)
  682. }
  683. if (
  684. destroyed &&
  685. softAssertCompatEnabled(DeprecationTypes.OPTIONS_DESTROYED, instance)
  686. ) {
  687. registerLifecycleHook(onUnmounted, destroyed)
  688. }
  689. }
  690. if (isArray(expose)) {
  691. if (expose.length) {
  692. const exposed = instance.exposed || (instance.exposed = {})
  693. expose.forEach(key => {
  694. Object.defineProperty(exposed, key, {
  695. get: () => publicThis[key],
  696. set: val => (publicThis[key] = val),
  697. })
  698. })
  699. } else if (!instance.exposed) {
  700. instance.exposed = {}
  701. }
  702. }
  703. // options that are handled when creating the instance but also need to be
  704. // applied from mixins
  705. if (render && instance.render === NOOP) {
  706. instance.render = render as InternalRenderFunction
  707. }
  708. if (inheritAttrs != null) {
  709. instance.inheritAttrs = inheritAttrs
  710. }
  711. // asset options.
  712. if (components) instance.components = components as any
  713. if (directives) instance.directives = directives
  714. if (
  715. __COMPAT__ &&
  716. filters &&
  717. isCompatEnabled(DeprecationTypes.FILTERS, instance)
  718. ) {
  719. instance.filters = filters
  720. }
  721. if (__SSR__ && serverPrefetch) {
  722. markAsyncBoundary(instance)
  723. }
  724. }
  725. export function resolveInjections(
  726. injectOptions: ComponentInjectOptions,
  727. ctx: any,
  728. checkDuplicateProperties = NOOP as any,
  729. ): void {
  730. if (isArray(injectOptions)) {
  731. injectOptions = normalizeInject(injectOptions)!
  732. }
  733. for (const key in injectOptions) {
  734. const opt = injectOptions[key]
  735. let injected: unknown
  736. if (isObject(opt)) {
  737. if ('default' in opt) {
  738. injected = inject(
  739. opt.from || key,
  740. opt.default,
  741. true /* treat default function as factory */,
  742. )
  743. } else {
  744. injected = inject(opt.from || key)
  745. }
  746. } else {
  747. injected = inject(opt)
  748. }
  749. if (isRef(injected)) {
  750. // unwrap injected refs (ref #4196)
  751. Object.defineProperty(ctx, key, {
  752. enumerable: true,
  753. configurable: true,
  754. get: () => (injected as Ref).value,
  755. set: v => ((injected as Ref).value = v),
  756. })
  757. } else {
  758. ctx[key] = injected
  759. }
  760. if (__DEV__) {
  761. checkDuplicateProperties!(OptionTypes.INJECT, key)
  762. }
  763. }
  764. }
  765. function callHook(
  766. hook: Function,
  767. instance: ComponentInternalInstance,
  768. type: LifecycleHooks,
  769. ) {
  770. callWithAsyncErrorHandling(
  771. isArray(hook)
  772. ? hook.map(h => h.bind(instance.proxy!))
  773. : hook.bind(instance.proxy!),
  774. instance,
  775. type,
  776. )
  777. }
  778. export function createWatcher(
  779. raw: ComponentWatchOptionItem,
  780. ctx: Data,
  781. publicThis: ComponentPublicInstance,
  782. key: string,
  783. ): void {
  784. let getter = key.includes('.')
  785. ? createPathGetter(publicThis, key)
  786. : () => (publicThis as any)[key]
  787. const options: WatchOptions = {}
  788. if (__COMPAT__) {
  789. const instance =
  790. currentInstance && getCurrentScope() === currentInstance.scope
  791. ? currentInstance
  792. : null
  793. const newValue = getter()
  794. if (
  795. isArray(newValue) &&
  796. isCompatEnabled(DeprecationTypes.WATCH_ARRAY, instance)
  797. ) {
  798. options.deep = true
  799. }
  800. const baseGetter = getter
  801. getter = () => {
  802. const val = baseGetter()
  803. if (
  804. isArray(val) &&
  805. checkCompatEnabled(DeprecationTypes.WATCH_ARRAY, instance)
  806. ) {
  807. traverse(val)
  808. }
  809. return val
  810. }
  811. }
  812. if (isString(raw)) {
  813. const handler = ctx[raw]
  814. if (isFunction(handler)) {
  815. if (__COMPAT__) {
  816. watch(getter, handler as WatchCallback, options)
  817. } else {
  818. watch(getter, handler as WatchCallback)
  819. }
  820. } else if (__DEV__) {
  821. warn(`Invalid watch handler specified by key "${raw}"`, handler)
  822. }
  823. } else if (isFunction(raw)) {
  824. if (__COMPAT__) {
  825. watch(getter, raw.bind(publicThis), options)
  826. } else {
  827. watch(getter, raw.bind(publicThis))
  828. }
  829. } else if (isObject(raw)) {
  830. if (isArray(raw)) {
  831. raw.forEach(r => createWatcher(r, ctx, publicThis, key))
  832. } else {
  833. const handler = isFunction(raw.handler)
  834. ? raw.handler.bind(publicThis)
  835. : (ctx[raw.handler] as WatchCallback)
  836. if (isFunction(handler)) {
  837. watch(getter, handler, __COMPAT__ ? extend(raw, options) : raw)
  838. } else if (__DEV__) {
  839. warn(`Invalid watch handler specified by key "${raw.handler}"`, handler)
  840. }
  841. }
  842. } else if (__DEV__) {
  843. warn(`Invalid watch option: "${key}"`, raw)
  844. }
  845. }
  846. /**
  847. * Resolve merged options and cache it on the component.
  848. * This is done only once per-component since the merging does not involve
  849. * instances.
  850. */
  851. export function resolveMergedOptions(
  852. instance: ComponentInternalInstance,
  853. ): MergedComponentOptions {
  854. const base = instance.type as ComponentOptions
  855. const { mixins, extends: extendsOptions } = base
  856. const {
  857. mixins: globalMixins,
  858. optionsCache: cache,
  859. config: { optionMergeStrategies },
  860. } = instance.appContext
  861. const cached = cache.get(base)
  862. let resolved: MergedComponentOptions
  863. if (cached) {
  864. resolved = cached
  865. } else if (!globalMixins.length && !mixins && !extendsOptions) {
  866. if (
  867. __COMPAT__ &&
  868. isCompatEnabled(DeprecationTypes.PRIVATE_APIS, instance)
  869. ) {
  870. resolved = extend({}, base) as MergedComponentOptions
  871. resolved.parent = instance.parent && instance.parent.proxy
  872. resolved.propsData = instance.vnode.props
  873. } else {
  874. resolved = base as MergedComponentOptions
  875. }
  876. } else {
  877. resolved = {}
  878. if (globalMixins.length) {
  879. globalMixins.forEach(m =>
  880. mergeOptions(resolved, m, optionMergeStrategies, true),
  881. )
  882. }
  883. mergeOptions(resolved, base, optionMergeStrategies)
  884. }
  885. if (isObject(base)) {
  886. cache.set(base, resolved)
  887. }
  888. return resolved
  889. }
  890. export function mergeOptions(
  891. to: any,
  892. from: any,
  893. strats: Record<string, OptionMergeFunction>,
  894. asMixin = false,
  895. ): any {
  896. if (__COMPAT__ && isFunction(from)) {
  897. from = from.options
  898. }
  899. const { mixins, extends: extendsOptions } = from
  900. if (extendsOptions) {
  901. mergeOptions(to, extendsOptions, strats, true)
  902. }
  903. if (mixins) {
  904. mixins.forEach((m: ComponentOptionsMixin) =>
  905. mergeOptions(to, m, strats, true),
  906. )
  907. }
  908. for (const key in from) {
  909. if (asMixin && key === 'expose') {
  910. __DEV__ &&
  911. warn(
  912. `"expose" option is ignored when declared in mixins or extends. ` +
  913. `It should only be declared in the base component itself.`,
  914. )
  915. } else {
  916. const strat = internalOptionMergeStrats[key] || (strats && strats[key])
  917. to[key] = strat ? strat(to[key], from[key]) : from[key]
  918. }
  919. }
  920. return to
  921. }
  922. export const internalOptionMergeStrats: Record<string, Function> = {
  923. data: mergeDataFn,
  924. props: mergeEmitsOrPropsOptions,
  925. emits: mergeEmitsOrPropsOptions,
  926. // objects
  927. methods: mergeObjectOptions,
  928. computed: mergeObjectOptions,
  929. // lifecycle
  930. beforeCreate: mergeAsArray,
  931. created: mergeAsArray,
  932. beforeMount: mergeAsArray,
  933. mounted: mergeAsArray,
  934. beforeUpdate: mergeAsArray,
  935. updated: mergeAsArray,
  936. beforeDestroy: mergeAsArray,
  937. beforeUnmount: mergeAsArray,
  938. destroyed: mergeAsArray,
  939. unmounted: mergeAsArray,
  940. activated: mergeAsArray,
  941. deactivated: mergeAsArray,
  942. errorCaptured: mergeAsArray,
  943. serverPrefetch: mergeAsArray,
  944. // assets
  945. components: mergeObjectOptions,
  946. directives: mergeObjectOptions,
  947. // watch
  948. watch: mergeWatchOptions,
  949. // provide / inject
  950. provide: mergeDataFn,
  951. inject: mergeInject,
  952. }
  953. if (__COMPAT__) {
  954. internalOptionMergeStrats.filters = mergeObjectOptions
  955. }
  956. function mergeDataFn(to: any, from: any) {
  957. if (!from) {
  958. return to
  959. }
  960. if (!to) {
  961. return from
  962. }
  963. return function mergedDataFn(this: ComponentPublicInstance) {
  964. return (
  965. __COMPAT__ && isCompatEnabled(DeprecationTypes.OPTIONS_DATA_MERGE, null)
  966. ? deepMergeData
  967. : extend
  968. )(
  969. isFunction(to) ? to.call(this, this) : to,
  970. isFunction(from) ? from.call(this, this) : from,
  971. )
  972. }
  973. }
  974. function mergeInject(
  975. to: ComponentInjectOptions | undefined,
  976. from: ComponentInjectOptions,
  977. ) {
  978. return mergeObjectOptions(normalizeInject(to), normalizeInject(from))
  979. }
  980. function normalizeInject(
  981. raw: ComponentInjectOptions | undefined,
  982. ): ObjectInjectOptions | undefined {
  983. if (isArray(raw)) {
  984. const res: ObjectInjectOptions = {}
  985. for (let i = 0; i < raw.length; i++) {
  986. res[raw[i]] = raw[i]
  987. }
  988. return res
  989. }
  990. return raw
  991. }
  992. function mergeAsArray<T = Function>(to: T[] | T | undefined, from: T | T[]) {
  993. return to ? [...new Set([].concat(to as any, from as any))] : from
  994. }
  995. function mergeObjectOptions(to: Object | undefined, from: Object | undefined) {
  996. return to ? extend(Object.create(null), to, from) : from
  997. }
  998. function mergeEmitsOrPropsOptions(
  999. to: EmitsOptions | undefined,
  1000. from: EmitsOptions | undefined,
  1001. ): EmitsOptions | undefined
  1002. function mergeEmitsOrPropsOptions(
  1003. to: ComponentPropsOptions | undefined,
  1004. from: ComponentPropsOptions | undefined,
  1005. ): ComponentPropsOptions | undefined
  1006. function mergeEmitsOrPropsOptions(
  1007. to: ComponentPropsOptions | EmitsOptions | undefined,
  1008. from: ComponentPropsOptions | EmitsOptions | undefined,
  1009. ) {
  1010. if (to) {
  1011. if (isArray(to) && isArray(from)) {
  1012. return [...new Set([...to, ...from])]
  1013. }
  1014. return extend(
  1015. Object.create(null),
  1016. normalizePropsOrEmits(to),
  1017. normalizePropsOrEmits(from ?? {}),
  1018. )
  1019. } else {
  1020. return from
  1021. }
  1022. }
  1023. function mergeWatchOptions(
  1024. to: ComponentWatchOptions | undefined,
  1025. from: ComponentWatchOptions | undefined,
  1026. ) {
  1027. if (!to) return from
  1028. if (!from) return to
  1029. const merged = extend(Object.create(null), to)
  1030. for (const key in from) {
  1031. merged[key] = mergeAsArray(to[key], from[key])
  1032. }
  1033. return merged
  1034. }
  1035. // Deprecated legacy types, kept because they were previously exported ---------
  1036. /**
  1037. * @deprecated
  1038. */
  1039. export type ComponentOptionsWithoutProps<
  1040. Props = {},
  1041. RawBindings = {},
  1042. D = {},
  1043. C extends ComputedOptions = {},
  1044. M extends MethodOptions = {},
  1045. Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
  1046. Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
  1047. E extends EmitsOptions = {},
  1048. EE extends string = string,
  1049. I extends ComponentInjectOptions = {},
  1050. II extends string = string,
  1051. S extends SlotsType = {},
  1052. LC extends Record<string, Component> = {},
  1053. Directives extends Record<string, Directive> = {},
  1054. Exposed extends string = string,
  1055. Provide extends ComponentProvideOptions = ComponentProvideOptions,
  1056. TE extends ComponentTypeEmits = {},
  1057. ResolvedEmits extends EmitsOptions = {} extends E
  1058. ? TypeEmitsToOptions<TE>
  1059. : E,
  1060. PE = Props & EmitsToProps<ResolvedEmits>,
  1061. > = ComponentOptionsBase<
  1062. PE,
  1063. RawBindings,
  1064. D,
  1065. C,
  1066. M,
  1067. Mixin,
  1068. Extends,
  1069. E,
  1070. EE,
  1071. {},
  1072. I,
  1073. II,
  1074. S,
  1075. LC,
  1076. Directives,
  1077. Exposed,
  1078. Provide
  1079. > & {
  1080. props?: never
  1081. /**
  1082. * @private for language-tools use only
  1083. */
  1084. __typeProps?: Props
  1085. /**
  1086. * @private for language-tools use only
  1087. */
  1088. __typeEmits?: TE
  1089. } & ThisType<
  1090. CreateComponentPublicInstanceWithMixins<
  1091. PE,
  1092. RawBindings,
  1093. D,
  1094. C,
  1095. M,
  1096. Mixin,
  1097. Extends,
  1098. ResolvedEmits,
  1099. EE,
  1100. {},
  1101. false,
  1102. I,
  1103. S,
  1104. LC,
  1105. Directives,
  1106. Exposed
  1107. >
  1108. >
  1109. /**
  1110. * @deprecated
  1111. */
  1112. export type ComponentOptionsWithArrayProps<
  1113. PropNames extends string = string,
  1114. RawBindings = {},
  1115. D = {},
  1116. C extends ComputedOptions = {},
  1117. M extends MethodOptions = {},
  1118. Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
  1119. Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
  1120. E extends EmitsOptions = EmitsOptions,
  1121. EE extends string = string,
  1122. I extends ComponentInjectOptions = {},
  1123. II extends string = string,
  1124. S extends SlotsType = {},
  1125. LC extends Record<string, Component> = {},
  1126. Directives extends Record<string, Directive> = {},
  1127. Exposed extends string = string,
  1128. Provide extends ComponentProvideOptions = ComponentProvideOptions,
  1129. Props = Prettify<Readonly<{ [key in PropNames]?: any } & EmitsToProps<E>>>,
  1130. > = ComponentOptionsBase<
  1131. Props,
  1132. RawBindings,
  1133. D,
  1134. C,
  1135. M,
  1136. Mixin,
  1137. Extends,
  1138. E,
  1139. EE,
  1140. {},
  1141. I,
  1142. II,
  1143. S,
  1144. LC,
  1145. Directives,
  1146. Exposed,
  1147. Provide
  1148. > & {
  1149. props: PropNames[]
  1150. } & ThisType<
  1151. CreateComponentPublicInstanceWithMixins<
  1152. Props,
  1153. RawBindings,
  1154. D,
  1155. C,
  1156. M,
  1157. Mixin,
  1158. Extends,
  1159. E,
  1160. Props,
  1161. {},
  1162. false,
  1163. I,
  1164. S,
  1165. LC,
  1166. Directives,
  1167. Exposed
  1168. >
  1169. >
  1170. /**
  1171. * @deprecated
  1172. */
  1173. export type ComponentOptionsWithObjectProps<
  1174. PropsOptions = ComponentObjectPropsOptions,
  1175. RawBindings = {},
  1176. D = {},
  1177. C extends ComputedOptions = {},
  1178. M extends MethodOptions = {},
  1179. Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
  1180. Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
  1181. E extends EmitsOptions = EmitsOptions,
  1182. EE extends string = string,
  1183. I extends ComponentInjectOptions = {},
  1184. II extends string = string,
  1185. S extends SlotsType = {},
  1186. LC extends Record<string, Component> = {},
  1187. Directives extends Record<string, Directive> = {},
  1188. Exposed extends string = string,
  1189. Provide extends ComponentProvideOptions = ComponentProvideOptions,
  1190. Props = Prettify<
  1191. Readonly<ExtractPropTypes<PropsOptions>> & Readonly<EmitsToProps<E>>
  1192. >,
  1193. Defaults = ExtractDefaultPropTypes<PropsOptions>,
  1194. > = ComponentOptionsBase<
  1195. Props,
  1196. RawBindings,
  1197. D,
  1198. C,
  1199. M,
  1200. Mixin,
  1201. Extends,
  1202. E,
  1203. EE,
  1204. Defaults,
  1205. I,
  1206. II,
  1207. S,
  1208. LC,
  1209. Directives,
  1210. Exposed,
  1211. Provide
  1212. > & {
  1213. props: PropsOptions & ThisType<void>
  1214. } & ThisType<
  1215. CreateComponentPublicInstanceWithMixins<
  1216. Props,
  1217. RawBindings,
  1218. D,
  1219. C,
  1220. M,
  1221. Mixin,
  1222. Extends,
  1223. E,
  1224. Props,
  1225. Defaults,
  1226. false,
  1227. I,
  1228. S,
  1229. LC,
  1230. Directives
  1231. >
  1232. >