Open mtraynham opened 7 years ago
I've been looking more at this. Angular 2 had an issue and relevant commit for this as well, which seems like it makes no upstream changes to either reflect library.
For propMetadata
, they are checking if the class extends another class and merging all property metadata fields here.
For parameters, It looks like they are collecting the annotations themselves for only the child class and seperately for the parent here, deduping as necessary.
Here's a simplified version of debugging this...
import 'core-js/es7/reflect';
import {reflector} from 'ng-metadata/src/core/reflection/reflection';
import {Input} from 'ng-metadata/src/core/directives/decorators';
import {Host, Inject} from 'ng-metadata/src/core/di/decorators';
abstract class AbstractPropertyComponent {
@Input() public a: string;
}
export class APropertyComponent extends AbstractPropertyComponent {
@Input() public b: string;
}
const aPropMetadata: {[p: string]: any[]} = reflector.propMetadata(APropertyComponent);
console.log(aPropMetadata);
abstract class AbstractConstructorComponent {
private form: any;
constructor (@Inject('form') @Host() form: any) {
this.form = form;
}
}
class AConstructorComponent extends AbstractConstructorComponent {
private $http: any;
constructor (@Inject('form') @Host() form: any,
@Inject('$http') $http: any) {
super(form);
this.$http = $http;
}
}
class BConstructorComponent extends AbstractConstructorComponent {
private app: any;
constructor (@Inject('form') @Host() form: any,
@Inject('app') @Host() app: any) {
super(form);
this.app = app;
}
}
const aConstructorAnnotations: any[][] = reflector.parameters(AConstructorComponent);
console.log(aConstructorAnnotations);
const bConstructorAnnotations: any[][] = reflector.parameters(BConstructorComponent);
console.log(bConstructorAnnotations);
As a preamble on how I came across these bugs, I have a form that uses a variety of components, from string inputs to selects, etc. Some of the components may be more custom than others, but they all share a set of input/output bindings and may share some
@Host
components.I tried this with both core-js and reflect-metadata with the same results.
The two issues I found with Plunkr and examples on how to recreate:
@Input
(and potentially@Output
) decorators are not inherited if the child component class specifies it's own@Input
.The code below has:
@Input a
,@Input a
@Input b
, and does not inherit@Input a
The expected output of this code should be a string,
a a b
. The actual output is justa b
Here is this bugs Plunkr example (all code is in app.module.ts).
@Host
(and potentially@Self
/@SkipSelf
) constructor decorators incorrectly get applied to the parent class, adding parameter information to all child classes.The code below has:
@Inject('form') @Host
of anIFormController
,@Inject('$http')
, theIHttpService
@Inject('app') @Host
the parentAppComponent
.I believe the BComponent's
@Host
on the second parameter is getting applied to every second parameter of any child ofAbstractComponent
and thus the$http
services becomes a required directive.Here is this bugs Plunkr example (all code is in app.module.ts).
This actually breaks Angular with an error logged as: