From 8bea2e39658d6382e590c2c424483c75ae19ef56 Mon Sep 17 00:00:00 2001 From: Thomas Nguyen Date: Mon, 12 Aug 2024 14:18:00 -0700 Subject: [PATCH] refactor(core): Call stopPropagation and preventDefault unconditionally within the patched methods. (#57354) This fixes a few tests in g3 and is a bug fix for the event dispatcher. Otherwise, bubbling might continue. PR Close #57354 --- .../event-dispatch/src/event_dispatcher.ts | 4 +++ .../event_dispatch/event_dispatch_spec.ts | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/packages/core/primitives/event-dispatch/src/event_dispatcher.ts b/packages/core/primitives/event-dispatch/src/event_dispatcher.ts index a003d920c8a..c3c71d79746 100644 --- a/packages/core/primitives/event-dispatch/src/event_dispatcher.ts +++ b/packages/core/primitives/event-dispatch/src/event_dispatcher.ts @@ -92,8 +92,10 @@ export class EventDispatcher { function prepareEventForBubbling(eventInfoWrapper: EventInfoWrapper) { const event = eventInfoWrapper.getEvent(); + const originalStopPropagation = eventInfoWrapper.getEvent().stopPropagation.bind(event); const stopPropagation = () => { event[PROPAGATION_STOPPED_SYMBOL] = true; + originalStopPropagation(); }; patchEventInstance(event, 'stopPropagation', stopPropagation); patchEventInstance(event, 'stopImmediatePropagation', stopPropagation); @@ -107,9 +109,11 @@ function propagationStopped(eventInfoWrapper: EventInfoWrapper) { function prepareEventForReplay(eventInfoWrapper: EventInfoWrapper) { const event = eventInfoWrapper.getEvent(); const target = eventInfoWrapper.getTargetElement(); + const originalPreventDefault = event.preventDefault.bind(event); patchEventInstance(event, 'target', target); patchEventInstance(event, 'eventPhase', EventPhase.REPLAY); patchEventInstance(event, 'preventDefault', () => { + originalPreventDefault(); throw new Error( PREVENT_DEFAULT_ERROR_MESSAGE + (ngDevMode ? PREVENT_DEFAULT_ERROR_MESSAGE_DETAILS : ''), ); diff --git a/packages/core/test/event_dispatch/event_dispatch_spec.ts b/packages/core/test/event_dispatch/event_dispatch_spec.ts index 5222e36dafd..5d2cb4d7175 100644 --- a/packages/core/test/event_dispatch/event_dispatch_spec.ts +++ b/packages/core/test/event_dispatch/event_dispatch_spec.ts @@ -188,6 +188,35 @@ describe('event dispatch', () => { bottomEl.click(); expect(onClickSpy).toHaveBeenCalledTimes(1); }); + it('should call the original stopPropagation method', async () => { + @Component({ + standalone: true, + selector: 'app', + template: ` +
+
+
+ `, + }) + class SimpleComponent { + onClick(e: Event) { + e.stopPropagation(); + e.preventDefault(); + } + } + configureTestingModule([SimpleComponent]); + fixture = TestBed.createComponent(SimpleComponent); + const nativeElement = fixture.debugElement.nativeElement; + const bottomEl = nativeElement.querySelector('#bottom')!; + const event = new MouseEvent('click', {bubbles: true}); + spyOn(event, 'stopPropagation'); + const stopPropagation = event.stopPropagation; + spyOn(event, 'preventDefault'); + const preventDefault = event.preventDefault; + bottomEl.dispatchEvent(event); + expect(stopPropagation).toHaveBeenCalled(); + expect(preventDefault).toHaveBeenCalled(); + }); }); describe('manual listening', () => {