fix(forms): use strict runtimeType checks instead of instanceof
Currently, validators extending built-in validators are treated as built-in. This can result in an error when both a real built-in validator and a custom one are applied to the same element. Closes #6981
This commit is contained in:
parent
8f47aa3530
commit
50548fb565
|
@ -1,5 +1,5 @@
|
||||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {isBlank, isPresent, looseIdentical} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, looseIdentical, hasConstructor} from 'angular2/src/facade/lang';
|
||||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||||
|
|
||||||
import {ControlContainer} from './control_container';
|
import {ControlContainer} from './control_container';
|
||||||
|
@ -82,11 +82,13 @@ export function selectValueAccessor(dir: NgControl,
|
||||||
var builtinAccessor;
|
var builtinAccessor;
|
||||||
var customAccessor;
|
var customAccessor;
|
||||||
valueAccessors.forEach(v => {
|
valueAccessors.forEach(v => {
|
||||||
if (v instanceof DefaultValueAccessor) {
|
if (hasConstructor(v, DefaultValueAccessor)) {
|
||||||
defaultAccessor = v;
|
defaultAccessor = v;
|
||||||
|
|
||||||
} else if (v instanceof CheckboxControlValueAccessor || v instanceof NumberValueAccessor ||
|
} else if (hasConstructor(v, CheckboxControlValueAccessor) ||
|
||||||
v instanceof SelectControlValueAccessor || v instanceof RadioControlValueAccessor) {
|
hasConstructor(v, NumberValueAccessor) ||
|
||||||
|
hasConstructor(v, SelectControlValueAccessor) ||
|
||||||
|
hasConstructor(v, RadioControlValueAccessor)) {
|
||||||
if (isPresent(builtinAccessor))
|
if (isPresent(builtinAccessor))
|
||||||
_throwError(dir, "More than one built-in value accessor matches");
|
_throwError(dir, "More than one built-in value accessor matches");
|
||||||
builtinAccessor = v;
|
builtinAccessor = v;
|
||||||
|
|
|
@ -353,3 +353,7 @@ var global = null;
|
||||||
dynamic evalExpression(String sourceUrl, String expr, String declarations, Map<String, String> vars) {
|
dynamic evalExpression(String sourceUrl, String expr, String declarations, Map<String, String> vars) {
|
||||||
throw "Dart does not support evaluating expression during runtime!";
|
throw "Dart does not support evaluating expression during runtime!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasConstructor(Object value, Type type) {
|
||||||
|
return value.runtimeType == type;
|
||||||
|
}
|
||||||
|
|
|
@ -464,3 +464,7 @@ export function evalExpression(sourceUrl: string, expr: string, declarations: st
|
||||||
export function isPrimitive(obj: any): boolean {
|
export function isPrimitive(obj: any): boolean {
|
||||||
return !isJsObject(obj);
|
return !isJsObject(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hasConstructor(value: Object, type: Type): boolean {
|
||||||
|
return value.constructor === type;
|
||||||
|
}
|
|
@ -4,9 +4,13 @@ import {
|
||||||
RegExpWrapper,
|
RegExpWrapper,
|
||||||
RegExpMatcherWrapper,
|
RegExpMatcherWrapper,
|
||||||
StringWrapper,
|
StringWrapper,
|
||||||
CONST_EXPR
|
CONST_EXPR,
|
||||||
|
hasConstructor
|
||||||
} from 'angular2/src/facade/lang';
|
} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
|
class MySuperclass {}
|
||||||
|
class MySubclass extends MySuperclass {}
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('RegExp', () => {
|
describe('RegExp', () => {
|
||||||
it('should expose the index for each match', () => {
|
it('should expose the index for each match', () => {
|
||||||
|
@ -119,5 +123,13 @@ export function main() {
|
||||||
expect(StringWrapper.stripRight(null, "S")).toEqual(null);
|
expect(StringWrapper.stripRight(null, "S")).toEqual(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('hasConstructor', () => {
|
||||||
|
it("should be true when the type matches",
|
||||||
|
() => { expect(hasConstructor(new MySuperclass(), MySuperclass)).toEqual(true); });
|
||||||
|
|
||||||
|
it("should be false for subtypes",
|
||||||
|
() => { expect(hasConstructor(new MySubclass(), MySuperclass)).toEqual(false); });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue