fix(ivy): not throwing error for unknown properties on container nodes (#29691)
Fixes Ivy not throwing an error if it runs into an invalid property binding on a container node (e.g. `<div *ngFor="let row of rows">` instead of `<div *ngFor="let row if rows">`). This PR resolves FW-1219. PR Close #29691
This commit is contained in:
		
							parent
							
								
									66b87cef33
								
							
						
					
					
						commit
						d144a3bd91
					
				| @ -161,6 +161,12 @@ function elementPropertyInternal<T>( | ||||
|       (element as RElement).setProperty ? (element as any).setProperty(propName, value) : | ||||
|                                           (element as any)[propName] = value; | ||||
|     } | ||||
|   } else if (tNode.type === TNodeType.Container) { | ||||
|     // If the node is a container and the property didn't
 | ||||
|     // match any of the inputs or schemas we should throw.
 | ||||
|     if (ngDevMode && !matchingSchemas(lView, tNode.tagName)) { | ||||
|       throw createUnknownPropertyError(propName, tNode); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -209,8 +215,7 @@ function validateAgainstUnknownProperties( | ||||
|       // and isn't a synthetic animation property...
 | ||||
|       propName[0] !== ANIMATION_PROP_PREFIX) { | ||||
|     // ... it is probably a user error and we should throw.
 | ||||
|     throw new Error( | ||||
|         `Template error: Can't bind to '${propName}' since it isn't a known property of '${tNode.tagName}'.`); | ||||
|     throw createUnknownPropertyError(propName, tNode); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -257,3 +262,13 @@ function savePropertyDebugData( | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Creates an error that should be thrown when encountering an unknown property on an element. | ||||
|  * @param propName Name of the invalid property. | ||||
|  * @param tNode Node on which we encountered the error. | ||||
|  */ | ||||
| function createUnknownPropertyError(propName: string, tNode: TNode): Error { | ||||
|   return new Error( | ||||
|       `Template error: Can't bind to '${propName}' since it isn't a known property of '${tNode.tagName}'.`); | ||||
| } | ||||
|  | ||||
| @ -1634,6 +1634,21 @@ function declareTests(config?: {useJit: boolean}) { | ||||
|             } | ||||
|           }); | ||||
| 
 | ||||
|       it('should throw on bindings to unknown properties of containers', () => { | ||||
|         TestBed.configureTestingModule({imports: [CommonModule], declarations: [MyComp]}); | ||||
|         const template = '<div *ngFor="let item in ctxArrProp">{{item}}</div>'; | ||||
|         TestBed.overrideComponent(MyComp, {set: {template}}); | ||||
| 
 | ||||
|         try { | ||||
|           const fixture = TestBed.createComponent(MyComp); | ||||
|           fixture.detectChanges(); | ||||
|           throw 'Should throw'; | ||||
|         } catch (e) { | ||||
|           expect(e.message).toMatch( | ||||
|               /Can't bind to 'ngForIn' since it isn't a known property of 'div'./); | ||||
|         } | ||||
|       }); | ||||
| 
 | ||||
|       it('should not throw for property binding to a non-existing property when there is a matching directive property', | ||||
|          () => { | ||||
|            TestBed.configureTestingModule({declarations: [MyComp, MyDir]}); | ||||
| @ -2103,12 +2118,14 @@ class MyComp { | ||||
|   ctxProp: string; | ||||
|   ctxNumProp: number; | ||||
|   ctxBoolProp: boolean; | ||||
|   ctxArrProp: number[]; | ||||
|   toStringThrow = {toString: function() { throw 'boom'; }}; | ||||
| 
 | ||||
|   constructor() { | ||||
|     this.ctxProp = 'initial value'; | ||||
|     this.ctxNumProp = 0; | ||||
|     this.ctxBoolProp = false; | ||||
|     this.ctxArrProp = [0, 1, 2]; | ||||
|   } | ||||
| 
 | ||||
|   throwError() { throw 'boom'; } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user