refactor(core): remove `ViewResolver` and `ViewResolverMock`

The methods on `ViewResolverMock` have been merged into `DirectiveResolver`.

BREAKING CHANGE:
- ES5 users can no longer use the `View(…)` function to provide `ViewMetadata`.
  This mirrors the removal of the `@View` decorator a while ago.
This commit is contained in:
Tobias Bosch 2016-07-28 06:31:26 -07:00
parent 20b03bad11
commit 0988cc82b0
25 changed files with 308 additions and 535 deletions

View File

@ -143,8 +143,7 @@ export class CodeGenerator {
const resolver = new CompileMetadataResolver(
new compiler.NgModuleResolver(staticReflector),
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
new compiler.ViewResolver(staticReflector), config, console, elementSchemaRegistry,
staticReflector);
config, console, elementSchemaRegistry, staticReflector);
const offlineCompiler = new compiler.OfflineCompiler(
resolver, normalizer, tmplParser, new StyleCompiler(urlResolver), new ViewCompiler(config),
new NgModuleCompiler(), new TypeScriptEmitter(reflectorHost));

View File

@ -152,8 +152,7 @@ class Extractor {
const resolver = new CompileMetadataResolver(
new compiler.NgModuleResolver(staticReflector),
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
new compiler.ViewResolver(staticReflector), config, console, elementSchemaRegistry,
staticReflector);
config, console, elementSchemaRegistry, staticReflector);
// TODO(vicb): handle implicit
const extractor = new MessageExtractor(htmlParser, expressionParser, [], {});

View File

@ -11,7 +11,7 @@
* @description
* Starting point to import all compiler APIs.
*/
export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, NgModuleResolver, OfflineCompiler, PipeResolver, RenderTypes, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, ViewResolver, XHR, analyzeAppProvidersForDeprecatedConfiguration, createOfflineCompileUrlResolver, platformCoreDynamic} from './src/compiler';
export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, NgModuleResolver, OfflineCompiler, PipeResolver, RenderTypes, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, XHR, analyzeAppProvidersForDeprecatedConfiguration, createOfflineCompileUrlResolver, platformCoreDynamic} from './src/compiler';
export {ElementSchemaRegistry} from './src/schema/element_schema_registry';
export * from './src/template_ast';

View File

@ -406,7 +406,8 @@ export class CompileTemplateMetadata {
export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
static create(
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
lifecycleHooks, providers, viewProviders, queries, viewQueries, entryComponents, template}: {
lifecycleHooks, providers, viewProviders, queries, viewQueries, entryComponents,
viewDirectives, viewPipes, template}: {
type?: CompileTypeMetadata,
isComponent?: boolean,
selector?: string,
@ -423,6 +424,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
queries?: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[],
entryComponents?: CompileTypeMetadata[],
viewDirectives?: CompileTypeMetadata[],
viewPipes?: CompileTypeMetadata[],
template?: CompileTemplateMetadata
} = {}): CompileDirectiveMetadata {
var hostListeners: {[key: string]: string} = {};
@ -472,6 +475,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
queries,
viewQueries,
entryComponents,
viewDirectives,
viewPipes,
template,
});
}
@ -492,12 +497,17 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
viewQueries: CompileQueryMetadata[];
// Note: Need to keep types here to prevent cycles!
entryComponents: CompileTypeMetadata[];
// Note: Need to keep types here to prevent cycles!
viewDirectives: CompileTypeMetadata[];
// Note: Need to keep types here to prevent cycles!
viewPipes: CompileTypeMetadata[];
template: CompileTemplateMetadata;
constructor(
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, hostListeners,
hostProperties, hostAttributes, lifecycleHooks, providers, viewProviders, queries,
viewQueries, entryComponents, template}: {
viewQueries, entryComponents, viewDirectives, viewPipes, template}: {
type?: CompileTypeMetadata,
isComponent?: boolean,
selector?: string,
@ -516,6 +526,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
queries?: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[],
entryComponents?: CompileTypeMetadata[],
viewDirectives?: CompileTypeMetadata[],
viewPipes?: CompileTypeMetadata[],
template?: CompileTemplateMetadata,
} = {}) {
this.type = type;
@ -534,6 +546,9 @@ export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
this.queries = _normalizeArray(queries);
this.viewQueries = _normalizeArray(viewQueries);
this.entryComponents = _normalizeArray(entryComponents);
this.viewDirectives = _normalizeArray(viewDirectives);
this.viewPipes = _normalizeArray(viewPipes);
this.template = template;
}

View File

@ -17,7 +17,6 @@ export {RuntimeCompiler} from './runtime_compiler';
export * from './url_resolver';
export * from './xhr';
export {ViewResolver} from './view_resolver';
export {DirectiveResolver} from './directive_resolver';
export {PipeResolver} from './pipe_resolver';
export {NgModuleResolver} from './ng_module_resolver';
@ -38,7 +37,6 @@ import {DomElementSchemaRegistry} from './schema/dom_element_schema_registry';
import {UrlResolver, DEFAULT_PACKAGE_URL_PROVIDER} from './url_resolver';
import {Parser} from './expression_parser/parser';
import {Lexer} from './expression_parser/lexer';
import {ViewResolver} from './view_resolver';
import {DirectiveResolver} from './directive_resolver';
import {PipeResolver} from './pipe_resolver';
import {NgModuleResolver} from './ng_module_resolver';
@ -76,7 +74,6 @@ export const COMPILER_PROVIDERS: Array<any|Type|{[k: string]: any}|any[]> =
DomElementSchemaRegistry,
/*@ts2dart_Provider*/ {provide: ElementSchemaRegistry, useExisting: DomElementSchemaRegistry},
UrlResolver,
ViewResolver,
DirectiveResolver,
PipeResolver,
NgModuleResolver

View File

