Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions modules/angular2/platform/testing/browser_static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {MockNgZone} from 'angular2/src/mock/ng_zone_mock';
import {XHRImpl} from "angular2/src/platform/browser/xhr_impl";
import {XHR} from 'angular2/compiler';

import {TestComponentBuilder} from 'angular2/src/testing/test_component_builder';
import {TEST_COMPONENT_BUILDER_PROVIDERS} from 'angular2/src/testing/test_component_builder';

import {BrowserDetection} from 'angular2/src/testing/utils';

Expand Down Expand Up @@ -52,7 +52,7 @@ export const ADDITIONAL_TEST_BROWSER_PROVIDERS: Array<any /*Type | Provider | an
new Provider(DirectiveResolver, {useClass: MockDirectiveResolver}),
new Provider(ViewResolver, {useClass: MockViewResolver}),
Log,
TestComponentBuilder,
TEST_COMPONENT_BUILDER_PROVIDERS,
new Provider(NgZone, {useClass: MockNgZone}),
new Provider(LocationStrategy, {useClass: MockLocationStrategy}),
new Provider(AnimationBuilder, {useClass: MockAnimationBuilder}),
Expand Down
4 changes: 2 additions & 2 deletions modules/angular2/platform/testing/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {MockLocationStrategy} from 'angular2/src/mock/mock_location_strategy';
import {LocationStrategy} from 'angular2/src/router/location_strategy';
import {MockNgZone} from 'angular2/src/mock/ng_zone_mock';

import {TestComponentBuilder} from 'angular2/src/testing/test_component_builder';
import {TEST_COMPONENT_BUILDER_PROVIDERS} from 'angular2/src/testing/test_component_builder';
import {XHR} from 'angular2/src/compiler/xhr';
import {BrowserDetection} from 'angular2/src/testing/utils';

Expand Down Expand Up @@ -83,7 +83,7 @@ export const TEST_SERVER_APPLICATION_PROVIDERS: Array<any /*Type | Provider | an
new Provider(DirectiveResolver, {useClass: MockDirectiveResolver}),
new Provider(ViewResolver, {useClass: MockViewResolver}),
Log,
TestComponentBuilder,
TEST_COMPONENT_BUILDER_PROVIDERS,
new Provider(NgZone, {useClass: MockNgZone}),
new Provider(LocationStrategy, {useClass: MockLocationStrategy}),
new Provider(AnimationBuilder, {useClass: MockAnimationBuilder}),
Expand Down
6 changes: 3 additions & 3 deletions modules/angular2/src/compiler/proto_view_compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,12 +365,12 @@ function keyValueArrayToStringMap(keyValueArray: any[][]): {[key: string]: any}
}

function codeGenDirectivesArray(directives: CompileDirectiveMetadata[]): string {
var expressions = directives.map(directiveType => typeRef(directiveType.type));
var expressions = directives.map(directiveType => codeGenType(directiveType.type));
return `[${expressions.join(',')}]`;
}

function codeGenTypesArray(types: CompileTypeMetadata[]): string {
var expressions = types.map(typeRef);
var expressions = types.map(codeGenType);
return `[${expressions.join(',')}]`;
}

Expand All @@ -382,7 +382,7 @@ function codeGenViewType(value: ViewType): string {
}
}

function typeRef(type: CompileTypeMetadata): string {
export function codeGenType(type: CompileTypeMetadata): string {
return `${moduleRef(type.moduleUrl)}${type.name}`;
}

Expand Down
16 changes: 10 additions & 6 deletions modules/angular2/src/compiler/template_compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,12 @@ export class TemplateCompiler {
this._compileComponentRuntime(hostCacheKey, hostMeta, [compMeta], [], []);
}
return this._compiledTemplateDone.get(hostCacheKey)
.then((compiledTemplate: CompiledTemplate) =>
new HostViewFactory(compMeta.selector, compiledTemplate.viewFactory));
.then((hostCompiledTemplate) => {
return this._compiledTemplateDone.get(type).then((componentCompiledTemplate) => {
return new HostViewFactory(compMeta.selector, hostCompiledTemplate.viewFactory,
componentCompiledTemplate.viewFactory);
});
});
}

clearCache() {
Expand All @@ -146,15 +150,15 @@ export class TemplateCompiler {
components.forEach(componentWithDirs => {
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
assertComponent(compMeta);
this._compileComponentCodeGen(compMeta, componentWithDirs.directives, componentWithDirs.pipes,
declarations);
var componentViewFactoryExpression = this._compileComponentCodeGen(
compMeta, componentWithDirs.directives, componentWithDirs.pipes, declarations);
if (compMeta.dynamicLoadable) {
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
var viewFactoryExpression =
var hostViewFactoryExpression =
this._compileComponentCodeGen(hostMeta, [compMeta], [], declarations);
var constructionKeyword = IS_DART ? 'const' : 'new';
var compiledTemplateExpr =
`${constructionKeyword} ${APP_VIEW_MODULE_REF}HostViewFactory('${compMeta.selector}',${viewFactoryExpression})`;
`${constructionKeyword} ${APP_VIEW_MODULE_REF}HostViewFactory('${compMeta.selector}',${hostViewFactoryExpression},${componentViewFactoryExpression})`;
var varName = codeGenHostViewFactoryName(compMeta.type);
declarations.push(`${codeGenExportVariable(varName)}${compiledTemplateExpr};`);
}
Expand Down
19 changes: 15 additions & 4 deletions modules/angular2/src/compiler/view_compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
isString,
StringWrapper,
IS_DART,
CONST_EXPR
CONST_EXPR,
assertionsEnabled
} from 'angular2/src/facade/lang';
import {SetWrapper, StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {
Expand Down Expand Up @@ -58,7 +59,8 @@ import {
APP_EL_MODULE_REF,
METADATA_MODULE_REF,
CompileProtoView,
CompileProtoElement
CompileProtoElement,
codeGenType
} from './proto_view_compiler';

export const VIEW_JIT_IMPORTS = CONST_EXPR({
Expand Down Expand Up @@ -227,15 +229,20 @@ class CodeGenViewFactory implements ViewFactory<Expression, Statement> {
appEl: Expression, component: CompileDirectiveMetadata,
contentNodesByNgContentIndex: Expression[][],
targetStatements: Statement[]) {
var viewFactoryExpr = this.componentViewFactory(component);
var codeGenContentNodes;
if (this.component.type.isHost) {
codeGenContentNodes = `${view.expression}.projectableNodes`;
} else {
codeGenContentNodes =
`[${contentNodesByNgContentIndex.map( nodes => codeGenFlatArray(nodes) ).join(',')}]`;
if (assertionsEnabled()) {
viewFactoryExpr =
`viewManager.getComponentViewFactory(${codeGenType(component.type)}, ${viewFactoryExpr})`;
}
}
targetStatements.push(new Statement(
`${this.componentViewFactory(component)}(${renderer.expression}, ${viewManager.expression}, ${appEl.expression}, ${codeGenContentNodes}, null, null, null);`));
`${viewFactoryExpr}(${renderer.expression}, ${viewManager.expression}, ${appEl.expression}, ${codeGenContentNodes}, null, null, null);`));
}

getProjectedNodes(projectableNodes: Expression, ngContentIndex: number): Expression {
Expand Down Expand Up @@ -366,15 +373,19 @@ class RuntimeViewFactory implements ViewFactory<any, any> {
contentNodesByNgContentIndex: Array<Array<any | any[]>>,
targetStatements: any[]) {
var flattenedContentNodes;
var viewFactory = this.componentViewFactory(component);
if (this.component.type.isHost) {
flattenedContentNodes = appView.projectableNodes;
} else {
flattenedContentNodes = ListWrapper.createFixedSize(contentNodesByNgContentIndex.length);
for (var i = 0; i < contentNodesByNgContentIndex.length; i++) {
flattenedContentNodes[i] = flattenArray(contentNodesByNgContentIndex[i], []);
}
if (assertionsEnabled()) {
viewFactory = viewManager.getComponentViewFactory(component.type.runtime, viewFactory);
}
}
this.componentViewFactory(component)(renderer, viewManager, appEl, flattenedContentNodes);
viewFactory(renderer, viewManager, appEl, flattenedContentNodes);
}

getProjectedNodes(projectableNodes: any[][], ngContentIndex: number): any[] {
Expand Down
3 changes: 2 additions & 1 deletion modules/angular2/src/core/application_common_providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {ResolvedMetadataCache} from 'angular2/src/core/linker/resolved_metadata_
import {AppViewManager} from './linker/view_manager';
import {AppViewManager_} from "./linker/view_manager";
import {ViewResolver} from './linker/view_resolver';
import {AppViewListener} from './linker/view_listener';
import {AppViewListener, ViewFactoryProxy} from './linker/view_listener';
import {DirectiveResolver} from './linker/directive_resolver';
import {PipeResolver} from './linker/pipe_resolver';
import {Compiler} from './linker/compiler';
Expand All @@ -33,6 +33,7 @@ export const APPLICATION_COMMON_PROVIDERS: Array<Type | Provider | any[]> = CONS
ResolvedMetadataCache,
new Provider(AppViewManager, {useClass: AppViewManager_}),
AppViewListener,
ViewFactoryProxy,
ViewResolver,
new Provider(IterableDiffers, {useValue: defaultIterableDiffers}),
new Provider(KeyValueDiffers, {useValue: defaultKeyValueDiffers}),
Expand Down
3 changes: 2 additions & 1 deletion modules/angular2/src/core/linker/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,8 @@ export class AppProtoView {

@CONST()
export class HostViewFactory {
constructor(public selector: string, public viewFactory: Function) {}
constructor(public selector: string, public viewFactory: Function,
public componentViewFactory: Function) {}
}

export function flattenNestedViewRenderNodes(nodes: any[]): any[] {
Expand Down
13 changes: 13 additions & 0 deletions modules/angular2/src/core/linker/view_listener.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Injectable} from 'angular2/src/core/di';
import {Type} from 'angular2/src/facade/lang';
import * as viewModule from './view';

/**
Expand All @@ -9,3 +10,15 @@ export class AppViewListener {
onViewCreated(view: viewModule.AppView) {}
onViewDestroyed(view: viewModule.AppView) {}
}

/**
* Proxy that allows to intercept component view factories.
* This also works for precompiled templates, if they were
* generated in development mode.
*/
@Injectable()
export class ViewFactoryProxy {
getComponentViewFactory(component: Type, originalViewFactory: Function): Function {
return originalViewFactory;
}
}
15 changes: 11 additions & 4 deletions modules/angular2/src/core/linker/view_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import {
Provider,
Injectable,
ResolvedProvider,
forwardRef
forwardRef,
OpaqueToken,
Optional
} from 'angular2/src/core/di';
import {isPresent, isBlank, isArray} from 'angular2/src/facade/lang';
import {isPresent, isBlank, isArray, Type, CONST_EXPR} from 'angular2/src/facade/lang';
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {BaseException} from 'angular2/src/facade/exceptions';
import {AppView, HostViewFactory, flattenNestedViewRenderNodes} from './view';
Expand All @@ -22,7 +24,7 @@ import {
} from './view_ref';
import {ViewContainerRef} from './view_container_ref';
import {TemplateRef, TemplateRef_} from './template_ref';
import {AppViewListener} from './view_listener';
import {AppViewListener, ViewFactoryProxy} from './view_listener';
import {RootRenderer, RenderComponentType} from 'angular2/src/core/render/api';
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
import {APP_ID} from 'angular2/src/core/application_tokens';
Expand Down Expand Up @@ -186,7 +188,7 @@ export class AppViewManager_ extends AppViewManager {
private _nextCompTypeId: number = 0;

constructor(private _renderer: RootRenderer, private _viewListener: AppViewListener,
@Inject(APP_ID) private _appId: string) {
private _viewFactoryProxy: ViewFactoryProxy, @Inject(APP_ID) private _appId: string) {
super();
}

Expand Down Expand Up @@ -328,6 +330,11 @@ export class AppViewManager_ extends AppViewManager {
styles);
}

