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
This commit is contained in:
Thomas Nguyen
2024-08-12 14:18:00 -07:00
committed by Andrew Kushnir
parent 8e945c7cc9
commit 8bea2e3965
2 changed files with 33 additions and 0 deletions
@@ -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 : ''),
);
@@ -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: `
<div id="top" (click)="onClick($event)">
<div id="bottom" (click)="onClick($event)"></div>
</div>
`,
})
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', () => {