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…
Reference in New Issue