Skip to content

Commit 8c37b7e

Browse files
erictsangxrkirov
authored andcommitted
fix(directive): throw if output the same event more than once
Close: #4798
1 parent c8e909f commit 8c37b7e

2 files changed

Lines changed: 33 additions & 5 deletions

File tree

modules/angular2/src/core/linker/directive_resolver.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {resolveForwardRef, Injectable} from 'angular2/src/core/di';
22
import {Type, isPresent, isBlank, stringify} from 'angular2/src/facade/lang';
33
import {BaseException} from 'angular2/src/facade/exceptions';
44
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
5+
56
import {
67
DirectiveMetadata,
78
ComponentMetadata,
@@ -38,15 +39,16 @@ export class DirectiveResolver {
3839
var metadata = typeMetadata.find(_isDirectiveMetadata);
3940
if (isPresent(metadata)) {
4041
var propertyMetadata = reflector.propMetadata(type);
41-
return this._mergeWithPropertyMetadata(metadata, propertyMetadata);
42+
return this._mergeWithPropertyMetadata(metadata, propertyMetadata, type);
4243
}
4344
}
4445

4546
throw new BaseException(`No Directive annotation found on ${stringify(type)}`);
4647
}
4748

4849
private _mergeWithPropertyMetadata(dm: DirectiveMetadata,
49-
propertyMetadata: {[key: string]: any[]}): DirectiveMetadata {
50+
propertyMetadata: {[key: string]: any[]},
51+
directiveType: Type): DirectiveMetadata {
5052
var inputs = [];
5153
var outputs = [];
5254
var host: {[key: string]: string} = {};
@@ -100,13 +102,27 @@ export class DirectiveResolver {
100102
}
101103
});
102104
});
103-
return this._merge(dm, inputs, outputs, host, queries);
105+
return this._merge(dm, inputs, outputs, host, queries, directiveType);
104106
}
105107

106108
private _merge(dm: DirectiveMetadata, inputs: string[], outputs: string[],
107-
host: {[key: string]: string}, queries: {[key: string]: any}): DirectiveMetadata {
109+
host: {[key: string]: string}, queries: {[key: string]: any},
110+
directiveType: Type): DirectiveMetadata {
108111
var mergedInputs = isPresent(dm.inputs) ? ListWrapper.concat(dm.inputs, inputs) : inputs;
109-
var mergedOutputs = isPresent(dm.outputs) ? ListWrapper.concat(dm.outputs, outputs) : outputs;
112+
113+
var mergedOutputs;
114+
if (isPresent(dm.outputs)) {
115+
dm.outputs.forEach((propName: string) => {
116+
if (ListWrapper.contains(outputs, propName)) {
117+
throw new BaseException(
118+
`Output event '${propName}' defined multiple times in '${stringify(directiveType)}'`);
119+
}
120+
});
121+
mergedOutputs = ListWrapper.concat(dm.outputs, outputs);
122+
} else {
123+
mergedOutputs = outputs;
124+
}
125+
110126
var mergedHost = isPresent(dm.host) ? StringMapWrapper.merge(dm.host, host) : host;
111127
var mergedQueries =
112128
isPresent(dm.queries) ? StringMapWrapper.merge(dm.queries, queries) : queries;

modules/angular2/test/core/linker/directive_resolver_spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ class SomeDirectiveWithOutputs {
3939
c;
4040
}
4141

42+
43+
@Directive({selector: 'someDirective', outputs: ['a']})
44+
class SomeDirectiveWithDuplicateOutputs {
45+
@Output() a;
46+
}
47+
4248
@Directive({selector: 'someDirective', properties: ['a']})
4349
class SomeDirectiveWithProperties {
4450
}
@@ -153,6 +159,12 @@ export function main() {
153159
var directiveMetadata = resolver.resolve(SomeDirectiveWithGetterOutputs);
154160
expect(directiveMetadata.outputs).toEqual(['a: renamed']);
155161
});
162+
163+
it('should throw if duplicate outputs', () => {
164+
expect(() => { resolver.resolve(SomeDirectiveWithDuplicateOutputs); })
165+
.toThrowError(
166+
`Output event 'a' defined multiple times in 'SomeDirectiveWithDuplicateOutputs'`);
167+
});
156168
});
157169

158170
describe('host', () => {

0 commit comments

Comments
 (0)