Skip to content

Commit

Permalink
fix(core): allow abstract class as injection token
Browse files Browse the repository at this point in the history
  • Loading branch information
trotyl authored and mhevery committed Sep 23, 2018
1 parent 7f1cace commit 38cf92d
Show file tree
Hide file tree
Showing 9 changed files with 29 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ export class DepAppModule {
@Injectable({providedIn: DepAppModule})
export class ShakeableService {
constructor(readonly normal: NormalService) {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class TokenModule {

export const TOKEN = new InjectionToken('test', {
providedIn: TokenModule,
factory: () => new Service(inject(Dep)),
factory: () => new Service(inject(Dep), inject(AbstractDep)),
});


Expand Down Expand Up @@ -49,6 +49,11 @@ export class Dep {
readonly data = 'fromToken';
}

@Injectable({providedIn: 'root', useValue: {value: 42}})
export abstract class AbstractDep {
abstract value: number;
}

export class Service {
constructor(readonly dep: Dep) {}
constructor(readonly dep: Dep, unused: AbstractDep) {}
}
3 changes: 2 additions & 1 deletion packages/compiler/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ export const createSelf = makeMetadataFactory('Self');
export const createSkipSelf = makeMetadataFactory('SkipSelf');
export const createHost = makeMetadataFactory('Host');

export interface Type extends Function { new (...args: any[]): any; }
export interface Type extends Function { prototype: any; }

export const Type = Function;

export enum SecurityContext {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/application_ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ export class ApplicationRef {

// Create a factory associated with the current module if it's not bound to some other
const ngModule = componentFactory instanceof ComponentFactoryBoundToModule ?
null :
undefined :
this._injector.get(NgModuleRef);
const selectorOrNode = rootSelectorOrNode || componentFactory.selector;
const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/di/r3_injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import {OnDestroy} from '../metadata/lifecycle_hooks';
import {Type} from '../type';
import {Constructor, Type} from '../type';
import {stringify} from '../util';

import {InjectableDef, InjectableType, InjectorType, InjectorTypeWithProviders, getInjectableDef, getInjectorDef} from './defs';
Expand Down Expand Up @@ -336,7 +336,7 @@ function injectableDefRecord(token: Type<any>| InjectionToken<any>): Record<any>
}
// TODO(alxhub): there should probably be a strict mode which throws here instead of assuming a
// no-args constructor.
return makeRecord(() => new (token as Type<any>)());
return makeRecord(() => new (token as Constructor<any>)());
}
return makeRecord(injectableDef.factory);
}
Expand All @@ -358,7 +358,7 @@ function providerToRecord(provider: SingleProvider): Record<any> {
} else {
const classRef = (provider as StaticClassProvider | ClassProvider).useClass || token;
if (hasDeps(provider)) {
factory = () => new (classRef)(...injectArgs(provider.deps));
factory = () => new (classRef as Constructor<any>)(...injectArgs(provider.deps));
} else {
return injectableDefRecord(classRef);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/reflection/reflection_capabilities.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 {Type, isType} from '../type';
import {Constructor, Type, isType} from '../type';
import {global, stringify} from '../util';
import {ANNOTATIONS, PARAMETERS, PROP_METADATA} from '../util/decorators';

Expand All @@ -29,7 +29,7 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {

isReflectionEnabled(): boolean { return true; }

factory<T>(t: Type<T>): (args: any[]) => T { return (...args: any[]) => new t(...args); }
factory<T>(t: Constructor<T>): (args: any[]) => T { return (...args: any[]) => new t(...args); }

/** @internal */
_zipTypesAndAnnotations(paramTypes: any[], paramAnnotations: any[]): any[][] {
Expand Down
16 changes: 8 additions & 8 deletions packages/core/src/render3/definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,13 +296,13 @@ export function defineComponent<T>(componentDefinition: {
declaredInputs: declaredInputs,
outputs: invertObject(componentDefinition.outputs),
exportAs: componentDefinition.exportAs || null,
onInit: type.prototype.ngOnInit || null,
doCheck: type.prototype.ngDoCheck || null,
afterContentInit: type.prototype.ngAfterContentInit || null,
afterContentChecked: type.prototype.ngAfterContentChecked || null,
afterViewInit: type.prototype.ngAfterViewInit || null,
afterViewChecked: type.prototype.ngAfterViewChecked || null,
onDestroy: type.prototype.ngOnDestroy || null,
onInit: (type.prototype as any).ngOnInit || null,
doCheck: (type.prototype as any).ngDoCheck || null,
afterContentInit: (type.prototype as any).ngAfterContentInit || null,
afterContentChecked: (type.prototype as any).ngAfterContentChecked || null,
afterViewInit: (type.prototype as any).ngAfterViewInit || null,
afterViewChecked: (type.prototype as any).ngAfterViewChecked || null,
onDestroy: (type.prototype as any).ngOnDestroy || null,
onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush,
directiveDefs: directiveTypes ?
() => (typeof directiveTypes === 'function' ? directiveTypes() : directiveTypes)
Expand Down Expand Up @@ -660,7 +660,7 @@ export function definePipe<T>(pipeDef: {
name: pipeDef.name,
factory: pipeDef.factory,
pure: pipeDef.pure !== false,
onDestroy: pipeDef.type.prototype.ngOnDestroy || null
onDestroy: (pipeDef.type.prototype as any).ngOnDestroy || null
}) as never;
}

Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ export function isType(v: any): v is Type<any> {
return typeof v === 'function';
}

export interface Type<T> extends Function { new (...args: any[]): T; }
export interface Type<T> extends Function { prototype: T; }

export interface Constructor<T> extends Type<T> { new (...args: any[]): T; }
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ class ToDoAppComponent {

// NON-NORMATIVE
(ToDoAppComponent.ngComponentDef as r3.ComponentDefInternal<any>).directiveDefs = () =>
[ToDoItemComponent.ngComponentDef, (NgForOf as r3.DirectiveType<NgForOf<any>>).ngDirectiveDef];
[ToDoItemComponent.ngComponentDef,
(NgForOf as any as r3.DirectiveType<NgForOf<any>>).ngDirectiveDef];
// /NON-NORMATIVE

@Component({
Expand Down

0 comments on commit 38cf92d

Please sign in to comment.