Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions packages/core/src/core_render3_private_export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,5 @@ export {
publishGlobalUtil as ɵpublishGlobalUtil,
publishDefaultGlobalUtils as ɵpublishDefaultGlobalUtils
} from './render3/global_utils';
export {
SWITCH_INJECTOR_FACTORY__POST_R3__ as ɵSWITCH_INJECTOR_FACTORY__POST_R3__,
} from './di/injector';

// clang-format on
30 changes: 15 additions & 15 deletions packages/core/src/di.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@
*/

/**
* @module
* @description
* The `di` module provides dependency injection container services.
* This file should not be necessary because node resolution should just default to `./di/index`!
*
* However it does not seem to work and it breaks:
* - //packages/animations/browser/test:test_web_chromium-local
* - //packages/compiler-cli/test:extract_i18n
* - //packages/compiler-cli/test:ngc
* - //packages/compiler-cli/test:perform_watch
* - //packages/compiler-cli/test/diagnostics:check_types
* - //packages/compiler-cli/test/transformers:test
* - //packages/compiler/test:test
* - //tools/public_api_guard:core_api
*
* Remove this file once the above is solved or wait until `ngc` is deleted and then it should be
* safe to delete this file.
*/

export * from './di/metadata';
export {InjectableType, InjectorType, defineInjectable, defineInjector} from './di/interface/defs';
export {forwardRef, resolveForwardRef, ForwardRefFn} from './di/forward_ref';
export {Injectable, InjectableDecorator, InjectableProvider} from './di/injectable';
export {INJECTOR, Injector} from './di/injector';
export {inject, InjectFlags} from './di/injector_compatibility';
export {ReflectiveInjector} from './di/reflective_injector';
export {StaticProvider, ValueProvider, ConstructorSansProvider, ExistingProvider, FactoryProvider, Provider, TypeProvider, ClassProvider} from './di/interface/provider';
export {createInjector} from './di/r3_injector';
export {ResolvedReflectiveFactory, ResolvedReflectiveProvider} from './di/reflective_provider';
export {ReflectiveKey} from './di/reflective_key';
export {InjectionToken} from './di/injection_token';
export * from './di/index';
27 changes: 27 additions & 0 deletions packages/core/src/di/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

/**
* @module
* @description
* The `di` module provides dependency injection container services.
*/

export * from './metadata';
export {InjectFlags} from './interface/injector';
export {defineInjectable, defineInjector, InjectableType, InjectorType} from './interface/defs';
export {forwardRef, resolveForwardRef, ForwardRefFn} from './forward_ref';
export {Injectable, InjectableDecorator, InjectableProvider} from './injectable';
export {INJECTOR, Injector} from './injector';
export {inject} from './injector_compatibility';
export {ReflectiveInjector} from './reflective_injector';
export {StaticProvider, ValueProvider, ConstructorSansProvider, ExistingProvider, FactoryProvider, Provider, TypeProvider, ClassProvider} from './interface/provider';
export {createInjector} from './r3_injector';
export {ResolvedReflectiveFactory, ResolvedReflectiveProvider} from './reflective_provider';
export {ReflectiveKey} from './reflective_key';
export {InjectionToken} from './injection_token';
4 changes: 2 additions & 2 deletions packages/core/src/di/injectable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {Type} from '../interface/type';
import {compileInjectable as render3CompileInjectable} from '../render3/jit/injectable';
import {TypeDecorator, makeDecorator} from '../util/decorators';

import {InjectableDef, InjectableType, defineInjectable, getInjectableDef} from './interface/defs';
import {ClassSansProvider, ConstructorSansProvider, ExistingSansProvider, FactorySansProvider, StaticClassSansProvider, ValueSansProvider} from './interface/provider';
import {ClassSansProvider, ConstructorSansProvider, ExistingSansProvider, FactorySansProvider, StaticClassSansProvider, ValueSansProvider,} from './interface/provider';
import {InjectableType, defineInjectable, getInjectableDef, InjectableDef} from './interface/defs';
import {convertInjectableProviderToFactory} from './util';


Expand Down
10 changes: 7 additions & 3 deletions packages/core/src/di/injection_token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,17 @@ export class InjectionToken<T> {
providedIn?: Type<any>| 'root' | null,
factory: () => T
}) {
if (options !== undefined) {
this.ngInjectableDef = undefined;
if (typeof options == 'number') {
// This is a special hack to assign __NG_ELEMENT_ID__ to this instance.
// __NG_ELEMENT_ID__ is Used by Ivy to determine bloom filter id.
// We are using it to assign `-1` which is used to identify `Injector`.
(this as any).__NG_ELEMENT_ID__ = options;
} else if (options !== undefined) {
this.ngInjectableDef = defineInjectable({
providedIn: options.providedIn || 'root',
factory: options.factory,
});
} else {
this.ngInjectableDef = undefined;
}
}

Expand Down
23 changes: 11 additions & 12 deletions packages/core/src/di/injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@
*/

import {Type} from '../interface/type';
import {injectInjector} from '../render3/di';
import {noop} from '../util/noop';
import {getClosureSafeProperty} from '../util/property';
import {stringify} from '../util/stringify';

import {resolveForwardRef} from './forward_ref';
import {InjectionToken} from './injection_token';
import {InjectFlags, inject} from './injector_compatibility';
import {inject} from './injector_compatibility';
import {defineInjectable} from './interface/defs';
import {InjectFlags} from './interface/injector';
import {ConstructorProvider, ExistingProvider, FactoryProvider, StaticClassProvider, StaticProvider, ValueProvider} from './interface/provider';
import {Inject, Optional, Self, SkipSelf} from './metadata';

Expand All @@ -31,7 +30,10 @@ export const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
*
* @publicApi
*/
export const INJECTOR = new InjectionToken<Injector>('INJECTOR');
export const INJECTOR = new InjectionToken<Injector>(
'INJECTOR',
-1 as any // `-1` is used by Ivy DI system as special value to recognize it as `Injector`.
);

export class NullInjector implements Injector {
get(token: any, notFoundValue: any = _THROW_IF_NOT_FOUND): any {
Expand Down Expand Up @@ -109,16 +111,13 @@ export abstract class Injector {
factory: () => inject(INJECTOR),
});

/** @internal */
/** @nocollapse */
static __NG_ELEMENT_ID__: () => Injector = () => SWITCH_INJECTOR_FACTORY();
/**
* @internal
* @nocollapse
*/
static __NG_ELEMENT_ID__ = -1;
}

export const SWITCH_INJECTOR_FACTORY__POST_R3__ = function() {
return injectInjector();
};
const SWITCH_INJECTOR_FACTORY__PRE_R3__ = noop;
const SWITCH_INJECTOR_FACTORY: typeof injectInjector = SWITCH_INJECTOR_FACTORY__PRE_R3__;


const IDENT = function<T>(value: T): T {
Expand Down
25 changes: 1 addition & 24 deletions packages/core/src/di/injector_compatibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,10 @@ import {stringify} from '../util/stringify';
import {InjectionToken} from './injection_token';
import {Injector} from './injector';
import {InjectableDef, getInjectableDef} from './interface/defs';
import {InjectFlags} from './interface/injector';
import {Inject, Optional, Self, SkipSelf} from './metadata';


/**
* Injection flags for DI.
*
* @publicApi
*/
export enum InjectFlags {
// TODO(alxhub): make this 'const' when ngc no longer writes exports of it into ngfactory files.

Default = 0b0000,

/**
* Specifies that an injector should retrieve a dependency from any injector until reaching the
* host element of the current component. (Only used with Element Injector)
*/
Host = 0b0001,
/** Don't descend into ancestors of the node requesting injection. */
Self = 0b0010,
/** Skip the node that is requesting injection. */
SkipSelf = 0b0100,
/** Inject `defaultValue` instead if token not found. */
Optional = 0b1000,
}



/**
* Current injector value used by `inject`.
Expand Down
31 changes: 31 additions & 0 deletions packages/core/src/di/interface/injector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/


/**
* Injection flags for DI.
*
* @publicApi
*/
export enum InjectFlags {
// TODO(alxhub): make this 'const' when ngc no longer writes exports of it into ngfactory files.

Default = 0b0000,

/**
* Specifies that an injector should retrieve a dependency from any injector until reaching the
* host element of the current component. (Only used with Element Injector)
*/
Host = 0b0001,
/** Don't ascend to ancestors of the node requesting injection. */
Self = 0b0010,
/** Skip the node that is requesting injection. */
SkipSelf = 0b0100,
/** Inject `defaultValue` instead if token not found. */
Optional = 0b1000,
}
7 changes: 1 addition & 6 deletions packages/core/src/di/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Type} from '../interface/type';
import {ReflectionCapabilities} from '../reflection/reflection_capabilities';
import {makeDecorator, makeParamDecorator} from '../util/decorators';
import {EMPTY_ARRAY} from '../view/util';

import {ClassSansProvider, ConstructorProvider, ConstructorSansProvider, ExistingProvider, ExistingSansProvider, FactoryProvider, FactorySansProvider, StaticClassProvider, StaticClassSansProvider, ValueProvider, ValueSansProvider} from './interface/provider';
import {makeParamDecorator} from '../util/decorators';



Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/di/r3_injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import {stringify} from '../util/stringify';
import {resolveForwardRef} from './forward_ref';
import {InjectionToken} from './injection_token';
import {INJECTOR, Injector, NullInjector, THROW_IF_NOT_FOUND, USE_VALUE} from './injector';
import {InjectFlags, inject, injectArgs, setCurrentInjector} from './injector_compatibility';
import {inject, injectArgs, setCurrentInjector} from './injector_compatibility';
import {InjectableDef, InjectableType, InjectorType, InjectorTypeWithProviders, getInjectableDef, getInjectorDef} from './interface/defs';
import {ClassProvider, ConstructorProvider, ExistingProvider, FactoryProvider, Provider, StaticClassProvider, StaticProvider, TypeProvider, ValueProvider} from './interface/provider';
import {InjectFlags} from './interface/injector';
import {ClassProvider, ConstructorProvider, ExistingProvider, FactoryProvider, StaticClassProvider, StaticProvider, TypeProvider, ValueProvider} from './interface/provider';
import {APP_ROOT} from './scope';


Expand Down
1 change: 0 additions & 1 deletion packages/core/src/di/scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Type} from '../interface/type';
import {InjectionToken} from './injection_token';


