fix(compiler): dedup directives in template compiler
Closes #5311 Closes #5464
This commit is contained in:
parent
6ddfff5cd5
commit
87ddc8fb6a
|
@ -8,7 +8,6 @@ import {
|
|||
RegExpWrapper
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {MapWrapper, StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import * as cpl from './directive_metadata';
|
||||
import * as md from 'angular2/src/core/metadata/directives';
|
||||
import {DirectiveResolver} from 'angular2/src/core/linker/directive_resolver';
|
||||
|
@ -77,16 +76,10 @@ export class RuntimeMetadataResolver {
|
|||
}
|
||||
}
|
||||
|
||||
return removeDuplicates(directives).map(type => this.getMetadata(type));
|
||||
return directives.map(type => this.getMetadata(type));
|
||||
}
|
||||
}
|
||||
|
||||
function removeDuplicates(items: any[]): any[] {
|
||||
let m = new Map<any, any>();
|
||||
items.forEach(i => m.set(i, null));
|
||||
return MapWrapper.keys(m);
|
||||
}
|
||||
|
||||
function flattenDirectives(view: ViewMetadata, platformDirectives: any[]): Type[] {
|
||||
let directives = [];
|
||||
if (isPresent(platformDirectives)) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {IS_DART, Type, Json, isBlank, stringify} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {ListWrapper, SetWrapper} from 'angular2/src/facade/collection';
|
||||
import {ListWrapper, SetWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||
import {
|
||||
CompiledComponentTemplate,
|
||||
|
@ -96,6 +96,7 @@ export class TemplateCompiler {
|
|||
private _compileComponentRuntime(
|
||||
cacheKey: any, compMeta: CompileDirectiveMetadata, viewDirectives: CompileDirectiveMetadata[],
|
||||
compilingComponentCacheKeys: Set<any>): CompiledComponentTemplate {
|
||||
let uniqViewDirectives = removeDuplicates(viewDirectives);
|
||||
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
|
||||
var done = this._compiledTemplateDone.get(cacheKey);
|
||||
if (isBlank(compiledTemplate)) {
|
||||
|
@ -109,7 +110,7 @@ export class TemplateCompiler {
|
|||
compilingComponentCacheKeys.add(cacheKey);
|
||||
done = PromiseWrapper
|
||||
.all([<any>this._styleCompiler.compileComponentRuntime(compMeta.template)].concat(
|
||||
viewDirectives.map(dirMeta => this.normalizeDirectiveMetadata(dirMeta))))
|
||||
uniqViewDirectives.map(dirMeta => this.normalizeDirectiveMetadata(dirMeta))))
|
||||
.then((stylesAndNormalizedViewDirMetas: any[]) => {
|
||||
var childPromises = [];
|
||||
var normalizedViewDirMetas = stylesAndNormalizedViewDirMetas.slice(1);
|
||||
|
@ -175,9 +176,9 @@ export class TemplateCompiler {
|
|||
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
|
||||
assertComponent(compMeta);
|
||||
componentMetas.push(compMeta);
|
||||
this._processTemplateCodeGen(compMeta,
|
||||
<CompileDirectiveMetadata[]>componentWithDirs.directives,
|
||||
declarations, templateArguments);
|
||||
|
||||
this._processTemplateCodeGen(compMeta, componentWithDirs.directives, declarations,
|
||||
templateArguments);
|
||||
if (compMeta.dynamicLoadable) {
|
||||
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||
componentMetas.push(hostMeta);
|
||||
|
@ -212,9 +213,10 @@ export class TemplateCompiler {
|
|||
private _processTemplateCodeGen(compMeta: CompileDirectiveMetadata,
|
||||
directives: CompileDirectiveMetadata[],
|
||||
targetDeclarations: string[], targetTemplateArguments: any[][]) {
|
||||
let uniqueDirectives = removeDuplicates(directives);
|
||||
var styleExpr = this._styleCompiler.compileComponentCodeGen(compMeta.template);
|
||||
var parsedTemplate =
|
||||
this._templateParser.parse(compMeta.template.template, directives, compMeta.type.name);
|
||||
var parsedTemplate = this._templateParser.parse(compMeta.template.template, uniqueDirectives,
|
||||
compMeta.type.name);
|
||||
var changeDetectorsExprs = this._cdCompiler.compileComponentCodeGen(
|
||||
compMeta.type, compMeta.changeDetection, parsedTemplate);
|
||||
var commandsExpr = this._commandCompiler.compileComponentCodeGen(
|
||||
|
@ -263,3 +265,17 @@ function addAll(source: any[], target: any[]) {
|
|||
function codeGenComponentTemplateFactory(nestedCompType: CompileDirectiveMetadata): string {
|
||||
return `${moduleRef(templateModuleUrl(nestedCompType.type.moduleUrl))}${templateGetterName(nestedCompType.type)}`;
|
||||
}
|
||||
|
||||
function removeDuplicates(items: CompileDirectiveMetadata[]): CompileDirectiveMetadata[] {
|
||||
let res = [];
|
||||
items.forEach(item => {
|
||||
let hasMatch =
|
||||
res.filter(r => r.type.name == item.type.name && r.type.moduleUrl == item.type.moduleUrl &&
|
||||
r.type.runtime == item.type.runtime)
|
||||
.length > 0;
|
||||
if (!hasMatch) {
|
||||
res.push(item);
|
||||
}
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
afterEach,
|
||||
AsyncTestCompleter,
|
||||
inject,
|
||||
beforeEachBindings
|
||||
beforeEachProviders
|
||||
} from 'angular2/testing_internal';
|
||||
|
||||
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||
|
@ -57,7 +57,7 @@ export function main() {
|
|||
var compiler: TemplateCompiler;
|
||||
var runtimeMetadataResolver: RuntimeMetadataResolver;
|
||||
|
||||
beforeEachBindings(() => TEST_PROVIDERS);
|
||||
beforeEachProviders(() => TEST_PROVIDERS);
|
||||
beforeEach(inject([TemplateCompiler, RuntimeMetadataResolver],
|
||||
(_compiler, _runtimeMetadataResolver) => {
|
||||
compiler = _compiler;
|
||||
|
@ -122,9 +122,18 @@ export function main() {
|
|||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should dedup directives', inject([AsyncTestCompleter], (async) => {
|
||||
compile([CompWithDupDirectives, TreeComp])
|
||||
.then((humanizedTemplate) => {
|
||||
expect(humanizedTemplate['commands'][1]['commands'][0]).toEqual("<tree>");
|
||||
async.done();
|
||||
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
xdescribe('compileHostComponentRuntime', () => {
|
||||
describe('compileHostComponentRuntime', () => {
|
||||
function compile(components: Type[]): Promise<any[]> {
|
||||
return compiler.compileHostComponentRuntime(components[0])
|
||||
.then((compiledHostTemplate) => humanizeTemplate(compiledHostTemplate.template));
|
||||
|
@ -179,7 +188,6 @@ export function main() {
|
|||
});
|
||||
xhr.flush();
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('compileTemplatesCodeGen', () => {
|
||||
|
@ -290,6 +298,15 @@ class CompWithBindingsAndStyles {
|
|||
class TreeComp {
|
||||
}
|
||||
|
||||
@Component({selector: 'comp-wit-dup-tpl', moduleId: THIS_MODULE_ID})
|
||||
@View({
|
||||
template: '<tree></tree>',
|
||||
directives: [TreeComp, TreeComp],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
class CompWithDupDirectives {
|
||||
}
|
||||
|
||||
@Component({selector: 'comp-url', moduleId: THIS_MODULE_ID})
|
||||
@View({templateUrl: 'compUrl.html', encapsulation: ViewEncapsulation.None})
|
||||
class CompWithTemplateUrl {
|
||||
|
@ -349,7 +366,7 @@ export function humanizeTemplate(
|
|||
}
|
||||
|
||||
class TestContext implements CompWithBindingsAndStyles, TreeComp, CompWithTemplateUrl,
|
||||
CompWithEmbeddedTemplate {
|
||||
CompWithEmbeddedTemplate, CompWithDupDirectives {
|
||||
someProp: string;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue