refactor(core): Cleanup non-standard Injector
handling. (#39621)
Due to historical reasons `Injector.__NG_ELEMENT_ID__` was set to `-1`. This changes it to be consistent with other `*Ref.__NG_ELEMENT_ID__` constructs. PR Close #39621
This commit is contained in:
parent
585875c3f4
commit
8574c3000e
@ -255,21 +255,6 @@
|
||||
"packages/core/src/render3/definition.ts",
|
||||
"packages/core/src/metadata/ng_module.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/application_ref.ts",
|
||||
"packages/core/src/application_tokens.ts",
|
||||
"packages/core/src/linker/component_factory.ts",
|
||||
"packages/core/src/change_detection/change_detection.ts",
|
||||
"packages/core/src/change_detection/change_detector_ref.ts",
|
||||
"packages/core/src/render3/view_ref.ts",
|
||||
"packages/core/src/linker/view_container_ref.ts",
|
||||
"packages/core/src/render3/di.ts",
|
||||
"packages/core/src/di/injector_compatibility.ts",
|
||||
"packages/core/src/di/injector.ts",
|
||||
"packages/core/src/di/r3_injector.ts",
|
||||
"packages/core/src/render3/definition.ts",
|
||||
"packages/core/src/metadata/ng_module.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/application_ref.ts",
|
||||
"packages/core/src/application_tokens.ts",
|
||||
@ -641,16 +626,6 @@
|
||||
"packages/core/src/render3/definition.ts",
|
||||
"packages/core/src/metadata/ng_module.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/application_ref.ts",
|
||||
"packages/core/src/linker/compiler.ts",
|
||||
"packages/core/src/render3/ng_module_ref.ts",
|
||||
"packages/core/src/di/injector_compatibility.ts",
|
||||
"packages/core/src/di/injector.ts",
|
||||
"packages/core/src/di/r3_injector.ts",
|
||||
"packages/core/src/render3/definition.ts",
|
||||
"packages/core/src/metadata/ng_module.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/application_ref.ts",
|
||||
"packages/core/src/linker/compiler.ts",
|
||||
@ -786,20 +761,6 @@
|
||||
"packages/core/src/render3/definition.ts",
|
||||
"packages/core/src/metadata/ng_module.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/application_ref.ts",
|
||||
"packages/core/src/metadata/resource_loading.ts",
|
||||
"packages/core/src/metadata/directives.ts",
|
||||
"packages/core/src/render3/jit/directive.ts",
|
||||
"packages/core/src/render3/jit/environment.ts",
|
||||
"packages/core/src/render3/index.ts",
|
||||
"packages/core/src/render3/pipe.ts",
|
||||
"packages/core/src/di/injector_compatibility.ts",
|
||||
"packages/core/src/di/injector.ts",
|
||||
"packages/core/src/di/r3_injector.ts",
|
||||
"packages/core/src/render3/definition.ts",
|
||||
"packages/core/src/metadata/ng_module.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/application_ref.ts",
|
||||
"packages/core/src/metadata/resource_loading.ts",
|
||||
@ -900,6 +861,16 @@
|
||||
"packages/core/src/view/entrypoint.ts",
|
||||
"packages/core/src/view/services.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/di.ts",
|
||||
"packages/core/src/di/index.ts",
|
||||
"packages/core/src/di/injectable.ts",
|
||||
"packages/core/src/di/jit/injectable.ts",
|
||||
"packages/core/src/di/jit/environment.ts",
|
||||
"packages/core/src/di/injector_compatibility.ts",
|
||||
"packages/core/src/di/injector.ts",
|
||||
"packages/core/src/di/null_injector.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/di/injectable.ts",
|
||||
"packages/core/src/di/jit/injectable.ts"
|
||||
@ -908,6 +879,11 @@
|
||||
"packages/core/src/di/injector_compatibility.ts",
|
||||
"packages/core/src/di/injector.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/di/injector_compatibility.ts",
|
||||
"packages/core/src/di/injector.ts",
|
||||
"packages/core/src/di/null_injector.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/di/injector_compatibility.ts",
|
||||
"packages/core/src/di/injector.ts",
|
||||
@ -921,6 +897,10 @@
|
||||
"packages/core/src/metadata/ng_module.ts",
|
||||
"packages/core/src/di/util.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/di/injector_token.ts",
|
||||
"packages/core/src/di/injector.ts"
|
||||
],
|
||||
[
|
||||
"packages/core/src/di/injector.ts",
|
||||
"packages/core/src/di/r3_injector.ts"
|
||||
|
4
goldens/public-api/core/core.d.ts
vendored
4
goldens/public-api/core/core.d.ts
vendored
@ -837,11 +837,11 @@ export declare interface RendererType2 {
|
||||
}
|
||||
|
||||
export declare class ResolvedReflectiveFactory {
|
||||
dependencies: ɵangular_packages_core_core_e[];
|
||||
dependencies: ɵangular_packages_core_core_d[];
|
||||
factory: Function;
|
||||
constructor(
|
||||
factory: Function,
|
||||
dependencies: ɵangular_packages_core_core_e[]);
|
||||
dependencies: ɵangular_packages_core_core_d[]);
|
||||
}
|
||||
|
||||
export declare interface ResolvedReflectiveProvider {
|
||||
|
@ -12,7 +12,7 @@
|
||||
"master": {
|
||||
"uncompressed": {
|
||||
"runtime-es2015": 3037,
|
||||
"main-es2015": 449483,
|
||||
"main-es2015": 448796,
|
||||
"polyfills-es2015": 52415
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
"master": {
|
||||
"uncompressed": {
|
||||
"runtime-es2015": 1485,
|
||||
"main-es2015": 147252,
|
||||
"main-es2015": 146680,
|
||||
"polyfills-es2015": 36964
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ export {ɵɵdefineInjectable, defineInjectable, ɵɵdefineInjector, InjectableTy
|
||||
export {forwardRef, resolveForwardRef, ForwardRefFn} from './forward_ref';
|
||||
export {Injectable, InjectableDecorator, InjectableProvider} from './injectable';
|
||||
export {Injector} from './injector';
|
||||
export {ɵɵinject, inject, INJECTOR, ɵɵinvalidFactoryDep} from './injector_compatibility';
|
||||
export {ɵɵinject, inject, ɵɵinvalidFactoryDep} from './injector_compatibility';
|
||||
export {INJECTOR} from './injector_token';
|
||||
export {ReflectiveInjector} from './reflective_injector';
|
||||
export {ClassProvider, ClassSansProvider, ConstructorProvider, ConstructorSansProvider, ExistingProvider, ExistingSansProvider, FactoryProvider, FactorySansProvider, Provider, StaticClassProvider, StaticClassSansProvider, StaticProvider, TypeProvider, ValueProvider, ValueSansProvider} from './interface/provider';
|
||||
export {ResolvedReflectiveFactory, ResolvedReflectiveProvider} from './reflective_provider';
|
||||
|
76
packages/core/src/di/inject_switch.ts
Normal file
76
packages/core/src/di/inject_switch.ts
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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
|
||||
*/
|
||||
|
||||
import {Type} from '../interface/type';
|
||||
import {assertNotEqual} from '../util/assert';
|
||||
import {stringify} from '../util/stringify';
|
||||
import {InjectionToken} from './injection_token';
|
||||
import {getInjectableDef, ɵɵInjectableDef} from './interface/defs';
|
||||
import {InjectFlags} from './interface/injector';
|
||||
|
||||
|
||||
/**
|
||||
* Current implementation of inject.
|
||||
*
|
||||
* By default, it is `injectInjectorOnly`, which makes it `Injector`-only aware. It can be changed
|
||||
* to `directiveInject`, which brings in the `NodeInjector` system of ivy. It is designed this
|
||||
* way for two reasons:
|
||||
* 1. `Injector` should not depend on ivy logic.
|
||||
* 2. To maintain tree shake-ability we don't want to bring in unnecessary code.
|
||||
*/
|
||||
let _injectImplementation: (<T>(token: Type<T>|InjectionToken<T>, flags?: InjectFlags) => T | null)|
|
||||
undefined;
|
||||
export function getInjectImplementation() {
|
||||
return _injectImplementation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the current inject implementation.
|
||||
*/
|
||||
export function setInjectImplementation(
|
||||
impl: (<T>(token: Type<T>|InjectionToken<T>, flags?: InjectFlags) => T | null)|
|
||||
undefined): (<T>(token: Type<T>|InjectionToken<T>, flags?: InjectFlags) => T | null)|undefined {
|
||||
const previous = _injectImplementation;
|
||||
_injectImplementation = impl;
|
||||
return previous;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injects `root` tokens in limp mode.
|
||||
*
|
||||
* If no injector exists, we can still inject tree-shakable providers which have `providedIn` set to
|
||||
* `"root"`. This is known as the limp mode injection. In such case the value is stored in the
|
||||
* `InjectableDef`.
|
||||
*/
|
||||
export function injectRootLimpMode<T>(
|
||||
token: Type<T>|InjectionToken<T>, notFoundValue: T|undefined, flags: InjectFlags): T|null {
|
||||
const injectableDef: ɵɵInjectableDef<T>|null = getInjectableDef(token);
|
||||
if (injectableDef && injectableDef.providedIn == 'root') {
|
||||
return injectableDef.value === undefined ? injectableDef.value = injectableDef.factory() :
|
||||
injectableDef.value;
|
||||
}
|
||||
if (flags & InjectFlags.Optional) return null;
|
||||
if (notFoundValue !== undefined) return notFoundValue;
|
||||
throw new Error(`Injector: NOT_FOUND [${stringify(token)}]`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert that `_injectImplementation` is not `fn`.
|
||||
*
|
||||
* This is useful, to prevent infinite recursion.
|
||||
*
|
||||
* @param fn Function which it should not equal to
|
||||
*/
|
||||
export function assertInjectImplementationNotEqual(
|
||||
fn: (<T>(token: Type<T>|InjectionToken<T>, flags?: InjectFlags) => T | null)) {
|
||||
ngDevMode &&
|
||||
assertNotEqual(_injectImplementation, fn, 'Calling ɵɵinject would cause infinite recursion');
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import {Type} from '../interface/type';
|
||||
import {assertLessThan} from '../util/assert';
|
||||
|
||||
import {ɵɵdefineInjectable} from './interface/defs';
|
||||
|
||||
@ -61,9 +62,10 @@ export class InjectionToken<T> {
|
||||
}) {
|
||||
this.ɵprov = undefined;
|
||||
if (typeof options == 'number') {
|
||||
(typeof ngDevMode === 'undefined' || ngDevMode) &&
|
||||
assertLessThan(options, 0, 'Only negative numbers are supported here');
|
||||
// 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`.
|
||||
// See `InjectorMarkers`
|
||||
(this as any).__NG_ELEMENT_ID__ = options;
|
||||
} else if (options !== undefined) {
|
||||
this.ɵprov = ɵɵdefineInjectable({
|
||||
|
@ -8,14 +8,16 @@
|
||||
|
||||
import {AbstractType, Type} from '../interface/type';
|
||||
import {stringify} from '../util/stringify';
|
||||
|
||||
import {resolveForwardRef} from './forward_ref';
|
||||
import {InjectionToken} from './injection_token';
|
||||
import {catchInjectorError, formatError, INJECTOR, NG_TEMP_TOKEN_PATH, NullInjector, setCurrentInjector, THROW_IF_NOT_FOUND, USE_VALUE, ɵɵinject} from './injector_compatibility';
|
||||
import {catchInjectorError, formatError, NG_TEMP_TOKEN_PATH, setCurrentInjector, THROW_IF_NOT_FOUND, USE_VALUE, ɵɵinject} from './injector_compatibility';
|
||||
import {InjectorMarkers} from './injector_marker';
|
||||
import {INJECTOR} from './injector_token';
|
||||
import {getInjectableDef, ɵɵ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';
|
||||
import {NullInjector} from './null_injector';
|
||||
import {createInjector} from './r3_injector';
|
||||
import {INJECTOR_SCOPE} from './scope';
|
||||
|
||||
@ -113,7 +115,7 @@ export abstract class Injector {
|
||||
* @internal
|
||||
* @nocollapse
|
||||
*/
|
||||
static __NG_ELEMENT_ID__ = -1;
|
||||
static __NG_ELEMENT_ID__ = InjectorMarkers.Injector;
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,28 +14,14 @@ import {getClosureSafeProperty} from '../util/property';
|
||||
import {stringify} from '../util/stringify';
|
||||
|
||||
import {resolveForwardRef} from './forward_ref';
|
||||
import {getInjectImplementation, injectRootLimpMode} from './inject_switch';
|
||||
import {InjectionToken} from './injection_token';
|
||||
import {Injector} from './injector';
|
||||
import {getInjectableDef, ɵɵInjectableDef} from './interface/defs';
|
||||
import {InjectFlags} from './interface/injector';
|
||||
import {ValueProvider} from './interface/provider';
|
||||
import {Inject, Optional, Self, SkipSelf} from './metadata';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An InjectionToken that gets the current `Injector` for `createInjector()`-style injectors.
|
||||
*
|
||||
* Requesting this token instead of `Injector` allows `StaticInjector` to be tree-shaken from a
|
||||
* project.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
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`.
|
||||
);
|
||||
|
||||
const _THROW_IF_NOT_FOUND = {};
|
||||
export const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
|
||||
|
||||
@ -62,41 +48,6 @@ export function setCurrentInjector(injector: Injector|null|undefined): Injector|
|
||||
return former;
|
||||
}
|
||||
|
||||
/**
|
||||
* Current implementation of inject.
|
||||
*
|
||||
* By default, it is `injectInjectorOnly`, which makes it `Injector`-only aware. It can be changed
|
||||
* to `directiveInject`, which brings in the `NodeInjector` system of ivy. It is designed this
|
||||
* way for two reasons:
|
||||
* 1. `Injector` should not depend on ivy logic.
|
||||
* 2. To maintain tree shake-ability we don't want to bring in unnecessary code.
|
||||
*/
|
||||
let _injectImplementation: (<T>(token: Type<T>|InjectionToken<T>, flags?: InjectFlags) => T | null)|
|
||||
undefined;
|
||||
|
||||
/**
|
||||
* Sets the current inject implementation.
|
||||
*/
|
||||
export function setInjectImplementation(
|
||||
impl: (<T>(token: Type<T>|InjectionToken<T>, flags?: InjectFlags) => T | null)|
|
||||
undefined): (<T>(token: Type<T>|InjectionToken<T>, flags?: InjectFlags) => T | null)|undefined {
|
||||
const previous = _injectImplementation;
|
||||
_injectImplementation = impl;
|
||||
return previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that `_injectImplementation` is not `fn`.
|
||||
*
|
||||
* This is useful, to prevent infinite recursion.
|
||||
*
|
||||
* @param fn Function which it should not equal to
|
||||
*/
|
||||
export function assertInjectImplementationNot(
|
||||
fn: (<T>(token: Type<T>|InjectionToken<T>, flags?: InjectFlags) => T | null)) {
|
||||
ngDevMode &&
|
||||
assertNotEqual(_injectImplementation, fn, 'Calling ɵɵinject would cause infinite recursion');
|
||||
}
|
||||
|
||||
export function injectInjectorOnly<T>(token: Type<T>|InjectionToken<T>): T;
|
||||
export function injectInjectorOnly<T>(token: Type<T>|InjectionToken<T>, flags?: InjectFlags): T|
|
||||
@ -128,7 +79,7 @@ export function injectInjectorOnly<T>(
|
||||
export function ɵɵinject<T>(token: Type<T>|InjectionToken<T>): T;
|
||||
export function ɵɵinject<T>(token: Type<T>|InjectionToken<T>, flags?: InjectFlags): T|null;
|
||||
export function ɵɵinject<T>(token: Type<T>|InjectionToken<T>, flags = InjectFlags.Default): T|null {
|
||||
return (_injectImplementation || injectInjectorOnly)(resolveForwardRef(token), flags);
|
||||
return (getInjectImplementation() || injectInjectorOnly)(resolveForwardRef(token), flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,24 +132,6 @@ Please check that 1) the type for the parameter at index ${
|
||||
*/
|
||||
export const inject = ɵɵinject;
|
||||
|
||||
/**
|
||||
* Injects `root` tokens in limp mode.
|
||||
*
|
||||
* If no injector exists, we can still inject tree-shakable providers which have `providedIn` set to
|
||||
* `"root"`. This is known as the limp mode injection. In such case the value is stored in the
|
||||
* `InjectableDef`.
|
||||
*/
|
||||
export function injectRootLimpMode<T>(
|
||||
token: Type<T>|InjectionToken<T>, notFoundValue: T|undefined, flags: InjectFlags): T|null {
|
||||
const injectableDef: ɵɵInjectableDef<T>|null = getInjectableDef(token);
|
||||
if (injectableDef && injectableDef.providedIn == 'root') {
|
||||
return injectableDef.value === undefined ? injectableDef.value = injectableDef.factory() :
|
||||
injectableDef.value;
|
||||
}
|
||||
if (flags & InjectFlags.Optional) return null;
|
||||
if (notFoundValue !== undefined) return notFoundValue;
|
||||
throw new Error(`Injector: NOT_FOUND [${stringify(token)}]`);
|
||||
}
|
||||
|
||||
export function injectArgs(types: (Type<any>|InjectionToken<any>|any[])[]): any[] {
|
||||
const args: any[] = [];
|
||||
@ -236,22 +169,6 @@ export function injectArgs(types: (Type<any>|InjectionToken<any>|any[])[]): any[
|
||||
}
|
||||
|
||||
|
||||
export class NullInjector implements Injector {
|
||||
get(token: any, notFoundValue: any = THROW_IF_NOT_FOUND): any {
|
||||
if (notFoundValue === THROW_IF_NOT_FOUND) {
|
||||
// Intentionally left behind: With dev tools open the debugger will stop here. There is no
|
||||
// reason why correctly written application should cause this exception.
|
||||
// TODO(misko): uncomment the next line once `ngDevMode` works with closure.
|
||||
// if (ngDevMode) debugger;
|
||||
const error = new Error(`NullInjectorError: No provider for ${stringify(token)}!`);
|
||||
error.name = 'NullInjectorError';
|
||||
throw error;
|
||||
}
|
||||
return notFoundValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function catchInjectorError(
|
||||
e: any, token: any, injectorErrorName: string, source: string|null): never {
|
||||
const tokenPath: any[] = e[NG_TEMP_TOKEN_PATH];
|
||||
|
24
packages/core/src/di/injector_marker.ts
Normal file
24
packages/core/src/di/injector_marker.ts
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Special markers which can be left on `Type.__NG_ELEMENT_ID__` which are used by the Ivy's
|
||||
* `NodeInjector`. Usually these markers contain factory functions. But in case of this special
|
||||
* marker we can't leave behind a function because it would create tree shaking problem.
|
||||
*
|
||||
* Currently only `Injector` is special.
|
||||
*
|
||||
* NOTE: the numbers here must be negative, because positive numbers are used as IDs for bloom
|
||||
* filter.
|
||||
*/
|
||||
export const enum InjectorMarkers {
|
||||
/**
|
||||
* Marks that the current type is `Injector`
|
||||
*/
|
||||
Injector = -1
|
||||
}
|
28
packages/core/src/di/injector_token.ts
Normal file
28
packages/core/src/di/injector_token.ts
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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
|
||||
*/
|
||||
|
||||
import {InjectionToken} from './injection_token';
|
||||
import {Injector} from './injector';
|
||||
import {InjectorMarkers} from './injector_marker';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An InjectionToken that gets the current `Injector` for `createInjector()`-style injectors.
|
||||
*
|
||||
* Requesting this token instead of `Injector` allows `StaticInjector` to be tree-shaken from a
|
||||
* project.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export const INJECTOR = new InjectionToken<Injector>(
|
||||
'INJECTOR',
|
||||
// Dissable tslint because this is const enum which gets inlined not top level prop access.
|
||||
// tslint:disable-next-line: no-toplevel-property-access
|
||||
InjectorMarkers.Injector as any, // Special value used by Ivy to identify `Injector`.
|
||||
);
|
23
packages/core/src/di/null_injector.ts
Normal file
23
packages/core/src/di/null_injector.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC 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
|
||||
*/
|
||||
|
||||
import {stringify} from '../util/stringify';
|
||||
import {Injector} from '.';
|
||||
import {THROW_IF_NOT_FOUND} from './injector_compatibility';
|
||||
|
||||
|
||||
export class NullInjector implements Injector {
|
||||
get(token: any, notFoundValue: any = THROW_IF_NOT_FOUND): any {
|
||||
if (notFoundValue === THROW_IF_NOT_FOUND) {
|
||||
const error = new Error(`NullInjectorError: No provider for ${stringify(token)}!`);
|
||||
error.name = 'NullInjectorError';
|
||||
throw error;
|
||||
}
|
||||
return notFoundValue;
|
||||
}
|
||||
}
|
@ -19,10 +19,12 @@ import {stringify} from '../util/stringify';
|
||||
import {resolveForwardRef} from './forward_ref';
|
||||
import {InjectionToken} from './injection_token';
|
||||
import {Injector} from './injector';
|
||||
import {catchInjectorError, injectArgs, INJECTOR, NG_TEMP_TOKEN_PATH, NullInjector, setCurrentInjector, THROW_IF_NOT_FOUND, USE_VALUE, ɵɵinject} from './injector_compatibility';
|
||||
import {catchInjectorError, injectArgs, NG_TEMP_TOKEN_PATH, setCurrentInjector, THROW_IF_NOT_FOUND, USE_VALUE, ɵɵinject} from './injector_compatibility';
|
||||
import {INJECTOR} from './injector_token';
|
||||
import {getInheritedInjectableDef, getInjectableDef, getInjectorDef, InjectorType, InjectorTypeWithProviders, ɵɵInjectableDef} from './interface/defs';
|
||||
import {InjectFlags} from './interface/injector';
|
||||
import {ClassProvider, ConstructorProvider, ExistingProvider, FactoryProvider, StaticClassProvider, StaticProvider, TypeProvider, ValueProvider} from './interface/provider';
|
||||
import {NullInjector} from './null_injector';
|
||||
import {INJECTOR_SCOPE} from './scope';
|
||||
|
||||
|
||||
|
@ -7,9 +7,10 @@
|
||||
*/
|
||||
|
||||
import {isForwardRef, resolveForwardRef} from '../di/forward_ref';
|
||||
import {injectRootLimpMode, setInjectImplementation} from '../di/inject_switch';
|
||||
import {InjectionToken} from '../di/injection_token';
|
||||
import {Injector} from '../di/injector';
|
||||
import {injectRootLimpMode, setInjectImplementation} from '../di/injector_compatibility';
|
||||
import {InjectorMarkers} from '../di/injector_marker';
|
||||
import {getInjectorDef} from '../di/interface/defs';
|
||||
import {InjectFlags} from '../di/interface/injector';
|
||||
import {Type} from '../interface/type';
|
||||
@ -415,8 +416,11 @@ export function getOrCreateInjectable<T>(
|
||||
// so just call the factory function to create it.
|
||||
if (typeof bloomHash === 'function') {
|
||||
if (!enterDI(lView, tNode, flags)) {
|
||||
// Failed to enter DI use module injector instead.
|
||||
return lookupTokenUsingModuleInjector<T>(lView, token, flags, notFoundValue);
|
||||
// Failed to enter DI, try module injector instead. If a token is injected with the @Host
|
||||
// flag, the module injector is not searched for that token in Ivy.
|
||||
return (flags & InjectFlags.Host) ?
|
||||
notFoundValueOrThrow<T>(notFoundValue, token, flags) :
|
||||
lookupTokenUsingModuleInjector<T>(lView, token, flags, notFoundValue);
|
||||
}
|
||||
try {
|
||||
const value = bloomHash();
|
||||
@ -429,32 +433,6 @@ export function getOrCreateInjectable<T>(
|
||||
leaveDI();
|
||||
}
|
||||
} else if (typeof bloomHash === 'number') {
|
||||
// This is a value used to identify __NG_ELEMENT_ID__
|
||||
// `-1` is a special value used to identify `Injector` types in NodeInjector
|
||||
// This is a workaround for the fact that if the `Injector.__NG_ELEMENT_ID__`
|
||||
// would have a factory function (such as `ElementRef`) it would cause Ivy
|
||||
// to be pulled into the ViewEngine, because they both share `Injector` type.
|
||||
// This should be refactored to follow `ElementRef` pattern once ViewEngine is
|
||||
// removed
|
||||
if (bloomHash === -1) {
|
||||
if (!enterDI(lView, tNode, flags)) {
|
||||
// Failed to enter DI, try module injector instead. If a token is injected with the @Host
|
||||
// flag, the module injector is not searched for that token in Ivy.
|
||||
return (flags & InjectFlags.Host) ?
|
||||
notFoundValueOrThrow<T>(notFoundValue, token, flags) :
|
||||
lookupTokenUsingModuleInjector<T>(lView, token, flags, notFoundValue);
|
||||
}
|
||||
try {
|
||||
// Retrieving current `TNode` and `LView` from the state (rather than using `tNode` and
|
||||
// `lView`), because entering DI (by calling `enterDI`) may cause these values to change
|
||||
// (in case `@SkipSelf` flag is present).
|
||||
return new NodeInjector(getCurrentTNode()! as TDirectiveHostNode, getLView()) as any;
|
||||
} finally {
|
||||
leaveDI();
|
||||
}
|
||||
}
|
||||
// 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
|
||||
// injector tree. This is used to know if viewProviders can be accessed on the current
|
||||
// injector.
|
||||
@ -525,6 +503,10 @@ export function getOrCreateInjectable<T>(
|
||||
|
||||
const NOT_FOUND = {};
|
||||
|
||||
export function createNodeInjector(): Injector {
|
||||
return new NodeInjector(getCurrentTNode()! as TDirectiveHostNode, getLView()) as any;
|
||||
}
|
||||
|
||||
function searchTokensOnInjector<T>(
|
||||
injectorIndex: number, lView: LView, token: Type<T>|InjectionToken<T>,
|
||||
previousTView: TView|null, flags: InjectFlags, hostTElementNode: TNode|null) {
|
||||
@ -674,7 +656,17 @@ export function bloomHashBitOrFactory(token: Type<any>|InjectionToken<any>|strin
|
||||
// First check with `hasOwnProperty` so we don't get an inherited ID.
|
||||
token.hasOwnProperty(NG_ELEMENT_ID) ? (token as any)[NG_ELEMENT_ID] : undefined;
|
||||
// Negative token IDs are used for special objects such as `Injector`
|
||||
return (typeof tokenId === 'number' && tokenId > 0) ? tokenId & BLOOM_MASK : tokenId;
|
||||
if (typeof tokenId === 'number') {
|
||||
if (tokenId >= 0) {
|
||||
return tokenId & BLOOM_MASK;
|
||||
} else {
|
||||
ngDevMode &&
|
||||
assertEqual(tokenId, InjectorMarkers.Injector, 'Expecting to get Special Injector Id');
|
||||
return createNodeInjector;
|
||||
}
|
||||
} else {
|
||||
return tokenId;
|
||||
}
|
||||
}
|
||||
|
||||
export function bloomHasToken(bloomHash: number, injectorIndex: number, injectorView: LView|TData) {
|
||||
|
@ -6,7 +6,8 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {InjectFlags, InjectionToken, resolveForwardRef} from '../../di';
|
||||
import {assertInjectImplementationNot, ɵɵinject} from '../../di/injector_compatibility';
|
||||
import {assertInjectImplementationNotEqual} from '../../di/inject_switch';
|
||||
import {ɵɵinject} from '../../di/injector_compatibility';
|
||||
import {Type} from '../../interface/type';
|
||||
import {getOrCreateInjectable, injectAttributeImpl} from '../di';
|
||||
import {TDirectiveHostNode} from '../interfaces/node';
|
||||
@ -45,7 +46,7 @@ export function ɵɵdirectiveInject<T>(
|
||||
// if inject utilities are used before bootstrapping.
|
||||
if (lView === null) {
|
||||
// Verify that we will not get into infinite loop.
|
||||
ngDevMode && assertInjectImplementationNot(ɵɵdirectiveInject);
|
||||
ngDevMode && assertInjectImplementationNotEqual(ɵɵdirectiveInject);
|
||||
return ɵɵinject(token, flags);
|
||||
}
|
||||
const tNode = getCurrentTNode();
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {Injector} from '../di/injector';
|
||||
import {INJECTOR} from '../di/injector_compatibility';
|
||||
import {INJECTOR} from '../di/injector_token';
|
||||
import {InjectFlags} from '../di/interface/injector';
|
||||
import {createInjectorWithoutInjectorInstances, R3Injector} from '../di/r3_injector';
|
||||
import {Type} from '../interface/type';
|
||||
|
@ -8,8 +8,7 @@
|
||||
|
||||
import {WrappedValue} from '../change_detection/change_detection_util';
|
||||
import {PipeTransform} from '../change_detection/pipe_transform';
|
||||
import {setInjectImplementation} from '../di/injector_compatibility';
|
||||
|
||||
import {setInjectImplementation} from '../di/inject_switch';
|
||||
import {getFactoryDef} from './definition';
|
||||
import {setIncludeViewProviders} from './di';
|
||||
import {RuntimeError, RuntimeErrorCode} from './error_code';
|
||||
|
@ -8,7 +8,8 @@
|
||||
|
||||
import {resolveForwardRef} from '../di/forward_ref';
|
||||
import {Injector} from '../di/injector';
|
||||
import {INJECTOR, setCurrentInjector} from '../di/injector_compatibility';
|
||||
import {setCurrentInjector} from '../di/injector_compatibility';
|
||||
import {INJECTOR} from '../di/injector_token';
|
||||
import {getInjectableDef, ɵɵInjectableDef} from '../di/interface/defs';
|
||||
import {INJECTOR_SCOPE} from '../di/scope';
|
||||
import {NgModuleRef} from '../linker/ng_module_factory';
|
||||
|
@ -833,6 +833,9 @@
|
||||
{
|
||||
"name": "createLView"
|
||||
},
|
||||
{
|
||||
"name": "createNodeInjector"
|
||||
},
|
||||
{
|
||||
"name": "createPlatformFactory"
|
||||
},
|
||||
|
@ -1073,6 +1073,9 @@
|
||||
{
|
||||
"name": "createNewSegmentGroup"
|
||||
},
|
||||
{
|
||||
"name": "createNodeInjector"
|
||||
},
|
||||
{
|
||||
"name": "createPlatformFactory"
|
||||
},
|
||||
|
@ -272,6 +272,9 @@
|
||||
{
|
||||
"name": "createLView"
|
||||
},
|
||||
{
|
||||
"name": "createNodeInjector"
|
||||
},
|
||||
{
|
||||
"name": "createTView"
|
||||
},
|
||||
|
@ -9,7 +9,7 @@
|
||||
import {NgModuleRef, ɵINJECTOR_SCOPE as INJECTOR_SCOPE} from '@angular/core';
|
||||
import {inject, InjectFlags} from '@angular/core/src/di';
|
||||
import {Injector} from '@angular/core/src/di/injector';
|
||||
import {INJECTOR} from '@angular/core/src/di/injector_compatibility';
|
||||
import {INJECTOR} from '@angular/core/src/di/injector_token';
|
||||
import {ɵɵdefineInjectable, ɵɵInjectableDef} from '@angular/core/src/di/interface/defs';
|
||||
import {NgModuleDefinition, NgModuleProviderDef, NodeFlags} from '@angular/core/src/view';
|
||||
import {moduleDef} from '@angular/core/src/view/ng_module';
|
||||
|
Loading…
x
Reference in New Issue
Block a user