Expand Down
1 change: 1 addition & 0 deletions packages/core/src/render/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {injectRenderer2 as render3InjectRenderer2} from '../render3/view_engine_
import {noop} from '../util/noop';



/**
* @deprecated Use `RendererType2` (and `Renderer2`) instead.
* @publicApi
Expand Down
23 changes: 14 additions & 9 deletions packages/core/src/render3/di.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/

import {InjectionToken} from '../di/injection_token';
import {InjectFlags, InjectionToken} from '../di';
import {Injector} from '../di/injector';
import {InjectFlags, injectRootLimpMode, setInjectImplementation} from '../di/injector_compatibility';
import {injectRootLimpMode, setInjectImplementation} from '../di/injector_compatibility';
import {getInjectableDef, getInjectorDef} from '../di/interface/defs';
import {Type} from '../interface/type';

import {assertDefined, assertEqual} from '../util/assert';

import {getComponentDef, getDirectiveDef, getPipeDef} from './definition';
import {NG_ELEMENT_ID} from './fields';
import {DirectiveDef} from './interfaces/definition';
Expand Down Expand Up @@ -285,6 +285,10 @@ export function injectAttributeImpl(tNode: TNode, attrNameToInject: string): str
* Look for the injector providing the token by walking up the node injector tree and then
* the module injector tree.
*
* This function patches `token` with `__NG_ELEMENT_ID__` which contains the id for the bloom
* filter. Negative values are reserved for special objects.
* - `-1` is reserved for injecting `Injector` (implemented by `NodeInjector`)
*
* @param tNode The Node where the search for the injector should start
* @param lView The `LView` that contains the `tNode`
* @param token The token to look for
Expand Down Expand Up @@ -315,6 +319,10 @@ export function getOrCreateInjectable<T>(
setTNodeAndViewData(savePreviousOrParentTNode, saveLView);
}
} else if (typeof bloomHash == 'number') {
if (bloomHash === -1) {
// `-1` is a special value used to identify `Injector` types.
Comment thread
mhevery marked this conversation as resolved.
Outdated
return new NodeInjector(tNode, lView) as any;
}
// If the token has a bloom hash, then it is a token which could be in NodeInjector.

// A reference to the previous injector TView that was found while climbing the element
Expand Down Expand Up @@ -528,6 +536,7 @@ export function getNodeInjectable(
*
* @param token the injection token
* @returns the matching bit to check in the bloom filter or `null` if the token is not known.
* When the returned value is negative then it represents special values such as `Injector`.
*/
export function bloomHashBitOrFactory(token: Type<any>| InjectionToken<any>| string): number|
Function|undefined {
Expand All @@ -536,7 +545,8 @@ export function bloomHashBitOrFactory(token: Type<any>| InjectionToken<any>| str
return token.charCodeAt(0) || 0;
}
const tokenId: number|undefined = (token as any)[NG_ELEMENT_ID];
return typeof tokenId === 'number' ? tokenId & BLOOM_MASK : tokenId;
// Negative token IDs are used for special objects such as `Injector`
Comment thread
mhevery marked this conversation as resolved.
Outdated
return (typeof tokenId === 'number' && tokenId > 0) ? tokenId & BLOOM_MASK : tokenId;
}

