perf(core): use native addEventListener for faster rendering. (#18107)

Angular can make many assumptions about its event handlers. As a result
the bookkeeping for native addEventListener is significantly cheaper
than Zone's addEventLister which can't make such assumptions.

This change bypasses the Zone's addEventListener if present and always
uses the native addEventHandler. As a result registering event listeners
is about 3 times faster.

PR Close #18107
This commit is contained in:
Miško Hevery
2017-07-13 15:36:11 -07:00
committed by Miško Hevery
parent 8bcb268140
commit 6279e50d78
11 changed files with 122 additions and 42 deletions

View File

@ -189,14 +189,7 @@ export function listenToElementOutputs(view: ViewData, compView: ViewData, def:
}
function renderEventHandlerClosure(view: ViewData, index: number, eventName: string) {
return (event: any) => {
try {
return dispatchEvent(view, index, eventName, event);
} catch (e) {
// Attention: Don't rethrow, to keep in sync with directive events.
view.root.errorHandler.handleError(e);
}
}
return (event: any) => dispatchEvent(view, index, eventName, event);
}

View File

@ -138,14 +138,7 @@ export function createDirectiveInstance(view: ViewData, def: NodeDef): any {
}
function eventHandlerClosure(view: ViewData, index: number, eventName: string) {
return (event: any) => {
try {
return dispatchEvent(view, index, eventName, event);
} catch (e) {
// Attention: Don't rethrow, as it would cancel Observable subscriptions!
view.root.errorHandler.handleError(e);
}
}
return (event: any) => dispatchEvent(view, index, eventName, event);
}
export function checkAndUpdateDirectiveInline(

View File

@ -126,12 +126,18 @@ export function markParentViewsForCheckProjectedViews(view: ViewData, endView: V
}
export function dispatchEvent(
view: ViewData, nodeIndex: number, eventName: string, event: any): boolean {
const nodeDef = view.def.nodes[nodeIndex];
const startView =
nodeDef.flags & NodeFlags.ComponentView ? asElementData(view, nodeIndex).componentView : view;
markParentViewsForCheck(startView);
return Services.handleEvent(view, nodeIndex, eventName, event);
view: ViewData, nodeIndex: number, eventName: string, event: any): boolean|undefined {
try {
const nodeDef = view.def.nodes[nodeIndex];
const startView = nodeDef.flags & NodeFlags.ComponentView ?
asElementData(view, nodeIndex).componentView :
view;
markParentViewsForCheck(startView);
return Services.handleEvent(view, nodeIndex, eventName, event);
} catch (e) {
// Attention: Don't rethrow, as it would cancel Observable subscriptions!
view.root.errorHandler.handleError(e);
}
}
export function declaredViewContainer(view: ViewData): ElementData|null {