fix(ivy): directives without selector should not be supported (#28021)
PR Close #28021
This commit is contained in:
		
							parent
							
								
									7374dfd1fa
								
							
						
					
					
						commit
						76ed13bffe
					
				| @ -165,6 +165,9 @@ export function extractDirectiveMetadata( | |||||||
|     } |     } | ||||||
|     selector = resolved; |     selector = resolved; | ||||||
|   } |   } | ||||||
|  |   if (!selector) { | ||||||
|  |     throw new Error(`Directive ${clazz.name !.text} has no selector, please add it!`); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   const host = extractHostBindings(directive, decoratedElements, evaluator, coreModule); |   const host = extractHostBindings(directive, decoratedElements, evaluator, coreModule); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -640,9 +640,6 @@ describe('compiler compliance', () => { | |||||||
|           'spec.ts': ` |           'spec.ts': ` | ||||||
|             import {Component, Directive, NgModule} from '@angular/core'; |             import {Component, Directive, NgModule} from '@angular/core'; | ||||||
| 
 | 
 | ||||||
|             @Directive({}) |  | ||||||
|             export class EmptyOutletDirective {} |  | ||||||
| 
 |  | ||||||
|             @Component({template: '<router-outlet></router-outlet>'}) |             @Component({template: '<router-outlet></router-outlet>'}) | ||||||
|             export class EmptyOutletComponent {} |             export class EmptyOutletComponent {} | ||||||
| 
 | 
 | ||||||
| @ -652,16 +649,6 @@ describe('compiler compliance', () => { | |||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       // EmptyOutletDirective definition should be:
 |  | ||||||
|       const EmptyOutletDirectiveDefinition = ` |  | ||||||
|         … |  | ||||||
|         EmptyOutletDirective.ngDirectiveDef = $r3$.ɵdefineDirective({ |  | ||||||
|           type: EmptyOutletDirective, |  | ||||||
|           selectors: [], |  | ||||||
|           factory: function EmptyOutletDirective_Factory(t) { return new (t || EmptyOutletDirective)(); } |  | ||||||
|         }); |  | ||||||
|       `;
 |  | ||||||
| 
 |  | ||||||
|       // EmptyOutletComponent definition should be:
 |       // EmptyOutletComponent definition should be:
 | ||||||
|       const EmptyOutletComponentDefinition = ` |       const EmptyOutletComponentDefinition = ` | ||||||
|         … |         … | ||||||
| @ -683,13 +670,48 @@ describe('compiler compliance', () => { | |||||||
|       const result = compile(files, angularFiles); |       const result = compile(files, angularFiles); | ||||||
|       const source = result.source; |       const source = result.source; | ||||||
| 
 | 
 | ||||||
|       expectEmit( |  | ||||||
|           source, EmptyOutletDirectiveDefinition, |  | ||||||
|           'Incorrect EmptyOutletDirective.ngDirectiveDefDef'); |  | ||||||
|       expectEmit( |       expectEmit( | ||||||
|           source, EmptyOutletComponentDefinition, 'Incorrect EmptyOutletComponent.ngComponentDef'); |           source, EmptyOutletComponentDefinition, 'Incorrect EmptyOutletComponent.ngComponentDef'); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     it('should not support directives without selector', () => { | ||||||
|  |       const files = { | ||||||
|  |         app: { | ||||||
|  |           'spec.ts': ` | ||||||
|  |             import {Component, Directive, NgModule} from '@angular/core'; | ||||||
|  | 
 | ||||||
|  |             @Directive({}) | ||||||
|  |             export class EmptyOutletDirective {} | ||||||
|  | 
 | ||||||
|  |             @NgModule({declarations: [EmptyOutletDirective]}) | ||||||
|  |             export class MyModule{} | ||||||
|  |           ` | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       expect(() => compile(files, angularFiles)) | ||||||
|  |           .toThrowError('Directive EmptyOutletDirective has no selector, please add it!'); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('should not support directives with empty selector', () => { | ||||||
|  |       const files = { | ||||||
|  |         app: { | ||||||
|  |           'spec.ts': ` | ||||||
|  |             import {Component, Directive, NgModule} from '@angular/core'; | ||||||
|  | 
 | ||||||
|  |             @Directive({selector: ''}) | ||||||
|  |             export class EmptyOutletDirective {} | ||||||
|  | 
 | ||||||
|  |             @NgModule({declarations: [EmptyOutletDirective]}) | ||||||
|  |             export class MyModule{} | ||||||
|  |           ` | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       expect(() => compile(files, angularFiles)) | ||||||
|  |           .toThrowError('Directive EmptyOutletDirective has no selector, please add it!'); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|     it('should not treat ElementRef, ViewContainerRef, or ChangeDetectorRef specially when injecting', |     it('should not treat ElementRef, ViewContainerRef, or ChangeDetectorRef specially when injecting', | ||||||
|        () => { |        () => { | ||||||
|          const files = { |          const files = { | ||||||
|  | |||||||
| @ -164,9 +164,9 @@ export function compileDirectiveFromMetadata( | |||||||
|   addFeatures(definitionMap, meta); |   addFeatures(definitionMap, meta); | ||||||
|   const expression = o.importExpr(R3.defineDirective).callFn([definitionMap.toLiteralMap()]); |   const expression = o.importExpr(R3.defineDirective).callFn([definitionMap.toLiteralMap()]); | ||||||
| 
 | 
 | ||||||
|   // On the type side, remove newlines from the selector as it will need to fit into a TypeScript
 |   if (!meta.selector) { | ||||||
|   // string literal, which must be on one line.
 |     throw new Error(`Directive ${meta.name} has no selector, please add it!`); | ||||||
|   const selectorForType = (meta.selector || '').replace(/\n/g, ''); |   } | ||||||
| 
 | 
 | ||||||
|   const type = createTypeForDef(meta, R3.DirectiveDefWithMeta); |   const type = createTypeForDef(meta, R3.DirectiveDefWithMeta); | ||||||
|   return {expression, type, statements}; |   return {expression, type, statements}; | ||||||
|  | |||||||
| @ -1423,21 +1423,19 @@ function declareTests(config?: {useJit: boolean}) { | |||||||
|         expect(getDOM().querySelectorAll(fixture.nativeElement, 'script').length).toEqual(0); |         expect(getDOM().querySelectorAll(fixture.nativeElement, 'script').length).toEqual(0); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       fixmeIvy('FW-662: Components without selector are not supported') |       it('should throw when using directives without selector', () => { | ||||||
|           .it('should throw when using directives without selector', () => { |         @Directive({}) | ||||||
|             @Directive({}) |         class SomeDirective { | ||||||
|             class SomeDirective { |         } | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             @Component({selector: 'comp', template: ''}) |         @Component({selector: 'comp', template: ''}) | ||||||
|             class SomeComponent { |         class SomeComponent { | ||||||
|             } |         } | ||||||
| 
 | 
 | ||||||
|             TestBed.configureTestingModule({declarations: [MyComp, SomeDirective, SomeComponent]}); |         TestBed.configureTestingModule({declarations: [MyComp, SomeDirective, SomeComponent]}); | ||||||
|             expect(() => TestBed.createComponent(MyComp)) |         expect(() => TestBed.createComponent(MyComp)) | ||||||
|                 .toThrowError( |             .toThrowError(`Directive ${stringify(SomeDirective)} has no selector, please add it!`); | ||||||
|                     `Directive ${stringify(SomeDirective)} has no selector, please add it!`); |       }); | ||||||
|           }); |  | ||||||
| 
 | 
 | ||||||
|       it('should use a default element name for components without selectors', () => { |       it('should use a default element name for components without selectors', () => { | ||||||
|         let noSelectorComponentFactory: ComponentFactory<SomeComponent> = undefined !; |         let noSelectorComponentFactory: ComponentFactory<SomeComponent> = undefined !; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user