From 0ee09cdd7e5f076355775322ae7d21de8f23c40a Mon Sep 17 00:00:00 2001 From: Alex Rickabaugh Date: Tue, 4 Jun 2019 13:50:48 -0700 Subject: [PATCH] refactor(ivy): fix type of factory functions to allow explicit types (#30855) Factory functions written by the compiler optionally allow an explicit type to be passed. If called with this type, an instance of the given type will be created instead of the type for which the factory was generated. This is used to power inheritance of Angular types, as if the constructor of a class is inherited from its superclass, then the factory function of the superclass must be used (it has all the DI info) to construct an instance of the derived class. This commit adjusts typings in a few places to allow factory functions to be called with this extra type parameter. PR Close #30855 --- packages/core/src/di/interface/defs.ts | 2 +- packages/core/src/di/jit/environment.ts | 2 +- packages/core/src/render3/di.ts | 4 ++-- packages/core/src/render3/interfaces/definition.ts | 2 +- packages/core/src/render3/pipe.ts | 2 +- packages/core/test/render3/ivy/jit_spec.ts | 2 +- tools/public_api_guard/core/core.d.ts | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/core/src/di/interface/defs.ts b/packages/core/src/di/interface/defs.ts index 55e76bb804..f6c3b935a2 100644 --- a/packages/core/src/di/interface/defs.ts +++ b/packages/core/src/di/interface/defs.ts @@ -47,7 +47,7 @@ export interface ɵɵInjectableDef { /** * Factory method to execute to create an instance of the injectable. */ - factory: () => T; + factory: (t?: Type) => T; /** * In a case of no explicit injector, a location where the instance of the injectable is stored. diff --git a/packages/core/src/di/jit/environment.ts b/packages/core/src/di/jit/environment.ts index 9bd8141b10..302a2eec70 100644 --- a/packages/core/src/di/jit/environment.ts +++ b/packages/core/src/di/jit/environment.ts @@ -24,7 +24,7 @@ export const angularCoreDiEnv: {[name: string]: Function} = { 'ɵɵgetFactoryOf': getFactoryOf, }; -function getFactoryOf(type: Type): ((type: Type| null) => T)|null { +function getFactoryOf(type: Type): ((type?: Type) => T)|null { const typeAny = type as any; const def = getInjectableDef(typeAny) || getInjectorDef(typeAny); if (!def || def.factory === undefined) { diff --git a/packages/core/src/render3/di.ts b/packages/core/src/render3/di.ts index c8507b871a..58c8f4bf7a 100644 --- a/packages/core/src/render3/di.ts +++ b/packages/core/src/render3/di.ts @@ -15,7 +15,7 @@ import {assertDefined, assertEqual} from '../util/assert'; import {getComponentDef, getDirectiveDef, getPipeDef} from './definition'; import {NG_ELEMENT_ID} from './fields'; -import {DirectiveDef} from './interfaces/definition'; +import {DirectiveDef, FactoryFn} from './interfaces/definition'; import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector'; import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType} from './interfaces/node'; import {DECLARATION_VIEW, INJECTOR, LView, TData, TVIEW, TView, T_HOST} from './interfaces/view'; @@ -637,7 +637,7 @@ export class NodeInjector implements Injector { /** * @codeGenApi */ -export function ɵɵgetFactoryOf(type: Type): ((type: Type| null) => T)|null { +export function ɵɵgetFactoryOf(type: Type): FactoryFn|null { const typeAny = type as any; const def = getComponentDef(typeAny) || getDirectiveDef(typeAny) || getPipeDef(typeAny) || getInjectableDef(typeAny) || getInjectorDef(typeAny); diff --git a/packages/core/src/render3/interfaces/definition.ts b/packages/core/src/render3/interfaces/definition.ts index 5817ec267e..cb4af4b03f 100644 --- a/packages/core/src/render3/interfaces/definition.ts +++ b/packages/core/src/render3/interfaces/definition.ts @@ -47,7 +47,7 @@ export type FactoryFn = { /** * If no constructor to instantiate is provided, an instance of type T itself is created. */ - (t: null): T; + (t?: undefined): T; }; /** diff --git a/packages/core/src/render3/pipe.ts b/packages/core/src/render3/pipe.ts index a1168e366c..43a1939127 100644 --- a/packages/core/src/render3/pipe.ts +++ b/packages/core/src/render3/pipe.ts @@ -42,7 +42,7 @@ export function ɵɵpipe(index: number, pipeName: string): any { pipeDef = tView.data[adjustedIndex] as PipeDef; } - const pipeInstance = pipeDef.factory(null); + const pipeInstance = pipeDef.factory(); store(index, pipeInstance); return pipeInstance; } diff --git a/packages/core/test/render3/ivy/jit_spec.ts b/packages/core/test/render3/ivy/jit_spec.ts index d0bf5b9e44..c9280808e6 100644 --- a/packages/core/test/render3/ivy/jit_spec.ts +++ b/packages/core/test/render3/ivy/jit_spec.ts @@ -244,7 +244,7 @@ ivyEnabled && describe('render3 jit', () => { const pipeDef = (P as any).ngPipeDef as PipeDef

; expect(pipeDef.name).toBe('test-pipe'); expect(pipeDef.pure).toBe(false, 'pipe should not be pure'); - expect(pipeDef.factory(null) instanceof P) + expect(pipeDef.factory() instanceof P) .toBe(true, 'factory() should create an instance of the pipe'); }); diff --git a/tools/public_api_guard/core/core.d.ts b/tools/public_api_guard/core/core.d.ts index 92c4521d98..e3be97aa64 100644 --- a/tools/public_api_guard/core/core.d.ts +++ b/tools/public_api_guard/core/core.d.ts @@ -837,7 +837,7 @@ export declare function ɵɵenableBindings(): void; export declare function ɵɵgetCurrentView(): OpaqueViewState; -export declare function ɵɵgetFactoryOf(type: Type): ((type: Type | null) => T) | null; +export declare function ɵɵgetFactoryOf(type: Type): FactoryFn | null; export declare function ɵɵgetInheritedFactory(type: Type): (type: Type) => T; @@ -868,7 +868,7 @@ export declare function ɵɵinject(token: Type | InjectionToken): T; export declare function ɵɵinject(token: Type | InjectionToken, flags?: InjectFlags): T | null; export interface ɵɵInjectableDef { - factory: () => T; + factory: (t?: Type) => T; providedIn: InjectorType | 'root' | 'any' | null; token: unknown; value: T | undefined;