All files / runtime/src/directives vModel.ts

100% Statements 48/48
93.75% Branches 15/16
100% Functions 4/4
100% Lines 48/48

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 491x 1x 1x 1x 1x 1x 1x 1x 1x 13x 13x 13x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 5x 5x 6x 6x 1x 6x 1x 1x 6x 5x 1x 1x 1x 8x 8x 8x 3x 3x 5x 1x 1x  
import { ObjectDirective, VNode } from '@vue/runtime-core'
import { getViewMeta, NSVModelDescriptor } from '../registry'
import { addEventListener } from '../modules/events'
import { INSVElement } from '../nodes'
import { isArray, invokeArrayFns } from '@vue/shared'
 
type AssignerFn = (value: any) => void
 
const getModelAssigner = (vnode: VNode): AssignerFn => {
  const fn = vnode.props!['onUpdate:modelValue']
  return isArray(fn) ? (value) => invokeArrayFns(fn, value) : fn
}
 
function toNumber(val: string): number | string {
  const n = parseFloat(val)
  return isNaN(n) ? val : n
}
 
type ModelDirective<T> = ObjectDirective<T & { _assign: AssignerFn }>
 
export const vModel: ModelDirective<INSVElement> = {
  beforeMount(el, { value, modifiers: { trim, number } }, vnode) {
    el._assign = getModelAssigner(vnode)
    const castToNumber = number
    const { prop, event } = getViewMeta(el.tagName).model as NSVModelDescriptor
    el._assign(value)
    el.setAttribute(prop, value)
 
    addEventListener(el, event, () => {
      let propValue: unknown = el.getAttribute(prop)
      if (trim && typeof propValue === 'string') {
        propValue = propValue.trim()
      } else if (castToNumber && typeof propValue === 'string') {
        propValue = toNumber(propValue)
      }
      el._assign(propValue)
    })
  },
 
  beforeUpdate(el, { value, oldValue }, vnode) {
    const { prop } = getViewMeta(el.tagName).model as NSVModelDescriptor
    el._assign = getModelAssigner(vnode)
    if (value === oldValue) {
      return
    }
    el.setAttribute(prop, value)
  },
}