Skip to content

Commit

Permalink
refactor(core): Move global dispatch behavior into Dispatcher. (#55692)
Browse files Browse the repository at this point in the history
This behavior is now implemented by calling `dispatch` whether or not
the `action` is populated. The `Dispatcher` then does global dispatch
and early returns if there's no action.

PR Close #55692
  • Loading branch information
tbondwilkinson authored and AndrewKushnir committed May 7, 2024
1 parent 67bb310 commit 0fb455f
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 111 deletions.
17 changes: 6 additions & 11 deletions packages/core/primitives/event-dispatch/src/base_dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ export class BaseDispatcher {
* @param dispatchDelegate A function that should handle dispatching an `EventInfoWrapper` to handlers.
*/
constructor(
private readonly dispatchDelegate: (
eventInfoWrapper: EventInfoWrapper,
isGlobalDispatch?: boolean,
) => void,
private readonly dispatchDelegate: (eventInfoWrapper: EventInfoWrapper) => void,
{eventReplayer = undefined}: {eventReplayer?: Replayer} = {},
) {
this.eventReplayer = eventReplayer;
Expand All @@ -67,20 +64,18 @@ export class BaseDispatcher {
*
* @param eventInfo The info for the event that triggered this call or the
* queue of events from EventContract.
* @param isGlobalDispatch If true, dispatches a global event instead of a
* regular jsaction handler.
*/
dispatch(eventInfo: EventInfo, isGlobalDispatch?: boolean): void {
dispatch(eventInfo: EventInfo): void {
const eventInfoWrapper = new EventInfoWrapper(eventInfo);
if (eventInfoWrapper.getIsReplay()) {
if (isGlobalDispatch || !this.eventReplayer) {
if (!this.eventReplayer) {
return;
}
this.queueEventInfoWrapper(eventInfoWrapper);
this.scheduleEventReplay();
return;
}
this.dispatchDelegate(eventInfoWrapper, isGlobalDispatch);
this.dispatchDelegate(eventInfoWrapper);
}

/** Queue an `EventInfoWrapper` for replay. */
Expand Down Expand Up @@ -117,7 +112,7 @@ export function registerDispatcher(
eventContract: UnrenamedEventContract,
dispatcher: BaseDispatcher,
) {
eventContract.ecrd((eventInfo: EventInfo, globalDispatch?: boolean) => {
dispatcher.dispatch(eventInfo, globalDispatch);
eventContract.ecrd((eventInfo: EventInfo) => {
dispatcher.dispatch(eventInfo);
}, Restriction.I_AM_THE_JSACTION_FRAMEWORK);
}
38 changes: 23 additions & 15 deletions packages/core/primitives/event-dispatch/src/dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ export class Dispatcher {
) {
this.eventReplayer = eventReplayer;
this.baseDispatcher = new BaseDispatcher(
(eventInfoWrapper: EventInfoWrapper, isGlobalDispatch?: boolean) => {
this.dispatchToHandler(eventInfoWrapper, isGlobalDispatch);
(eventInfoWrapper: EventInfoWrapper) => {
this.dispatchToHandler(eventInfoWrapper);
},
{
eventReplayer: (eventInfoWrappers) => {
Expand Down Expand Up @@ -102,42 +102,50 @@ export class Dispatcher {
*
* @param eventInfo The info for the event that triggered this call or the
* queue of events from EventContract.
* @param isGlobalDispatch If true, dispatches a global event instead of a
* regular jsaction handler.
*/
dispatch(eventInfo: EventInfo, isGlobalDispatch?: boolean): void {
this.baseDispatcher.dispatch(eventInfo, isGlobalDispatch);
this.baseDispatcher.dispatch(eventInfo);
}

/**
* Dispatches an `EventInfoWrapper`.
*/
private dispatchToHandler(eventInfoWrapper: EventInfoWrapper, isGlobalDispatch?: boolean) {
if (isGlobalDispatch) {
private dispatchToHandler(eventInfoWrapper: EventInfoWrapper) {
if (this.globalHandlers.size) {
const globalEventInfoWrapper = eventInfoWrapper.clone();

// In some cases, `populateAction` will rewrite `click` events to
// `clickonly`. Revert back to a regular click, otherwise we won't be able
// to execute global event handlers registered on click events.
if (globalEventInfoWrapper.getEventType() === EventType.CLICKONLY) {
globalEventInfoWrapper.setEventType(EventType.CLICK);
}
// Skip everything related to jsaction handlers, and execute the global
// handlers.
const ev = eventInfoWrapper.getEvent();
const eventTypeHandlers = this.globalHandlers.get(eventInfoWrapper.getEventType());
const event = globalEventInfoWrapper.getEvent();
const eventTypeHandlers = this.globalHandlers.get(globalEventInfoWrapper.getEventType());
let shouldPreventDefault = false;
if (eventTypeHandlers) {
for (const handler of eventTypeHandlers) {
if (handler(ev) === false) {
if (handler(event) === false) {
shouldPreventDefault = true;
}
}
}
if (shouldPreventDefault) {
eventLib.preventDefault(ev);
eventLib.preventDefault(event);
}
}

const action = eventInfoWrapper.getAction();
if (!action) {
return;
}

if (this.stopPropagation) {
stopPropagation(eventInfoWrapper);
}

const action = eventInfoWrapper.getAction()!;

let handler: EventInfoWrapperHandler | void = undefined;
if (this.getHandler) {
handler = this.getHandler(eventInfoWrapper);
Expand Down Expand Up @@ -307,7 +315,7 @@ export function stopPropagation(eventInfoWrapper: EventInfoWrapper) {
* Dispatcher.
*/
export function registerDispatcher(eventContract: UnrenamedEventContract, dispatcher: Dispatcher) {
eventContract.ecrd((eventInfo: EventInfo, globalDispatch?: boolean) => {
dispatcher.dispatch(eventInfo, globalDispatch);
eventContract.ecrd((eventInfo: EventInfo) => {
dispatcher.dispatch(eventInfo);
}, Restriction.I_AM_THE_JSACTION_FRAMEWORK);
}
25 changes: 5 additions & 20 deletions packages/core/primitives/event-dispatch/src/eventcontract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,29 +163,14 @@ export class EventContract implements UnrenamedEventContract {
// All events are queued when the dispatcher isn't yet loaded.
eventInfoLib.setIsReplay(eventInfo, true);
this.queuedEventInfos?.push(eventInfo);
}
this.actionResolver.resolve(eventInfo);

if (!this.dispatcher) {
return;
}
const globalEventInfo: eventInfoLib.EventInfo = eventInfoLib.cloneEventInfo(eventInfo);

// In some cases, `populateAction` will rewrite `click` events to
// `clickonly`. Revert back to a regular click, otherwise we won't be able
// to execute global event handlers registered on click events.
if (eventInfoLib.getEventType(globalEventInfo) === EventType.CLICKONLY) {
eventInfoLib.setEventType(globalEventInfo, EventType.CLICK);
}

this.dispatcher(globalEventInfo, /* dispatch global event */ true);

this.actionResolver.resolve(eventInfo);
const action = eventInfoLib.getAction(eventInfo);
if (!action) {
return;
}
if (shouldPreventDefaultBeforeDispatching(eventInfoLib.getActionElement(action), eventInfo)) {
eventLib.preventDefault(eventInfoLib.getEvent(eventInfo));
if (action) {
if (shouldPreventDefaultBeforeDispatching(eventInfoLib.getActionElement(action), eventInfo)) {
eventLib.preventDefault(eventInfoLib.getEvent(eventInfo));
}
}

this.dispatcher(eventInfo);
Expand Down
24 changes: 18 additions & 6 deletions packages/core/primitives/event-dispatch/test/dispatcher_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
*/

import {Dispatcher, Replayer} from '../src/dispatcher';
import {ActionInfo, createEventInfo, EventInfo, EventInfoWrapper} from '../src/event_info';
import {
ActionInfo,
createEventInfo,
EventInfo,
EventInfoWrapper,
unsetAction,
} from '../src/event_info';
import {createEvent} from '../src/replay';

function createMockClickEvent() {
Expand Down Expand Up @@ -137,7 +143,8 @@ describe('dispatcher test.ts', () => {
await expectAsync(replayed).toBePending();

const eventInfo1 = createTestEventInfo({isReplay: true});
dispatcher.dispatch(eventInfo1, /* globalDispatch= */ true);
unsetAction(eventInfo1);
dispatcher.dispatch(eventInfo1);

await expectAsync(replayed).toBePending();
});
Expand Down Expand Up @@ -199,7 +206,9 @@ describe('dispatcher test.ts', () => {
const dispatcher = new Dispatcher();
dispatcher.registerGlobalHandler('click', handler);

dispatcher.dispatch(createTestEventInfo(), true);
const eventInfo = createTestEventInfo();
unsetAction(eventInfo);
dispatcher.dispatch(eventInfo);

expect(handler).toHaveBeenCalledTimes(1);
});
Expand All @@ -213,7 +222,8 @@ describe('dispatcher test.ts', () => {
event: createEvent({type: 'mousedown'} as Event),
eventType: 'mousedown',
});
dispatcher.dispatch(eventInfo, true);
unsetAction(eventInfo);
dispatcher.dispatch(eventInfo);

expect(handler).not.toHaveBeenCalled();
});
Expand All @@ -234,7 +244,8 @@ describe('dispatcher test.ts', () => {
container,
action: {name: 'foo', element: targetElement},
});
dispatcher.dispatch(eventInfo, true);
unsetAction(eventInfo);
dispatcher.dispatch(eventInfo);
});
targetElement.addEventListener('click', targetHandler);
const parentHandler = jasmine.createSpy('parentHandler');
Expand Down Expand Up @@ -263,7 +274,8 @@ describe('dispatcher test.ts', () => {
container,
action: {name: 'foo', element: targetElement},
});
dispatcher.dispatch(eventInfo, /* globalDispatch= */ true);
unsetAction(eventInfo);
dispatcher.dispatch(eventInfo);
});
targetElement.addEventListener('click', targetHandler);
const parentHandler = jasmine.createSpy('parentHandler');
Expand Down
Loading

0 comments on commit 0fb455f

Please sign in to comment.