/** @internal */
getComponentViewFactory(component: Type, originalViewFactory: Function): Function {
return this._viewFactoryProxy.getComponentViewFactory(component, originalViewFactory);
}

private _attachViewToContainer(view: AppView, vcAppElement: AppElement, viewIndex: number) {
if (view.proto.type === ViewType.COMPONENT) {
throw new BaseException(`Component views can't be moved!`);
Expand Down
77 changes: 66 additions & 11 deletions modules/angular2/src/testing/test_component_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import {
ViewMetadata,
EmbeddedViewRef,
ViewResolver,
provide
provide,
Provider
} from 'angular2/core';

import {Type, isPresent, isBlank} from 'angular2/src/facade/lang';
import {Promise} from 'angular2/src/facade/async';
import {Type, isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
import {ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
import {Compiler, Compiler_} from 'angular2/src/core/linker/compiler';
import {ViewFactoryProxy} from 'angular2/src/core/linker/view_listener';

import {ViewRef_} from 'angular2/src/core/linker/view_ref';
import {ViewRef_, HostViewFactoryRef_} from 'angular2/src/core/linker/view_ref';
import {AppView} from 'angular2/src/core/linker/view';

import {el} from './utils';
Expand All @@ -25,7 +28,6 @@ import {DOM} from 'angular2/src/platform/dom/dom_adapter';

import {DebugElement_} from 'angular2/src/core/debug/debug_element';


/**
* Fixture for debugging and testing a component.
*/
Expand Down Expand Up @@ -82,6 +84,20 @@ export class ComponentFixture_ extends ComponentFixture {

var _nextRootElementId = 0;

@Injectable()
export class TestViewFactoryProxy implements ViewFactoryProxy {
private _componentFactoryOverrides: Map<Type, Function> = new Map<Type, Function>();

getComponentViewFactory(component: Type, originalViewFactory: Function): Function {
var override = this._componentFactoryOverrides.get(component);
return isPresent(override) ? override : originalViewFactory;
}

setComponentViewFactory(component: Type, viewFactory: Function) {
this._componentFactoryOverrides.set(component, viewFactory);
}
}

/**
* Builds a ComponentFixture for use in component level tests.
*/
Expand All @@ -97,7 +113,8 @@ export class TestComponentBuilder {
_viewBindingsOverrides = new Map<Type, any[]>();
/** @internal */
_viewOverrides = new Map<Type, ViewMetadata>();

/** @internal */
_componentOverrides = new Map<Type, Type>();

constructor(private _injector: Injector) {}

Expand All @@ -107,6 +124,23 @@ export class TestComponentBuilder {
clone._viewOverrides = MapWrapper.clone(this._viewOverrides);
clone._directiveOverrides = MapWrapper.clone(this._directiveOverrides);
clone._templateOverrides = MapWrapper.clone(this._templateOverrides);
clone._componentOverrides = MapWrapper.clone(this._componentOverrides);
return clone;
}

/**
* Overrides a component with another component.
* This also works with precompiled templates if they were generated
* in development mode.
*
* @param {Type} original component
* @param {Type} mock component
*
* @return {TestComponentBuilder}
*/
overrideComponent(componentType: Type, mockType: Type): TestComponentBuilder {
var clone = this._clone();
clone._componentOverrides.set(componentType, mockType);
return clone;
}

Expand Down Expand Up @@ -246,10 +280,31 @@ export class TestComponentBuilder {
DOM.remove(oldRoots[i]);
}
DOM.appendChild(doc.body, rootEl);


return this._injector.get(DynamicComponentLoader)
.loadAsRoot(rootComponentType, `#${rootElId}`, this._injector)
.then((componentRef) => { return new ComponentFixture_(componentRef); });
var originalCompTypes = [];
var mockHostViewFactoryPromises = [];
var compiler: Compiler_ = this._injector.get(Compiler);
var viewFactoryProxy: TestViewFactoryProxy = this._injector.get(TestViewFactoryProxy);
this._componentOverrides.forEach((mockCompType, originalCompType) => {
originalCompTypes.push(originalCompType);
mockHostViewFactoryPromises.push(compiler.compileInHost(mockCompType));
});
return PromiseWrapper.all(mockHostViewFactoryPromises)
.then((mockHostViewFactories: HostViewFactoryRef_[]) => {
for (var i = 0; i < mockHostViewFactories.length; i++) {
var originalCompType = originalCompTypes[i];
viewFactoryProxy.setComponentViewFactory(
originalCompType,
mockHostViewFactories[i].internalHostViewFactory.componentViewFactory);
}
return this._injector.get(DynamicComponentLoader)
.loadAsRoot(rootComponentType, `#${rootElId}`, this._injector)
.then((componentRef) => { return new ComponentFixture_(componentRef); });
});
}
}

export const TEST_COMPONENT_BUILDER_PROVIDERS = CONST_EXPR([
TestViewFactoryProxy,
CONST_EXPR(new Provider(ViewFactoryProxy, {useExisting: TestViewFactoryProxy})),
TestComponentBuilder
]);
2 changes: 1 addition & 1 deletion modules/angular2/test/compiler/runtime_compiler_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function main() {

beforeEachProviders(() => {
templateCompilerSpy = new SpyTemplateCompiler();
someHostViewFactory = new HostViewFactory(null, null);
someHostViewFactory = new HostViewFactory(null, null, null);
templateCompilerSpy.spy('compileHostComponentRuntime')
.andReturn(PromiseWrapper.resolve(someHostViewFactory));
return [provide(TemplateCompiler, {useValue: templateCompilerSpy})];
Expand Down
1 change: 1 addition & 0 deletions modules/angular2/test/compiler/template_compiler_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ export function humanizeViewFactory(
cachedResults = new Map<AppProtoView, any>();
}
var viewManager = new SpyAppViewManager();
viewManager.spy('getComponentViewFactory').andCallFake((component, viewFactory) => viewFactory);
viewManager.spy('createRenderComponentType')
.andCallFake((encapsulation: ViewEncapsulation, styles: Array<string | any[]>) => {
return new RenderComponentType('someId', encapsulation, styles);
Expand Down
2 changes: 1 addition & 1 deletion modules/angular2/test/core/linker/compiler_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function main() {
beforeEachProviders(() => [provide(Compiler, {useClass: Compiler_})]);

beforeEach(inject([Compiler], (_compiler) => {
someHostViewFactory = new HostViewFactory(null, null);
someHostViewFactory = new HostViewFactory(null, null, null);
reflector.registerType(SomeComponent, new ReflectionInfo([someHostViewFactory]));
}));

Expand Down
Loading