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

100% Statements 30/30
100% Branches 18/18
100% Functions 2/2
100% Lines 30/30

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    83x   83x 83x           83x   83x   83x 4944x 4944x 10x                 4x     6x 2x 2x 2x 2x           6x 6x 6x 6x     6x 6x   6x 6x       83x         295x 33x   262x 262x 262x 2x                
import { 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
  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(type as ComponentOptions)) {
      pushWarningContext(vnode)
      warnDeprecation(DeprecationTypes.COMPONENT_V_MODEL, { type } as any, type)
      popWarningContext()
      warnedTypes.add(type as ComponentOptions)
    }
 
    // v3 compiled model code -> v2 compat props
    // modelValue -> value
    // onUpdate:modelValue -> onModelCompat:input
    const { prop = 'value', event = 'input' } = (type as any).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']
  }
}
 
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
    )
  }
}