Skip to content

Commit d011c9f

Browse files
tbondwilkinsonatscott
authored andcommitted
refactor(core): Refactor EarlyEventContract to prepare for using it as a container. (angular#56900)
This is the first step towards combining `EarlyEventContract` and `EventContract`. It contains a few refactors, such as making names more consistent. The goal of this refactor is to remove the `EarlyEventContract` class altogether, as well as `EventContract`. To install the early event contract with the default events in early script tag, users will call: `bootstrapGlobalEarlyEventContract()` And for boostraping: `registerGlobalDispatcher(dispatcher)` PR Close angular#56900
1 parent 78c44ec commit d011c9f

File tree

21 files changed

+243
-220
lines changed

21 files changed

+243
-220
lines changed

goldens/public-api/core/primitives/event-dispatch/index.api.md

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ export const Attribute: {
99
JSACTION: "jsaction";
1010
};
1111

12-
// @public
13-
export function bootstrapEarlyEventContract(field: string, container: HTMLElement, appId: string, eventTypes?: string[], captureEventTypes?: string[], earlyJsactionTracker?: EventContractTracker<EarlyJsactionDataContainer>): void;
14-
1512
// @public (undocumented)
1613
export interface EarlyJsactionDataContainer {
1714
// (undocumented)
1815
_ejsa?: EarlyJsactionData;
16+
// (undocumented)
17+
_ejsas?: {
18+
[appId: string]: EarlyJsactionData | undefined;
19+
};
1920
}
2021

2122
// @public
@@ -30,7 +31,7 @@ export class EventContract implements UnrenamedEventContract {
3031
// (undocumented)
3132
static MOUSE_SPECIAL_SUPPORT: boolean;
3233
registerDispatcher(dispatcher: Dispatcher, restriction: Restriction): void;
33-
replayEarlyEvents(earlyJsactionContainer?: EarlyJsactionDataContainer): void;
34+
replayEarlyEvents(earlyJsactionData?: EarlyJsactionData | undefined): void;
3435
}
3536

3637
// @public
@@ -42,13 +43,6 @@ export class EventContractContainer implements EventContractContainerManager {
4243
readonly element: Element;
4344
}
4445

45-
// @public (undocumented)
46-
export type EventContractTracker<T> = {
47-
[key: string]: {
48-
[appId: string]: T;
49-
};
50-
};
51-
5246
// @public
5347
export class EventDispatcher {
5448
constructor(dispatchDelegate: (event: Event, actionName: string) => void);
@@ -105,19 +99,18 @@ export const EventPhase: {
10599
};
106100

107101
// @public
108-
export const isCaptureEvent: (eventType: string) => boolean;
102+
export function getActionCache(element: Element): {
103+
[key: string]: string | undefined;
104+
};
109105

110106
// @public
111-
export const isSupportedEvent: (eventType: string) => boolean;
107+
export const isCaptureEventType: (eventType: string) => boolean;
112108

113109
// @public
114-
export function registerDispatcher(eventContract: UnrenamedEventContract, dispatcher: EventDispatcher): void;
115-
116-
// @public (undocumented)
117-
export function registerEventType(element: Element, eventType: string, action: string): void;
110+
export const isEarlyEventType: (eventType: string) => boolean;
118111

119-
// @public (undocumented)
120-
export function unregisterEventType(element: Element, eventType: string): void;
112+
// @public
113+
export function registerDispatcher(eventContract: UnrenamedEventContract, dispatcher: EventDispatcher): void;
121114

122115
// (No @packageDocumentation comment for this package)
123116

goldens/size-tracking/integration-payloads.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"uncompressed": {
5757
"main": 207890,
5858
"polyfills": 33807,
59-
"event-dispatch-contract.min": 648
59+
"event-dispatch-contract.min": 476
6060
}
6161
}
6262
}

packages/core/primitives/event-dispatch/contract_binary.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {bootstrapEarlyEventContract} from './src/register_events';
9+
import {bootstrapAppScopedEarlyEventContract} from './src/bootstrap_app_scoped';
1010

11-
(window as any)['__jsaction_bootstrap'] = bootstrapEarlyEventContract;
11+
(window as any)['__jsaction_bootstrap'] = bootstrapAppScopedEarlyEventContract;

