Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions packages/compiler-cli/test/ngtsc/host_directives_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,59 @@ runInEachFileSystem(() => {

expect(messages).toEqual([]);
});

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the error being fixed here was only in the runtime, not the compiler. I ported the tests over to the compiler for consistency.

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);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
60 changes: 60 additions & 0 deletions packages/core/test/acceptance/host_directives_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
});
});