X Tutup
Skip to content

Commit 87ddc8f

Browse files
committed
fix(compiler): dedup directives in template compiler
Closes #5311 Closes #5464
1 parent 6ddfff5 commit 87ddc8f

File tree

3 files changed

+46
-20
lines changed

3 files changed

+46
-20
lines changed

modules/angular2/src/compiler/runtime_metadata.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
RegExpWrapper
99
} from 'angular2/src/facade/lang';
1010
import {BaseException} from 'angular2/src/facade/exceptions';
11-
import {MapWrapper, StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
1211
import * as cpl from './directive_metadata';
1312
import * as md from 'angular2/src/core/metadata/directives';
1413
import {DirectiveResolver} from 'angular2/src/core/linker/directive_resolver';
@@ -77,16 +76,10 @@ export class RuntimeMetadataResolver {
7776
}
7877
}
7978

80-
return removeDuplicates(directives).map(type => this.getMetadata(type));
79+
return directives.map(type => this.getMetadata(type));
8180
}
8281
}
8382

84-
function removeDuplicates(items: any[]): any[] {
85-
let m = new Map<any, any>();
86-
items.forEach(i => m.set(i, null));
87-
return MapWrapper.keys(m);
88-
}
89-
9083
function flattenDirectives(view: ViewMetadata, platformDirectives: any[]): Type[] {
9184
let directives = [];
9285
if (isPresent(platformDirectives)) {

modules/angular2/src/compiler/template_compiler.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {IS_DART, Type, Json, isBlank, stringify} from 'angular2/src/facade/lang';
22
import {BaseException} from 'angular2/src/facade/exceptions';
3-
import {ListWrapper, SetWrapper} from 'angular2/src/facade/collection';
3+
import {ListWrapper, SetWrapper, MapWrapper} from 'angular2/src/facade/collection';
44
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
55
import {
66
CompiledComponentTemplate,
@@ -96,6 +96,7 @@ export class TemplateCompiler {
9696
private _compileComponentRuntime(
9797
cacheKey: any, compMeta: CompileDirectiveMetadata, viewDirectives: CompileDirectiveMetadata[],
9898
compilingComponentCacheKeys: Set<any>): CompiledComponentTemplate {
99+
let uniqViewDirectives = removeDuplicates(viewDirectives);
99100
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
100101
var done = this._compiledTemplateDone.get(cacheKey);
101102
if (isBlank(compiledTemplate)) {
@@ -109,7 +110,7 @@ export class TemplateCompiler {
109110
compilingComponentCacheKeys.add(cacheKey);
110111
done = PromiseWrapper
111112
.all([<any>this._styleCompiler.compileComponentRuntime(compMeta.template)].concat(
112-
viewDirectives.map(dirMeta => this.normalizeDirectiveMetadata(dirMeta))))
113+
uniqViewDirectives.map(dirMeta => this.normalizeDirectiveMetadata(dirMeta))))
113114
.then((stylesAndNormalizedViewDirMetas: any[]) => {
114115
var childPromises = [];
115116
var normalizedViewDirMetas = stylesAndNormalizedViewDirMetas.slice(1);
@@ -175,9 +176,9 @@ export class TemplateCompiler {
175176
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
176177
assertComponent(compMeta);
177178
componentMetas.push(compMeta);
178-
this._processTemplateCodeGen(compMeta,
179-
<CompileDirectiveMetadata[]>componentWithDirs.directives,
180-
declarations, templateArguments);
179+
180+
this._processTemplateCodeGen(compMeta, componentWithDirs.directives, declarations,
181+
templateArguments);
181182
if (compMeta.dynamicLoadable) {
182183
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
183184
componentMetas.push(hostMeta);
@@ -212,9 +213,10 @@ export class TemplateCompiler {
212213
private _processTemplateCodeGen(compMeta: CompileDirectiveMetadata,
213214
directives: CompileDirectiveMetadata[],
214215
targetDeclarations: string[], targetTemplateArguments: any[][]) {
216+
let uniqueDirectives = removeDuplicates(directives);
215217
var styleExpr = this._styleCompiler.compileComponentCodeGen(compMeta.template);
216-
var parsedTemplate =
217-
this._templateParser.parse(compMeta.template.template, directives, compMeta.type.name);
218+
var parsedTemplate = this._templateParser.parse(compMeta.template.template, uniqueDirectives,
219+
compMeta.type.name);
218220
var changeDetectorsExprs = this._cdCompiler.compileComponentCodeGen(
219221
compMeta.type, compMeta.changeDetection, parsedTemplate);
220222
var commandsExpr = this._commandCompiler.compileComponentCodeGen(
@@ -263,3 +265,17 @@ function addAll(source: any[], target: any[]) {
263265
function codeGenComponentTemplateFactory(nestedCompType: CompileDirectiveMetadata): string {
264266
return `${moduleRef(templateModuleUrl(nestedCompType.type.moduleUrl))}${templateGetterName(nestedCompType.type)}`;
265267
}
268+
269+
function removeDuplicates(items: CompileDirectiveMetadata[]): CompileDirectiveMetadata[] {
270+
let res = [];
271+
items.forEach(item => {
272+
let hasMatch =
273+
res.filter(r => r.type.name == item.type.name && r.type.moduleUrl == item.type.moduleUrl &&
274+
r.type.runtime == item.type.runtime)
275+
.length > 0;
276+
if (!hasMatch) {
277+
res.push(item);
278+
}
279+
});
280+
return res;
281+
}

modules/angular2/test/compiler/template_compiler_spec.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
afterEach,
1111
AsyncTestCompleter,
1212
inject,
13-
beforeEachBindings
13+
beforeEachProviders
1414
} from 'angular2/testing_internal';
1515

1616
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
@@ -57,7 +57,7 @@ export function main() {
5757
var compiler: TemplateCompiler;
5858
var runtimeMetadataResolver: RuntimeMetadataResolver;
5959

60-
beforeEachBindings(() => TEST_PROVIDERS);
60+
beforeEachProviders(() => TEST_PROVIDERS);
6161
beforeEach(inject([TemplateCompiler, RuntimeMetadataResolver],
6262
(_compiler, _runtimeMetadataResolver) => {
6363
compiler = _compiler;
@@ -122,9 +122,18 @@ export function main() {
122122
async.done();
123123
});
124124
}));
125+
126+
it('should dedup directives', inject([AsyncTestCompleter], (async) => {
127+
compile([CompWithDupDirectives, TreeComp])
128+
.then((humanizedTemplate) => {
129+
expect(humanizedTemplate['commands'][1]['commands'][0]).toEqual("<tree>");
130+
async.done();
131+
132+
});
133+
}));
125134
}
126135

127-
xdescribe('compileHostComponentRuntime', () => {
136+
describe('compileHostComponentRuntime', () => {
128137
function compile(components: Type[]): Promise<any[]> {
129138
return compiler.compileHostComponentRuntime(components[0])
130139
.then((compiledHostTemplate) => humanizeTemplate(compiledHostTemplate.template));
@@ -179,7 +188,6 @@ export function main() {
179188
});
180189
xhr.flush();
181190
}));
182-
183191
});
184192

185193
describe('compileTemplatesCodeGen', () => {
@@ -290,6 +298,15 @@ class CompWithBindingsAndStyles {
290298
class TreeComp {
291299
}
292300

301+
@Component({selector: 'comp-wit-dup-tpl', moduleId: THIS_MODULE_ID})
302+
@View({
303+
template: '<tree></tree>',
304+
directives: [TreeComp, TreeComp],
305+
encapsulation: ViewEncapsulation.None
306+
})
307+
class CompWithDupDirectives {
308+
}
309+
293310
@Component({selector: 'comp-url', moduleId: THIS_MODULE_ID})
294311
@View({templateUrl: 'compUrl.html', encapsulation: ViewEncapsulation.None})
295312
class CompWithTemplateUrl {
@@ -349,7 +366,7 @@ export function humanizeTemplate(
349366
}
350367

351368
class TestContext implements CompWithBindingsAndStyles, TreeComp, CompWithTemplateUrl,
352-
CompWithEmbeddedTemplate {
369+
CompWithEmbeddedTemplate, CompWithDupDirectives {
353370
someProp: string;
354371
}
355372

0 commit comments

Comments
 (0)
X Tutup