| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306 |
- import {
- type AsyncComponentInternalOptions,
- type Component,
- type ComponentInternalInstance,
- type ComponentInternalOptions,
- type Data,
- type InternalRenderFunction,
- type SetupContext,
- getCurrentInstance,
- } from './component'
- import {
- type LooseRequired,
- NOOP,
- type Prettify,
- extend,
- isArray,
- isFunction,
- isObject,
- isPromise,
- isString,
- } from '@vue/shared'
- import { type Ref, getCurrentScope, isRef, traverse } from '@vue/reactivity'
- import { computed } from './apiComputed'
- import {
- type WatchCallback,
- type WatchOptions,
- createPathGetter,
- watch,
- } from './apiWatch'
- import { inject, provide } from './apiInject'
- import {
- type DebuggerHook,
- type ErrorCapturedHook,
- onActivated,
- onBeforeMount,
- onBeforeUnmount,
- onBeforeUpdate,
- onDeactivated,
- onErrorCaptured,
- onMounted,
- onRenderTracked,
- onRenderTriggered,
- onServerPrefetch,
- onUnmounted,
- onUpdated,
- } from './apiLifecycle'
- import {
- type ComputedGetter,
- type WritableComputedOptions,
- reactive,
- } from '@vue/reactivity'
- import type {
- ComponentObjectPropsOptions,
- ComponentPropsOptions,
- ExtractDefaultPropTypes,
- ExtractPropTypes,
- } from './componentProps'
- import type {
- EmitsOptions,
- EmitsToProps,
- TypeEmitsToOptions,
- } from './componentEmits'
- import type { Directive } from './directives'
- import {
- type ComponentPublicInstance,
- type CreateComponentPublicInstanceWithMixins,
- type IntersectionMixin,
- type UnwrapMixinsType,
- isReservedPrefix,
- } from './componentPublicInstance'
- import { warn } from './warning'
- import type { VNodeChild } from './vnode'
- import { callWithAsyncErrorHandling } from './errorHandling'
- import { deepMergeData } from './compat/data'
- import { DeprecationTypes, checkCompatEnabled } from './compat/compatConfig'
- import {
- type CompatConfig,
- isCompatEnabled,
- softAssertCompatEnabled,
- } from './compat/compatConfig'
- import type { OptionMergeFunction } from './apiCreateApp'
- import { LifecycleHooks } from './enums'
- import type { SlotsType } from './componentSlots'
- import {
- type ComponentTypeEmits,
- normalizePropsOrEmits,
- } from './apiSetupHelpers'
- import { markAsyncBoundary } from './helpers/useId'
- /**
- * Interface for declaring custom options.
- *
- * @example
- * ```ts
- * declare module 'vue' {
- * interface ComponentCustomOptions {
- * beforeRouteUpdate?(
- * to: Route,
- * from: Route,
- * next: () => void
- * ): void
- * }
- * }
- * ```
- */
- export interface ComponentCustomOptions {}
- export type RenderFunction = () => VNodeChild
- export interface ComponentOptionsBase<
- Props,
- RawBindings,
- D,
- C extends ComputedOptions,
- M extends MethodOptions,
- Mixin extends ComponentOptionsMixin,
- Extends extends ComponentOptionsMixin,
- E extends EmitsOptions,
- EE extends string = string,
- Defaults = {},
- I extends ComponentInjectOptions = {},
- II extends string = string,
- S extends SlotsType = {},
- LC extends Record<string, Component> = {},
- Directives extends Record<string, Directive> = {},
- Exposed extends string = string,
- Provide extends ComponentProvideOptions = ComponentProvideOptions,
- >
- extends
- LegacyOptions<Props, D, C, M, Mixin, Extends, I, II, Provide>,
- ComponentInternalOptions,
- AsyncComponentInternalOptions,
- ComponentCustomOptions {
- setup?: (
- this: void,
- props: LooseRequired<
- Props &
- Prettify<
- UnwrapMixinsType<
- IntersectionMixin<Mixin> & IntersectionMixin<Extends>,
- 'P'
- >
- >
- >,
- ctx: SetupContext<E, S>,
- ) => Promise<RawBindings> | RawBindings | RenderFunction | void
- name?: string
- template?: string | object // can be a direct DOM node
- // Note: we are intentionally using the signature-less `Function` type here
- // since any type with signature will cause the whole inference to fail when
- // the return expression contains reference to `this`.
- // Luckily `render()` doesn't need any arguments nor does it care about return
- // type.
- render?: Function
- // NOTE: extending both LC and Record<string, Component> allows objects to be forced
- // to be of type Component, while still inferring LC generic
- components?: LC & Record<string, Component>
- // NOTE: extending both Directives and Record<string, Directive> allows objects to be forced
- // to be of type Directive, while still inferring Directives generic
- directives?: Directives & Record<string, Directive>
- inheritAttrs?: boolean
- emits?: (E | EE[]) & ThisType<void>
- slots?: S
- expose?: Exposed[]
- serverPrefetch?(): void | Promise<any>
- // Runtime compiler only -----------------------------------------------------
- compilerOptions?: RuntimeCompilerOptions
- // Internal ------------------------------------------------------------------
- /**
- * SSR only. This is produced by compiler-ssr and attached in compiler-sfc
- * not user facing, so the typing is lax and for test only.
- * @internal
- */
- ssrRender?: (
- ctx: any,
- push: (item: any) => void,
- parentInstance: ComponentInternalInstance,
- attrs: Data | undefined,
- // for compiler-optimized bindings
- $props: ComponentInternalInstance['props'],
- $setup: ComponentInternalInstance['setupState'],
- $data: ComponentInternalInstance['data'],
- $options: ComponentInternalInstance['ctx'],
- ) => void
- /**
- * Only generated by compiler-sfc to mark a ssr render function inlined and
- * returned from setup()
- * @internal
- */
- __ssrInlineRender?: boolean
- // Type differentiators ------------------------------------------------------
- // Note these are internal but need to be exposed in d.ts for type inference
- // to work!
- // type-only differentiator to separate OptionWithoutProps from a constructor
- // type returned by defineComponent() or FunctionalComponent
- call?: (this: unknown, ...args: unknown[]) => never
- // type-only differentiators for built-in Vnode types
- __isFragment?: never
- __isTeleport?: never
- __isSuspense?: never
- __defaults?: Defaults
- }
- /**
- * Subset of compiler options that makes sense for the runtime.
- */
- export interface RuntimeCompilerOptions {
- isCustomElement?: (tag: string) => boolean
- whitespace?: 'preserve' | 'condense'
- comments?: boolean
- delimiters?: [string, string]
- }
- export type ComponentOptions<
- Props = {},
- RawBindings = any,
- D = any,
- C extends ComputedOptions = any,
- M extends MethodOptions = any,
- Mixin extends ComponentOptionsMixin = any,
- Extends extends ComponentOptionsMixin = any,
- E extends EmitsOptions = any,
- EE extends string = string,
- Defaults = {},
- I extends ComponentInjectOptions = {},
- II extends string = string,
- S extends SlotsType = {},
- LC extends Record<string, Component> = {},
- Directives extends Record<string, Directive> = {},
- Exposed extends string = string,
- Provide extends ComponentProvideOptions = ComponentProvideOptions,
- > = ComponentOptionsBase<
- Props,
- RawBindings,
- D,
- C,
- M,
- Mixin,
- Extends,
- E,
- EE,
- Defaults,
- I,
- II,
- S,
- LC,
- Directives,
- Exposed,
- Provide
- > &
- ThisType<
- CreateComponentPublicInstanceWithMixins<
- {},
- RawBindings,
- D,
- C,
- M,
- Mixin,
- Extends,
- E,
- Readonly<Props>,
- Defaults,
- false,
- I,
- S,
- LC,
- Directives
- >
- >
- export type ComponentOptionsMixin = ComponentOptionsBase<
- any,
- any,
- any,
- any,
- any,
- any,
- any,
- any,
- any,
- any,
- any,
- any,
- any,
- any,
- any,
- any,
- any
- >
- export type ComputedOptions = Record<
- string,
- ComputedGetter<any> | WritableComputedOptions<any>
- >
- export interface MethodOptions {
- [key: string]: Function
- }
- export type ExtractComputedReturns<T extends any> = {
- [key in keyof T]: T[key] extends { get: (...args: any[]) => infer TReturn }
- ? TReturn
- : T[key] extends (...args: any[]) => infer TReturn
- ? TReturn
- : never
- }
- export type ObjectWatchOptionItem = {
- handler: WatchCallback | string
- } & WatchOptions
- type WatchOptionItem = string | WatchCallback | ObjectWatchOptionItem
- type ComponentWatchOptionItem = WatchOptionItem | WatchOptionItem[]
- type ComponentWatchOptions = Record<string, ComponentWatchOptionItem>
- export type ComponentProvideOptions = ObjectProvideOptions | Function
- type ObjectProvideOptions = Record<string | symbol, unknown>
- export type ComponentInjectOptions = string[] | ObjectInjectOptions
- type ObjectInjectOptions = Record<
- string | symbol,
- string | symbol | { from?: string | symbol; default?: unknown }
- >
- export type InjectToObject<T extends ComponentInjectOptions> =
- T extends string[]
- ? {
- [K in T[number]]?: unknown
- }
- : T extends ObjectInjectOptions
- ? {
- [K in keyof T]?: unknown
- }
- : never
- interface LegacyOptions<
- Props,
- D,
- C extends ComputedOptions,
- M extends MethodOptions,
- Mixin extends ComponentOptionsMixin,
- Extends extends ComponentOptionsMixin,
- I extends ComponentInjectOptions,
- II extends string,
- Provide extends ComponentProvideOptions = ComponentProvideOptions,
- > {
- compatConfig?: CompatConfig
- // allow any custom options
- [key: string]: any
- // state
- // Limitation: we cannot expose RawBindings on the `this` context for data
- // since that leads to some sort of circular inference and breaks ThisType
- // for the entire component.
- data?: (
- this: CreateComponentPublicInstanceWithMixins<
- Props,
- {},
- {},
- {},
- MethodOptions,
- Mixin,
- Extends
- >,
- vm: CreateComponentPublicInstanceWithMixins<
- Props,
- {},
- {},
- {},
- MethodOptions,
- Mixin,
- Extends
- >,
- ) => D
- computed?: C
- methods?: M
- watch?: ComponentWatchOptions
- provide?: Provide
- inject?: I | II[]
- // assets
- filters?: Record<string, Function>
- // composition
- mixins?: Mixin[]
- extends?: Extends
- // lifecycle
- beforeCreate?(): any
- created?(): any
- beforeMount?(): any
- mounted?(): any
- beforeUpdate?(): any
- updated?(): any
- activated?(): any
- deactivated?(): any
- /** @deprecated use `beforeUnmount` instead */
- beforeDestroy?(): any
- beforeUnmount?(): any
- /** @deprecated use `unmounted` instead */
- destroyed?(): any
- unmounted?(): any
- renderTracked?: DebuggerHook
- renderTriggered?: DebuggerHook
- errorCaptured?: ErrorCapturedHook
- /**
- * runtime compile only
- * @deprecated use `compilerOptions.delimiters` instead.
- */
- delimiters?: [string, string]
- /**
- * #3468
- *
- * type-only, used to assist Mixin's type inference,
- * TypeScript will try to simplify the inferred `Mixin` type,
- * with the `__differentiator`, TypeScript won't be able to combine different mixins,
- * because the `__differentiator` will be different
- */
- __differentiator?: keyof D | keyof C | keyof M
- }
- type MergedHook<T = () => void> = T | T[]
- export type MergedComponentOptions = ComponentOptions &
- MergedComponentOptionsOverride
- export type MergedComponentOptionsOverride = {
- beforeCreate?: MergedHook
- created?: MergedHook
- beforeMount?: MergedHook
- mounted?: MergedHook
- beforeUpdate?: MergedHook
- updated?: MergedHook
- activated?: MergedHook
- deactivated?: MergedHook
- /** @deprecated use `beforeUnmount` instead */
- beforeDestroy?: MergedHook
- beforeUnmount?: MergedHook
- /** @deprecated use `unmounted` instead */
- destroyed?: MergedHook
- unmounted?: MergedHook
- renderTracked?: MergedHook<DebuggerHook>
- renderTriggered?: MergedHook<DebuggerHook>
- errorCaptured?: MergedHook<ErrorCapturedHook>
- }
- export type OptionTypesKeys = 'P' | 'B' | 'D' | 'C' | 'M' | 'Defaults'
- export type OptionTypesType<
- P = {},
- B = {},
- D = {},
- C extends ComputedOptions = {},
- M extends MethodOptions = {},
- Defaults = {},
- > = {
- P: P
- B: B
- D: D
- C: C
- M: M
- Defaults: Defaults
- }
- enum OptionTypes {
- PROPS = 'Props',
- DATA = 'Data',
- COMPUTED = 'Computed',
- METHODS = 'Methods',
- INJECT = 'Inject',
- }
- function createDuplicateChecker() {
- const cache = Object.create(null)
- return (type: OptionTypes, key: string) => {
- if (cache[key]) {
- warn(`${type} property "${key}" is already defined in ${cache[key]}.`)
- } else {
- cache[key] = type
- }
- }
- }
- export let shouldCacheAccess = true
- export function applyOptions(instance: ComponentInternalInstance): void {
- const options = resolveMergedOptions(instance)
- const publicThis = instance.proxy! as any
- const ctx = instance.ctx
- // do not cache property access on public proxy during state initialization
- shouldCacheAccess = false
- // call beforeCreate first before accessing other options since
- // the hook may mutate resolved options (#2791)
- if (options.beforeCreate) {
- callHook(options.beforeCreate, instance, LifecycleHooks.BEFORE_CREATE)
- }
- const {
- // state
- data: dataOptions,
- computed: computedOptions,
- methods,
- watch: watchOptions,
- provide: provideOptions,
- inject: injectOptions,
- // lifecycle
- created,
- beforeMount,
- mounted,
- beforeUpdate,
- updated,
- activated,
- deactivated,
- beforeDestroy,
- beforeUnmount,
- destroyed,
- unmounted,
- render,
- renderTracked,
- renderTriggered,
- errorCaptured,
- serverPrefetch,
- // public API
- expose,
- inheritAttrs,
- // assets
- components,
- directives,
- filters,
- } = options
- const checkDuplicateProperties = __DEV__ ? createDuplicateChecker() : null
- if (__DEV__) {
- const [propsOptions] = instance.propsOptions
- if (propsOptions) {
- for (const key in propsOptions) {
- checkDuplicateProperties!(OptionTypes.PROPS, key)
- }
- }
- }
- // options initialization order (to be consistent with Vue 2):
- // - props (already done outside of this function)
- // - inject
- // - methods
- // - data (deferred since it relies on `this` access)
- // - computed
- // - watch (deferred since it relies on `this` access)
- if (injectOptions) {
- resolveInjections(injectOptions, ctx, checkDuplicateProperties)
- }
- if (methods) {
- for (const key in methods) {
- const methodHandler = (methods as MethodOptions)[key]
- if (isFunction(methodHandler)) {
- // In dev mode, we use the `createRenderContext` function to define
- // methods to the proxy target, and those are read-only but
- // reconfigurable, so it needs to be redefined here
- if (__DEV__) {
- Object.defineProperty(ctx, key, {
- value: methodHandler.bind(publicThis),
- configurable: true,
- enumerable: true,
- writable: true,
- })
- } else {
- ctx[key] = methodHandler.bind(publicThis)
- }
- if (__DEV__) {
- checkDuplicateProperties!(OptionTypes.METHODS, key)
- }
- } else if (__DEV__) {
- warn(
- `Method "${key}" has type "${typeof methodHandler}" in the component definition. ` +
- `Did you reference the function correctly?`,
- )
- }
- }
- }
- if (dataOptions) {
- if (__DEV__ && !isFunction(dataOptions)) {
- warn(
- `The data option must be a function. ` +
- `Plain object usage is no longer supported.`,
- )
- }
- const data = dataOptions.call(publicThis, publicThis)
- if (__DEV__ && isPromise(data)) {
- warn(
- `data() returned a Promise - note data() cannot be async; If you ` +
- `intend to perform data fetching before component renders, use ` +
- `async setup() + <Suspense>.`,
- )
- }
- if (!isObject(data)) {
- __DEV__ && warn(`data() should return an object.`)
- } else {
- instance.data = reactive(data)
- if (__DEV__) {
- for (const key in data) {
- checkDuplicateProperties!(OptionTypes.DATA, key)
- // expose data on ctx during dev
- if (!isReservedPrefix(key[0])) {
- Object.defineProperty(ctx, key, {
- configurable: true,
- enumerable: true,
- get: () => data[key],
- set: NOOP,
- })
- }
- }
- }
- }
- }
- // state initialization complete at this point - start caching access
- shouldCacheAccess = true
- if (computedOptions) {
- for (const key in computedOptions) {
- const opt = (computedOptions as ComputedOptions)[key]
- const get = isFunction(opt)
- ? opt.bind(publicThis, publicThis)
- : isFunction(opt.get)
- ? opt.get.bind(publicThis, publicThis)
- : NOOP
- if (__DEV__ && get === NOOP) {
- warn(`Computed property "${key}" has no getter.`)
- }
- const set =
- !isFunction(opt) && isFunction(opt.set)
- ? opt.set.bind(publicThis)
- : __DEV__
- ? () => {
- warn(
- `Write operation failed: computed property "${key}" is readonly.`,
- )
- }
- : NOOP
- const c = computed({
- get,
- set,
- })
- Object.defineProperty(ctx, key, {
- enumerable: true,
- configurable: true,
- get: () => c.value,
- set: v => (c.value = v),
- })
- if (__DEV__) {
- checkDuplicateProperties!(OptionTypes.COMPUTED, key)
- }
- }
- }
- if (watchOptions) {
- for (const key in watchOptions) {
- createWatcher(watchOptions[key], ctx, publicThis, key)
- }
- }
- if (provideOptions) {
- const provides = isFunction(provideOptions)
- ? provideOptions.call(publicThis)
- : provideOptions
- Reflect.ownKeys(provides).forEach(key => {
- provide(key, provides[key])
- })
- }
- if (created) {
- callHook(created, instance, LifecycleHooks.CREATED)
- }
- function registerLifecycleHook(
- register: Function,
- hook?: Function | Function[],
- ) {
- if (isArray(hook)) {
- hook.forEach(_hook => register(_hook.bind(publicThis)))
- } else if (hook) {
- register(hook.bind(publicThis))
- }
- }
- registerLifecycleHook(onBeforeMount, beforeMount)
- registerLifecycleHook(onMounted, mounted)
- registerLifecycleHook(onBeforeUpdate, beforeUpdate)
- registerLifecycleHook(onUpdated, updated)
- registerLifecycleHook(onActivated, activated)
- registerLifecycleHook(onDeactivated, deactivated)
- registerLifecycleHook(onErrorCaptured, errorCaptured)
- registerLifecycleHook(onRenderTracked, renderTracked)
- registerLifecycleHook(onRenderTriggered, renderTriggered)
- registerLifecycleHook(onBeforeUnmount, beforeUnmount)
- registerLifecycleHook(onUnmounted, unmounted)
- registerLifecycleHook(onServerPrefetch, serverPrefetch)
- if (__COMPAT__) {
- if (
- beforeDestroy &&
- softAssertCompatEnabled(DeprecationTypes.OPTIONS_BEFORE_DESTROY, instance)
- ) {
- registerLifecycleHook(onBeforeUnmount, beforeDestroy)
- }
- if (
- destroyed &&
- softAssertCompatEnabled(DeprecationTypes.OPTIONS_DESTROYED, instance)
- ) {
- registerLifecycleHook(onUnmounted, destroyed)
- }
- }
- if (isArray(expose)) {
- if (expose.length) {
- const exposed = instance.exposed || (instance.exposed = {})
- expose.forEach(key => {
- Object.defineProperty(exposed, key, {
- get: () => publicThis[key],
- set: val => (publicThis[key] = val),
- enumerable: true,
- })
- })
- } else if (!instance.exposed) {
- instance.exposed = {}
- }
- }
- // options that are handled when creating the instance but also need to be
- // applied from mixins
- if (render && instance.render === NOOP) {
- instance.render = render as InternalRenderFunction
- }
- if (inheritAttrs != null) {
- instance.inheritAttrs = inheritAttrs
- }
- // asset options.
- if (components) instance.components = components as any
- if (directives) instance.directives = directives
- if (
- __COMPAT__ &&
- filters &&
- isCompatEnabled(DeprecationTypes.FILTERS, instance)
- ) {
- instance.filters = filters
- }
- if (__SSR__ && serverPrefetch) {
- markAsyncBoundary(instance)
- }
- }
- export function resolveInjections(
- injectOptions: ComponentInjectOptions,
- ctx: any,
- checkDuplicateProperties = NOOP as any,
- ): void {
- if (isArray(injectOptions)) {
- injectOptions = normalizeInject(injectOptions)!
- }
- for (const key in injectOptions) {
- const opt = injectOptions[key]
- let injected: unknown
- if (isObject(opt)) {
- if ('default' in opt) {
- injected = inject(
- opt.from || key,
- opt.default,
- true /* treat default function as factory */,
- )
- } else {
- injected = inject(opt.from || key)
- }
- } else {
- injected = inject(opt)
- }
- if (isRef(injected)) {
- // unwrap injected refs (ref #4196)
- Object.defineProperty(ctx, key, {
- enumerable: true,
- configurable: true,
- get: () => (injected as Ref).value,
- set: v => ((injected as Ref).value = v),
- })
- } else {
- ctx[key] = injected
- }
- if (__DEV__) {
- checkDuplicateProperties!(OptionTypes.INJECT, key)
- }
- }
- }
- function callHook(
- hook: Function,
- instance: ComponentInternalInstance,
- type: LifecycleHooks,
- ) {
- callWithAsyncErrorHandling(
- isArray(hook)
- ? hook.map(h => h.bind(instance.proxy!))
- : hook.bind(instance.proxy!),
- instance,
- type,
- )
- }
- export function createWatcher(
- raw: ComponentWatchOptionItem,
- ctx: Data,
- publicThis: ComponentPublicInstance,
- key: string,
- ): void {
- let getter = key.includes('.')
- ? createPathGetter(publicThis, key)
- : () => publicThis[key as keyof typeof publicThis]
- const options: WatchOptions = {}
- if (__COMPAT__) {
- const cur = getCurrentInstance()
- const instance = cur && getCurrentScope() === cur.scope ? cur : null
- const newValue = getter()
- if (
- isArray(newValue) &&
- isCompatEnabled(DeprecationTypes.WATCH_ARRAY, instance)
- ) {
- options.deep = true
- }
- const baseGetter = getter
- getter = () => {
- const val = baseGetter()
- if (
- isArray(val) &&
- checkCompatEnabled(DeprecationTypes.WATCH_ARRAY, instance)
- ) {
- traverse(val)
- }
- return val
- }
- }
- if (isString(raw)) {
- const handler = ctx[raw]
- if (isFunction(handler)) {
- if (__COMPAT__) {
- watch(getter, handler as WatchCallback, options)
- } else {
- watch(getter, handler as WatchCallback)
- }
- } else if (__DEV__) {
- warn(`Invalid watch handler specified by key "${raw}"`, handler)
- }
- } else if (isFunction(raw)) {
- if (__COMPAT__) {
- watch(getter, raw.bind(publicThis), options)
- } else {
- watch(getter, raw.bind(publicThis))
- }
- } else if (isObject(raw)) {
- if (isArray(raw)) {
- raw.forEach(r => createWatcher(r, ctx, publicThis, key))
- } else {
- const handler = isFunction(raw.handler)
- ? raw.handler.bind(publicThis)
- : (ctx[raw.handler] as WatchCallback)
- if (isFunction(handler)) {
- watch(getter, handler, __COMPAT__ ? extend(raw, options) : raw)
- } else if (__DEV__) {
- warn(`Invalid watch handler specified by key "${raw.handler}"`, handler)
- }
- }
- } else if (__DEV__) {
- warn(`Invalid watch option: "${key}"`, raw)
- }
- }
- /**
- * Resolve merged options and cache it on the component.
- * This is done only once per-component since the merging does not involve
- * instances.
- */
- export function resolveMergedOptions(
- instance: ComponentInternalInstance,
- ): MergedComponentOptions {
- const base = instance.type as ComponentOptions
- const { mixins, extends: extendsOptions } = base
- const {
- mixins: globalMixins,
- optionsCache: cache,
- config: { optionMergeStrategies },
- } = instance.appContext
- const cached = cache.get(base)
- let resolved: MergedComponentOptions
- if (cached) {
- resolved = cached
- } else if (!globalMixins.length && !mixins && !extendsOptions) {
- if (
- __COMPAT__ &&
- isCompatEnabled(DeprecationTypes.PRIVATE_APIS, instance)
- ) {
- resolved = extend({}, base) as MergedComponentOptions
- resolved.parent = instance.parent && instance.parent.proxy
- resolved.propsData = instance.vnode.props
- } else {
- resolved = base as MergedComponentOptions
- }
- } else {
- resolved = {}
- if (globalMixins.length) {
- globalMixins.forEach(m =>
- mergeOptions(resolved, m, optionMergeStrategies, true),
- )
- }
- mergeOptions(resolved, base, optionMergeStrategies)
- }
- if (isObject(base)) {
- cache.set(base, resolved)
- }
- return resolved
- }
- export function mergeOptions(
- to: any,
- from: any,
- strats: Record<string, OptionMergeFunction>,
- asMixin = false,
- ): any {
- if (__COMPAT__ && isFunction(from)) {
- from = from.options
- }
- const { mixins, extends: extendsOptions } = from
- if (extendsOptions) {
- mergeOptions(to, extendsOptions, strats, true)
- }
- if (mixins) {
- mixins.forEach((m: ComponentOptionsMixin) =>
- mergeOptions(to, m, strats, true),
- )
- }
- for (const key in from) {
- if (asMixin && key === 'expose') {
- __DEV__ &&
- warn(
- `"expose" option is ignored when declared in mixins or extends. ` +
- `It should only be declared in the base component itself.`,
- )
- } else {
- const strat = internalOptionMergeStrats[key] || (strats && strats[key])
- to[key] = strat ? strat(to[key], from[key]) : from[key]
- }
- }
- return to
- }
- export const internalOptionMergeStrats: Record<string, Function> = {
- data: mergeDataFn,
- props: mergeEmitsOrPropsOptions,
- emits: mergeEmitsOrPropsOptions,
- // objects
- methods: mergeObjectOptions,
- computed: mergeObjectOptions,
- // lifecycle
- beforeCreate: mergeAsArray,
- created: mergeAsArray,
- beforeMount: mergeAsArray,
- mounted: mergeAsArray,
- beforeUpdate: mergeAsArray,
- updated: mergeAsArray,
- beforeDestroy: mergeAsArray,
- beforeUnmount: mergeAsArray,
- destroyed: mergeAsArray,
- unmounted: mergeAsArray,
- activated: mergeAsArray,
- deactivated: mergeAsArray,
- errorCaptured: mergeAsArray,
- serverPrefetch: mergeAsArray,
- // assets
- components: mergeObjectOptions,
- directives: mergeObjectOptions,
- // watch
- watch: mergeWatchOptions,
- // provide / inject
- provide: mergeDataFn,
- inject: mergeInject,
- }
- if (__COMPAT__) {
- internalOptionMergeStrats.filters = mergeObjectOptions
- }
- function mergeDataFn(to: any, from: any) {
- if (!from) {
- return to
- }
- if (!to) {
- return from
- }
- return function mergedDataFn(this: ComponentPublicInstance) {
- return (
- __COMPAT__ && isCompatEnabled(DeprecationTypes.OPTIONS_DATA_MERGE, null)
- ? deepMergeData
- : extend
- )(
- isFunction(to) ? to.call(this, this) : to,
- isFunction(from) ? from.call(this, this) : from,
- )
- }
- }
- function mergeInject(
- to: ComponentInjectOptions | undefined,
- from: ComponentInjectOptions,
- ) {
- return mergeObjectOptions(normalizeInject(to), normalizeInject(from))
- }
- function normalizeInject(
- raw: ComponentInjectOptions | undefined,
- ): ObjectInjectOptions | undefined {
- if (isArray(raw)) {
- const res: ObjectInjectOptions = {}
- for (let i = 0; i < raw.length; i++) {
- res[raw[i]] = raw[i]
- }
- return res
- }
- return raw
- }
- function mergeAsArray<T = Function>(to: T[] | T | undefined, from: T | T[]) {
- return to ? [...new Set([].concat(to as any, from as any))] : from
- }
- function mergeObjectOptions(to: Object | undefined, from: Object | undefined) {
- return to ? extend(Object.create(null), to, from) : from
- }
- function mergeEmitsOrPropsOptions(
- to: EmitsOptions | undefined,
- from: EmitsOptions | undefined,
- ): EmitsOptions | undefined
- function mergeEmitsOrPropsOptions(
- to: ComponentPropsOptions | undefined,
- from: ComponentPropsOptions | undefined,
- ): ComponentPropsOptions | undefined
- function mergeEmitsOrPropsOptions(
- to: ComponentPropsOptions | EmitsOptions | undefined,
- from: ComponentPropsOptions | EmitsOptions | undefined,
- ) {
- if (to) {
- if (isArray(to) && isArray(from)) {
- return [...new Set([...to, ...from])]
- }
- return extend(
- Object.create(null),
- normalizePropsOrEmits(to),
- normalizePropsOrEmits(from ?? {}),
- )
- } else {
- return from
- }
- }
- function mergeWatchOptions(
- to: ComponentWatchOptions | undefined,
- from: ComponentWatchOptions | undefined,
- ) {
- if (!to) return from
- if (!from) return to
- const merged = extend(Object.create(null), to)
- for (const key in from) {
- merged[key] = mergeAsArray(to[key], from[key])
- }
- return merged
- }
- // Deprecated legacy types, kept because they were previously exported ---------
- /**
- * @deprecated
- */
- export type ComponentOptionsWithoutProps<
- Props = {},
- RawBindings = {},
- D = {},
- C extends ComputedOptions = {},
- M extends MethodOptions = {},
- Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
- Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
- E extends EmitsOptions = {},
- EE extends string = string,
- I extends ComponentInjectOptions = {},
- II extends string = string,
- S extends SlotsType = {},
- LC extends Record<string, Component> = {},
- Directives extends Record<string, Directive> = {},
- Exposed extends string = string,
- Provide extends ComponentProvideOptions = ComponentProvideOptions,
- TE extends ComponentTypeEmits = {},
- ResolvedEmits extends EmitsOptions = {} extends E
- ? TypeEmitsToOptions<TE>
- : E,
- PE = Props & EmitsToProps<ResolvedEmits>,
- > = ComponentOptionsBase<
- PE,
- RawBindings,
- D,
- C,
- M,
- Mixin,
- Extends,
- E,
- EE,
- {},
- I,
- II,
- S,
- LC,
- Directives,
- Exposed,
- Provide
- > & {
- props?: never
- /**
- * @private for language-tools use only
- */
- __typeProps?: Props
- /**
- * @private for language-tools use only
- */
- __typeEmits?: TE
- } & ThisType<
- CreateComponentPublicInstanceWithMixins<
- PE,
- RawBindings,
- D,
- C,
- M,
- Mixin,
- Extends,
- ResolvedEmits,
- EE,
- {},
- false,
- I,
- S,
- LC,
- Directives,
- string
- >
- >
- /**
- * @deprecated
- */
- export type ComponentOptionsWithArrayProps<
- PropNames extends string = string,
- RawBindings = {},
- D = {},
- C extends ComputedOptions = {},
- M extends MethodOptions = {},
- Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
- Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
- E extends EmitsOptions = EmitsOptions,
- EE extends string = string,
- I extends ComponentInjectOptions = {},
- II extends string = string,
- S extends SlotsType = {},
- LC extends Record<string, Component> = {},
- Directives extends Record<string, Directive> = {},
- Exposed extends string = string,
- Provide extends ComponentProvideOptions = ComponentProvideOptions,
- Props = Prettify<Readonly<{ [key in PropNames]?: any } & EmitsToProps<E>>>,
- > = ComponentOptionsBase<
- Props,
- RawBindings,
- D,
- C,
- M,
- Mixin,
- Extends,
- E,
- EE,
- {},
- I,
- II,
- S,
- LC,
- Directives,
- Exposed,
- Provide
- > & {
- props: PropNames[]
- } & ThisType<
- CreateComponentPublicInstanceWithMixins<
- Props,
- RawBindings,
- D,
- C,
- M,
- Mixin,
- Extends,
- E,
- Props,
- {},
- false,
- I,
- S,
- LC,
- Directives,
- string
- >
- >
- /**
- * @deprecated
- */
- export type ComponentOptionsWithObjectProps<
- PropsOptions = ComponentObjectPropsOptions,
- RawBindings = {},
- D = {},
- C extends ComputedOptions = {},
- M extends MethodOptions = {},
- Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
- Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
- E extends EmitsOptions = EmitsOptions,
- EE extends string = string,
- I extends ComponentInjectOptions = {},
- II extends string = string,
- S extends SlotsType = {},
- LC extends Record<string, Component> = {},
- Directives extends Record<string, Directive> = {},
- Exposed extends string = string,
- Provide extends ComponentProvideOptions = ComponentProvideOptions,
- Props = Prettify<
- Readonly<ExtractPropTypes<PropsOptions>> & Readonly<EmitsToProps<E>>
- >,
- Defaults = ExtractDefaultPropTypes<PropsOptions>,
- > = ComponentOptionsBase<
- Props,
- RawBindings,
- D,
- C,
- M,
- Mixin,
- Extends,
- E,
- EE,
- Defaults,
- I,
- II,
- S,
- LC,
- Directives,
- Exposed,
- Provide
- > & {
- props: PropsOptions & ThisType<void>
- } & ThisType<
- CreateComponentPublicInstanceWithMixins<
- Props,
- RawBindings,
- D,
- C,
- M,
- Mixin,
- Extends,
- E,
- Props,
- Defaults,
- false,
- I,
- S,
- LC,
- Directives
- >
- >
|