From a40e8837992693da2480418b35a3ef971c76624c Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Mon, 31 Oct 2016 10:31:48 -0700 Subject: [PATCH] refactor(compiler): inline `view.contentChildren` --- .../src/view_compiler/compile_element.ts | 3 ++ .../src/view_compiler/compile_view.ts | 1 + .../src/view_compiler/view_builder.ts | 10 +++-- .../core/src/linker/component_factory.ts | 2 +- modules/@angular/core/src/linker/element.ts | 16 ++++++++ modules/@angular/core/src/linker/view.ts | 37 ++++--------------- modules/@angular/core/src/linker/view_ref.ts | 2 +- .../ng2_static_ftl/tree_root.ngfactory.ts | 3 +- 8 files changed, 38 insertions(+), 36 deletions(-) diff --git a/modules/@angular/compiler/src/view_compiler/compile_element.ts b/modules/@angular/compiler/src/view_compiler/compile_element.ts index 5cb928cefa..132e4ec37b 100644 --- a/modules/@angular/compiler/src/view_compiler/compile_element.ts +++ b/modules/@angular/compiler/src/view_compiler/compile_element.ts @@ -98,6 +98,9 @@ export class CompileElement extends CompileNode { this.view.createMethod.addStmt(statement); this.appElement = o.THIS_EXPR.prop(fieldName); this.instances.set(resolveIdentifierToken(Identifiers.AppElement).reference, this.appElement); + if (this.hasViewContainer) { + this.view.viewContainerAppElements.push(this.appElement); + } } private _createComponentFactoryResolver() { diff --git a/modules/@angular/compiler/src/view_compiler/compile_view.ts b/modules/@angular/compiler/src/view_compiler/compile_view.ts index 224c7cfe7d..8e4550d86f 100644 --- a/modules/@angular/compiler/src/view_compiler/compile_view.ts +++ b/modules/@angular/compiler/src/view_compiler/compile_view.ts @@ -32,6 +32,7 @@ export class CompileView implements NameResolver { public nodes: CompileNode[] = []; // root nodes or AppElements for ViewContainers public rootNodesOrAppElements: o.Expression[] = []; + public viewContainerAppElements: o.Expression[] = []; public createMethod: CompileMethod; public animationBindingsMethod: CompileMethod; diff --git a/modules/@angular/compiler/src/view_compiler/view_builder.ts b/modules/@angular/compiler/src/view_compiler/view_builder.ts index 90b1c3befc..4d1ada17e6 100644 --- a/modules/@angular/compiler/src/view_compiler/view_builder.ts +++ b/modules/@angular/compiler/src/view_compiler/view_builder.ts @@ -473,6 +473,8 @@ function createViewClass( function generateDestroyMethod(view: CompileView): o.Statement[] { const stmts: o.Statement[] = []; + view.viewContainerAppElements.forEach( + (appElement) => { stmts.push(appElement.callMethod('destroyNestedViews', []).toStmt()); }); view.viewChildren.forEach( (viewChild) => { stmts.push(viewChild.callMethod('destroy', []).toStmt()); }); stmts.push(...view.destroyMethod.finish()); @@ -572,9 +574,11 @@ function generateDetectChangesMethod(view: CompileView): o.Statement[] { } stmts.push(...view.animationBindingsMethod.finish()); stmts.push(...view.detectChangesInInputsMethod.finish()); - stmts.push( - o.THIS_EXPR.callMethod('detectContentChildrenChanges', [DetectChangesVars.throwOnChange]) - .toStmt()); + view.viewContainerAppElements.forEach((appElement) => { + stmts.push( + appElement.callMethod('detectChangesInNestedViews', [DetectChangesVars.throwOnChange]) + .toStmt()); + }); var afterContentStmts = view.updateContentQueriesMethod.finish().concat( view.afterContentLifecycleCallbacksMethod.finish()); if (afterContentStmts.length > 0) { diff --git a/modules/@angular/core/src/linker/component_factory.ts b/modules/@angular/core/src/linker/component_factory.ts index 9764252e30..af62faa330 100644 --- a/modules/@angular/core/src/linker/component_factory.ts +++ b/modules/@angular/core/src/linker/component_factory.ts @@ -75,7 +75,7 @@ export class ComponentRef_ extends ComponentRef { get changeDetectorRef(): ChangeDetectorRef { return this._hostElement.parentView.ref; }; get componentType(): Type { return this._componentType; } - destroy(): void { this._hostElement.parentView.destroy(); } + destroy(): void { this._hostElement.parentView.detachAndDestroy(); } onDestroy(callback: Function): void { this.hostView.onDestroy(callback); } } diff --git a/modules/@angular/core/src/linker/element.ts b/modules/@angular/core/src/linker/element.ts index 7273ec3be9..d18744dbba 100644 --- a/modules/@angular/core/src/linker/element.ts +++ b/modules/@angular/core/src/linker/element.ts @@ -46,6 +46,22 @@ export class AppElement { get parentInjector(): Injector { return this.parentView.injector(this.parentIndex); } get injector(): Injector { return this.parentView.injector(this.index); } + detectChangesInNestedViews(throwOnChange: boolean): void { + if (this.nestedViews) { + for (var i = 0; i < this.nestedViews.length; i++) { + this.nestedViews[i].detectChanges(throwOnChange); + } + } + } + + destroyNestedViews(): void { + if (this.nestedViews) { + for (var i = 0; i < this.nestedViews.length; i++) { + this.nestedViews[i].destroy(); + } + } + } + mapNestedViews(nestedViewClass: any, callback: Function): any[] { var result: any[] /** TODO #9100 */ = []; if (isPresent(this.nestedViews)) { diff --git a/modules/@angular/core/src/linker/view.ts b/modules/@angular/core/src/linker/view.ts index e532ded49f..648488bc32 100644 --- a/modules/@angular/core/src/linker/view.ts +++ b/modules/@angular/core/src/linker/view.ts @@ -33,7 +33,6 @@ export abstract class AppView { rootNodesOrAppElements: any[]; allNodes: any[]; disposables: Function[]; - contentChildren: AppView[] = []; viewContainerElement: AppElement = null; numberOfChecks: number = 0; @@ -124,29 +123,19 @@ export abstract class AppView { } } - destroy() { + detachAndDestroy() { if (this._hasExternalHostElement) { this.renderer.detachView(this.flatRootNodes); } else if (isPresent(this.viewContainerElement)) { this.viewContainerElement.detachView(this.viewContainerElement.nestedViews.indexOf(this)); } - this._destroyRecurse(); + this.destroy(); } - private _destroyRecurse() { + destroy() { if (this.cdMode === ChangeDetectorStatus.Destroyed) { return; } - var children = this.contentChildren; - for (var i = 0; i < children.length; i++) { - children[i]._destroyRecurse(); - } - this.destroyLocal(); - - this.cdMode = ChangeDetectorStatus.Destroyed; - } - - destroyLocal() { var hostElement = this.type === ViewType.COMPONENT ? this.declarationAppElement.nativeElement : null; for (var i = 0; i < this.disposables.length; i++) { @@ -161,6 +150,8 @@ export abstract class AppView { } else { this.renderer.destroyView(hostElement, this.allNodes); } + + this.cdMode = ChangeDetectorStatus.Destroyed; } /** @@ -222,28 +213,16 @@ export abstract class AppView { /** * Overwritten by implementations */ - detectChangesInternal(throwOnChange: boolean): void { - this.detectContentChildrenChanges(throwOnChange); - } - - detectContentChildrenChanges(throwOnChange: boolean) { - for (var i = 0; i < this.contentChildren.length; ++i) { - var child = this.contentChildren[i]; - if (child.cdMode === ChangeDetectorStatus.Detached) continue; - child.detectChanges(throwOnChange); - } - } + detectChangesInternal(throwOnChange: boolean): void {} markContentChildAsMoved(renderAppElement: AppElement): void { this.dirtyParentQueriesInternal(); } addToContentChildren(renderAppElement: AppElement): void { - renderAppElement.parentView.contentChildren.push(this); this.viewContainerElement = renderAppElement; this.dirtyParentQueriesInternal(); } removeFromContentChildren(renderAppElement: AppElement): void { - ListWrapper.remove(renderAppElement.parentView.contentChildren, this); this.dirtyParentQueriesInternal(); this.viewContainerElement = null; } @@ -310,10 +289,10 @@ export class DebugAppView extends AppView { } } - destroyLocal() { + destroy() { this._resetDebug(); try { - super.destroyLocal(); + super.destroy(); } catch (e) { this._rethrowWithContext(e); throw e; diff --git a/modules/@angular/core/src/linker/view_ref.ts b/modules/@angular/core/src/linker/view_ref.ts index adfe78393b..6a8c753634 100644 --- a/modules/@angular/core/src/linker/view_ref.ts +++ b/modules/@angular/core/src/linker/view_ref.ts @@ -119,5 +119,5 @@ export class ViewRef_ implements EmbeddedViewRef, ChangeDetectorRef { onDestroy(callback: Function) { this._view.disposables.push(callback); } - destroy() { this._view.destroy(); } + destroy() { this._view.detachAndDestroy(); } } diff --git a/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts b/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts index e8ac52ce84..cfb5a54dea 100644 --- a/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts +++ b/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts @@ -113,7 +113,7 @@ class _View_TreeRootComponent0 extends import1.AppView { destroyInternal() { this._TreeComponent0_0_4View.destroyInternal(); } detectChangesInternal(throwOnChange: boolean): void { this._TreeComponent0_0_4View.updateData(this.parent.context.data); - this.detectContentChildrenChanges(throwOnChange); this._TreeComponent0_0_4View.detectChangesInternal(throwOnChange); } }