fix(ivy): inherited listeners from grand super classes invoked multiple times (#30169)
Fixes event listeners that come from more than one level of inheritance being invoked multiple times. This PR resolves FW-1294. PR Close #30169
This commit is contained in:
parent
ad94e02981
commit
37c598db04
|
@ -171,6 +171,10 @@ function inheritHostBindings(
|
|||
definition: DirectiveDef<any>| ComponentDef<any>,
|
||||
superHostBindings: HostBindingsFunction<any>) {
|
||||
const prevHostBindings = definition.hostBindings;
|
||||
// If the subclass does not have a host bindings function, we set the subclass host binding
|
||||
// function to be the superclass's (in this feature). We should check if they're the same here
|
||||
// to ensure we don't inherit it twice.
|
||||
if (superHostBindings !== prevHostBindings) {
|
||||
if (prevHostBindings) {
|
||||
// because inheritance is unknown during compile time, the runtime code
|
||||
// needs to be informed of the super-class depth so that instruction code
|
||||
|
@ -196,3 +200,4 @@ function inheritHostBindings(
|
|||
definition.hostBindings = superHostBindings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,27 +253,91 @@ describe('acceptance integration tests', () => {
|
|||
expect(clicks).toBe(1);
|
||||
});
|
||||
|
||||
// TODO(crisbeto): this fails even with decorated classes
|
||||
// in master. To be enabled as a part of FW-1294.
|
||||
xit('should inherit host listeners from undecorated grand superclasses', () => {
|
||||
it('should inherit host listeners from superclasses once', () => {
|
||||
let clicks = 0;
|
||||
|
||||
@Directive({selector: '[baseButton]'})
|
||||
class BaseButton {
|
||||
@HostListener('click')
|
||||
handleClick() { clicks++; }
|
||||
}
|
||||
|
||||
@Component({selector: '[subButton]', template: '<ng-content></ng-content>'})
|
||||
class SubButton extends BaseButton {
|
||||
}
|
||||
|
||||
@Component({template: '<button subButton>Click me</button>'})
|
||||
class App {
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [SubButton, BaseButton, App]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
const button = fixture.debugElement.query(By.directive(SubButton)).nativeElement;
|
||||
|
||||
button.click();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(clicks).toBe(1);
|
||||
});
|
||||
|
||||
it('should inherit host listeners from grand superclasses once', () => {
|
||||
let clicks = 0;
|
||||
|
||||
@Directive({selector: '[superBaseButton]'})
|
||||
class SuperBaseButton {
|
||||
@HostListener('click')
|
||||
handleClick() { clicks++; }
|
||||
}
|
||||
|
||||
class BaseButton extends SuperBaseButton {}
|
||||
@Directive({selector: '[baseButton]'})
|
||||
class BaseButton extends SuperBaseButton {
|
||||
}
|
||||
|
||||
@Component({selector: '[sub-button]', template: '<ng-content></ng-content>'})
|
||||
@Component({selector: '[subButton]', template: '<ng-content></ng-content>'})
|
||||
class SubButton extends BaseButton {
|
||||
}
|
||||
|
||||
@Component({template: '<button sub-button>Click me</button>'})
|
||||
@Component({template: '<button subButton>Click me</button>'})
|
||||
class App {
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [SubButton, App]});
|
||||
TestBed.configureTestingModule({declarations: [SubButton, SuperBaseButton, BaseButton, App]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
const button = fixture.debugElement.query(By.directive(SubButton)).nativeElement;
|
||||
|
||||
button.click();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(clicks).toBe(1);
|
||||
});
|
||||
|
||||
it('should inherit host listeners from grand grand superclasses once', () => {
|
||||
let clicks = 0;
|
||||
|
||||
@Directive({selector: '[superSuperBaseButton]'})
|
||||
class SuperSuperBaseButton {
|
||||
@HostListener('click')
|
||||
handleClick() { clicks++; }
|
||||
}
|
||||
|
||||
@Directive({selector: '[superBaseButton]'})
|
||||
class SuperBaseButton extends SuperSuperBaseButton {
|
||||
}
|
||||
|
||||
@Directive({selector: '[baseButton]'})
|
||||
class BaseButton extends SuperBaseButton {
|
||||
}
|
||||
|
||||
@Component({selector: '[subButton]', template: '<ng-content></ng-content>'})
|
||||
class SubButton extends BaseButton {
|
||||
}
|
||||
|
||||
@Component({template: '<button subButton>Click me</button>'})
|
||||
class App {
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule(
|
||||
{declarations: [SubButton, SuperBaseButton, SuperSuperBaseButton, BaseButton, App]});
|
||||
const fixture = TestBed.createComponent(App);
|
||||
const button = fixture.debugElement.query(By.directive(SubButton)).nativeElement;
|
||||
|
||||
|
|
Loading…
Reference in New Issue