Skip to content

Commit cfb2e28

Browse files
committed
fix(runtime-dom): invoker value is actually unknown at runtime
1 parent 3be4e3c commit cfb2e28

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

packages/runtime-dom/__tests__/patchEvents.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,11 @@ describe(`runtime-dom: events patching`, () => {
192192
testElement.dispatchEvent(new CustomEvent('foobar'))
193193
expect(fn2).toHaveBeenCalledTimes(1)
194194
})
195+
196+
it('handles an unknown type', () => {
197+
const el = document.createElement('div')
198+
patchProp(el, 'onClick', null, 'test')
199+
el.dispatchEvent(new Event('click'))
200+
expect('[Vue warn]: Wrong type passed to the event invoker, did you maybe forget @ or : in front of your prop? Received test').toHaveBeenWarned()
201+
})
195202
})

packages/runtime-dom/src/modules/events.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { hyphenate, isArray } from '@vue/shared'
1+
import { hyphenate, isArray, isString, isFunction } from '@vue/shared'
22
import {
33
ErrorCodes,
44
ComponentInternalInstance,
5-
callWithAsyncErrorHandling
5+
callWithAsyncErrorHandling, warn
66
} from '@vue/runtime-core'
77

88
interface Invoker extends EventListener {
@@ -81,7 +81,7 @@ const getNow = () =>
8181
cachedNow || (p.then(() => (cachedNow = 0)), (cachedNow = Date.now()))
8282

8383
function createInvoker(
84-
initialValue: EventValue,
84+
initialValue: EventValue | unknown,
8585
instance: ComponentInternalInstance | null
8686
) {
8787
const invoker: Invoker = (e: Event & { _vts?: number }) => {
@@ -109,23 +109,34 @@ function createInvoker(
109109
[e]
110110
)
111111
}
112-
invoker.value = initialValue
112+
invoker.value = sanitizeEventValue(initialValue)
113113
invoker.attached = getNow()
114114
return invoker
115115
}
116116

117+
function sanitizeEventValue(value: unknown): EventValue {
118+
if (isFunction(value) || isArray(value)) {
119+
return value as EventValue
120+
}
121+
122+
if (__DEV__) {
123+
warn('Wrong type passed to the event invoker, did you maybe forget @ or : in front of your prop? Received ' + (isString(value) ? value : typeof value))
124+
}
125+
return () => {}
126+
}
127+
117128
function patchStopImmediatePropagation(
118129
e: Event,
119-
value: EventValue
130+
value: EventValue | unknown
120131
): EventValue {
121132
if (isArray(value)) {
122133
const originalStop = e.stopImmediatePropagation
123134
e.stopImmediatePropagation = () => {
124135
originalStop.call(e)
125136
;(e as any)._stopped = true
126137
}
127-
return value.map(fn => (e: Event) => !(e as any)._stopped && fn && fn(e))
138+
return (value as Function[]).map(fn => (e: Event) => !(e as any)._stopped && fn && fn(e))
128139
} else {
129-
return value
140+
return sanitizeEventValue(value)
130141
}
131142
}

0 commit comments

Comments
 (0)