packages/core/primitives/event-dispatch/index.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,11 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
export {EventDispatcher, EventPhase, registerDispatcher} from './src/event_dispatcher';
10-
export {EventContractContainer} from './src/event_contract_container';
9+
export {Attribute} from './src/attribute';
10+
export {getDefaulted as getActionCache} from './src/cache';
1111
export type {EarlyJsactionDataContainer} from './src/earlyeventcontract';
12-
export {EventContract} from './src/eventcontract';
13-
export {bootstrapEarlyEventContract} from './src/register_events';
14-
15-
export type {EventContractTracker} from './src/register_events';
12+
export {EventContractContainer} from './src/event_contract_container';
13+
export {EventDispatcher, EventPhase, registerDispatcher} from './src/event_dispatcher';
1614
export {EventInfoWrapper} from './src/event_info';
17-
export {isSupportedEvent, isCaptureEvent} from './src/event_type';
18-
export {Attribute} from './src/attribute';
19-
export {registerEventType, unregisterEventType} from './src/cache';
15+
export {isEarlyEventType, isCaptureEventType} from './src/event_type';
16+
export {EventContract} from './src/eventcontract';

packages/core/primitives/event-dispatch/src/a11y_click.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export function preventDefaultForA11yClick(eventInfo: eventInfoLib.EventInfo) {
4646
export function populateClickOnlyAction(
4747
actionElement: Element,
4848
eventInfo: eventInfoLib.EventInfo,
49-
actionMap: {[key: string]: string},
49+
actionMap: {[key: string]: string | undefined},
5050
) {
5151
if (
5252
// If there's already an action, don't attempt to set a CLICKONLY
@@ -60,5 +60,5 @@ export function populateClickOnlyAction(
6060
return;
6161
}
6262
eventInfoLib.setEventType(eventInfo, EventType.CLICKONLY);
63-
eventInfoLib.setAction(eventInfo, actionMap[EventType.CLICKONLY], actionElement);
63+
eventInfoLib.setAction(eventInfo, actionMap[EventType.CLICKONLY]!, actionElement);
6464
}

packages/core/primitives/event-dispatch/src/action_resolver.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class ActionResolver {
4141
private populateClickOnlyAction?: (
4242
actionElement: Element,
4343
eventInfo: eventInfoLib.EventInfo,
44-
actionMap: {[key: string]: string},
44+
actionMap: {[key: string]: string | undefined},
4545
) => void = undefined;
4646

4747
constructor({
@@ -243,8 +243,8 @@ export class ActionResolver {
243243
* @param actionElement The DOM node to retrieve the jsaction map from.
244244
* @return Map from event to qualified name of the jsaction bound to it.
245245
*/
246-
private parseActions(actionElement: Element): {[key: string]: string} {
247-
let actionMap: {[key: string]: string} | undefined = cache.get(actionElement);
246+
private parseActions(actionElement: Element): {[key: string]: string | undefined} {
247+
let actionMap: {[key: string]: string | undefined} | undefined = cache.get(actionElement);
248248
if (!actionMap) {
249249
const jsactionAttribute = actionElement.getAttribute(Attribute.JSACTION);
250250
if (!jsactionAttribute) {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {Restriction} from './restriction';
10+
import {EarlyJsactionDataContainer, addEvents, createEarlyJsactionData} from './earlyeventcontract';
11+
import {EventInfo} from './event_info';
12+
13+
/**
14+
* Creates an `EarlyJsactionData`, adds events to it, and populates it on a nested object on
15+
* the window.
16+
*/
17+
export function bootstrapAppScopedEarlyEventContract(
18+
container: HTMLElement,
19+
appId: string,
20+
bubbleEventTypes: string[],
21+
captureEventTypes: string[],
22+
dataContainer: EarlyJsactionDataContainer = window,
23+
) {
24+
const earlyJsactionData = createEarlyJsactionData(container);
25+
if (!dataContainer._ejsas) {
26+
dataContainer._ejsas = {};
27+
}
28+
dataContainer._ejsas[appId] = earlyJsactionData;
29+
addEvents(earlyJsactionData, bubbleEventTypes);
30+
addEvents(earlyJsactionData, captureEventTypes, /* capture= */ true);
31+
}
32+
33+
/**
34+
* Registers a dispatcher function on the `EarlyJsactionData` present on the nested object on the
35+
* window.
36+
*/
37+
export function registerAppScopedDispatcher(
38+
restriction: Restriction,
39+
appId: string,
40+
dispatcher: (eventInfo: EventInfo) => void,
41+
dataContainer: EarlyJsactionDataContainer = window,
42+
) {
43+
dataContainer._ejsas![appId]!.d = dispatcher;
44+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {BUBBLE_EVENT_TYPES, CAPTURE_EVENT_TYPES} from './event_type';
10+
import {Restriction} from './restriction';
11+
import {addEvents, createEarlyJsactionData} from './earlyeventcontract';
12+
import {EventInfo} from './event_info';
13+
14+
/** Creates an `EarlyJsactionData`, adds events to it, and populates it on the window. */
15+
export function bootstrapGlobalEarlyEventContract() {
16+
const earlyJsactionData = createEarlyJsactionData(window.document.documentElement);
17+
addEvents(earlyJsactionData, BUBBLE_EVENT_TYPES);
18+
addEvents(earlyJsactionData, CAPTURE_EVENT_TYPES, /* capture= */ true);
19+
window._ejsa = earlyJsactionData;
20+
}
21+
22+
/** Registers a dispatcher function on the `EarlyJsactionData` present on the window. */
23+
export function registerGlobalDispatcher(
24+
restriction: Restriction,
25+
dispatcher: (eventInfo: EventInfo) => void,
26+
) {
27+
window._ejsa!.d = dispatcher;
28+
}

packages/core/primitives/event-dispatch/src/cache.ts

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,29 @@ import {Property} from './property';
1111
/**
1212
* Map from jsaction annotation to a parsed map from event name to action name.
1313
*/
14-
const parseCache: {[key: string]: {[key: string]: string}} = {};
15-
16-
export function registerEventType(element: Element, eventType: string, action: string) {
17-
const cache = get(element) || {};
18-
cache[eventType] = action;
19-
set(element, cache);
20-
}
21-
22-
export function unregisterEventType(element: Element, eventType: string) {
23-
const cache = get(element);
24-
if (cache) {
25-
cache[eventType] = undefined as unknown as string;
26-
}
27-
}
14+
const parseCache: {[key: string]: {[key: string]: string | undefined}} = {};
2815

2916
/**
3017
* Reads the jsaction parser cache from the given DOM Element.
31-
*
32-
* @param element .
33-
* @return Map from event to qualified name of the jsaction bound to it.
3418
*/
35-
export function get(element: Element): {[key: string]: string} {
36-
// @ts-ignore
19+
export function get(element: Element): {[key: string]: string | undefined} | undefined {
3720
return element[Property.JSACTION];
3821
}
3922

23+
/**
24+
* Reads the jsaction parser cache for the given DOM element. If no cache is yet present,
25+
* creates an empty one.
26+
*/
27+
export function getDefaulted(element: Element): {[key: string]: string | undefined} {
28+
const cache = get(element) ?? {};
29+
set(element, cache);
30+
return cache;
31+
}
32+
4033
/**
4134
* Writes the jsaction parser cache to the given DOM Element.
42-
*
43-
* @param element .
44-
* @param actionMap Map from event to qualified name of the jsaction bound to
45-
* it.
4635
*/
47-
export function set(element: Element, actionMap: {[key: string]: string}) {
48-
// @ts-ignore
36+
export function set(element: Element, actionMap: {[key: string]: string | undefined}) {
4937
element[Property.JSACTION] = actionMap;
5038
}
5139

@@ -55,7 +43,7 @@ export function set(element: Element, actionMap: {[key: string]: string}) {
5543
* @param text Unparsed jsaction attribute value.
5644
* @return Parsed jsaction attribute value, if already present in the cache.
5745
*/
58-
export function getParsed(text: string): {[key: string]: string} | undefined {
46+
export function getParsed(text: string): {[key: string]: string | undefined} | undefined {
5947
return parseCache[text];
6048
}
6149

@@ -65,7 +53,7 @@ export function getParsed(text: string): {[key: string]: string} | undefined {
6553
* @param text Unparsed jsaction attribute value.
6654
* @param parsed Attribute value parsed into the action map.
6755
*/
68-
export function setParsed(text: string, parsed: {[key: string]: string}) {
56+
export function setParsed(text: string, parsed: {[key: string]: string | undefined}) {
6957
parseCache[text] = parsed;
7058
}
7159

0 commit comments

Comments
 (0)