perf(core): minor improvements to listener instructions (#41807)
Makes the following improvements to the listener instructions to make them slightly smaller and more memory-efficient. 1. Removes the default value from the `useCapture` parameter since it generates more code than just castint to `false`. 2. Removes the `useCapture` and `eventTargetResolver` parameters from `ɵɵsyntheticHostListener` since they won't be generated by the compiler, as far as I can tell. 3. Makes it so that we don't have to return a target name from a `GlobalTargetResolver`. This allows us to save on some memory, because we can return a reference to the target without having to wrap it in an object literal. DEPRECATIONS: `EventManagerPlugin.getGlobalEventTarget` is now deprecated and won't be called from Ivy code anymore. Global events will go through `addEventListener`. PR Close #41807
This commit is contained in:
parent
2dd96e08ae
commit
6581a1b48d
|
@ -32,7 +32,7 @@ export declare const EVENT_MANAGER_PLUGINS: InjectionToken<ɵangular_packages_pl
|
|||
export declare class EventManager {
|
||||
constructor(plugins: ɵangular_packages_platform_browser_platform_browser_g[], _zone: NgZone);
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function;
|
||||
addGlobalEventListener(target: string, eventName: string, handler: Function): Function;
|
||||
/** @deprecated */ addGlobalEventListener(target: string, eventName: string, handler: Function): Function;
|
||||
getZone(): NgZone;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
|
||||
import {assertIndexInRange} from '../../util/assert';
|
||||
import {EMPTY_OBJ} from '../../util/empty';
|
||||
import {isObservable} from '../../util/lang';
|
||||
import {PropertyAliasValue, TNode, TNodeFlags, TNodeType} from '../interfaces/node';
|
||||
import {GlobalTargetResolver, isProceduralRenderer, Renderer3} from '../interfaces/renderer';
|
||||
|
@ -39,13 +38,14 @@ import {getOrCreateLViewCleanup, getOrCreateTViewCleanup, handleError, loadCompo
|
|||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵlistener(
|
||||
eventName: string, listenerFn: (e?: any) => any, useCapture = false,
|
||||
eventName: string, listenerFn: (e?: any) => any, useCapture?: boolean,
|
||||
eventTargetResolver?: GlobalTargetResolver): typeof ɵɵlistener {
|
||||
const lView = getLView();
|
||||
const tView = getTView();
|
||||
const tNode = getCurrentTNode()!;
|
||||
listenerInternal(
|
||||
tView, lView, lView[RENDERER], tNode, eventName, listenerFn, useCapture, eventTargetResolver);
|
||||
tView, lView, lView[RENDERER], tNode, eventName, listenerFn, !!useCapture,
|
||||
eventTargetResolver);
|
||||
return ɵɵlistener;
|
||||
}
|
||||
|
||||
|
@ -71,15 +71,13 @@ export function ɵɵlistener(
|
|||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵsyntheticHostListener(
|
||||
eventName: string, listenerFn: (e?: any) => any, useCapture = false,
|
||||
eventTargetResolver?: GlobalTargetResolver): typeof ɵɵsyntheticHostListener {
|
||||
eventName: string, listenerFn: (e?: any) => any): typeof ɵɵsyntheticHostListener {
|
||||
const tNode = getCurrentTNode()!;
|
||||
const lView = getLView();
|
||||
const tView = getTView();
|
||||
const currentDef = getCurrentDirectiveDef(tView.data);
|
||||
const renderer = loadComponentRenderer(currentDef, tNode, lView);
|
||||
listenerInternal(
|
||||
tView, lView, renderer, tNode, eventName, listenerFn, useCapture, eventTargetResolver);
|
||||
listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, false);
|
||||
return ɵɵsyntheticHostListener;
|
||||
}
|
||||
|
||||
|
@ -117,7 +115,7 @@ function findExistingListener(
|
|||
|
||||
function listenerInternal(
|
||||
tView: TView, lView: LView, renderer: Renderer3, tNode: TNode, eventName: string,
|
||||
listenerFn: (e?: any) => any, useCapture = false,
|
||||
listenerFn: (e?: any) => any, useCapture: boolean,
|
||||
eventTargetResolver?: GlobalTargetResolver): void {
|
||||
const isTNodeDirectiveHost = isDirectiveHost(tNode);
|
||||
const firstCreatePass = tView.firstCreatePass;
|
||||
|
@ -136,11 +134,10 @@ function listenerInternal(
|
|||
// add native event listener - applicable to elements only
|
||||
if (tNode.type & TNodeType.AnyRNode) {
|
||||
const native = getNativeByTNode(tNode, lView) as RElement;
|
||||
const resolved = eventTargetResolver ? eventTargetResolver(native) : EMPTY_OBJ as any;
|
||||
const target = resolved.target || native;
|
||||
const target = eventTargetResolver ? eventTargetResolver(native) : native;
|
||||
const lCleanupIndex = lCleanup.length;
|
||||
const idxOrTargetGetter = eventTargetResolver ?
|
||||
(_lView: LView) => eventTargetResolver(unwrapRNode(_lView[tNode.index])).target :
|
||||
(_lView: LView) => eventTargetResolver(unwrapRNode(_lView[tNode.index])) :
|
||||
tNode.index;
|
||||
|
||||
// In order to match current behavior, native DOM event listeners must be added for all
|
||||
|
@ -176,11 +173,8 @@ function listenerInternal(
|
|||
(<any>existingListener).__ngLastListenerFn__ = listenerFn;
|
||||
processOutputs = false;
|
||||
} else {
|
||||
// The first argument of `listen` function in Procedural Renderer is:
|
||||
// - either a target name (as a string) in case of global target (window, document, body)
|
||||
// - or element reference (in all other cases)
|
||||
listenerFn = wrapListener(tNode, lView, context, listenerFn, false /** preventDefault */);
|
||||
const cleanupFn = renderer.listen(resolved.name || target, eventName, listenerFn);
|
||||
const cleanupFn = renderer.listen(target as RElement, eventName, listenerFn);
|
||||
ngDevMode && ngDevMode.rendererAddEventListener++;
|
||||
|
||||
lCleanup.push(listenerFn, cleanupFn);
|
||||
|
|
|
@ -30,9 +30,7 @@ export type Renderer3 = ObjectOrientedRenderer3|ProceduralRenderer3;
|
|||
|
||||
export type GlobalTargetName = 'document'|'window'|'body';
|
||||
|
||||
export type GlobalTargetResolver = (element: any) => {
|
||||
name: GlobalTargetName, target: EventTarget
|
||||
};
|
||||
export type GlobalTargetResolver = (element: any) => EventTarget;
|
||||
|
||||
/**
|
||||
* Object Oriented style of API needed to create elements and text nodes.
|
||||
|
|
|
@ -23,7 +23,7 @@ export const defaultScheduler =
|
|||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵresolveWindow(element: RElement&{ownerDocument: Document}) {
|
||||
return {name: 'window', target: element.ownerDocument.defaultView};
|
||||
return element.ownerDocument.defaultView;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,7 @@ export function ɵɵresolveWindow(element: RElement&{ownerDocument: Document}) {
|
|||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵresolveDocument(element: RElement&{ownerDocument: Document}) {
|
||||
return {name: 'document', target: element.ownerDocument};
|
||||
return element.ownerDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,7 +39,7 @@ export function ɵɵresolveDocument(element: RElement&{ownerDocument: Document})
|
|||
* @codeGenApi
|
||||
*/
|
||||
export function ɵɵresolveBody(element: RElement&{ownerDocument: Document}) {
|
||||
return {name: 'body', target: element.ownerDocument.body};
|
||||
return element.ownerDocument.body;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,6 +57,7 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
|||
return node instanceof DocumentFragment;
|
||||
}
|
||||
|
||||
/** @deprecated No longer being used in Ivy code. To be removed in version 14. */
|
||||
getGlobalEventTarget(doc: Document, target: string): EventTarget|null {
|
||||
if (target === 'window') {
|
||||
return window;
|
||||
|
|
|
@ -58,6 +58,7 @@ export class EventManager {
|
|||
* @param handler A function to call when the notification occurs. Receives the
|
||||
* event object as an argument.
|
||||
* @returns A callback function that can be used to remove the handler.
|
||||
* @deprecated No longer being used in Ivy code. To be removed in version 14.
|
||||
*/
|
||||
addGlobalEventListener(target: string, eventName: string, handler: Function): Function {
|
||||
const plugin = this._findPluginFor(eventName);
|
||||
|
|
|
@ -62,6 +62,7 @@ export class DominoAdapter extends BrowserDomAdapter {
|
|||
return node.shadowRoot == node;
|
||||
}
|
||||
|
||||
/** @deprecated No longer being used in Ivy code. To be removed in version 14. */
|
||||
getGlobalEventTarget(doc: Document, target: string): EventTarget|null {
|
||||
if (target === 'window') {
|
||||
return doc.defaultView;
|
||||
|
|
|
@ -22,6 +22,7 @@ export class ServerEventManagerPlugin /* extends EventManagerPlugin which is pri
|
|||
return getDOM().onAndCancel(element, eventName, handler);
|
||||
}
|
||||
|
||||
/** @deprecated No longer being used in Ivy code. To be removed in version 14. */
|
||||
addGlobalEventListener(element: string, eventName: string, handler: Function): Function {
|
||||
const target: HTMLElement = getDOM().getGlobalEventTarget(this.doc, element);
|
||||
if (!target) {
|
||||
|
|
Loading…
Reference in New Issue