Skip to content

Commit

Permalink
fix(ivy): listeners inherited twice if sub class has own propMetadata
Browse files Browse the repository at this point in the history
Fixes host listeners being inherited twice, if the sub class has its own `propMetadata`. This is related to #29170 which fixed something similar, however all of the test cases there had a super class with some metadata and a sub class that didn't have any. The issue manifested itself in the `MatTreeToggle` which inherits a listener from the `CdkTreeToggle` and adds an extra `Input` of its own, causing the listener to be added twice.
  • Loading branch information
crisbeto committed Mar 16, 2019
1 parent 604f37b commit 082458a
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/render3/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function setClassMetadata(
// decorator types. Decorators on individual fields are not merged, as it's also incredibly
// unlikely that a field will be decorated both with an Angular decorator and a non-Angular
// decorator that's also been downleveled.
if (clazz.propDecorators !== undefined) {
if (clazz.hasOwnProperty('propDecorators') && clazz.propDecorators !== undefined) {
clazz.propDecorators = {...clazz.propDecorators, ...propDecorators};
} else {
clazz.propDecorators = propDecorators;
Expand Down
26 changes: 25 additions & 1 deletion packages/core/test/render3/jit/directive_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Directive, HostListener} from '@angular/core';
import {Directive, HostListener, Input} from '@angular/core';
import {setClassMetadata} from '@angular/core/src/render3/metadata';

import {convertToR3QueryMetadata, directiveMetadata, extendsDirectlyFromObject} from '../../../src/render3/jit/directive';
Expand Down Expand Up @@ -130,5 +130,29 @@ describe('jit directive helper functions', () => {
expect(directiveMetadata(SuperDirective, {}).propMetadata.handleClick).toBeFalsy();
expect(directiveMetadata(SubDirective, {}).propMetadata.handleClick).toBeFalsy();
});

it('should not inherit propMetadata from super class when sub class has its own propMetadata',
() => {
class SuperDirective {}
setClassMetadata(SuperDirective, [{type: Directive}], null, {
someInput: [{type: Input}],
handleClick: [{type: HostListener, args: ['click', ['$event']]}]
});

class SubDirective extends SuperDirective {}
setClassMetadata(
SubDirective, [{type: Directive}], null, {someOtherInput: [{type: Input}]});

const superPropMetadata = directiveMetadata(SuperDirective, {}).propMetadata;
const subPropMetadata = directiveMetadata(SubDirective, {}).propMetadata;

expect(superPropMetadata.handleClick).toBeTruthy();
expect(superPropMetadata.someInput).toBeTruthy();

expect(subPropMetadata.handleClick).toBeFalsy();
expect(subPropMetadata.someInput).toBeFalsy();
expect(subPropMetadata.someOtherInput).toBeTruthy();
});

});
});

0 comments on commit 082458a

Please sign in to comment.