From bda1909ede42c49de69eb10f70325475f869cb9d Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Mon, 31 Oct 2016 14:41:16 -0700 Subject: [PATCH] refactor(compiler): remove `view.rootNodes` and `view.projectableNodes` They are replaced by generated visitor functions `view.visitRootNodes` / `view.visitProjectableNodes`. --- modules/@angular/compiler/src/identifiers.ts | 5 - .../src/view_compiler/compile_element.ts | 6 +- .../src/view_compiler/compile_view.ts | 18 ++- .../compiler/src/view_compiler/constants.ts | 1 - .../compiler/src/view_compiler/util.ts | 23 ---- .../src/view_compiler/view_builder.ts | 129 ++++++++++++++---- .../core/src/linker/component_factory.ts | 13 +- modules/@angular/core/src/linker/element.ts | 8 ++ .../@angular/core/src/linker/template_ref.ts | 2 +- modules/@angular/core/src/linker/view.ts | 94 ++++++------- .../@angular/core/src/linker/view_utils.ts | 40 +----- .../linker/projection_integration_spec.ts | 21 ++- .../ng2_static_ftl/tree_root.ngfactory.ts | 4 +- 13 files changed, 193 insertions(+), 171 deletions(-) diff --git a/modules/@angular/compiler/src/identifiers.ts b/modules/@angular/compiler/src/identifiers.ts index 81bff855ac..d1914e2314 100644 --- a/modules/@angular/compiler/src/identifiers.ts +++ b/modules/@angular/compiler/src/identifiers.ts @@ -162,11 +162,6 @@ export class Identifiers { moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.checkBinding }; - static flattenNestedViewRenderNodes: IdentifierSpec = { - name: 'flattenNestedViewRenderNodes', - moduleUrl: VIEW_UTILS_MODULE_URL, - runtime: view_utils.flattenNestedViewRenderNodes - }; static devModeEqual: IdentifierSpec = {name: 'devModeEqual', moduleUrl: CD_MODULE_URL, runtime: devModeEqual}; static interpolate: IdentifierSpec = { diff --git a/modules/@angular/compiler/src/view_compiler/compile_element.ts b/modules/@angular/compiler/src/view_compiler/compile_element.ts index 132e4ec37b..b6f6d389e6 100644 --- a/modules/@angular/compiler/src/view_compiler/compile_element.ts +++ b/modules/@angular/compiler/src/view_compiler/compile_element.ts @@ -19,7 +19,7 @@ import {ProviderAst, ProviderAstType, ReferenceAst, TemplateAst} from '../templa import {CompileMethod} from './compile_method'; import {CompileQuery, addQueryToTokenMap, createQueryList} from './compile_query'; -import {CompileView} from './compile_view'; +import {CompileView, CompileViewRootNode} from './compile_view'; import {InjectMethodVars, ViewProperties} from './constants'; import {ComponentFactoryDependency, DirectiveWrapperDependency, ViewFactoryDependency} from './deps'; import {getPropertyInView, injectFromViewParentInjector} from './util'; @@ -51,7 +51,7 @@ export class CompileElement extends CompileNode { private _queries = new Map(); private _componentConstructorViewQueryLists: o.Expression[] = []; - public contentNodesByNgContentIndex: Array[] = null; + public contentNodesByNgContentIndex: Array[] = null; public embeddedView: CompileView; public referenceTokens: {[key: string]: CompileTokenMetadata}; @@ -293,7 +293,7 @@ export class CompileElement extends CompileNode { this.view.createMethod, this.view.updateContentQueriesMethod))); } - addContentNode(ngContentIndex: number, nodeExpr: o.Expression) { + addContentNode(ngContentIndex: number, nodeExpr: CompileViewRootNode) { this.contentNodesByNgContentIndex[ngContentIndex].push(nodeExpr); } diff --git a/modules/@angular/compiler/src/view_compiler/compile_view.ts b/modules/@angular/compiler/src/view_compiler/compile_view.ts index 8e4550d86f..256d5dff61 100644 --- a/modules/@angular/compiler/src/view_compiler/compile_view.ts +++ b/modules/@angular/compiler/src/view_compiler/compile_view.ts @@ -23,6 +23,18 @@ import {CompilePipe} from './compile_pipe'; import {CompileQuery, addQueryToTokenMap, createQueryList} from './compile_query'; import {getPropertyInView, getViewFactoryName} from './util'; +export enum CompileViewRootNodeType { + Node, + ViewContainer, + NgContent +} + +export class CompileViewRootNode { + constructor( + public type: CompileViewRootNodeType, public expr: o.Expression, + public ngContentIndex?: number) {} +} + export class CompileView implements NameResolver { public viewType: ViewType; public viewQueries: Map; @@ -30,8 +42,10 @@ export class CompileView implements NameResolver { public viewChildren: o.Expression[] = []; public nodes: CompileNode[] = []; - // root nodes or AppElements for ViewContainers - public rootNodesOrAppElements: o.Expression[] = []; + + public rootNodes: CompileViewRootNode[] = []; + public lastRenderNode: o.Expression = o.NULL_EXPR; + public viewContainerAppElements: o.Expression[] = []; public createMethod: CompileMethod; diff --git a/modules/@angular/compiler/src/view_compiler/constants.ts b/modules/@angular/compiler/src/view_compiler/constants.ts index b6c4d2cf9b..a927f30a81 100644 --- a/modules/@angular/compiler/src/view_compiler/constants.ts +++ b/modules/@angular/compiler/src/view_compiler/constants.ts @@ -45,7 +45,6 @@ export class ViewConstructorVars { export class ViewProperties { static renderer = o.THIS_EXPR.prop('renderer'); - static projectableNodes = o.THIS_EXPR.prop('projectableNodes'); static viewUtils = o.THIS_EXPR.prop('viewUtils'); } diff --git a/modules/@angular/compiler/src/view_compiler/util.ts b/modules/@angular/compiler/src/view_compiler/util.ts index da9f9e29d3..aa0d0f2df5 100644 --- a/modules/@angular/compiler/src/view_compiler/util.ts +++ b/modules/@angular/compiler/src/view_compiler/util.ts @@ -69,29 +69,6 @@ export function getViewFactoryName( return `viewFactory_${component.type.name}${embeddedTemplateIndex}`; } -export function createFlatArray(expressions: o.Expression[]): o.Expression { - var lastNonArrayExpressions: o.Expression[] = []; - var result: o.Expression = o.literalArr([]); - for (var i = 0; i < expressions.length; i++) { - var expr = expressions[i]; - if (expr.type instanceof o.ArrayType) { - if (lastNonArrayExpressions.length > 0) { - result = - result.callMethod(o.BuiltinMethod.ConcatArray, [o.literalArr(lastNonArrayExpressions)]); - lastNonArrayExpressions = []; - } - result = result.callMethod(o.BuiltinMethod.ConcatArray, [expr]); - } else { - lastNonArrayExpressions.push(expr); - } - } - if (lastNonArrayExpressions.length > 0) { - result = - result.callMethod(o.BuiltinMethod.ConcatArray, [o.literalArr(lastNonArrayExpressions)]); - } - return result; -} - export function getHandleEventMethodName(elementIndex: number): string { return `handleEvent_${elementIndex}`; } \ No newline at end of file diff --git a/modules/@angular/compiler/src/view_compiler/view_builder.ts b/modules/@angular/compiler/src/view_compiler/view_builder.ts index 4d1ada17e6..d53667f07a 100644 --- a/modules/@angular/compiler/src/view_compiler/view_builder.ts +++ b/modules/@angular/compiler/src/view_compiler/view_builder.ts @@ -15,14 +15,15 @@ import {isPresent} from '../facade/lang'; import {Identifiers, identifierToken, resolveIdentifier} from '../identifiers'; import {createClassStmt} from '../output/class_builder'; import * as o from '../output/output_ast'; +import {ParseSourceSpan} from '../parse_util'; import {ChangeDetectorStatus, ViewType, isDefaultChangeDetectionStrategy} from '../private_import_core'; import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast'; import {CompileElement, CompileNode} from './compile_element'; -import {CompileView} from './compile_view'; +import {CompileView, CompileViewRootNode, CompileViewRootNodeType} from './compile_view'; import {ChangeDetectorStatusEnum, DetectChangesVars, InjectMethodVars, ViewConstructorVars, ViewEncapsulationEnum, ViewProperties, ViewTypeEnum} from './constants'; import {ComponentFactoryDependency, DirectiveWrapperDependency, ViewFactoryDependency} from './deps'; -import {createFlatArray, getViewFactoryName} from './util'; +import {getViewFactoryName} from './util'; const IMPLICIT_TEMPLATE_VAR = '\$implicit'; const CLASS_ATTR = 'class'; @@ -38,9 +39,12 @@ export function buildView( Array): number { var builderVisitor = new ViewBuilderVisitor(view, targetDependencies); - templateVisitAll( - builderVisitor, template, - view.declarationElement.isNull() ? view.declarationElement : view.declarationElement.parent); + const parentEl = + view.declarationElement.isNull() ? view.declarationElement : view.declarationElement.parent; + templateVisitAll(builderVisitor, template, parentEl); + if (view.viewType === ViewType.EMBEDDED) { + view.lastRenderNode = builderVisitor.getOrCreateLastRenderNode(); + } return builderVisitor.nestedViewCount; } @@ -73,10 +77,16 @@ class ViewBuilderVisitor implements TemplateAstVisitor { if (this._isRootNode(parent)) { // store appElement as root node only for ViewContainers if (this.view.viewType !== ViewType.COMPONENT) { - this.view.rootNodesOrAppElements.push(vcAppEl || node.renderNode); + this.view.rootNodes.push(new CompileViewRootNode( + vcAppEl ? CompileViewRootNodeType.ViewContainer : CompileViewRootNodeType.Node, + vcAppEl || node.renderNode)); } } else if (isPresent(parent.component) && isPresent(ngContentIndex)) { - parent.addContentNode(ngContentIndex, vcAppEl || node.renderNode); + parent.addContentNode( + ngContentIndex, + new CompileViewRootNode( + vcAppEl ? CompileViewRootNodeType.ViewContainer : CompileViewRootNodeType.Node, + vcAppEl || node.renderNode)); } } @@ -97,6 +107,23 @@ class ViewBuilderVisitor implements TemplateAstVisitor { } } + getOrCreateLastRenderNode(): o.Expression { + const view = this.view; + if (view.rootNodes.length === 0 || + view.rootNodes[view.rootNodes.length - 1].type !== CompileViewRootNodeType.Node) { + var fieldName = `_el_${view.nodes.length}`; + view.fields.push( + new o.ClassField(fieldName, o.importType(view.genConfig.renderTypes.renderElement))); + view.createMethod.addStmt(o.THIS_EXPR.prop(fieldName) + .set(ViewProperties.renderer.callMethod( + 'createTemplateAnchor', [o.NULL_EXPR, o.NULL_EXPR])) + .toStmt()); + view.rootNodes.push( + new CompileViewRootNode(CompileViewRootNodeType.Node, o.THIS_EXPR.prop(fieldName))) + } + return view.rootNodes[view.rootNodes.length - 1].expr; + } + visitBoundText(ast: BoundTextAst, parent: CompileElement): any { return this._visitText(ast, '', parent); } @@ -129,9 +156,6 @@ class ViewBuilderVisitor implements TemplateAstVisitor { // have debug information for them... this.view.createMethod.resetDebugInfo(null, ast); var parentRenderNode = this._getParentRenderNode(parent); - var nodesExpression = ViewProperties.projectableNodes.key( - o.literal(ast.index), - new o.ArrayType(o.importType(this.view.genConfig.renderTypes.renderNode))); if (parentRenderNode !== o.NULL_EXPR) { this.view.createMethod.addStmt( ViewProperties.renderer @@ -139,18 +163,20 @@ class ViewBuilderVisitor implements TemplateAstVisitor { 'projectNodes', [ parentRenderNode, - o.importExpr(resolveIdentifier(Identifiers.flattenNestedViewRenderNodes)) - .callFn([nodesExpression]) + o.THIS_EXPR.callMethod('projectedNodes', [o.literal(ast.index)]) ]) .toStmt()); } else if (this._isRootNode(parent)) { if (this.view.viewType !== ViewType.COMPONENT) { // store root nodes only for embedded/host views - this.view.rootNodesOrAppElements.push(nodesExpression); + this.view.rootNodes.push( + new CompileViewRootNode(CompileViewRootNodeType.NgContent, null, ast.index)); } } else { if (isPresent(parent.component) && isPresent(ast.ngContentIndex)) { - parent.addContentNode(ast.ngContentIndex, nodesExpression); + parent.addContentNode( + ast.ngContentIndex, + new CompileViewRootNode(CompileViewRootNodeType.NgContent, null, ast.index)); } } return null; @@ -220,18 +246,8 @@ class ViewBuilderVisitor implements TemplateAstVisitor { compileElement.afterChildren(this.view.nodes.length - nodeIndex - 1); if (isPresent(compViewExpr)) { - var codeGenContentNodes: o.Expression; - if (this.view.component.type.isHost) { - codeGenContentNodes = ViewProperties.projectableNodes; - } else { - codeGenContentNodes = o.literalArr( - compileElement.contentNodesByNgContentIndex.map(nodes => createFlatArray(nodes))); - } this.view.createMethod.addStmt( - compViewExpr - .callMethod( - 'create', [compileElement.getComponent(), codeGenContentNodes, o.NULL_EXPR]) - .toStmt()); + compViewExpr.callMethod('create', [compileElement.getComponent(), o.NULL_EXPR]).toStmt()); } return null; } @@ -457,7 +473,8 @@ function createViewClass( generateDetectChangesMethod(view)), new o.ClassMethod('dirtyParentQueriesInternal', [], view.dirtyParentQueriesMethod.finish()), new o.ClassMethod('destroyInternal', [], generateDestroyMethod(view)), - new o.ClassMethod('detachInternal', [], view.detachMethod.finish()) + new o.ClassMethod('detachInternal', [], view.detachMethod.finish()), + generateVisitRootNodesMethod(view), generateVisitProjectableNodesMethod(view) ].filter((method) => method.body.length > 0); var superClass = view.genConfig.genDebugInfo ? Identifiers.DebugAppView : Identifiers.AppView; @@ -554,7 +571,7 @@ function generateCreateMethod(view: CompileView): o.Statement[] { .callMethod( 'init', [ - createFlatArray(view.rootNodesOrAppElements), + view.lastRenderNode, o.literalArr(view.nodes.map(node => node.renderNode)), o.literalArr(view.disposables), ]) @@ -634,3 +651,61 @@ function getChangeDetectionMode(view: CompileView): ChangeDetectorStatus { } return mode; } + +function generateVisitRootNodesMethod(view: CompileView): o.ClassMethod { + const cbVar = o.variable('cb'); + const ctxVar = o.variable('ctx'); + const stmts: o.Statement[] = generateVisitNodesStmts(view.rootNodes, cbVar, ctxVar); + return new o.ClassMethod( + 'visitRootNodesInternal', + [new o.FnParam(cbVar.name, o.DYNAMIC_TYPE), new o.FnParam(ctxVar.name, o.DYNAMIC_TYPE)], + stmts); +} + +function generateVisitProjectableNodesMethod(view: CompileView): o.ClassMethod { + const nodeIndexVar = o.variable('nodeIndex'); + const ngContentIndexVar = o.variable('ngContentIndex'); + const cbVar = o.variable('cb'); + const ctxVar = o.variable('ctx'); + const stmts: o.Statement[] = []; + view.nodes.forEach((node) => { + if (node instanceof CompileElement && node.component) { + node.contentNodesByNgContentIndex.forEach((projectedNodes, ngContentIndex) => { + stmts.push(new o.IfStmt( + nodeIndexVar.equals(o.literal(node.nodeIndex)) + .and(ngContentIndexVar.equals(o.literal(ngContentIndex))), + generateVisitNodesStmts(projectedNodes, cbVar, ctxVar))); + }); + } + }); + return new o.ClassMethod( + 'visitProjectableNodesInternal', + [ + new o.FnParam(nodeIndexVar.name, o.NUMBER_TYPE), + new o.FnParam(ngContentIndexVar.name, o.NUMBER_TYPE), + new o.FnParam(cbVar.name, o.DYNAMIC_TYPE), new o.FnParam(ctxVar.name, o.DYNAMIC_TYPE) + ], + stmts); +} + +function generateVisitNodesStmts( + nodes: CompileViewRootNode[], cb: o.Expression, ctx: o.Expression): o.Statement[] { + const stmts: o.Statement[] = []; + nodes.forEach((node) => { + switch (node.type) { + case CompileViewRootNodeType.Node: + stmts.push(cb.callFn([node.expr, ctx]).toStmt()); + break; + case CompileViewRootNodeType.ViewContainer: + stmts.push(cb.callFn([node.expr.prop('nativeElement'), ctx]).toStmt()); + stmts.push(node.expr.callMethod('visitNestedViewRootNodes', [cb, ctx]).toStmt()); + break; + case CompileViewRootNodeType.NgContent: + stmts.push( + o.THIS_EXPR.callMethod('visitProjectedNodes', [o.literal(node.ngContentIndex), cb, ctx]) + .toStmt()); + break; + } + }); + return stmts; +} diff --git a/modules/@angular/core/src/linker/component_factory.ts b/modules/@angular/core/src/linker/component_factory.ts index af62faa330..c028c1b08d 100644 --- a/modules/@angular/core/src/linker/component_factory.ts +++ b/modules/@angular/core/src/linker/component_factory.ts @@ -10,8 +10,10 @@ import {ChangeDetectorRef} from '../change_detection/change_detection'; import {Injector} from '../di/injector'; import {unimplemented} from '../facade/errors'; import {Type} from '../type'; + import {AppElement} from './element'; import {ElementRef} from './element_ref'; +import {AppView} from './view'; import {ViewRef} from './view_ref'; import {ViewUtils} from './view_utils'; @@ -104,8 +106,15 @@ export class ComponentFactory { projectableNodes = []; } // Note: Host views don't need a declarationAppElement! - var hostView = this._viewFactory(vu, injector, null); - var hostElement = hostView.create(EMPTY_CONTEXT, projectableNodes, rootSelectorOrNode); + var hostView: AppView = this._viewFactory(vu, injector, null); + hostView.visitProjectableNodesInternal = + (nodeIndex: number, ngContentIndex: number, cb: any, ctx: any) => { + const nodes = projectableNodes[ngContentIndex] || []; + for (var i = 0; i < nodes.length; i++) { + cb(nodes[i], ctx); + } + }; + var hostElement = hostView.create(EMPTY_CONTEXT, rootSelectorOrNode); return new ComponentRef_(hostElement, this._componentType); } } diff --git a/modules/@angular/core/src/linker/element.ts b/modules/@angular/core/src/linker/element.ts index d18744dbba..173f6e3c3f 100644 --- a/modules/@angular/core/src/linker/element.ts +++ b/modules/@angular/core/src/linker/element.ts @@ -62,6 +62,14 @@ export class AppElement { } } + visitNestedViewRootNodes(cb: (node: any, ctx: C) => void, c: C): void { + if (this.nestedViews) { + for (var i = 0; i < this.nestedViews.length; i++) { + this.nestedViews[i].visitRootNodesInternal(cb, c); + } + } + } + mapNestedViews(nestedViewClass: any, callback: Function): any[] { var result: any[] /** TODO #9100 */ = []; if (isPresent(this.nestedViews)) { diff --git a/modules/@angular/core/src/linker/template_ref.ts b/modules/@angular/core/src/linker/template_ref.ts index c18ebc9dcc..68a2aeb93d 100644 --- a/modules/@angular/core/src/linker/template_ref.ts +++ b/modules/@angular/core/src/linker/template_ref.ts @@ -48,7 +48,7 @@ export class TemplateRef_ extends TemplateRef { createEmbeddedView(context: C): EmbeddedViewRef { var view: AppView = this._viewFactory( this._appElement.parentView.viewUtils, this._appElement.parentInjector, this._appElement); - view.create(context || {}, null, null); + view.create(context || {}, null); return view.ref; } diff --git a/modules/@angular/core/src/linker/view.ts b/modules/@angular/core/src/linker/view.ts index 648488bc32..b7d2674b79 100644 --- a/modules/@angular/core/src/linker/view.ts +++ b/modules/@angular/core/src/linker/view.ts @@ -20,7 +20,7 @@ import {ElementInjector} from './element_injector'; import {ExpressionChangedAfterItHasBeenCheckedError, ViewDestroyedError, ViewWrappedError} from './errors'; import {ViewRef_} from './view_ref'; import {ViewType} from './view_type'; -import {ViewUtils, ensureSlotCount, flattenNestedViewRenderNodes} from './view_utils'; +import {ViewUtils, addToArray} from './view_utils'; var _scope_check: WtfScopeFn = wtfCreateScope(`AppView#check(ascii id)`); @@ -30,15 +30,13 @@ var _scope_check: WtfScopeFn = wtfCreateScope(`AppView#check(ascii id)`); */ export abstract class AppView { ref: ViewRef_; - rootNodesOrAppElements: any[]; + lastRootNode: any; allNodes: any[]; disposables: Function[]; viewContainerElement: AppElement = null; numberOfChecks: number = 0; - projectableNodes: Array; - renderer: Renderer; private _hasExternalHostElement: boolean; @@ -67,25 +65,9 @@ export abstract class AppView { get destroyed(): boolean { return this.cdMode === ChangeDetectorStatus.Destroyed; } - create(context: T, givenProjectableNodes: Array, rootSelectorOrNode: string|any): - AppElement { + create(context: T, rootSelectorOrNode: string|any): AppElement { this.context = context; - var projectableNodes: any[]; - switch (this.type) { - case ViewType.COMPONENT: - projectableNodes = ensureSlotCount(givenProjectableNodes, this.componentType.slotCount); - break; - case ViewType.EMBEDDED: - projectableNodes = this.declarationAppElement.parentView.projectableNodes; - break; - case ViewType.HOST: - // Note: Don't ensure the slot count for the projectableNodes as we store - // them only for the contained component view (which will later check the slot count...) - projectableNodes = givenProjectableNodes; - break; - } this._hasExternalHostElement = isPresent(rootSelectorOrNode); - this.projectableNodes = projectableNodes; return this.createInternal(rootSelectorOrNode); } @@ -95,8 +77,8 @@ export abstract class AppView { */ createInternal(rootSelectorOrNode: string|any): AppElement { return null; } - init(rootNodesOrAppElements: any[], allNodes: any[], disposables: Function[]) { - this.rootNodesOrAppElements = rootNodesOrAppElements; + init(lastRootNode: any, allNodes: any[], disposables: Function[]) { + this.lastRootNode = lastRootNode; this.allNodes = allNodes; this.disposables = disposables; if (this.type === ViewType.COMPONENT) { @@ -180,15 +162,41 @@ export abstract class AppView { return isPresent(this.declarationAppElement) ? this.declarationAppElement.parentView : null; } - get flatRootNodes(): any[] { return flattenNestedViewRenderNodes(this.rootNodesOrAppElements); } - - get lastRootNode(): any { - var lastNode = this.rootNodesOrAppElements.length > 0 ? - this.rootNodesOrAppElements[this.rootNodesOrAppElements.length - 1] : - null; - return _findLastRenderNode(lastNode); + get flatRootNodes(): any[] { + const nodes: any[] = []; + this.visitRootNodesInternal(addToArray, nodes); + return nodes; } + projectedNodes(ngContentIndex: number): any[] { + const nodes: any[] = []; + this.visitProjectedNodes(ngContentIndex, addToArray, nodes); + return nodes; + } + + visitProjectedNodes(ngContentIndex: number, cb: (node: any, ctx: C) => void, c: C): void { + const appEl = this.declarationAppElement; + switch (this.type) { + case ViewType.EMBEDDED: + appEl.parentView.visitProjectedNodes(ngContentIndex, cb, c); + break; + case ViewType.COMPONENT: + appEl.parentView.visitProjectableNodesInternal(appEl.index, ngContentIndex, cb, c); + break; + } + } + + /** + * Overwritten by implementations + */ + visitRootNodesInternal(cb: (node: any, ctx: C) => void, c: C): void {} + + /** + * Overwritten by implementations + */ + visitProjectableNodesInternal( + nodeIndex: number, ngContentIndex: number, cb: (node: any, ctx: C) => void, c: C): void {} + /** * Overwritten by implementations */ @@ -258,11 +266,10 @@ export class DebugAppView extends AppView { super(clazz, componentType, type, viewUtils, parentInjector, declarationAppElement, cdMode); } - create(context: T, givenProjectableNodes: Array, rootSelectorOrNode: string|any): - AppElement { + create(context: T, rootSelectorOrNode: string|any): AppElement { this._resetDebug(); try { - return super.create(context, givenProjectableNodes, rootSelectorOrNode); + return super.create(context, rootSelectorOrNode); } catch (e) { this._rethrowWithContext(e); throw e; @@ -339,24 +346,3 @@ export class DebugAppView extends AppView { }; } } - -function _findLastRenderNode(node: any): any { - var lastNode: any; - if (node instanceof AppElement) { - var appEl = node; - lastNode = appEl.nativeElement; - if (isPresent(appEl.nestedViews)) { - // Note: Views might have no root nodes at all! - for (var i = appEl.nestedViews.length - 1; i >= 0; i--) { - var nestedView = appEl.nestedViews[i]; - if (nestedView.rootNodesOrAppElements.length > 0) { - lastNode = _findLastRenderNode( - nestedView.rootNodesOrAppElements[nestedView.rootNodesOrAppElements.length - 1]); - } - } - } - } else { - lastNode = node; - } - return lastNode; -} diff --git a/modules/@angular/core/src/linker/view_utils.ts b/modules/@angular/core/src/linker/view_utils.ts index a88b17c4e8..083cf3daa9 100644 --- a/modules/@angular/core/src/linker/view_utils.ts +++ b/modules/@angular/core/src/linker/view_utils.ts @@ -48,44 +48,8 @@ export class ViewUtils { } } -export function flattenNestedViewRenderNodes(nodes: any[]): any[] { - return _flattenNestedViewRenderNodes(nodes, []); -} - -function _flattenNestedViewRenderNodes(nodes: any[], renderNodes: any[]): any[] { - for (var i = 0; i < nodes.length; i++) { - var node = nodes[i]; - if (node instanceof AppElement) { - var appEl = node; - renderNodes.push(appEl.nativeElement); - if (isPresent(appEl.nestedViews)) { - for (var k = 0; k < appEl.nestedViews.length; k++) { - _flattenNestedViewRenderNodes(appEl.nestedViews[k].rootNodesOrAppElements, renderNodes); - } - } - } else { - renderNodes.push(node); - } - } - return renderNodes; -} - -const EMPTY_ARR: any[] = []; - -export function ensureSlotCount(projectableNodes: any[][], expectedSlotCount: number): any[][] { - var res: any[][]; - if (!projectableNodes) { - res = EMPTY_ARR; - } else if (projectableNodes.length < expectedSlotCount) { - var givenSlotCount = projectableNodes.length; - res = new Array(expectedSlotCount); - for (var i = 0; i < expectedSlotCount; i++) { - res[i] = (i < givenSlotCount) ? projectableNodes[i] : EMPTY_ARR; - } - } else { - res = projectableNodes; - } - return res; +export function addToArray(e: any, array: any[]) { + array.push(e); } export const MAX_INTERPOLATION_VALUES = 9; diff --git a/modules/@angular/core/test/linker/projection_integration_spec.ts b/modules/@angular/core/test/linker/projection_integration_spec.ts index 206611fd2d..2f43d82200 100644 --- a/modules/@angular/core/test/linker/projection_integration_spec.ts +++ b/modules/@angular/core/test/linker/projection_integration_spec.ts @@ -7,9 +7,8 @@ */ import {Component, Directive, ElementRef, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core'; -import {getAllDebugNodes} from '@angular/core/src/debug/debug_node'; import {TestBed} from '@angular/core/testing'; -import {beforeEach, describe, it} from '@angular/core/testing/testing_internal'; +import {beforeEach, ddescribe, describe, iit, it} from '@angular/core/testing/testing_internal'; import {By} from '@angular/platform-browser/src/dom/debug/by'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {expect} from '@angular/platform-browser/testing/matchers'; @@ -236,6 +235,13 @@ export function main() { }); it('should support moving non projected light dom around', () => { + let sourceDirective: ManualViewportDirective; + + @Directive({selector: '[manual]'}) + class ManualViewportDirective { + constructor(public templateRef: TemplateRef) { sourceDirective = this; } + } + TestBed.configureTestingModule( {declarations: [Empty, ProjectDirective, ManualViewportDirective]}); TestBed.overrideComponent(MainComp, { @@ -248,17 +254,6 @@ export function main() { }); const main = TestBed.createComponent(MainComp); - var sourceDirective: any; - - // We can't use the child nodes to get a hold of this because it's not in the dom - // at - // all. - getAllDebugNodes().forEach((debug) => { - if (debug.providerTokens.indexOf(ManualViewportDirective) !== -1) { - sourceDirective = debug.injector.get(ManualViewportDirective); - } - }); - var projectDirective: ProjectDirective = main.debugElement.queryAllNodes(By.directive(ProjectDirective))[0].injector.get( ProjectDirective); 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 cfb5a54dea..29764743d7 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 @@ -43,8 +43,7 @@ class _View_TreeRootComponent_Host0 extends import1.AppView { viewFactory_TreeRootComponent0(this.viewUtils, this.injector(0), this._appEl_0); this._TreeRootComponent_0_4 = new import3.TreeRootComponent(); this._appEl_0.initComponent(this._TreeRootComponent_0_4, [], this._TreeRootComponent_0_4_View); - this._TreeRootComponent_0_4_View.create( - this._TreeRootComponent_0_4, this.projectableNodes, (null as any)); + this._TreeRootComponent_0_4_View.create(this._TreeRootComponent_0_4, (null as any)); this.init([].concat([this._el_0]), [this._el_0], []); return this._appEl_0; } @@ -147,6 +146,7 @@ class _View_TreeRootComponent1 extends import1.AppView { this._TreeComponent0_0_4View.updateData(this.parent.context.data); this._TreeComponent0_0_4View.detectChangesInternal(throwOnChange); } + visitRootNodesInternal(cb: any, context: any) { cb(this._el_0, context); } } function viewFactory_TreeRootComponent1( viewUtils: import4.ViewUtils, parentInjector: import5.Injector,