fix(core): host directives incorrectly validating aliased bindings (#50364)

Fixes that the host directives feature was incorrectly throwing the conflicting alias error when an aliased binding was being exposed under the same alias.

Fixes #48951.

PR Close #50364
This commit is contained in:
Kristiyan Kostadinov
2023-05-19 09:07:19 +02:00
committed by Jessica Janiuk
parent b89fae173e
commit 199ff4fe7f
3 changed files with 114 additions and 1 deletions
@@ -944,6 +944,59 @@ runInEachFileSystem(() => {
expect(messages).toEqual([]);
});
it('should not produce a diagnostic when exposing an aliased binding', () => {
env.write('test.ts', `
import {Directive, EventEmitter} from '@angular/core';
@Directive({
outputs: ['opened: triggerOpened'],
selector: '[trigger]',
standalone: true,
})
export class Trigger {
opened = new EventEmitter();
}
@Directive({
standalone: true,
selector: '[host]',
hostDirectives: [{directive: Trigger, outputs: ['triggerOpened']}]
})
export class Host {}
`);
const diags = env.driveDiagnostics();
expect(diags.length).toBe(0);
});
it('should not produce a diagnostic when exposing an inherited aliased binding', () => {
env.write('test.ts', `
import {Directive, EventEmitter} from '@angular/core';
@Directive({standalone: true})
export abstract class Base {
opened = new EventEmitter();
}
@Directive({
outputs: ['opened: triggerOpened'],
selector: '[trigger]',
standalone: true,
})
export class Trigger extends Base {}
@Directive({
standalone: true,
selector: '[host]',
hostDirectives: [{directive: Trigger, outputs: ['triggerOpened: hostOpened']}]
})
export class Host {}
`);
const diags = env.driveDiagnostics();
expect(diags.length).toBe(0);
});
});
});
});
@@ -204,7 +204,7 @@ function validateMappings(
const remappedPublicName = hostDirectiveBindings[publicName];
if (bindings.hasOwnProperty(remappedPublicName) &&
if (bindings.hasOwnProperty(remappedPublicName) && remappedPublicName !== publicName &&
bindings[remappedPublicName] !== publicName) {
throw new RuntimeError(
RuntimeErrorCode.HOST_DIRECTIVE_CONFLICTING_ALIAS,
@@ -3219,5 +3219,65 @@ describe('host directives', () => {
fixture.detectChanges();
}).not.toThrow();
});
it('should not throw when exposing an aliased binding', () => {
@Directive({
outputs: ['opened: triggerOpened'],
selector: '[trigger]',
standalone: true,
})
class Trigger {
opened = new EventEmitter();
}
@Directive({
standalone: true,
selector: '[host]',
hostDirectives: [{directive: Trigger, outputs: ['triggerOpened']}]
})
class Host {
}
@Component({template: '<div host></div>', standalone: true, imports: [Host]})
class App {
}
expect(() => {
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
}).not.toThrow();
});
it('should not throw when exposing an inherited aliased binding', () => {
@Directive({standalone: true})
abstract class Base {
opened = new EventEmitter();
}
@Directive({
outputs: ['opened: triggerOpened'],
selector: '[trigger]',
standalone: true,
})
class Trigger extends Base {
}
@Directive({
standalone: true,
selector: '[host]',
hostDirectives: [{directive: Trigger, outputs: ['triggerOpened: hostOpened']}]
})
class Host {
}
@Component({template: '<div host></div>', standalone: true, imports: [Host]})
class App {
}
expect(() => {
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
}).not.toThrow();
});
});
});