feat(ivy): Add InheritanceDefinitionFeature to support directive inheritance (#24570)
- Adds InheritanceDefinitionFeature to ivy - Ensures that lifecycle hooks are inherited from super classes whether they are defined as directives or not - Directives cannot inherit from Components - Components can inherit from Directives or Components - Ensures that Inputs, Outputs, and Host Bindings are inherited - Ensures that super class Features are run PR Close #24570
This commit is contained in:
@ -121,6 +121,10 @@ export function compileDirective(type: Type<any>, directive: Directive): void {
|
||||
}
|
||||
|
||||
|
||||
export function extendsDirectlyFromObject(type: Type<any>): boolean {
|
||||
return Object.getPrototypeOf(type.prototype) === Object.prototype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the `R3DirectiveMetadata` for a particular directive (either a `Directive` or a
|
||||
* `Component`).
|
||||
@ -136,14 +140,16 @@ function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMet
|
||||
|
||||
const inputsFromType: StringMap = {};
|
||||
const outputsFromType: StringMap = {};
|
||||
for (let field in propMetadata) {
|
||||
propMetadata[field].forEach(ann => {
|
||||
if (isInput(ann)) {
|
||||
inputsFromType[field] = ann.bindingPropertyName || field;
|
||||
} else if (isOutput(ann)) {
|
||||
outputsFromType[field] = ann.bindingPropertyName || field;
|
||||
}
|
||||
});
|
||||
for (const field in propMetadata) {
|
||||
if (propMetadata.hasOwnProperty(field)) {
|
||||
propMetadata[field].forEach(ann => {
|
||||
if (isInput(ann)) {
|
||||
inputsFromType[field] = ann.bindingPropertyName || field;
|
||||
} else if (isOutput(ann)) {
|
||||
outputsFromType[field] = ann.bindingPropertyName || field;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
@ -158,6 +164,7 @@ function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMet
|
||||
usesOnChanges: type.prototype.ngOnChanges !== undefined,
|
||||
},
|
||||
typeSourceSpan: null !,
|
||||
usesInheritance: !extendsDirectlyFromObject(type),
|
||||
};
|
||||
}
|
||||
|
||||
@ -174,14 +181,16 @@ function extractHostBindings(metadata: Directive, propMetadata: {[key: string]:
|
||||
}
|
||||
|
||||
// Next, loop over the properties of the object, looking for @HostBinding and @HostListener.
|
||||
for (let field in propMetadata) {
|
||||
propMetadata[field].forEach(ann => {
|
||||
if (isHostBinding(ann)) {
|
||||
properties[ann.hostPropertyName || field] = field;
|
||||
} else if (isHostListener(ann)) {
|
||||
listeners[ann.eventName || field] = `${field}(${(ann.args || []).join(',')})`;
|
||||
}
|
||||
});
|
||||
for (const field in propMetadata) {
|
||||
if (propMetadata.hasOwnProperty(field)) {
|
||||
propMetadata[field].forEach(ann => {
|
||||
if (isHostBinding(ann)) {
|
||||
properties[ann.hostPropertyName || field] = field;
|
||||
} else if (isHostListener(ann)) {
|
||||
listeners[ann.eventName || field] = `${field}(${(ann.args || []).join(',')})`;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {attributes, listeners, properties};
|
||||
|
@ -31,6 +31,7 @@ export const angularCoreEnv: {[name: string]: Function} = {
|
||||
'ɵinjectTemplateRef': r3.injectTemplateRef,
|
||||
'ɵinjectViewContainerRef': r3.injectViewContainerRef,
|
||||
'ɵNgOnChangesFeature': r3.NgOnChangesFeature,
|
||||
'ɵInheritDefinitionFeature': r3.InheritDefinitionFeature,
|
||||
'ɵa': r3.a,
|
||||
'ɵb': r3.b,
|
||||
'ɵC': r3.C,
|
||||
|
Reference in New Issue
Block a user