All files / runtime-core/src/compat componentVModel.ts

87.5% Statements 35/40
85.71% Branches 18/21
75% Functions 3/4
92.1% Lines 35/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 8684x   84x   84x 84x           84x   84x   84x 5010x 5010x 5010x 10x                 4x     6x 2x 2x 2x 2x           6x 6x 6x 6x 6x 6x     6x 6x   6x 6x         6x               84x         295x 33x   262x 262x 262x 2x                
import { extend, ShapeFlags } from '@vue/shared'
import { ComponentInternalInstance, ComponentOptions } from '../component'
import { callWithErrorHandling, ErrorCodes } from '../errorHandling'
import { VNode } from '../vnode'
import { popWarningContext, pushWarningContext } from '../warning'
import {
  DeprecationTypes,
  warnDeprecation,
  isCompatEnabled
} from './compatConfig'
 
export const compatModelEventPrefix = `onModelCompat:`
 
const warnedTypes = new WeakSet()
 
export function convertLegacyVModelProps(vnode: VNode) {
  const { type, shapeFlag, props, dynamicProps } = vnode
  const comp = type as ComponentOptions
  if (shapeFlag & ShapeFlags.COMPONENT && props && 'modelValue' in props) {
    if (
      !isCompatEnabled(
        DeprecationTypes.COMPONENT_V_MODEL,
        // this is a special case where we want to use the vnode component's
        // compat config instead of the current rendering instance (which is the
        // parent of the component that exposes v-model)
        { type } as any
      )
    ) {
      return
    }
 
    if (__DEV__ && !warnedTypes.has(comp)) {
      pushWarningContext(vnode)
      warnDeprecation(DeprecationTypes.COMPONENT_V_MODEL, { type } as any, comp)
      popWarningContext()
      warnedTypes.add(comp)
    }
 
    // v3 compiled model code -> v2 compat props
    // modelValue -> value
    // onUpdate:modelValue -> onModelCompat:input
    const model = comp.model || {}
    applyModelFromMixins(model, comp.mixins)
    const { prop = 'value', event = 'input' } = model
    if (prop !== 'modelValue') {
      props[prop] = props.modelValue
      delete props.modelValue
    }
    // important: update dynamic props
    if (dynamicProps) {
      dynamicProps[dynamicProps.indexOf('modelValue')] = prop
    }
    props[compatModelEventPrefix + event] = props['onUpdate:modelValue']
    delete props['onUpdate:modelValue']
  }
}
 
function applyModelFromMixins(model: any, mixins?: ComponentOptions[]) {
  Iif (mixins) {
    mixins.forEach(m => {
      Iif (m.model) extend(model, m.model)
      Iif (m.mixins) applyModelFromMixins(model, m.mixins)
    })
  }
}
 
export function compatModelEmit(
  instance: ComponentInternalInstance,
  event: string,
  args: any[]
) {
  if (!isCompatEnabled(DeprecationTypes.COMPONENT_V_MODEL, instance)) {
    return
  }
  const props = instance.vnode.props
  const modelHandler = props && props[compatModelEventPrefix + event]
  if (modelHandler) {
    callWithErrorHandling(
      modelHandler,
      instance,
      ErrorCodes.COMPONENT_EVENT_HANDLER,
      args
    )
  }
}