diff --git a/modules/@angular/compiler/src/view_compiler/compile_element.ts b/modules/@angular/compiler/src/view_compiler/compile_element.ts index ed3ecc1b65..2a839b1f14 100644 --- a/modules/@angular/compiler/src/view_compiler/compile_element.ts +++ b/modules/@angular/compiler/src/view_compiler/compile_element.ts @@ -42,7 +42,6 @@ export class CompileElement extends CompileNode { public compViewExpr: o.Expression = null; public viewContainer: o.ReadPropExpr; public elementRef: o.Expression; - public injector: o.Expression; public instances = new Map(); public directiveWrapperInstance = new Map(); private _resolvedProviders: Map; @@ -69,8 +68,9 @@ export class CompileElement extends CompileNode { this.elementRef = o.importExpr(resolveIdentifier(Identifiers.ElementRef)).instantiate([this.renderNode]); this.instances.set(resolveIdentifierToken(Identifiers.ElementRef).reference, this.elementRef); - this.injector = o.THIS_EXPR.callMethod('injector', [o.literal(this.nodeIndex)]); - this.instances.set(resolveIdentifierToken(Identifiers.Injector).reference, this.injector); + this.instances.set( + resolveIdentifierToken(Identifiers.Injector).reference, + o.THIS_EXPR.callMethod('injector', [o.literal(this.nodeIndex)])); this.instances.set( resolveIdentifierToken(Identifiers.Renderer).reference, o.THIS_EXPR.prop('renderer')); if (this.hasViewContainer) { @@ -115,7 +115,7 @@ export class CompileElement extends CompileNode { o.importExpr(resolveIdentifier(Identifiers.CodegenComponentFactoryResolver)).instantiate([ o.literalArr(entryComponents.map((entryComponent) => o.importExpr(entryComponent))), injectFromViewParentInjector( - resolveIdentifierToken(Identifiers.ComponentFactoryResolver), false) + this.view, resolveIdentifierToken(Identifiers.ComponentFactoryResolver), false) ]); var provider = new CompileProviderMetadata({ token: resolveIdentifierToken(Identifiers.ComponentFactoryResolver), @@ -373,7 +373,7 @@ export class CompileElement extends CompileNode { } if (!result) { - result = injectFromViewParentInjector(dep.token, dep.isOptional); + result = injectFromViewParentInjector(this.view, dep.token, dep.isOptional); } if (!result) { result = o.NULL_EXPR; diff --git a/modules/@angular/compiler/src/view_compiler/compile_pipe.ts b/modules/@angular/compiler/src/view_compiler/compile_pipe.ts index e80d4ff4f5..6c27149ffe 100644 --- a/modules/@angular/compiler/src/view_compiler/compile_pipe.ts +++ b/modules/@angular/compiler/src/view_compiler/compile_pipe.ts @@ -46,7 +46,7 @@ export class CompilePipe { resolveIdentifierToken(Identifiers.ChangeDetectorRef).reference) { return getPropertyInView(o.THIS_EXPR.prop('ref'), this.view, this.view.componentView); } - return injectFromViewParentInjector(diDep.token, false); + return injectFromViewParentInjector(view, diDep.token, false); }); this.view.fields.push(new o.ClassField(this.instance.name, o.importType(this.meta.type))); this.view.createMethod.resetDebugInfo(null, null); diff --git a/modules/@angular/compiler/src/view_compiler/constants.ts b/modules/@angular/compiler/src/view_compiler/constants.ts index 0861816ac6..e6a3b02d93 100644 --- a/modules/@angular/compiler/src/view_compiler/constants.ts +++ b/modules/@angular/compiler/src/view_compiler/constants.ts @@ -39,7 +39,6 @@ export class ChangeDetectorStatusEnum { export class ViewConstructorVars { static viewUtils = o.variable('viewUtils'); - static parentInjector = o.variable('parentInjector'); static parentView = o.variable('parentView'); static parentIndex = o.variable('parentIndex'); static parentElement = o.variable('parentElement'); diff --git a/modules/@angular/compiler/src/view_compiler/util.ts b/modules/@angular/compiler/src/view_compiler/util.ts index 6eee5101fa..ad87d8810a 100644 --- a/modules/@angular/compiler/src/view_compiler/util.ts +++ b/modules/@angular/compiler/src/view_compiler/util.ts @@ -12,6 +12,7 @@ import {createDiTokenExpression} from '../compiler_util/identifier_util'; import {isPresent} from '../facade/lang'; import {Identifiers, resolveIdentifier} from '../identifiers'; import * as o from '../output/output_ast'; +import {ViewType} from '../private_import_core'; import {CompileView} from './compile_view'; @@ -56,12 +57,18 @@ class _ReplaceViewTransformer extends o.ExpressionTransformer { } export function injectFromViewParentInjector( - token: CompileTokenMetadata, optional: boolean): o.Expression { - var args = [createDiTokenExpression(token)]; + view: CompileView, token: CompileTokenMetadata, optional: boolean): o.Expression { + let viewExpr: o.Expression; + if (view.viewType === ViewType.HOST) { + viewExpr = o.THIS_EXPR; + } else { + viewExpr = o.THIS_EXPR.prop('parentView'); + } + let args = [createDiTokenExpression(token), o.THIS_EXPR.prop('parentIndex')]; if (optional) { args.push(o.NULL_EXPR); } - return o.THIS_EXPR.prop('parentInjector').callMethod('get', args); + return viewExpr.callMethod('injectorGet', args); } export function getViewFactoryName( @@ -71,4 +78,4 @@ export function getViewFactoryName( 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 ad02c46dcc..139f8aa03e 100644 --- a/modules/@angular/compiler/src/view_compiler/view_builder.ts +++ b/modules/@angular/compiler/src/view_compiler/view_builder.ts @@ -232,12 +232,12 @@ class ViewBuilderVisitor implements TemplateAstVisitor { o.importType(resolveIdentifier(Identifiers.AppView), [o.importType(component.type)]))); this.view.viewChildren.push(compViewExpr); compileElement.setComponentView(compViewExpr); - this.view.createMethod.addStmt(compViewExpr - .set(o.importExpr(nestedComponentIdentifier).callFn([ - ViewProperties.viewUtils, compileElement.injector, - o.THIS_EXPR, o.literal(nodeIndex), renderNode - ])) - .toStmt()); + this.view.createMethod.addStmt( + compViewExpr + .set(o.importExpr(nestedComponentIdentifier).callFn([ + ViewProperties.viewUtils, o.THIS_EXPR, o.literal(nodeIndex), renderNode + ])) + .toStmt()); } compileElement.beforeChildren(); this._addRootNodeAndProject(compileElement); @@ -437,9 +437,6 @@ function createViewClass( var viewConstructorArgs = [ new o.FnParam( ViewConstructorVars.viewUtils.name, o.importType(resolveIdentifier(Identifiers.ViewUtils))), - new o.FnParam( - ViewConstructorVars.parentInjector.name, - o.importType(resolveIdentifier(Identifiers.Injector))), new o.FnParam( ViewConstructorVars.parentView.name, o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])), @@ -448,8 +445,7 @@ function createViewClass( ]; var superConstructorArgs = [ o.variable(view.className), renderCompTypeVar, ViewTypeEnum.fromValue(view.viewType), - ViewConstructorVars.viewUtils, ViewConstructorVars.parentInjector, - ViewConstructorVars.parentView, ViewConstructorVars.parentIndex, + ViewConstructorVars.viewUtils, ViewConstructorVars.parentView, ViewConstructorVars.parentIndex, ViewConstructorVars.parentElement, ChangeDetectorStatusEnum.fromValue(getChangeDetectionMode(view)) ]; @@ -507,9 +503,6 @@ function createViewFactory( var viewFactoryArgs = [ new o.FnParam( ViewConstructorVars.viewUtils.name, o.importType(resolveIdentifier(Identifiers.ViewUtils))), - new o.FnParam( - ViewConstructorVars.parentInjector.name, - o.importType(resolveIdentifier(Identifiers.Injector))), new o.FnParam( ViewConstructorVars.parentView.name, o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])), @@ -729,9 +722,7 @@ function generateCreateEmbeddedViewsMethod(view: CompileView) { stmts.push(new o.IfStmt( nodeIndexVar.equals(o.literal(node.nodeIndex)), [new o.ReturnStatement(node.embeddedView.viewFactory.callFn([ - ViewProperties.viewUtils, - o.THIS_EXPR.callMethod('injector', [o.literal(parentNodeIndex)]), o.THIS_EXPR, - o.literal(node.nodeIndex), node.renderNode + ViewProperties.viewUtils, o.THIS_EXPR, o.literal(node.nodeIndex), node.renderNode ]))])); } } diff --git a/modules/@angular/core/src/linker/component_factory.ts b/modules/@angular/core/src/linker/component_factory.ts index d154cdc2e9..190ec7c4e8 100644 --- a/modules/@angular/core/src/linker/component_factory.ts +++ b/modules/@angular/core/src/linker/component_factory.ts @@ -110,17 +110,7 @@ export class ComponentFactory { if (!projectableNodes) { projectableNodes = []; } - var hostView: AppView = this._viewFactory(vu, injector, null, null, null); - // TODO: implement this in the View class directly?! - // (behind a `if (this.type === ViewType.HOST)`) - // TODO: and pass the projectableNodes into `createHostView` - 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); - } - }; - return hostView.createHostView(rootSelectorOrNode); + var hostView: AppView = this._viewFactory(vu, null, null, null); + return hostView.createHostView(rootSelectorOrNode, injector, projectableNodes); } } diff --git a/modules/@angular/core/src/linker/element_injector.ts b/modules/@angular/core/src/linker/element_injector.ts index a736e9409b..bb7a7d53b6 100644 --- a/modules/@angular/core/src/linker/element_injector.ts +++ b/modules/@angular/core/src/linker/element_injector.ts @@ -15,13 +15,6 @@ export class ElementInjector extends Injector { constructor(private _view: AppView, private _nodeIndex: number) { super(); } get(token: any, notFoundValue: any = THROW_IF_NOT_FOUND): any { - var result = _UNDEFINED; - if (result === _UNDEFINED) { - result = this._view.injectorGet(token, this._nodeIndex, _UNDEFINED); - } - if (result === _UNDEFINED) { - result = this._view.parentInjector.get(token, notFoundValue); - } - return result; + return this._view.injectorGet(token, this._nodeIndex, notFoundValue); } } diff --git a/modules/@angular/core/src/linker/view.ts b/modules/@angular/core/src/linker/view.ts index f76a7c2891..28d8e35c62 100644 --- a/modules/@angular/core/src/linker/view.ts +++ b/modules/@angular/core/src/linker/view.ts @@ -7,7 +7,7 @@ */ import {ChangeDetectorRef, ChangeDetectorStatus} from '../change_detection/change_detection'; -import {Injector} from '../di/injector'; +import {Injector, THROW_IF_NOT_FOUND} from '../di/injector'; import {ListWrapper} from '../facade/collection'; import {isPresent} from '../facade/lang'; import {WtfScopeFn, wtfCreateScope, wtfLeave} from '../profile/profile'; @@ -30,6 +30,8 @@ var _scope_check: WtfScopeFn = wtfCreateScope(`AppView#check(ascii id)`); */ const EMPTY_CONTEXT = new Object(); +const UNDEFINED = new Object(); + /** * Cost of making objects: http://jsperf.com/instantiate-size-of-object * @@ -46,14 +48,16 @@ export abstract class AppView { renderer: Renderer; private _hasExternalHostElement: boolean; + private _hostInjector: Injector; + private _hostProjectableNodes: any[][]; private _animationContext: AnimationViewContext; public context: T; constructor( public clazz: any, public componentType: RenderComponentType, public type: ViewType, - public viewUtils: ViewUtils, public parentInjector: Injector, public parentView: AppView, - public parentIndex: number, public parentElement: any, public cdMode: ChangeDetectorStatus) { + public viewUtils: ViewUtils, public parentView: AppView, public parentIndex: number, + public parentElement: any, public cdMode: ChangeDetectorStatus) { this.ref = new ViewRef_(this); if (type === ViewType.COMPONENT || type === ViewType.HOST) { this.renderer = viewUtils.renderComponent(componentType); @@ -76,9 +80,12 @@ export abstract class AppView { return this.createInternal(null); } - createHostView(rootSelectorOrNode: string|any): ComponentRef { + createHostView(rootSelectorOrNode: string|any, hostInjector: Injector, projectableNodes: any[][]): + ComponentRef { this.context = EMPTY_CONTEXT; this._hasExternalHostElement = isPresent(rootSelectorOrNode); + this._hostInjector = hostInjector; + this._hostProjectableNodes = projectableNodes; return this.createInternal(rootSelectorOrNode); } @@ -102,8 +109,20 @@ export abstract class AppView { } } - injectorGet(token: any, nodeIndex: number, notFoundResult: any): any { - return this.injectorGetInternal(token, nodeIndex, notFoundResult); + injectorGet(token: any, nodeIndex: number, notFoundValue: any = THROW_IF_NOT_FOUND): any { + let result = UNDEFINED; + let view: AppView = this; + while (result === UNDEFINED) { + if (isPresent(nodeIndex)) { + result = view.injectorGetInternal(token, nodeIndex, UNDEFINED); + } + if (result === UNDEFINED && view.type === ViewType.HOST) { + result = view._hostInjector.get(token, notFoundValue); + } + nodeIndex = view.parentIndex; + view = view.parentView; + } + return result; } /** @@ -113,13 +132,7 @@ export abstract class AppView { return notFoundResult; } - injector(nodeIndex: number): Injector { - if (isPresent(nodeIndex)) { - return new ElementInjector(this, nodeIndex); - } else { - return this.parentInjector; - } - } + injector(nodeIndex: number): Injector { return new ElementInjector(this, nodeIndex); } detachAndDestroy() { if (this._hasExternalHostElement) { @@ -193,7 +206,14 @@ export abstract class AppView { this.parentView.visitProjectedNodes(ngContentIndex, cb, c); break; case ViewType.COMPONENT: - this.parentView.visitProjectableNodesInternal(this.parentIndex, ngContentIndex, cb, c); + if (this.parentView.type === ViewType.HOST) { + const nodes = this.parentView._hostProjectableNodes[ngContentIndex] || []; + for (var i = 0; i < nodes.length; i++) { + cb(nodes[i], c); + } + } else { + this.parentView.visitProjectableNodesInternal(this.parentIndex, ngContentIndex, cb, c); + } break; } } @@ -275,11 +295,9 @@ export class DebugAppView extends AppView { constructor( clazz: any, componentType: RenderComponentType, type: ViewType, viewUtils: ViewUtils, - parentInjector: Injector, parentView: AppView, parentIndex: number, parentNode: any, - cdMode: ChangeDetectorStatus, public staticNodeDebugInfos: StaticNodeDebugInfo[]) { - super( - clazz, componentType, type, viewUtils, parentInjector, parentView, parentIndex, parentNode, - cdMode); + parentView: AppView, parentIndex: number, parentNode: any, cdMode: ChangeDetectorStatus, + public staticNodeDebugInfos: StaticNodeDebugInfo[]) { + super(clazz, componentType, type, viewUtils, parentView, parentIndex, parentNode, cdMode); } create(context: T) { @@ -292,10 +310,12 @@ export class DebugAppView extends AppView { } } - createHostView(rootSelectorOrNode: string|any): ComponentRef { + createHostView( + rootSelectorOrNode: string|any, injector: Injector, + projectableNodes: any[][] = null): ComponentRef { this._resetDebug(); try { - return super.createHostView(rootSelectorOrNode); + return super.createHostView(rootSelectorOrNode, injector, projectableNodes); } catch (e) { this._rethrowWithContext(e); throw e; diff --git a/modules/benchmarks/src/tree/ng2_ftl/tree_host.ngfactory.ts b/modules/benchmarks/src/tree/ng2_ftl/tree_host.ngfactory.ts index 0ad8675955..bce4e1cecb 100644 --- a/modules/benchmarks/src/tree/ng2_ftl/tree_host.ngfactory.ts +++ b/modules/benchmarks/src/tree/ng2_ftl/tree_host.ngfactory.ts @@ -26,12 +26,11 @@ class _View_TreeComponent_Host0 extends import1.AppView { _vc_0: import2.ViewContainer; _TreeComponent_0_4: _View_TreeComponent0; constructor( - viewUtils: import4.ViewUtils, parentInjector: import5.Injector, - parentView: import1.AppView, parentIndex: number, parentElement: any) { + viewUtils: import4.ViewUtils, parentView: import1.AppView, parentIndex: number, + parentElement: any) { super( _View_TreeComponent_Host0, renderType_TreeComponent_Host, import6.ViewType.HOST, viewUtils, - parentInjector, parentView, parentIndex, parentElement, - import7.ChangeDetectorStatus.CheckAlways); + parentView, parentIndex, parentElement, import7.ChangeDetectorStatus.CheckAlways); } createInternal(rootSelector: string): import9.ComponentRef { this._el_0 = import4.selectOrCreateRenderHostElement( @@ -53,15 +52,13 @@ class _View_TreeComponent_Host0 extends import1.AppView { } } function viewFactory_TreeComponent_Host0( - viewUtils: import4.ViewUtils, parentInjector: import5.Injector, - parentView: import1.AppView, parentIndex: number, + viewUtils: import4.ViewUtils, parentView: import1.AppView, parentIndex: number, parentElement: any): import1.AppView { if ((renderType_TreeComponent_Host === (null as any))) { (renderType_TreeComponent_Host = viewUtils.createRenderComponentType('', 0, import8.ViewEncapsulation.None, [], {})); } - return new _View_TreeComponent_Host0( - viewUtils, parentInjector, parentView, parentIndex, parentElement); + return new _View_TreeComponent_Host0(viewUtils, parentView, parentIndex, parentElement); } export const TreeComponentNgFactory: import9.ComponentFactory = new import9.ComponentFactory( 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 8878f71df2..ea2009206a 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 @@ -29,11 +29,11 @@ class _View_TreeRootComponent_Host0 extends import1.AppView { _TreeRootComponent_0_4: import3.TreeRootComponent; _TreeRootComponent_0_4_View: any; constructor( - viewUtils: import4.ViewUtils, parentInjector: import5.Injector, - parentView: import1.AppView, parentIndex: number, parentElement: any) { + viewUtils: import4.ViewUtils, parentView: import1.AppView, parentIndex: number, + parentElement: any) { super( _View_TreeRootComponent_Host0, renderType_TreeRootComponent_Host, import6.ViewType.HOST, - viewUtils, parentInjector, parentView, parentIndex, parentElement, + viewUtils, parentView, parentIndex, parentElement, import7.ChangeDetectorStatus.CheckAlways); } createInternal(rootSelector: string): import9.ComponentRef { @@ -41,7 +41,7 @@ class _View_TreeRootComponent_Host0 extends import1.AppView { this.renderer, 'tree', import4.EMPTY_INLINE_ARRAY, rootSelector, (null as any)); this._appEl_0 = new import2.ViewContainer(0, (null as any), this, this._el_0); this._TreeRootComponent_0_4_View = - viewFactory_TreeRootComponent0(this.viewUtils, this.injector(0), this, 0, this._el_0); + viewFactory_TreeRootComponent0(this.viewUtils, this, 0, this._el_0); this._TreeRootComponent_0_4 = new import3.TreeRootComponent(); this._TreeRootComponent_0_4_View.create(this._TreeRootComponent_0_4, (null as any)); this.init([].concat([this._el_0]), [this._el_0], []); @@ -59,15 +59,13 @@ class _View_TreeRootComponent_Host0 extends import1.AppView { } } function viewFactory_TreeRootComponent_Host0( - viewUtils: import4.ViewUtils, parentInjector: import5.Injector, - parentView: import1.AppView, parentIndex: number, + viewUtils: import4.ViewUtils, parentView: import1.AppView, parentIndex: number, parentElement: any): import1.AppView { if ((renderType_TreeRootComponent_Host === (null as any))) { (renderType_TreeRootComponent_Host = viewUtils.createRenderComponentType('', 0, import8.ViewEncapsulation.None, [], {})); } - return new _View_TreeRootComponent_Host0( - viewUtils, parentInjector, parentView, parentIndex, parentElement); + return new _View_TreeRootComponent_Host0(viewUtils, parentView, parentIndex, parentElement); } export const TreeRootComponentNgFactory: import9.ComponentFactory = new import9.ComponentFactory( @@ -81,11 +79,11 @@ class _View_TreeRootComponent0 extends import1.AppView, parentIndex: number, parentElement: any) { + viewUtils: import4.ViewUtils, parentView: import1.AppView, parentIndex: number, + parentElement: any) { super( _View_TreeRootComponent0, renderType_TreeRootComponent, import6.ViewType.COMPONENT, - viewUtils, parentInjector, parentView, parentIndex, parentElement, + viewUtils, parentView, parentIndex, parentElement, import7.ChangeDetectorStatus.CheckAlways); } createInternal(rootSelector: string): import9.ComponentRef { @@ -101,8 +99,7 @@ class _View_TreeRootComponent0 extends import1.AppView { if (nodeIndex === 0) { - return viewFactory_TreeRootComponent1( - this.viewUtils, this.parentInjector, this, 0, this._anchor_0); + return viewFactory_TreeRootComponent1(this.viewUtils, this, 0, this._anchor_0); } } @@ -125,26 +122,24 @@ class _View_TreeRootComponent0 extends import1.AppView, parentIndex: number, + viewUtils: import4.ViewUtils, parentView: import1.AppView, parentIndex: number, parentElement: any): import1.AppView { if ((renderType_TreeRootComponent === (null as any))) { (renderType_TreeRootComponent = viewUtils.createRenderComponentType( '/Users/tbosch/projects/conf-demos/ngc-demo/src/ng2_static/root_tree.ts class TreeRootComponent - inline template', 0, import8.ViewEncapsulation.None, styles_TreeRootComponent, {})); } - return new _View_TreeRootComponent0( - viewUtils, parentInjector, parentView, parentIndex, parentElement); + return new _View_TreeRootComponent0(viewUtils, parentView, parentIndex, parentElement); } class _View_TreeRootComponent1 extends import1.AppView { _el_0: any; _TreeComponent0_0_4View: any; constructor( - viewUtils: import4.ViewUtils, parentInjector: import5.Injector, - parentView: import1.AppView, parentIndex: number, parentElement: any) { + viewUtils: import4.ViewUtils, parentView: import1.AppView, parentIndex: number, + parentElement: any) { super( _View_TreeRootComponent1, renderType_TreeRootComponent, import6.ViewType.EMBEDDED, - viewUtils, parentInjector, parentView, parentIndex, parentElement, + viewUtils, parentView, parentIndex, parentElement, import7.ChangeDetectorStatus.CheckAlways); } createInternal(rootSelector: string): import9.ComponentRef { @@ -161,9 +156,7 @@ class _View_TreeRootComponent1 extends import1.AppView { visitRootNodesInternal(cb: any, context: any) { cb(this._el_0, context); } } function viewFactory_TreeRootComponent1( - viewUtils: import4.ViewUtils, parentInjector: import5.Injector, - parentView: import1.AppView, parentIndex: number, + viewUtils: import4.ViewUtils, parentView: import1.AppView, parentIndex: number, parentElement: any): import1.AppView { - return new _View_TreeRootComponent1( - viewUtils, parentInjector, parentView, parentIndex, parentElement); + return new _View_TreeRootComponent1(viewUtils, parentView, parentIndex, parentElement); } \ No newline at end of file