Skip to content

Commit

Permalink
refactor(core): Use early event contract instead of the event contrac…
Browse files Browse the repository at this point in the history
…t in bootstrap. (#55587)

This also fixes an existing bug where we erase the jsaction attribute too early.

Now the event contract binary is 608 bytes :D.

PR Close #55587
  • Loading branch information
iteriani authored and tbondwilkinson committed May 9, 2024
1 parent f5b6b7f commit d7f7985
Show file tree
Hide file tree
Showing 17 changed files with 96 additions and 833 deletions.
35 changes: 11 additions & 24 deletions goldens/public-api/core/primitives/event-dispatch/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,18 @@
```ts

// @public
export function bootstrapEarlyEventContract(field: string, container: HTMLElement, appId: string, eventTypes: string[], captureEventTypes: string[], earlyJsactionTracker?: EventContractTracker<EarlyJsactionDataContainer>): void;

// @public
export function bootstrapEventContract(field: string, container: Element, appId: string, events: string[], earlyJsactionTracker?: EventContractTracker<EventContract>): void;

// @public
export class Dispatcher {
constructor(getHandler?: ((eventInfoWrapper: EventInfoWrapper) => EventInfoWrapperHandler | void) | undefined, { stopPropagation, eventReplayer, }?: {
stopPropagation?: boolean;
export class BaseDispatcher {
constructor(dispatchDelegate: (eventInfoWrapper: EventInfoWrapper) => void, { eventReplayer }?: {
eventReplayer?: Replayer;
});
canDispatch(eventInfoWrapper: EventInfoWrapper): boolean;
dispatch(eventInfo: EventInfo, isGlobalDispatch?: boolean): void;
hasAction(name: string): boolean;
registerEventInfoHandlers<T>(namespace: string, instance: T | null, methods: {
[key: string]: EventInfoWrapperHandler;
}): void;
registerGlobalHandler(eventType: string, handler: GlobalHandler): void;
setEventReplayer(eventReplayer: Replayer): void;
unregisterGlobalHandler(eventType: string, handler: GlobalHandler): void;
unregisterHandler(namespace: string, name: string): void;
dispatch(eventInfo: EventInfo): void;
queueEventInfoWrapper(eventInfoWrapper: EventInfoWrapper): void;
scheduleEventReplay(): void;
}

// @public
export function bootstrapEarlyEventContract(field: string, container: HTMLElement, appId: string, eventTypes?: string[], captureEventTypes?: string[], earlyJsactionTracker?: EventContractTracker<EarlyJsactionDataContainer>): void;

// @public (undocumented)
export interface EarlyJsactionDataContainer {
// (undocumented)
Expand All @@ -43,15 +32,13 @@ export class EventContract implements UnrenamedEventContract {
addEvent(eventType: string, prefixedEventType?: string): void;
cleanUp(): void;
// (undocumented)
static CUSTOM_EVENT_SUPPORT: boolean;
// (undocumented)
ecaacs?: (updateEventInfoForA11yClick: typeof a11yClickLib.updateEventInfoForA11yClick, preventDefaultForA11yClick: typeof a11yClickLib.preventDefaultForA11yClick, populateClickOnlyAction: typeof a11yClickLib.populateClickOnlyAction) => void;
ecrd(dispatcher: Dispatcher_2, restriction: Restriction): void;
ecrd(dispatcher: Dispatcher, restriction: Restriction): void;
exportAddA11yClickSupport(): void;
handler(eventType: string): EventHandler | undefined;
// (undocumented)
static MOUSE_SPECIAL_SUPPORT: boolean;
registerDispatcher(dispatcher: Dispatcher_2, restriction: Restriction): void;
registerDispatcher(dispatcher: Dispatcher, restriction: Restriction): void;
replayEarlyEvents(earlyJsactionContainer?: EarlyJsactionDataContainer): void;
}

Expand Down Expand Up @@ -112,7 +99,7 @@ export class EventInfoWrapper {
}

// @public
export function registerDispatcher(eventContract: UnrenamedEventContract, dispatcher: Dispatcher): void;
export function registerDispatcher(eventContract: UnrenamedEventContract, dispatcher: BaseDispatcher): void;

// (No @packageDocumentation comment for this package)

Expand Down
4 changes: 2 additions & 2 deletions goldens/size-tracking/integration-payloads.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@
},
"platform-server-hydration/browser": {
"uncompressed": {
"main": 200584,
"main": 207890,
"polyfills": 33807,
"event-dispatch-contract.min": 11293
"event-dispatch-contract.min": 704
}
}
}
4 changes: 2 additions & 2 deletions packages/core/primitives/event-dispatch/contract_binary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/

import {bootstrapEventContract} from './src/register_events';
import {bootstrapEarlyEventContract} from './src/register_events';

(window as any)['__jsaction_bootstrap'] = bootstrapEventContract;
(window as any)['__jsaction_bootstrap'] = bootstrapEarlyEventContract;
4 changes: 2 additions & 2 deletions packages/core/primitives/event-dispatch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/

export {Dispatcher, registerDispatcher} from './src/dispatcher';
export {BaseDispatcher, registerDispatcher} from './src/base_dispatcher';
export {EventContractContainer} from './src/event_contract_container';
export type {EarlyJsactionDataContainer} from './src/earlyeventcontract';
export {EventContract} from './src/eventcontract';
export {bootstrapEventContract, bootstrapEarlyEventContract} from './src/register_events';
export {bootstrapEarlyEventContract} from './src/register_events';

export type {EventContractTracker} from './src/register_events';
export {EventInfoWrapper} from './src/event_info';
17 changes: 0 additions & 17 deletions packages/core/primitives/event-dispatch/src/action_resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const DEFAULT_EVENT_TYPE: string = EventType.CLICK;
/** Resolves actions for Events. */
export class ActionResolver {
private a11yClickSupport: boolean = false;
private readonly customEventSupport: boolean;
private readonly syntheticMouseEventSupport: boolean;

private updateEventInfoForA11yClick?: (eventInfo: eventInfoLib.EventInfo) => void = undefined;
Expand All @@ -46,30 +45,14 @@ export class ActionResolver {
) => void = undefined;

constructor({
customEventSupport = false,
syntheticMouseEventSupport = false,
}: {
customEventSupport?: boolean;
syntheticMouseEventSupport?: boolean;
} = {}) {
this.customEventSupport = customEventSupport;
this.syntheticMouseEventSupport = syntheticMouseEventSupport;
}

resolve(eventInfo: eventInfoLib.EventInfo) {
if (this.customEventSupport) {
if (eventInfoLib.getEventType(eventInfo) === EventType.CUSTOM) {
const detail = (eventInfoLib.getEvent(eventInfo) as CustomEvent).detail;
// For custom events, use a secondary dispatch based on the internal
// custom type of the event.
if (!detail || !detail['_type']) {
// This should never happen.
return;
}
eventInfoLib.setEventType(eventInfo, detail['_type']);
}
}

this.populateAction(eventInfo);
}

Expand Down
124 changes: 0 additions & 124 deletions packages/core/primitives/event-dispatch/src/custom_events.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,3 @@ export const A11Y_CLICK_SUPPORT = false;
* flag can be overridden in a build rule.
*/
export const MOUSE_SPECIAL_SUPPORT = false;

/**
* @define Support for custom events, which are type EventType.CUSTOM. These are
* native DOM events with an additional type field and an optional payload.
*/
export const CUSTOM_EVENT_SUPPORT = false;
11 changes: 1 addition & 10 deletions packages/core/primitives/event-dispatch/src/eventcontract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ import {ActionResolver} from './action_resolver';
import {EarlyJsactionData, EarlyJsactionDataContainer} from './earlyeventcontract';
import * as eventLib from './event';
import {EventContractContainerManager} from './event_contract_container';
import {
A11Y_CLICK_SUPPORT,
CUSTOM_EVENT_SUPPORT,
MOUSE_SPECIAL_SUPPORT,
} from './event_contract_defines';
import {A11Y_CLICK_SUPPORT, MOUSE_SPECIAL_SUPPORT} from './event_contract_defines';
import * as eventInfoLib from './event_info';
import {EventType} from './event_type';
import {Restriction} from './restriction';
Expand Down Expand Up @@ -87,14 +83,12 @@ type EventHandler = (eventType: string, event: Event, container: Element) => voi
* be delay loaded in a generic way.
*/
export class EventContract implements UnrenamedEventContract {
static CUSTOM_EVENT_SUPPORT = CUSTOM_EVENT_SUPPORT;
static A11Y_CLICK_SUPPORT = A11Y_CLICK_SUPPORT;
static MOUSE_SPECIAL_SUPPORT = MOUSE_SPECIAL_SUPPORT;

private containerManager: EventContractContainerManager | null;

private readonly actionResolver = new ActionResolver({
customEventSupport: EventContract.CUSTOM_EVENT_SUPPORT,
syntheticMouseEventSupport: EventContract.MOUSE_SPECIAL_SUPPORT,
});

Expand Down Expand Up @@ -135,9 +129,6 @@ export class EventContract implements UnrenamedEventContract {

constructor(containerManager: EventContractContainerManager) {
this.containerManager = containerManager;
if (EventContract.CUSTOM_EVENT_SUPPORT) {
this.addEvent(EventType.CUSTOM);
}
if (EventContract.A11Y_CLICK_SUPPORT) {
// Add a11y click support to the `EventContract`.
this.addA11yClickSupport();
Expand Down
33 changes: 2 additions & 31 deletions packages/core/primitives/event-dispatch/src/register_events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,9 @@
*/

import {EarlyEventContract, EarlyJsactionDataContainer} from './earlyeventcontract';
import {EventContractContainer} from './event_contract_container';
import {EventContract} from './eventcontract';

export type EventContractTracker<T> = {[key: string]: {[appId: string]: T}};

/**
* Provides a factory function for bootstrapping an event contract on a
* specified object (by default, exposed on the `window`).
* @param field The property on the object that the event contract will be placed on.
* @param container The container that listens to events
* @param appId A given identifier for an application. If there are multiple apps on the page
* then this is how contracts can be initialized for each one.
* @param events An array of event names that should be listened to.
* @param earlyJsactionTracker The object that should receive the event contract.
*/
export function bootstrapEventContract(
field: string,
container: Element,
appId: string,
events: string[],
earlyJsactionTracker: EventContractTracker<EventContract> = window as unknown as EventContractTracker<EventContract>,
) {
if (!earlyJsactionTracker[field]) {
earlyJsactionTracker[field] = {};
}
const eventContract = new EventContract(new EventContractContainer(container));
earlyJsactionTracker[field][appId] = eventContract;
for (const ev of events) {
eventContract.addEvent(ev);
}
}

/**
* Provides a factory function for bootstrapping an event contract on a
* specified object (by default, exposed on the `window`).
Expand All @@ -63,6 +34,6 @@ export function bootstrapEarlyEventContract(
}
earlyJsactionTracker[field][appId] = {};
const eventContract = new EarlyEventContract(earlyJsactionTracker[field][appId], container);
eventTypes && eventContract.addEvents(eventTypes);
captureEventTypes && eventContract.addEvents(captureEventTypes, true);
if (eventTypes) eventContract.addEvents(eventTypes);
if (captureEventTypes) eventContract.addEvents(captureEventTypes, true);
}

0 comments on commit d7f7985

Please sign in to comment.