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

100% Statements 52/52
100% Branches 14/14
100% Functions 10/10
100% Lines 49/49

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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 10987x   87x 87x           87x         87x     330x 330x 141x   330x     87x         20x 7x   17x 1x           16x   17x 17x   20x     87x         2x 1x 1x   2x 2x 2x     87x         12x 12x   12x 1x 1x     11x 4x 2x     9x 9x 9x 1x   8x 3x 3x   6x 5x     87x         304x 304x 12x 8x           304x    
import { isArray } from '@vue/shared'
import { ComponentInternalInstance } from '../component'
import { callWithAsyncErrorHandling, ErrorCodes } from '../errorHandling'
import { assertCompatEnabled, DeprecationTypes } from './compatConfig'
 
interface EventRegistry {
  [event: string]: Function[] | undefined
}
 
const eventRegistryMap = /*#__PURE__*/ new WeakMap<
  ComponentInternalInstance,
  EventRegistry
>()
 
export function getRegistry(
  instance: ComponentInternalInstance
): EventRegistry {
  let events = eventRegistryMap.get(instance)
  if (!events) {
    eventRegistryMap.set(instance, (events = Object.create(null)))
  }
  return events!
}
 
export function on(
  instance: ComponentInternalInstance,
  event: string | string[],
  fn: Function
) {
  if (isArray(event)) {
    event.forEach(e => on(instance, e, fn))
  } else {
    if (event.startsWith('hook:')) {
      assertCompatEnabled(
        DeprecationTypes.INSTANCE_EVENT_HOOKS,
        instance,
        event
      )
    } else {
      assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER, instance)
    }
    const events = getRegistry(instance)
    ;(events[event] || (events[event] = [])).push(fn)
  }
  return instance.proxy
}
 
export function once(
  instance: ComponentInternalInstance,
  event: string,
  fn: Function
) {
  const wrapped = (...args: any[]) => {
    off(instance, event, wrapped)
    fn.call(instance.proxy, ...args)
  }
  wrapped.fn = fn
  on(instance, event, wrapped)
  return instance.proxy
}
 
export function off(
  instance: ComponentInternalInstance,
  event?: string | string[],
  fn?: Function
) {
  assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER, instance)
  const vm = instance.proxy
  // all
  if (!event) {
    eventRegistryMap.set(instance, Object.create(null))
    return vm
  }
  // array of events
  if (isArray(event)) {
    event.forEach(e => off(instance, e, fn))
    return vm
  }
  // specific event
  const events = getRegistry(instance)
  const cbs = events[event!]
  if (!cbs) {
    return vm
  }
  if (!fn) {
    events[event!] = undefined
    return vm
  }
  events[event!] = cbs.filter(cb => !(cb === fn || (cb as any).fn === fn))
  return vm
}
 
export function emit(
  instance: ComponentInternalInstance,
  event: string,
  args: any[]
) {
  const cbs = getRegistry(instance)[event]
  if (cbs) {
    callWithAsyncErrorHandling(
      cbs.map(cb => cb.bind(instance.proxy)),
      instance,
      ErrorCodes.COMPONENT_EVENT_HANDLER,
      args
    )
  }
  return instance.proxy
}