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 {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 {ControlContainer} from './control_container'; | ||||
| @ -82,11 +82,13 @@ export function selectValueAccessor(dir: NgControl, | ||||
|   var builtinAccessor; | ||||
|   var customAccessor; | ||||
|   valueAccessors.forEach(v => { | ||||
|     if (v instanceof DefaultValueAccessor) { | ||||
|     if (hasConstructor(v, DefaultValueAccessor)) { | ||||
|       defaultAccessor = v; | ||||
| 
 | ||||
|     } else if (v instanceof CheckboxControlValueAccessor || v instanceof NumberValueAccessor || | ||||
|                v instanceof SelectControlValueAccessor || v instanceof RadioControlValueAccessor) { | ||||
|     } else if (hasConstructor(v, CheckboxControlValueAccessor) || | ||||
|                hasConstructor(v, NumberValueAccessor) || | ||||
|                hasConstructor(v, SelectControlValueAccessor) || | ||||
|                hasConstructor(v, RadioControlValueAccessor)) { | ||||
|       if (isPresent(builtinAccessor)) | ||||
|         _throwError(dir, "More than one built-in value accessor matches"); | ||||
|       builtinAccessor = v; | ||||
|  | ||||
| @ -353,3 +353,7 @@ var global = null; | ||||
| dynamic evalExpression(String sourceUrl, String expr, String declarations, Map<String, String> vars) { | ||||
|   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 { | ||||
|   return !isJsObject(obj); | ||||
| } | ||||
| 
 | ||||
| export function hasConstructor(value: Object, type: Type): boolean { | ||||
|   return value.constructor === type; | ||||
| } | ||||
| @ -4,9 +4,13 @@ import { | ||||
|   RegExpWrapper, | ||||
|   RegExpMatcherWrapper, | ||||
|   StringWrapper, | ||||
|   CONST_EXPR | ||||
|   CONST_EXPR, | ||||
|   hasConstructor | ||||
| } from 'angular2/src/facade/lang'; | ||||
| 
 | ||||
| class MySuperclass {} | ||||
| class MySubclass extends MySuperclass {} | ||||
| 
 | ||||
| export function main() { | ||||
|   describe('RegExp', () => { | ||||
|     it('should expose the index for each match', () => { | ||||
| @ -119,5 +123,13 @@ export function main() { | ||||
|         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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user