export function bloomHasToken(
Expand Down Expand Up @@ -572,11 +582,6 @@ function shouldSearchParent(flags: InjectFlags, isFirstHostTNode: boolean): bool
return !(flags & InjectFlags.Self) && !(flags & InjectFlags.Host && isFirstHostTNode);
}

export function injectInjector() {
const tNode = getPreviousOrParentTNode() as TElementNode | TContainerNode | TElementContainerNode;
return new NodeInjector(tNode, getLView());
}

export class NodeInjector implements Injector {
constructor(
private _tNode: TElementNode|TContainerNode|TElementContainerNode|null,
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/render3/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export const NG_BASE_DEF = getClosureSafeProperty({ngBaseDef: getClosureSafeProp
* the key and the directive's unique ID as the value. This allows us to map directives to their
* bloom filter bit for DI.
*/
// TODO(misko): This is wrong. The NG_ELEMENT_ID should never be minified.
export const NG_ELEMENT_ID = getClosureSafeProperty({__NG_ELEMENT_ID__: getClosureSafeProperty});
4 changes: 1 addition & 3 deletions packages/core/src/render3/instructions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/

import {InjectFlags, InjectionToken, Injector} from '../di';
import {resolveForwardRef} from '../di/forward_ref';
import {InjectionToken} from '../di/injection_token';
import {Injector} from '../di/injector';
import {InjectFlags} from '../di/injector_compatibility';
import {Type} from '../interface/type';
import {QueryList} from '../linker';
import {Sanitizer} from '../sanitization/security';
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/render3/interfaces/injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
*/

import {InjectionToken} from '../../di/injection_token';
import {InjectFlags} from '../../di/injector_compatibility';
import {InjectFlags} from '../../di/interface/injector';
import {Type} from '../../interface/type';

import {TElementNode} from './node';
import {LView, TData} from './view';

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/render3/ng_module_ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import {INJECTOR, Injector} from '../di/injector';
import {InjectFlags} from '../di/injector_compatibility';
import {InjectFlags} from '../di/interface/injector';
import {StaticProvider} from '../di/interface/provider';
import {createInjector} from '../di/r3_injector';
import {Type} from '../interface/type';
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/view/refs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import {ApplicationRef} from '../application_ref';
import {ChangeDetectorRef} from '../change_detection/change_detection';
import {Injector} from '../di/injector';
import {InjectFlags} from '../di/injector_compatibility';
import {InjectFlags} from '../di/interface/injector';
import {Type} from '../interface/type';
import {ComponentFactory, ComponentRef} from '../linker/component_factory';
import {ComponentFactoryBoundToModule, ComponentFactoryResolver} from '../linker/component_factory_resolver';
Expand Down
Loading