@ -143,7 +143,16 @@ export class DirectiveResolver {
changeDetection: dm.changeDetection,
providers: dm.providers,
viewProviders: dm.viewProviders,
entryComponents: dm.entryComponents
entryComponents: dm.entryComponents,
directives: dm.directives,
pipes: dm.pipes,
template: dm.template,
templateUrl: dm.templateUrl,
styles: dm.styles,
styleUrls: dm.styleUrls,
encapsulation: dm.encapsulation,
animations: dm.animations,
interpolation: dm.interpolation
});
} else {

View File

@ -24,7 +24,6 @@ import {PipeResolver} from './pipe_resolver';
import {ElementSchemaRegistry} from './schema/element_schema_registry';
import {getUrlScheme} from './url_resolver';
import {MODULE_SUFFIX, ValueTransformer, sanitizeIdentifier, visitValue} from './util';
import {ViewResolver} from './view_resolver';
@Injectable()
export class CompileMetadataResolver {
@ -37,10 +36,8 @@ export class CompileMetadataResolver {
constructor(
private _ngModuleResolver: NgModuleResolver, private _directiveResolver: DirectiveResolver,
private _pipeResolver: PipeResolver, private _viewResolver: ViewResolver,
private _config: CompilerConfig, private _console: Console,
private _schemaRegistry: ElementSchemaRegistry,
private _reflector: ReflectorReader = reflector) {}
private _pipeResolver: PipeResolver, private _config: CompilerConfig,
private _console: Console, private _schemaRegistry: ElementSchemaRegistry, private _reflector: ReflectorReader = reflector) {}
private sanitizeTokenName(token: any): string {
let identifier = stringify(token);
@ -125,27 +122,28 @@ export class CompileMetadataResolver {
var changeDetectionStrategy: ChangeDetectionStrategy = null;
var viewProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = [];
var moduleUrl = staticTypeModuleUrl(directiveType);
var viewDirectiveTypes: cpl.CompileTypeMetadata[] = [];
var viewPipeTypes: cpl.CompileTypeMetadata[] = [];
var entryComponentTypes: cpl.CompileTypeMetadata[] = [];
let selector = dirMeta.selector;
if (dirMeta instanceof ComponentMetadata) {
var cmpMeta = <ComponentMetadata>dirMeta;
var viewMeta = this._viewResolver.resolve(directiveType);
assertArrayOfStrings('styles', viewMeta.styles);
assertInterpolationSymbols('interpolation', viewMeta.interpolation);
var animations = isPresent(viewMeta.animations) ?
viewMeta.animations.map(e => this.getAnimationEntryMetadata(e)) :
assertArrayOfStrings('styles', cmpMeta.styles);
assertInterpolationSymbols('interpolation', cmpMeta.interpolation);
var animations = isPresent(cmpMeta.animations) ?
cmpMeta.animations.map(e => this.getAnimationEntryMetadata(e)) :
null;
assertArrayOfStrings('styles', viewMeta.styles);
assertArrayOfStrings('styleUrls', viewMeta.styleUrls);
assertArrayOfStrings('styles', cmpMeta.styles);
assertArrayOfStrings('styleUrls', cmpMeta.styleUrls);
templateMeta = new cpl.CompileTemplateMetadata({
encapsulation: viewMeta.encapsulation,
template: viewMeta.template,
templateUrl: viewMeta.templateUrl,
styles: viewMeta.styles,
styleUrls: viewMeta.styleUrls,
encapsulation: cmpMeta.encapsulation,
template: cmpMeta.template,
templateUrl: cmpMeta.templateUrl,
styles: cmpMeta.styles,
styleUrls: cmpMeta.styleUrls,
animations: animations,
interpolation: viewMeta.interpolation
interpolation: cmpMeta.interpolation
});
changeDetectionStrategy = cmpMeta.changeDetection;
if (isPresent(dirMeta.viewProviders)) {
@ -156,7 +154,26 @@ export class CompileMetadataResolver {
if (cmpMeta.entryComponents) {
entryComponentTypes =
flattenArray(cmpMeta.entryComponents)
.map((cmp) => this.getTypeMetadata(cmp, staticTypeModuleUrl(cmp)));
.map((type) => this.getTypeMetadata(type, staticTypeModuleUrl(type)));
}
if (cmpMeta.directives) {
viewDirectiveTypes = flattenArray(cmpMeta.directives).map((type) => {
if (!type) {
throw new BaseException(
`Unexpected directive value '${type}' on the View of component '${stringify(directiveType)}'`);
}
return this.getTypeMetadata(type, staticTypeModuleUrl(type));
});
}
if (cmpMeta.pipes) {
viewPipeTypes = flattenArray(cmpMeta.pipes).map((type) => {
if (!type) {
throw new BaseException(
`Unexpected pipe value '${type}' on the View of component '${stringify(directiveType)}'`);
}
return this.getTypeMetadata(type, staticTypeModuleUrl(type));
});
}
if (!selector) {
selector = this._schemaRegistry.getDefaultComponentElementName();
@ -196,6 +213,8 @@ export class CompileMetadataResolver {
viewProviders: viewProviders,
queries: queries,
viewQueries: viewQueries,
viewDirectives: viewDirectiveTypes,
viewPipes: viewPipeTypes,
entryComponents: entryComponentTypes
});
this._directiveCache.set(directiveType, meta);
@ -386,20 +405,12 @@ export class CompileMetadataResolver {
return;
}
const addPipe = (pipeType: Type) => {
if (!pipeType) {
throw new BaseException(
`Unexpected pipe value '${pipeType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
}
const pipeMeta = this.getPipeMetadata(pipeType);
this._addPipeToModule(
pipeMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule, moduleMeta.declaredPipes);
};
const addDirective = (dirType: Type) => {
if (!dirType) {
throw new BaseException(
`Unexpected directive value '${dirType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
}
const dirMeta = this.getDirectiveMetadata(dirType);
if (this._addDirectiveToModule(
dirMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
@ -407,12 +418,11 @@ export class CompileMetadataResolver {
this._getTransitiveViewDirectivesAndPipes(dirMeta, moduleMeta);
}
};
const view = this._viewResolver.resolve(compMeta.type.runtime);
if (view.pipes) {
flattenArray(view.pipes).forEach(addPipe);
if (compMeta.viewPipes) {
compMeta.viewPipes.forEach((cplType) => addPipe(cplType.runtime));
}
if (view.directives) {
flattenArray(view.directives).forEach(addDirective);
if (compMeta.viewDirectives) {
compMeta.viewDirectives.forEach((cplType) => addDirective(cplType.runtime));
}
compMeta.entryComponents.forEach((entryComponentType) => {
if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) {

View File

@ -1,55 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable, ViewMetadata, ComponentMetadata,} from '@angular/core';
import {ReflectorReader, reflector} from '../core_private';
import {Type, stringify, isBlank, isPresent} from '../src/facade/lang';
import {BaseException} from '../src/facade/exceptions';
function _isComponentMetadata(obj: any): obj is ComponentMetadata {
return obj instanceof ComponentMetadata;
}
/**
* Resolves types to {@link ViewMetadata}.
*/
@Injectable()
export class ViewResolver {
constructor(private _reflector: ReflectorReader = reflector) {}
resolve(component: Type, throwIfNotFound = true): ViewMetadata {
const compMeta: ComponentMetadata =
this._reflector.annotations(component).find(_isComponentMetadata);
if (isPresent(compMeta)) {
if (isBlank(compMeta.template) && isBlank(compMeta.templateUrl)) {
throw new BaseException(
`Component '${stringify(component)}' must have either 'template' or 'templateUrl' set.`);
} else {
return new ViewMetadata({
templateUrl: compMeta.templateUrl,
template: compMeta.template,
directives: compMeta.directives,
pipes: compMeta.pipes,
encapsulation: compMeta.encapsulation,
styles: compMeta.styles,
styleUrls: compMeta.styleUrls,
animations: compMeta.animations,
interpolation: compMeta.interpolation
});
}
} else {
if (throwIfNotFound) {
throw new BaseException(
`Could not compile '${stringify(component)}' because it is not a component.`);
}
return null;
}
}
}

View File

@ -9,34 +9,35 @@
import {beforeEach, ddescribe, describe, expect, iit, it, inject,} from '@angular/core/testing/testing_internal';
import {stringify, isBlank} from '../src/facade/lang';
import {MockViewResolver} from '../testing';
import {Component, ViewMetadata, Injector} from '@angular/core';
import {MockDirectiveResolver} from '../testing';
import {Component, ViewMetadata, Injector, ComponentMetadata} from '@angular/core';
export function main() {
describe('MockViewResolver', () => {
var viewResolver: MockViewResolver;
describe('MockDirectiveResolver', () => {
var dirResolver: MockDirectiveResolver;
beforeEach(inject(
[Injector], (injector: Injector) => { viewResolver = new MockViewResolver(injector); }));
beforeEach(inject([Injector], (injector: Injector) => {
dirResolver = new MockDirectiveResolver(injector);
}));
describe('View overriding', () => {
it('should fallback to the default ViewResolver when templates are not overridden', () => {
var view = viewResolver.resolve(SomeComponent);
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
expect(view.template).toEqual('template');
expect(view.directives).toEqual([SomeDirective]);
});
it('should allow overriding the @View', () => {
viewResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
var view = viewResolver.resolve(SomeComponent);
dirResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
expect(view.template).toEqual('overridden template');
expect(isBlank(view.directives)).toBe(true);
});
it('should allow overriding a view after it has been resolved', () => {
viewResolver.resolve(SomeComponent);
viewResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
var view = viewResolver.resolve(SomeComponent);
dirResolver.resolve(SomeComponent);
dirResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
expect(view.template).toEqual('overridden template');
expect(isBlank(view.directives)).toBe(true);
});
@ -44,23 +45,23 @@ export function main() {
describe('inline template definition overriding', () => {
it('should allow overriding the default template', () => {
viewResolver.setInlineTemplate(SomeComponent, 'overridden template');
var view = viewResolver.resolve(SomeComponent);
dirResolver.setInlineTemplate(SomeComponent, 'overridden template');
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
expect(view.template).toEqual('overridden template');
expect(view.directives).toEqual([SomeDirective]);
});
it('should allow overriding an overridden @View', () => {
viewResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
viewResolver.setInlineTemplate(SomeComponent, 'overridden template x 2');
var view = viewResolver.resolve(SomeComponent);
dirResolver.setView(SomeComponent, new ViewMetadata({template: 'overridden template'}));
dirResolver.setInlineTemplate(SomeComponent, 'overridden template x 2');
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
expect(view.template).toEqual('overridden template x 2');
});
it('should allow overriding a view after it has been resolved', () => {
viewResolver.resolve(SomeComponent);
viewResolver.setInlineTemplate(SomeComponent, 'overridden template');
var view = viewResolver.resolve(SomeComponent);
dirResolver.resolve(SomeComponent);
dirResolver.setInlineTemplate(SomeComponent, 'overridden template');
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
expect(view.template).toEqual('overridden template');
});
});
@ -68,31 +69,31 @@ export function main() {
describe('Directive overriding', () => {
it('should allow overriding a directive from the default view', () => {
viewResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective);
var view = viewResolver.resolve(SomeComponent);
dirResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective);
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
expect(view.directives.length).toEqual(1);
expect(view.directives[0]).toBe(SomeOtherDirective);
});
it('should allow overriding a directive from an overridden @View', () => {
viewResolver.setView(SomeComponent, new ViewMetadata({directives: [SomeOtherDirective]}));
viewResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeComponent);
var view = viewResolver.resolve(SomeComponent);
dirResolver.setView(SomeComponent, new ViewMetadata({directives: [SomeOtherDirective]}));
dirResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeComponent);
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
expect(view.directives.length).toEqual(1);
expect(view.directives[0]).toBe(SomeComponent);
});
it('should throw when the overridden directive is not present', () => {
viewResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeDirective);
expect(() => { viewResolver.resolve(SomeComponent); })
dirResolver.overrideViewDirective(SomeComponent, SomeOtherDirective, SomeDirective);
expect(() => { dirResolver.resolve(SomeComponent); })
.toThrowError(
`Overriden directive ${stringify(SomeOtherDirective)} not found in the template of ${stringify(SomeComponent)}`);
});
it('should allow overriding a directive after its view has been resolved', () => {
viewResolver.resolve(SomeComponent);
viewResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective);
var view = viewResolver.resolve(SomeComponent);
dirResolver.resolve(SomeComponent);
dirResolver.overrideViewDirective(SomeComponent, SomeDirective, SomeOtherDirective);
var view = <ComponentMetadata>dirResolver.resolve(SomeComponent);
expect(view.directives.length).toEqual(1);
expect(view.directives[0]).toBe(SomeOtherDirective);
});

View File

@ -7,7 +7,7 @@
*/
import {DirectiveResolver} from '@angular/compiler/src/directive_resolver';
import {ContentChild, ContentChildren, Directive, DirectiveMetadata, HostBinding, HostListener, Input, Output, ViewChild, ViewChildren} from '@angular/core/src/metadata';
import {Component, ComponentMetadata, ContentChild, ContentChildren, Directive, DirectiveMetadata, HostBinding, HostListener, Input, Output, ViewChild, ViewChildren} from '@angular/core/src/metadata';
@Directive({selector: 'someDirective'})
class SomeDirective {
@ -104,6 +104,19 @@ class SomeDirectiveWithViewChild {
c: any;
}
class SomeDir {}
class SomePipe {}
@Component({
selector: 'sample',
template: 'some template',
directives: [SomeDir],
pipes: [SomePipe],
styles: ['some styles']
})
class ComponentWithTemplate {
}
class SomeDirectiveWithoutMetadata {}
export function main() {
@ -218,5 +231,15 @@ export function main() {
.toEqual({'c': new ViewChild('c'), 'a': new ViewChild('a')});
});
});
describe('view', () => {
it('should read out the template related metadata from the Component metadata', () => {
var compMetadata = <ComponentMetadata>resolver.resolve(ComponentWithTemplate);
expect(compMetadata.template).toEqual('some template');
expect(compMetadata.directives).toEqual([SomeDir]);
expect(compMetadata.pipes).toEqual([SomePipe]);
expect(compMetadata.styles).toEqual(['some styles']);
});
});
});
}

View File

@ -35,8 +35,8 @@ export function main() {
beforeEach(() => { resolver = new NgModuleResolver(); });
it('should read out the metadata from the class', () => {
var viewMetadata = resolver.resolve(SomeModule);
expect(viewMetadata).toEqual(new NgModuleMetadata({
var moduleMetadata = resolver.resolve(SomeModule);
expect(moduleMetadata).toEqual(new NgModuleMetadata({
declarations: [SomeClass1],
imports: [SomeClass2],
exports: [SomeClass3],

View File

@ -11,8 +11,8 @@ import {expect} from '@angular/platform-browser/testing/matchers';
import {Injectable, Component, Input, ViewMetadata, Compiler, ComponentFactory, Injector, NgModule, NgModuleFactory} from '@angular/core';
import {ConcreteType, stringify} from '../src/facade/lang';
import {fakeAsync, tick, TestComponentBuilder, ComponentFixture, configureCompiler} from '@angular/core/testing';
import {XHR, ViewResolver} from '@angular/compiler';
import {MockViewResolver} from '@angular/compiler/testing';
import {XHR, DirectiveResolver} from '@angular/compiler';
import {MockDirectiveResolver} from '@angular/compiler/testing';
import {SpyXHR} from './spies';
@ -33,19 +33,19 @@ export function main() {
let compiler: Compiler;
let xhr: SpyXHR;
let tcb: TestComponentBuilder;
let viewResolver: MockViewResolver;
let dirResolver: MockDirectiveResolver;
let injector: Injector;
beforeEach(() => { configureCompiler({providers: [{provide: XHR, useClass: SpyXHR}]}); });
beforeEach(inject(
[Compiler, TestComponentBuilder, XHR, ViewResolver, Injector],
[Compiler, TestComponentBuilder, XHR, DirectiveResolver, Injector],
(_compiler: Compiler, _tcb: TestComponentBuilder, _xhr: SpyXHR,
_viewResolver: MockViewResolver, _injector: Injector) => {
_dirResolver: MockDirectiveResolver, _injector: Injector) => {
compiler = _compiler;
tcb = _tcb;
xhr = _xhr;
viewResolver = _viewResolver;
dirResolver = _dirResolver;
injector = _injector;
}));
@ -74,12 +74,12 @@ export function main() {
});
it('should not update existing compilation results', () => {
viewResolver.setView(
dirResolver.setView(
SomeComp,
new ViewMetadata({template: '<child-cmp></child-cmp>', directives: [ChildComp]}));
viewResolver.setInlineTemplate(ChildComp, 'oldChild');
dirResolver.setInlineTemplate(ChildComp, 'oldChild');
let compFactory = compiler.compileComponentSync(SomeComp);
viewResolver.setInlineTemplate(ChildComp, 'newChild');
dirResolver.setInlineTemplate(ChildComp, 'newChild');
compiler.compileComponentSync(SomeComp);
let compRef = compFactory.create(injector);
expect(compRef.location.nativeElement).toHaveText('oldChild');
@ -151,9 +151,8 @@ export function main() {
}
xhr.spy('get').andCallFake(() => Promise.resolve(''));
viewResolver.setView(
SomeComp, new ViewMetadata({template: '', directives: [ChildComp]}));
viewResolver.setView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'}));
dirResolver.setView(SomeComp, new ViewMetadata({template: '', directives: [ChildComp]}));
dirResolver.setView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'}));
expect(() => compiler.compileModuleSync(SomeModule))
.toThrowError(
`Can't compile synchronously as ${stringify(ChildComp)} is still being loaded!`);

View File

@ -1,59 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {ViewResolver} from '@angular/compiler/src/view_resolver';
import {Component, ViewMetadata} from '@angular/core/src/metadata';
class SomeDir {}
class SomePipe {}
@Component({
selector: 'sample',
template: 'some template',
directives: [SomeDir],
pipes: [SomePipe],
styles: ['some styles']
})
class ComponentWithTemplate {
}
@Component({selector: 'sample'})
class ComponentWithoutView {
}
class SimpleClass {}
export function main() {
describe('ViewResolver', () => {
var resolver: ViewResolver;
beforeEach(() => { resolver = new ViewResolver(); });
it('should read out the View metadata from the Component metadata', () => {
var viewMetadata = resolver.resolve(ComponentWithTemplate);
expect(viewMetadata).toEqual(new ViewMetadata({
template: 'some template',
directives: [SomeDir],
pipes: [SomePipe],
styles: ['some styles']
}));
});
it('should throw when Component has neither template nor templateUrl set', () => {
expect(() => resolver.resolve(ComponentWithoutView))
.toThrowError(
/Component 'ComponentWithoutView' must have either 'template' or 'templateUrl' set/);
});
it('should throw when simple class has no component decorator', () => {
expect(() => resolver.resolve(SimpleClass))
.toThrowError('Could not compile \'SimpleClass\' because it is not a component.');
});
});
}

View File

@ -7,14 +7,12 @@
*/
export * from './testing/schema_registry_mock';
export * from './testing/view_resolver_mock';
export * from './testing/test_component_builder';
export * from './testing/directive_resolver_mock';
export * from './testing/ng_module_resolver_mock';
import {createPlatformFactory, CompilerOptions, PlatformRef} from '@angular/core';
import {platformCoreDynamic, DirectiveResolver, ViewResolver, NgModuleResolver} from './index';
import {MockViewResolver} from './testing/view_resolver_mock';
import {platformCoreDynamic, DirectiveResolver, NgModuleResolver} from './index';
import {MockDirectiveResolver} from './testing/directive_resolver_mock';
import {MockNgModuleResolver} from './testing/ng_module_resolver_mock';
@ -30,7 +28,6 @@ export const platformCoreDynamicTesting =
useValue: {
providers: [
{provide: DirectiveResolver, useClass: MockDirectiveResolver},
{provide: ViewResolver, useClass: MockViewResolver},
{provide: NgModuleResolver, useClass: MockNgModuleResolver}
]
},

View File

@ -6,12 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Compiler, ComponentMetadata, DirectiveMetadata, Injectable, Injector} from '@angular/core';
import {AnimationEntryMetadata, Compiler, ComponentMetadata, DirectiveMetadata, Injectable, Injector, ViewMetadata, resolveForwardRef} from '@angular/core';
import {DirectiveResolver} from '../src/directive_resolver';
import {Map} from '../src/facade/collection';
import {Type, isPresent} from '../src/facade/lang';
import {BaseException} from '../src/facade/exceptions';
import {Type, isArray, isPresent, stringify} from '../src/facade/lang';
/**
@ -22,33 +22,75 @@ import {Type, isPresent} from '../src/facade/lang';
export class MockDirectiveResolver extends DirectiveResolver {
private _providerOverrides = new Map<Type, any[]>();
private viewProviderOverrides = new Map<Type, any[]>();
private _views = new Map<Type, ViewMetadata>();
private _inlineTemplates = new Map<Type, string>();
private _animations = new Map<Type, AnimationEntryMetadata[]>();
private _directiveOverrides = new Map<Type, Map<Type, Type>>();
constructor(private _injector: Injector) { super(); }
private get _compiler(): Compiler { return this._injector.get(Compiler); }
private _clearCacheFor(component: Type) { this._compiler.clearCacheFor(component); }
resolve(type: Type, throwIfNotFound = true): DirectiveMetadata {
var dm = super.resolve(type, throwIfNotFound);
const dm = super.resolve(type, throwIfNotFound);
if (!dm) {
return null;
}
var providerOverrides = this._providerOverrides.get(type);
var viewProviderOverrides = this.viewProviderOverrides.get(type);
const providerOverrides = this._providerOverrides.get(type);
const viewProviderOverrides = this.viewProviderOverrides.get(type);
var providers = dm.providers;
let providers = dm.providers;
if (isPresent(providerOverrides)) {
var originalViewProviders: any[] = isPresent(dm.providers) ? dm.providers : [];
const originalViewProviders: any[] = isPresent(dm.providers) ? dm.providers : [];
providers = originalViewProviders.concat(providerOverrides);
}
if (dm instanceof ComponentMetadata) {
var viewProviders = dm.viewProviders;
let viewProviders = dm.viewProviders;
if (isPresent(viewProviderOverrides)) {
var originalViewProviders: any[] = isPresent(dm.viewProviders) ? dm.viewProviders : [];
const originalViewProviders: any[] = isPresent(dm.viewProviders) ? dm.viewProviders : [];
viewProviders = originalViewProviders.concat(viewProviderOverrides);
}
let view = this._views.get(type);
if (!view) {
view = dm;
}
const directives: any[] = [];
if (isPresent(view.directives)) {
flattenArray(view.directives, directives);
}
let animations = view.animations;
let templateUrl = view.templateUrl;
const directiveOverrides = this._directiveOverrides.get(type);
const inlineAnimations = this._animations.get(type);
if (isPresent(inlineAnimations)) {
animations = inlineAnimations;
}
let inlineTemplate = this._inlineTemplates.get(type);
if (isPresent(inlineTemplate)) {
templateUrl = null;
} else {
inlineTemplate = view.template;
}
if (isPresent(directiveOverrides) && isPresent(view.directives)) {
directiveOverrides.forEach((to, from) => {
var srcIndex = directives.indexOf(from);
if (srcIndex == -1) {
throw new BaseException(
`Overriden directive ${stringify(from)} not found in the template of ${stringify(type)}`);
}
directives[srcIndex] = to;
});
}
return new ComponentMetadata({
selector: dm.selector,
inputs: dm.inputs,
@ -60,7 +102,16 @@ export class MockDirectiveResolver extends DirectiveResolver {
changeDetection: dm.changeDetection,
providers: providers,
viewProviders: viewProviders,
entryComponents: dm.entryComponents
entryComponents: dm.entryComponents,
template: inlineTemplate,
templateUrl: templateUrl,
directives: directives.length > 0 ? directives : null,
animations: animations,
styles: view.styles,
styleUrls: view.styleUrls,
pipes: view.pipes,
encapsulation: view.encapsulation,
interpolation: view.interpolation
});
}
@ -77,11 +128,58 @@ export class MockDirectiveResolver extends DirectiveResolver {
setProvidersOverride(type: Type, providers: any[]): void {
this._providerOverrides.set(type, providers);
this._compiler.clearCacheFor(type);
this._clearCacheFor(type);
}
setViewProvidersOverride(type: Type, viewProviders: any[]): void {
this.viewProviderOverrides.set(type, viewProviders);
this._compiler.clearCacheFor(type);
this._clearCacheFor(type);
}
/**
* Overrides the {@link ViewMetadata} for a component.
*/
setView(component: Type, view: ViewMetadata): void {
this._views.set(component, view);
this._clearCacheFor(component);
}
/**
* Overrides the inline template for a component - other configuration remains unchanged.
*/
setInlineTemplate(component: Type, template: string): void {
this._inlineTemplates.set(component, template);
this._clearCacheFor(component);
}
setAnimations(component: Type, animations: AnimationEntryMetadata[]): void {
this._animations.set(component, animations);
this._clearCacheFor(component);
}
/**
* Overrides a directive from the component {@link ViewMetadata}.
*/
overrideViewDirective(component: Type, from: Type, to: Type): void {
var overrides = this._directiveOverrides.get(component);
if (!overrides) {
overrides = new Map<Type, Type>();
this._directiveOverrides.set(component, overrides);
}
overrides.set(from, to);
this._clearCacheFor(component);
}
}
function flattenArray(tree: any[], out: Array<Type|any[]>): void {
if (!isPresent(tree)) return;
for (var i = 0; i < tree.length; i++) {
var item = resolveForwardRef(tree[i]);
if (isArray(item)) {
flattenArray(item, out);
} else {
out.push(item);
}
}
}

View File

@ -9,7 +9,7 @@
import {AnimationEntryMetadata, Compiler, ComponentFactory, Inject, Injectable, Injector, NgZone, ViewMetadata} from '@angular/core';
import {ComponentFixture, ComponentFixtureNoNgZone, TestBed, TestComponentBuilder} from '@angular/core/testing';
import {DirectiveResolver, ViewResolver} from '../index';
import {DirectiveResolver} from '../index';
import {MapWrapper} from '../src/facade/collection';
import {ConcreteType, IS_DART, Type, isPresent} from '../src/facade/lang';
@ -101,15 +101,14 @@ export class OverridingTestComponentBuilder extends TestComponentBuilder {
private _applyMetadataOverrides() {
let mockDirectiveResolver = this._injector.get(DirectiveResolver);
let mockViewResolver = this._injector.get(ViewResolver);
this._viewOverrides.forEach((view, type) => { mockViewResolver.setView(type, view); });
this._viewOverrides.forEach((view, type) => { mockDirectiveResolver.setView(type, view); });
this._templateOverrides.forEach(
(template, type) => mockViewResolver.setInlineTemplate(type, template));
(template, type) => mockDirectiveResolver.setInlineTemplate(type, template));
this._animationOverrides.forEach(
(animationsEntry, type) => mockViewResolver.setAnimations(type, animationsEntry));
(animationsEntry, type) => mockDirectiveResolver.setAnimations(type, animationsEntry));
this._directiveOverrides.forEach((overrides, component) => {
overrides.forEach(
(to, from) => { mockViewResolver.overrideViewDirective(component, from, to); });
(to, from) => { mockDirectiveResolver.overrideViewDirective(component, from, to); });
});
this._bindingsOverrides.forEach(
(bindings, type) => mockDirectiveResolver.setProvidersOverride(type, bindings));

View File

@ -1,141 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AnimationEntryMetadata, BaseException, Compiler, Injectable, Injector, Type, ViewMetadata, resolveForwardRef} from '@angular/core';
import {ViewResolver} from '../index';
import {Map} from '../src/facade/collection';
import {isArray, isBlank, isPresent, stringify} from '../src/facade/lang';
@Injectable()
export class MockViewResolver extends ViewResolver {
/** @internal */
_views = new Map<Type, ViewMetadata>();
/** @internal */
_inlineTemplates = new Map<Type, string>();
/** @internal */
_animations = new Map<Type, AnimationEntryMetadata[]>();
/** @internal */
_directiveOverrides = new Map<Type, Map<Type, Type>>();
constructor(private _injector: Injector) { super(); }
private get _compiler(): Compiler { return this._injector.get(Compiler); }
private _clearCacheFor(component: Type) { this._compiler.clearCacheFor(component); }
/**
* Overrides the {@link ViewMetadata} for a component.
*/
setView(component: Type, view: ViewMetadata): void {
this._views.set(component, view);
this._clearCacheFor(component);
}
/**
* Overrides the inline template for a component - other configuration remains unchanged.
*/
setInlineTemplate(component: Type, template: string): void {
this._inlineTemplates.set(component, template);
this._clearCacheFor(component);
}
setAnimations(component: Type, animations: AnimationEntryMetadata[]): void {
this._animations.set(component, animations);
this._clearCacheFor(component);
}
/**
* Overrides a directive from the component {@link ViewMetadata}.
*/
overrideViewDirective(component: Type, from: Type, to: Type): void {
var overrides = this._directiveOverrides.get(component);
if (isBlank(overrides)) {
overrides = new Map<Type, Type>();
this._directiveOverrides.set(component, overrides);
}
overrides.set(from, to);
this._clearCacheFor(component);
}
/**
* Returns the {@link ViewMetadata} for a component:
* - Set the {@link ViewMetadata} to the overridden view when it exists or fallback to the default
* `ViewResolver`,
* see `setView`.
* - Override the directives, see `overrideViewDirective`.
* - Override the @View definition, see `setInlineTemplate`.
*/
resolve(component: Type, throwIfNotFound = true): ViewMetadata {
var view = this._views.get(component);
if (isBlank(view)) {
view = super.resolve(component, throwIfNotFound);
if (!view) {
return null;
}
}
var directives: any[] /** TODO #9100 */ = [];
if (isPresent(view.directives)) {
flattenArray(view.directives, directives);
}
var animations = view.animations;
var templateUrl = view.templateUrl;
var overrides = this._directiveOverrides.get(component);
var inlineAnimations = this._animations.get(component);
if (isPresent(inlineAnimations)) {
animations = inlineAnimations;
}
var inlineTemplate = this._inlineTemplates.get(component);
if (isPresent(inlineTemplate)) {
templateUrl = null;
} else {
inlineTemplate = view.template;
}
if (isPresent(overrides) && isPresent(view.directives)) {
overrides.forEach((to, from) => {
var srcIndex = directives.indexOf(from);
if (srcIndex == -1) {
throw new BaseException(
`Overriden directive ${stringify(from)} not found in the template of ${stringify(component)}`);
}
directives[srcIndex] = to;
});
}
view = new ViewMetadata({
template: inlineTemplate,
templateUrl: templateUrl,
directives: directives.length > 0 ? directives : null,
animations: animations,
styles: view.styles,
styleUrls: view.styleUrls,
pipes: view.pipes,
encapsulation: view.encapsulation,
interpolation: view.interpolation
});
return view;
}
}
function flattenArray(tree: any[], out: Array<Type|any[]>): void {
if (!isPresent(tree)) return;
for (var i = 0; i < tree.length; i++) {
var item = resolveForwardRef(tree[i]);
if (isArray(item)) {
flattenArray(item, out);
} else {
out.push(item);
}
}
}

View File

@ -17,7 +17,7 @@ import {AnimationEntryMetadata} from './animation/metadata';
import {AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di';
import {ComponentMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, InputMetadata, OutputMetadata, PipeMetadata} from './metadata/directives';
import {ModuleWithProviders, NgModuleMetadata, SchemaMetadata} from './metadata/ng_module';
import {ViewEncapsulation, ViewMetadata} from './metadata/view';
import {ViewEncapsulation} from './metadata/view';
export {ANALYZE_FOR_ENTRY_COMPONENTS, AttributeMetadata, ContentChildMetadata, ContentChildrenMetadata, QueryMetadata, ViewChildMetadata, ViewChildrenMetadata, ViewQueryMetadata} from './metadata/di';
export {ComponentMetadata, DirectiveMetadata, HostBindingMetadata, HostListenerMetadata, InputMetadata, OutputMetadata, PipeMetadata} from './metadata/directives';
@ -44,46 +44,7 @@ export interface DirectiveDecorator extends TypeDecorator {}
*
* @stable
*/
export interface ComponentDecorator extends TypeDecorator {
/**
* Chain {@link ViewMetadata} annotation.
*/
View(obj: {
templateUrl?: string,
template?: string,
directives?: Array<Type|any[]>,
pipes?: Array<Type|any[]>,
renderer?: string,
styles?: string[],
styleUrls?: string[],
animations?: AnimationEntryMetadata[],
interpolation?: [string, string]
}): ViewDecorator;
}
/**
* Interface for the {@link ViewMetadata} decorator function.
*
* See {@link ViewMetadataFactory}.
*
* @experimental
*/
export interface ViewDecorator extends TypeDecorator {
/**
* Chain {@link ViewMetadata} annotation.
*/
View(obj: {
templateUrl?: string,
template?: string,
directives?: Array<Type|any[]>,
pipes?: Array<Type|any[]>,
renderer?: string,
styles?: string[],
styleUrls?: string[],
animations?: AnimationEntryMetadata[],
interpolation?: [string, string]
}): ViewDecorator;
}
export interface ComponentDecorator extends TypeDecorator {}
/**
* Interface for the {@link NgModuleMetadata} decorator function.
@ -237,75 +198,6 @@ export interface ComponentMetadataFactory {
}): ComponentMetadata;
}
/**
* {@link ViewMetadata} factory for creating annotations, decorators or DSL.
*
* ### Example as TypeScript Decorator
*
* ```
* import {Component, View} from '@angular/core';
*
* @Component({...})
* class MyComponent {
* constructor() {
* ...
* }
* }
* ```
*
* ### Example as ES5 DSL
*
* ```
* var MyComponent = ng
* .Component({...})
* .View({...})
* .Class({
* constructor: function() {
* ...
* }
* })
* ```
*
* ### Example as ES5 annotation
*
* ```
* var MyComponent = function() {
* ...
* };
*
* MyComponent.annotations = [
* new ng.Component({...}),
* new ng.View({...})
* ]
* ```
*
* @experimental You should most likely use ComponentMetadataFactory instead
*/
export interface ViewMetadataFactory {
(obj: {
templateUrl?: string,
template?: string,
directives?: Array<Type|any[]>,
pipes?: Array<Type|any[]>,
encapsulation?: ViewEncapsulation,
styles?: string[],
styleUrls?: string[],
animations?: AnimationEntryMetadata[],
interpolation?: [string, string]
}): ViewDecorator;
new (obj: {
templateUrl?: string,
template?: string,
directives?: Array<Type|any[]>,
pipes?: Array<Type|any[]>,
encapsulation?: ViewEncapsulation,
styles?: string[],
styleUrls?: string[],
animations?: AnimationEntryMetadata[],
interpolation?: [string, string]
}): ViewMetadata;
}
/**
* {@link AttributeMetadata} factory for creating annotations, decorators or DSL.
*
@ -541,7 +433,7 @@ export interface NgModuleMetadataFactory {
* @Annotation
*/
export var Component: ComponentMetadataFactory =
<ComponentMetadataFactory>makeDecorator(ComponentMetadata, (fn: any) => fn.View = View);
<ComponentMetadataFactory>makeDecorator(ComponentMetadata);
// TODO(alexeagle): remove the duplication of this doc. It is copied from DirectiveMetadata.
/**
@ -580,7 +472,7 @@ export var Component: ComponentMetadataFactory =
* current `ElementInjector` resolves the constructor dependencies for each directive.
*
* Angular then resolves dependencies as follows, according to the order in which they appear in the
* {@link ViewMetadata}:
* {@link ComponentMetadata}:
*
* 1. Dependencies on the current element
* 2. Dependencies on element injectors and their parents until it encounters a Shadow DOM boundary
@ -829,7 +721,8 @@ export var Component: ComponentMetadataFactory =
* location in the current view
* where these actions are performed.
*
* Views are always created as children of the current {@link ViewMetadata}, and as siblings of the
* Views are always created as children of the current {@link ComponentMetadata}, and as siblings of
* the
* `<template>` element. Thus a
* directive in a child view cannot inject the directive that created it.
*
@ -928,41 +821,6 @@ export var Component: ComponentMetadataFactory =
export var Directive: DirectiveMetadataFactory =
<DirectiveMetadataFactory>makeDecorator(DirectiveMetadata);
// TODO(alexeagle): remove the duplication of this doc. It is copied from ViewMetadata.
/**
* Metadata properties available for configuring Views.
*
* Each Angular component requires a single `@Component` and at least one `@View` annotation. The
* `@View` annotation specifies the HTML template to use, and lists the directives that are active
* within the template.
*
* When a component is instantiated, the template is loaded into the component's shadow root, and
* the expressions and statements in the template are evaluated against the component.
*
* For details on the `@Component` annotation, see {@link ComponentMetadata}.
*
* ### Example
*
* ```
* @Component({
* selector: 'greet',
* template: 'Hello {{name}}!',
* directives: [GreetUser, Bold]
* })
* class Greet {
* name: string;
*
* constructor() {
* this.name = 'World';
* }
* }
* ```
* @deprecated
* @Annotation
*/
var View: ViewMetadataFactory =
<ViewMetadataFactory>makeDecorator(ViewMetadata, (fn: any) => fn.View = View);
/**
* Specifies that a constant attribute value should be injected.
*

View File

@ -50,7 +50,7 @@ import {ViewEncapsulation} from './view';
* current `ElementInjector` resolves the constructor dependencies for each directive.
*
* Angular then resolves dependencies as follows, according to the order in which they appear in the
* {@link ViewMetadata}:
* {@link ComponentMetadata}:
*
* 1. Dependencies on the current element
* 2. Dependencies on element injectors and their parents until it encounters a Shadow DOM boundary
@ -299,7 +299,8 @@ import {ViewEncapsulation} from './view';
* location in the current view
* where these actions are performed.
*
* Views are always created as children of the current {@link ViewMetadata}, and as siblings of the
* Views are always created as children of the current {@link ComponentMetadata}, and as siblings of
* the
* `<template>` element. Thus a
* directive in a child view cannot inject the directive that created it.
*
@ -787,8 +788,6 @@ export class DirectiveMetadata extends InjectableMetadata {
*
* All template expressions and statements are then evaluated against the component instance.
*
* For details on the `@View` annotation, see {@link ViewMetadata}.
*
* ## Lifecycle hooks
*
* When the component class implements some {@linkDocs guide/lifecycle-hooks} the
@ -877,12 +876,32 @@ export class ComponentMetadata extends DirectiveMetadata {
*/
moduleId: string;
/**
* Specifies a template URL for an Angular component.
*
* NOTE: Only one of `templateUrl` or `template` can be defined per View.
*
* <!-- TODO: what's the url relative to? -->
*/
templateUrl: string;
/**
* Specifies an inline template for an Angular component.
*
* NOTE: Only one of `templateUrl` or `template` can be defined per View.
*/
template: string;
/**
* Specifies stylesheet URLs for an Angular component.
*
* <!-- TODO: what's the url relative to? -->
*/
styleUrls: string[];
/**
* Specifies an inline stylesheet for an Angular component.
*/
styles: string[];
/**
@ -962,6 +981,12 @@ export class ComponentMetadata extends DirectiveMetadata {
pipes: Array<Type|any[]>;
/**
* Specify how the template and the styles should be encapsulated.
* The default is {@link ViewEncapsulation#Emulated `ViewEncapsulation.Emulated`} if the view
* has styles,
* otherwise {@link ViewEncapsulation#None `ViewEncapsulation.None`}.
*/
encapsulation: ViewEncapsulation;
interpolation: [string, string];

View File

@ -73,7 +73,7 @@ export var VIEW_ENCAPSULATION_VALUES =
* ```
* @ts2dart_const
*
* @experimental You should most likely be using ComponentMetadata instead.
* @deprecated Use ComponentMetadata instead.
*/
export class ViewMetadata {
/**

View File

@ -1525,7 +1525,8 @@ function declareTests({useJit}: {useJit: boolean}) {
tcb.createAsync(ComponentWithoutView);
expect(true).toBe(false);
} catch (e) {
expect(e.message).toContain(`must have either 'template' or 'templateUrl' set.`);
expect(e.message).toContain(
`No template specified for component ${stringify(ComponentWithoutView)}`);
}
}));

View File

@ -7,8 +7,8 @@
*/
import {LowerCasePipe, NgIf} from '@angular/common';
import {CompilerConfig, NgModuleResolver, ViewResolver} from '@angular/compiler';
import {MockNgModuleResolver, MockViewResolver} from '@angular/compiler/testing';
import {CompilerConfig, NgModuleResolver} from '@angular/compiler';
import {MockNgModuleResolver} from '@angular/compiler/testing';
import {ANALYZE_FOR_ENTRY_COMPONENTS, CUSTOM_ELEMENTS_SCHEMA, Compiler, Component, ComponentFactoryResolver, ComponentRef, ComponentResolver, DebugElement, Directive, Host, HostBinding, Inject, Injectable, Injector, Input, ModuleWithProviders, NgModule, NgModuleMetadata, NgModuleRef, OpaqueToken, Optional, Pipe, Provider, ReflectiveInjector, SelfMetadata, SkipSelf, SkipSelfMetadata, ViewMetadata, forwardRef, getDebugNode, provide} from '@angular/core';
import {Console} from '@angular/core/src/console';
import {ComponentFixture, configureCompiler} from '@angular/core/testing';
@ -125,11 +125,10 @@ function declareTests({useJit}: {useJit: boolean}) {
configureCompiler({useJit: useJit, providers: [{provide: Console, useValue: console}]});
});
beforeEach(
inject([Compiler, Injector, ViewResolver], (_compiler: Compiler, _injector: Injector) => {
compiler = _compiler;
injector = _injector;
}));
beforeEach(inject([Compiler, Injector], (_compiler: Compiler, _injector: Injector) => {
compiler = _compiler;
injector = _injector;
}));
function createModule<T>(
moduleType: ConcreteType<T>, parentInjector: Injector = null): NgModuleRef<T> {

View File

@ -19,15 +19,14 @@ export function main() {
});
it('should declare Component class', () => {
var MyComponent =
Component({}).View({}).View({}).Class({constructor: function() { this.works = true; }});
var MyComponent = Component({}).Class({constructor: function() { this.works = true; }});
expect(new MyComponent().works).toEqual(true);
});
it('should create type in ES5', () => {
function MyComponent(){};
var as: any /** TODO #9100 */;
(<any>MyComponent).annotations = as = Component({}).View({});
(<any>MyComponent).annotations = as = Component({});
expect(reflector.annotations(MyComponent)).toEqual(as.annotations);
});
});

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {CompilerConfig, DirectiveResolver, NgModuleResolver, ViewResolver, analyzeAppProvidersForDeprecatedConfiguration} from '@angular/compiler';
import {CompilerConfig, DirectiveResolver, NgModuleResolver, analyzeAppProvidersForDeprecatedConfiguration} from '@angular/compiler';
import {OverridingTestComponentBuilder, platformCoreDynamicTesting} from '@angular/compiler/testing';
import {Compiler, CompilerFactory, CompilerOptions, NgModule, PlatformRef, Provider, ReflectiveInjector, Type, createPlatform, createPlatformFactory} from '@angular/core';
import {TestComponentBuilder, TestComponentRenderer, initTestEnvironment} from '@angular/core/testing';

View File

@ -13,7 +13,7 @@ import {
ViewMetadata
} from '@angular/core';
import {CompilerConfig, ViewResolver} from '@angular/compiler';
import {CompilerConfig, DirectiveResolver} from '@angular/compiler';
import {getIntParameter, bindAction} from '@angular/testing/src/benchmark_util';
@ -21,8 +21,8 @@ function _createBindings(): any[] {
var multiplyTemplatesBy = getIntParameter('elements');
return [
{
provide: ViewResolver,
useFactory: () => new MultiplyViewResolver(
provide: DirectiveResolver,
useFactory: () => new MultiplyDirectiveResolver(
multiplyTemplatesBy,
[BenchmarkComponentNoBindings, BenchmarkComponentWithBindings]),
deps: []
@ -59,7 +59,7 @@ function measureWrapper(func, desc) {
}
class MultiplyViewResolver extends ViewResolver {
class MultiplyDirectiveResolver extends DirectiveResolver {
_multiplyBy: number;
_cache = new Map<Type, ViewMetadata>();