From: Evan You Date: Wed, 15 Apr 2020 14:35:34 +0000 (-0400) Subject: fix(runtime-dom/v-on): support event.stopImmediatePropagation on multiple listeners X-Git-Tag: v3.0.0-alpha.13~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d45e47569d366b932c0e3461afc6478b45a4602d;p=thirdparty%2Fvuejs%2Fcore.git fix(runtime-dom/v-on): support event.stopImmediatePropagation on multiple listeners close #916 --- diff --git a/packages/runtime-dom/__tests__/patchEvents.spec.ts b/packages/runtime-dom/__tests__/patchEvents.spec.ts index b870a8be34..2bb8e2ac08 100644 --- a/packages/runtime-dom/__tests__/patchEvents.spec.ts +++ b/packages/runtime-dom/__tests__/patchEvents.spec.ts @@ -134,4 +134,18 @@ describe(`runtime-dom: events patching`, () => { expect(fn).toHaveBeenCalledTimes(1) expect(fn2).toHaveBeenCalledWith(event) }) + + it('should support stopImmediatePropagation on multiple listeners', async () => { + const el = document.createElement('div') + const event = new Event('click') + const fn1 = jest.fn((e: Event) => { + e.stopImmediatePropagation() + }) + const fn2 = jest.fn() + patchProp(el, 'onClick', null, [fn1, fn2]) + el.dispatchEvent(event) + await timeout() + expect(fn1).toHaveBeenCalledTimes(1) + expect(fn2).toHaveBeenCalledTimes(0) + }) }) diff --git a/packages/runtime-dom/src/modules/events.ts b/packages/runtime-dom/src/modules/events.ts index 6789934c7e..bb3ae9be00 100644 --- a/packages/runtime-dom/src/modules/events.ts +++ b/packages/runtime-dom/src/modules/events.ts @@ -1,4 +1,4 @@ -import { EMPTY_OBJ } from '@vue/shared' +import { EMPTY_OBJ, isArray } from '@vue/shared' import { ComponentInternalInstance, callWithAsyncErrorHandling @@ -130,7 +130,7 @@ function createInvoker( // AFTER it was attached. if (e.timeStamp >= invoker.lastUpdated - 1) { callWithAsyncErrorHandling( - invoker.value, + patchStopImmediatePropagation(e, invoker.value), instance, ErrorCodes.NATIVE_EVENT_HANDLER, [e] @@ -142,3 +142,19 @@ function createInvoker( invoker.lastUpdated = 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(e)) + } else { + return value + } +}