fix(ivy): NgOnChangesFeature no longer included in hello_world (#28187)
- Wraps the NgOnChangesFeature in a factory such that no side effects occur in the module root - Adds comments to ngInherit property on feature definition interface to help guide others not to make the same mistake - Updates compiler to generate the feature properly after the change to it being a factory - Updates appropriate tests PR Close #28187
This commit is contained in:
parent
a95e81978b
commit
5430d2bc66
@ -2117,7 +2117,7 @@ describe('compiler compliance', () => {
|
|||||||
selectors: [["lifecycle-comp"]],
|
selectors: [["lifecycle-comp"]],
|
||||||
factory: function LifecycleComp_Factory(t) { return new (t || LifecycleComp)(); },
|
factory: function LifecycleComp_Factory(t) { return new (t || LifecycleComp)(); },
|
||||||
inputs: {nameMin: ["name", "nameMin"]},
|
inputs: {nameMin: ["name", "nameMin"]},
|
||||||
features: [$r3$.ɵNgOnChangesFeature],
|
features: [$r3$.ɵNgOnChangesFeature()],
|
||||||
consts: 0,
|
consts: 0,
|
||||||
vars: 0,
|
vars: 0,
|
||||||
template: function LifecycleComp_Template(rf, ctx) {},
|
template: function LifecycleComp_Template(rf, ctx) {},
|
||||||
@ -2239,7 +2239,7 @@ describe('compiler compliance', () => {
|
|||||||
factory: function ForOfDirective_Factory(t) {
|
factory: function ForOfDirective_Factory(t) {
|
||||||
return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef));
|
return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef));
|
||||||
},
|
},
|
||||||
features: [$r3$.ɵNgOnChangesFeature],
|
features: [$r3$.ɵNgOnChangesFeature()],
|
||||||
inputs: {forOf: "forOf"}
|
inputs: {forOf: "forOf"}
|
||||||
});
|
});
|
||||||
`;
|
`;
|
||||||
@ -2315,7 +2315,7 @@ describe('compiler compliance', () => {
|
|||||||
factory: function ForOfDirective_Factory(t) {
|
factory: function ForOfDirective_Factory(t) {
|
||||||
return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef));
|
return new (t || ForOfDirective)($r3$.ɵdirectiveInject(ViewContainerRef), $r3$.ɵdirectiveInject(TemplateRef));
|
||||||
},
|
},
|
||||||
features: [$r3$.ɵNgOnChangesFeature],
|
features: [$r3$.ɵNgOnChangesFeature()],
|
||||||
inputs: {forOf: "forOf"}
|
inputs: {forOf: "forOf"}
|
||||||
});
|
});
|
||||||
`;
|
`;
|
||||||
|
@ -125,7 +125,7 @@ function baseDirectiveFields(
|
|||||||
*/
|
*/
|
||||||
function addFeatures(
|
function addFeatures(
|
||||||
definitionMap: DefinitionMap, meta: R3DirectiveMetadata | R3ComponentMetadata) {
|
definitionMap: DefinitionMap, meta: R3DirectiveMetadata | R3ComponentMetadata) {
|
||||||
// e.g. `features: [NgOnChangesFeature]`
|
// e.g. `features: [NgOnChangesFeature()]`
|
||||||
const features: o.Expression[] = [];
|
const features: o.Expression[] = [];
|
||||||
|
|
||||||
const providers = meta.providers;
|
const providers = meta.providers;
|
||||||
@ -142,7 +142,7 @@ function addFeatures(
|
|||||||
features.push(o.importExpr(R3.InheritDefinitionFeature));
|
features.push(o.importExpr(R3.InheritDefinitionFeature));
|
||||||
}
|
}
|
||||||
if (meta.lifecycle.usesOnChanges) {
|
if (meta.lifecycle.usesOnChanges) {
|
||||||
features.push(o.importExpr(R3.NgOnChangesFeature));
|
features.push(o.importExpr(R3.NgOnChangesFeature).callFn(EMPTY_ARRAY));
|
||||||
}
|
}
|
||||||
if (features.length) {
|
if (features.length) {
|
||||||
definitionMap.set('features', o.literalArr(features));
|
definitionMap.set('features', o.literalArr(features));
|
||||||
|
@ -35,11 +35,18 @@ type OnChangesExpando = OnChanges & {
|
|||||||
* static ngComponentDef = defineComponent({
|
* static ngComponentDef = defineComponent({
|
||||||
* ...
|
* ...
|
||||||
* inputs: {name: 'publicName'},
|
* inputs: {name: 'publicName'},
|
||||||
* features: [NgOnChangesFeature]
|
* features: [NgOnChangesFeature()]
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function NgOnChangesFeature<T>(definition: DirectiveDef<T>): void {
|
export function NgOnChangesFeature<T>(): DirectiveDefFeature {
|
||||||
|
// This option ensures that the ngOnChanges lifecycle hook will be inherited
|
||||||
|
// from superclasses (in InheritDefinitionFeature).
|
||||||
|
(NgOnChangesFeatureImpl as DirectiveDefFeature).ngInherit = true;
|
||||||
|
return NgOnChangesFeatureImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
function NgOnChangesFeatureImpl<T>(definition: DirectiveDef<T>): void {
|
||||||
if (definition.type.prototype.ngOnChanges) {
|
if (definition.type.prototype.ngOnChanges) {
|
||||||
definition.setInput = ngOnChangesSetInput;
|
definition.setInput = ngOnChangesSetInput;
|
||||||
|
|
||||||
@ -91,11 +98,6 @@ function setSimpleChangesStore(instance: any, store: NgSimpleChangesStore): NgSi
|
|||||||
return instance[SIMPLE_CHANGES_STORE] = store;
|
return instance[SIMPLE_CHANGES_STORE] = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This option ensures that the ngOnChanges lifecycle hook will be inherited
|
|
||||||
// from superclasses (in InheritDefinitionFeature).
|
|
||||||
(NgOnChangesFeature as DirectiveDefFeature).ngInherit = true;
|
|
||||||
|
|
||||||
|
|
||||||
interface NgSimpleChangesStore {
|
interface NgSimpleChangesStore {
|
||||||
previous: SimpleChanges;
|
previous: SimpleChanges;
|
||||||
current: SimpleChanges|null;
|
current: SimpleChanges|null;
|
||||||
|
@ -302,11 +302,27 @@ export type PipeDefWithMeta<T, Name extends string> = PipeDef<T>;
|
|||||||
|
|
||||||
export interface DirectiveDefFeature {
|
export interface DirectiveDefFeature {
|
||||||
<T>(directiveDef: DirectiveDef<T>): void;
|
<T>(directiveDef: DirectiveDef<T>): void;
|
||||||
|
/**
|
||||||
|
* Marks a feature as something that {@link InheritDefinitionFeature} will execute
|
||||||
|
* during inheritance.
|
||||||
|
*
|
||||||
|
* NOTE: DO NOT SET IN ROOT OF MODULE! Doing so will result in tree-shakers/bundlers
|
||||||
|
* identifying the change as a side effect, and the feature will be included in
|
||||||
|
* every bundle.
|
||||||
|
*/
|
||||||
ngInherit?: true;
|
ngInherit?: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ComponentDefFeature {
|
export interface ComponentDefFeature {
|
||||||
<T>(componentDef: ComponentDef<T>): void;
|
<T>(componentDef: ComponentDef<T>): void;
|
||||||
|
/**
|
||||||
|
* Marks a feature as something that {@link InheritDefinitionFeature} will execute
|
||||||
|
* during inheritance.
|
||||||
|
*
|
||||||
|
* NOTE: DO NOT SET IN ROOT OF MODULE! Doing so will result in tree-shakers/bundlers
|
||||||
|
* identifying the change as a side effect, and the feature will be included in
|
||||||
|
* every bundle.
|
||||||
|
*/
|
||||||
ngInherit?: true;
|
ngInherit?: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,9 +80,6 @@
|
|||||||
{
|
{
|
||||||
"name": "NO_PARENT_INJECTOR"
|
"name": "NO_PARENT_INJECTOR"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "NgOnChangesFeature"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "NodeInjectorFactory"
|
"name": "NodeInjectorFactory"
|
||||||
},
|
},
|
||||||
@ -104,12 +101,6 @@
|
|||||||
{
|
{
|
||||||
"name": "SANITIZER"
|
"name": "SANITIZER"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "SIMPLE_CHANGES_STORE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "SimpleChange"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "TVIEW"
|
"name": "TVIEW"
|
||||||
},
|
},
|
||||||
@ -308,9 +299,6 @@
|
|||||||
{
|
{
|
||||||
"name": "getRootView"
|
"name": "getRootView"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "getSimpleChangesStore"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "hasParentInjector"
|
"name": "hasParentInjector"
|
||||||
},
|
},
|
||||||
@ -368,9 +356,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nextNgElementId"
|
"name": "nextNgElementId"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "ngOnChangesSetInput"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "noSideEffects"
|
"name": "noSideEffects"
|
||||||
},
|
},
|
||||||
@ -440,9 +425,6 @@
|
|||||||
{
|
{
|
||||||
"name": "setPreviousOrParentTNode"
|
"name": "setPreviousOrParentTNode"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "setSimpleChangesStore"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "setTNodeAndViewData"
|
"name": "setTNodeAndViewData"
|
||||||
},
|
},
|
||||||
@ -460,8 +442,5 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "viewAttached"
|
"name": "viewAttached"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wrapOnChanges"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -8,9 +8,6 @@
|
|||||||
{
|
{
|
||||||
"name": "EMPTY_ARRAY"
|
"name": "EMPTY_ARRAY"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "EMPTY_OBJ"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "EmptyErrorImpl"
|
"name": "EmptyErrorImpl"
|
||||||
},
|
},
|
||||||
@ -38,9 +35,6 @@
|
|||||||
{
|
{
|
||||||
"name": "NULL_INJECTOR"
|
"name": "NULL_INJECTOR"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "NgOnChangesFeature"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "NullInjector"
|
"name": "NullInjector"
|
||||||
},
|
},
|
||||||
@ -56,18 +50,12 @@
|
|||||||
{
|
{
|
||||||
"name": "R3Injector"
|
"name": "R3Injector"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "SIMPLE_CHANGES_STORE"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "ScopedService"
|
"name": "ScopedService"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Self"
|
"name": "Self"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "SimpleChange"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "SkipSelf"
|
"name": "SkipSelf"
|
||||||
},
|
},
|
||||||
@ -125,9 +113,6 @@
|
|||||||
{
|
{
|
||||||
"name": "getNullInjector"
|
"name": "getNullInjector"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "getSimpleChangesStore"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "hasDeps"
|
"name": "hasDeps"
|
||||||
},
|
},
|
||||||
@ -170,9 +155,6 @@
|
|||||||
{
|
{
|
||||||
"name": "makeRecord"
|
"name": "makeRecord"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "ngOnChangesSetInput"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "providerToFactory"
|
"name": "providerToFactory"
|
||||||
},
|
},
|
||||||
@ -185,13 +167,7 @@
|
|||||||
{
|
{
|
||||||
"name": "setCurrentInjector"
|
"name": "setCurrentInjector"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "setSimpleChangesStore"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "stringify"
|
"name": "stringify"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wrapOnChanges"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -143,9 +143,6 @@
|
|||||||
{
|
{
|
||||||
"name": "NgModuleRef"
|
"name": "NgModuleRef"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "NgOnChangesFeature"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "NodeInjector"
|
"name": "NodeInjector"
|
||||||
},
|
},
|
||||||
@ -185,9 +182,6 @@
|
|||||||
{
|
{
|
||||||
"name": "SANITIZER"
|
"name": "SANITIZER"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "SIMPLE_CHANGES_STORE"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "SWITCH_ELEMENT_REF_FACTORY"
|
"name": "SWITCH_ELEMENT_REF_FACTORY"
|
||||||
},
|
},
|
||||||
@ -197,9 +191,6 @@
|
|||||||
{
|
{
|
||||||
"name": "SWITCH_VIEW_CONTAINER_REF_FACTORY"
|
"name": "SWITCH_VIEW_CONTAINER_REF_FACTORY"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "SimpleChange"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "SkipSelf"
|
"name": "SkipSelf"
|
||||||
},
|
},
|
||||||
@ -785,9 +776,6 @@
|
|||||||
{
|
{
|
||||||
"name": "getRootView"
|
"name": "getRootView"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "getSimpleChangesStore"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "getSinglePropIndexValue"
|
"name": "getSinglePropIndexValue"
|
||||||
},
|
},
|
||||||
@ -1016,9 +1004,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nextNgElementId"
|
"name": "nextNgElementId"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "ngOnChangesSetInput"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "noSideEffects"
|
"name": "noSideEffects"
|
||||||
},
|
},
|
||||||
@ -1187,9 +1172,6 @@
|
|||||||
{
|
{
|
||||||
"name": "setSanitizeFlag"
|
"name": "setSanitizeFlag"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "setSimpleChangesStore"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "setStyle"
|
"name": "setStyle"
|
||||||
},
|
},
|
||||||
@ -1255,8 +1237,5 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "wrapListenerWithPreventDefault"
|
"name": "wrapListenerWithPreventDefault"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wrapOnChanges"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -40,7 +40,7 @@ NgForOf.ngDirectiveDef = defineDirective({
|
|||||||
type: NgTemplateOutletDef,
|
type: NgTemplateOutletDef,
|
||||||
selectors: [['', 'ngTemplateOutlet', '']],
|
selectors: [['', 'ngTemplateOutlet', '']],
|
||||||
factory: () => new NgTemplateOutletDef(directiveInject(ViewContainerRef as any)),
|
factory: () => new NgTemplateOutletDef(directiveInject(ViewContainerRef as any)),
|
||||||
features: [NgOnChangesFeature],
|
features: [NgOnChangesFeature()],
|
||||||
inputs:
|
inputs:
|
||||||
{ngTemplateOutlet: 'ngTemplateOutlet', ngTemplateOutletContext: 'ngTemplateOutletContext'}
|
{ngTemplateOutlet: 'ngTemplateOutlet', ngTemplateOutletContext: 'ngTemplateOutletContext'}
|
||||||
});
|
});
|
||||||
|
@ -357,7 +357,7 @@ describe('host bindings', () => {
|
|||||||
template: (rf: RenderFlags, ctx: InitHookComp) => {},
|
template: (rf: RenderFlags, ctx: InitHookComp) => {},
|
||||||
consts: 0,
|
consts: 0,
|
||||||
vars: 0,
|
vars: 0,
|
||||||
features: [NgOnChangesFeature],
|
features: [NgOnChangesFeature()],
|
||||||
hostBindings: (rf: RenderFlags, ctx: InitHookComp, elIndex: number) => {
|
hostBindings: (rf: RenderFlags, ctx: InitHookComp, elIndex: number) => {
|
||||||
if (rf & RenderFlags.Create) {
|
if (rf & RenderFlags.Create) {
|
||||||
allocHostVars(1);
|
allocHostVars(1);
|
||||||
|
@ -501,7 +501,7 @@ describe('InheritDefinitionFeature', () => {
|
|||||||
type: SuperDirective,
|
type: SuperDirective,
|
||||||
selectors: [['', 'superDir', '']],
|
selectors: [['', 'superDir', '']],
|
||||||
factory: () => new SuperDirective(),
|
factory: () => new SuperDirective(),
|
||||||
features: [NgOnChangesFeature],
|
features: [NgOnChangesFeature()],
|
||||||
inputs: {someInput: 'someInput'}
|
inputs: {someInput: 'someInput'}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2008,7 +2008,7 @@ describe('lifecycles', () => {
|
|||||||
vars: vars,
|
vars: vars,
|
||||||
inputs: {a: 'val1', b: ['publicVal2', 'val2']}, template,
|
inputs: {a: 'val1', b: ['publicVal2', 'val2']}, template,
|
||||||
directives: directives,
|
directives: directives,
|
||||||
features: [NgOnChangesFeature],
|
features: [NgOnChangesFeature()],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -2027,7 +2027,7 @@ describe('lifecycles', () => {
|
|||||||
selectors: [['', 'dir', '']],
|
selectors: [['', 'dir', '']],
|
||||||
factory: () => new Directive(),
|
factory: () => new Directive(),
|
||||||
inputs: {a: 'val1', b: ['publicVal2', 'val2']},
|
inputs: {a: 'val1', b: ['publicVal2', 'val2']},
|
||||||
features: [NgOnChangesFeature],
|
features: [NgOnChangesFeature()],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2732,7 +2732,7 @@ describe('lifecycles', () => {
|
|||||||
vars: vars,
|
vars: vars,
|
||||||
inputs: {val: 'val'}, template,
|
inputs: {val: 'val'}, template,
|
||||||
directives: directives,
|
directives: directives,
|
||||||
features: [NgOnChangesFeature],
|
features: [NgOnChangesFeature()],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1631,7 +1631,7 @@ describe('ViewContainerRef', () => {
|
|||||||
textBinding(0, interpolation1('', cmp.name, ''));
|
textBinding(0, interpolation1('', cmp.name, ''));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
features: [NgOnChangesFeature],
|
features: [NgOnChangesFeature()],
|
||||||
inputs: {name: 'name'}
|
inputs: {name: 'name'}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1678,7 +1678,7 @@ describe('ViewContainerRef', () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
directives: [ComponentWithHooks, DirectiveWithVCRef],
|
directives: [ComponentWithHooks, DirectiveWithVCRef],
|
||||||
features: [NgOnChangesFeature],
|
features: [NgOnChangesFeature()],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1771,7 +1771,7 @@ describe('ViewContainerRef', () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
directives: [ComponentWithHooks, DirectiveWithVCRef],
|
directives: [ComponentWithHooks, DirectiveWithVCRef],
|
||||||
features: [NgOnChangesFeature],
|
features: [NgOnChangesFeature()],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
tools/public_api_guard/common/common.d.ts
vendored
4
tools/public_api_guard/common/common.d.ts
vendored
@ -306,8 +306,8 @@ export declare class NgSwitchDefault {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export declare class NgTemplateOutlet implements OnChanges {
|
export declare class NgTemplateOutlet implements OnChanges {
|
||||||
ngTemplateOutlet: TemplateRef<any>;
|
ngTemplateOutlet: TemplateRef<any> | null;
|
||||||
ngTemplateOutletContext: Object;
|
ngTemplateOutletContext: Object | null;
|
||||||
constructor(_viewContainerRef: ViewContainerRef);
|
constructor(_viewContainerRef: ViewContainerRef);
|
||||||
ngOnChanges(changes: SimpleChanges): void;
|
ngOnChanges(changes: SimpleChanges): void;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user