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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | 51x 51x 51x 140x 51x 2x 51x 101x 101x 101x 24x 77x 77x 75x 75x 2x 2x 2x 51x 77x 3x 3x 4x 4x 77x 77x 51x 51x 51x 75x 75x 94x 93x 1x 1x 93x 75x 75x 75x 93x 9x 9x 1x 1x 18x 84x | import { hyphenate, isArray } from '@vue/shared' import { ComponentInternalInstance, callWithAsyncErrorHandling } from '@vue/runtime-core' import { ErrorCodes } from 'packages/runtime-core/src/errorHandling' interface Invoker extends EventListener { value: EventValue attached: number } type EventValue = Function | Function[] export function addEventListener( el: Element, event: string, handler: EventListener, options?: EventListenerOptions ) { el.addEventListener(event, handler, options) } export function removeEventListener( el: Element, event: string, handler: EventListener, options?: EventListenerOptions ) { el.removeEventListener(event, handler, options) } export function patchEvent( el: Element & { _vei?: Record<string, Invoker | undefined> }, rawName: string, prevValue: EventValue | null, nextValue: EventValue | null, instance: ComponentInternalInstance | null = null ) { // vei = vue event invokers const invokers = el._vei || (el._vei = {}) const existingInvoker = invokers[rawName] if (nextValue && existingInvoker) { // patch existingInvoker.value = nextValue } else { const [name, options] = parseName(rawName) if (nextValue) { // add const invoker = (invokers[rawName] = createInvoker(nextValue, instance)) addEventListener(el, name, invoker, options) } else if (existingInvoker) { // remove removeEventListener(el, name, existingInvoker, options) invokers[rawName] = undefined } } } const optionsModifierRE = /(?:Once|Passive|Capture)$/ function parseName(name: string): [string, EventListenerOptions | undefined] { let options: EventListenerOptions | undefined if (optionsModifierRE.test(name)) { options = {} let m while ((m = name.match(optionsModifierRE))) { name = name.slice(0, name.length - m[0].length) ;(options as any)[m[0].toLowerCase()] = true } } const event = name[2] === ':' ? name.slice(3) : hyphenate(name.slice(2)) return [event, options] } // To avoid the overhead of repeatedly calling Date.now(), we cache // and use the same timestamp for all event listeners attached in the same tick. let cachedNow: number = 0 const p = /*#__PURE__*/ Promise.resolve() const getNow = () => cachedNow || (p.then(() => (cachedNow = 0)), (cachedNow = Date.now())) function createInvoker( initialValue: EventValue, instance: ComponentInternalInstance | null ) { const invoker: Invoker = (e: Event & { _vts?: number }) => { // async edge case vuejs/vue#6566 // inner click event triggers patch, event handler // attached to outer element during patch, and triggered again. This // happens because browsers fire microtask ticks between event propagation. // this no longer happens for templates in Vue 3, but could still be // theoretically possible for hand-written render functions. // the solution: we save the timestamp when a handler is attached, // and also attach the timestamp to any event that was handled by vue // for the first time (to avoid inconsistent event timestamp implementations // or events fired from iframes, e.g. #2513) // The handler would only fire if the event passed to it was fired // AFTER it was attached. if (!e._vts) { e._vts = Date.now() } else if (e._vts <= invoker.attached) { return } callWithAsyncErrorHandling( patchStopImmediatePropagation(e, invoker.value), instance, ErrorCodes.NATIVE_EVENT_HANDLER, [e] ) } invoker.value = initialValue invoker.attached = getNow() return invoker } function patchStopImmediatePropagation( e: Event, value: EventValue ): EventValue { if (isArray(value)) { const originalStop = e.stopImmediatePropagation e.stopImmediatePropagation = () => { originalStop.call(e) ;(e as any)._stopped = true } return value.map(fn => (e: Event) => !(e as any)._stopped && fn && fn(e)) } else { return value } } |