static-injector 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/import/commonjs/index.js +419 -157
- package/import/es2015/di/create_injector.js +5 -1
- package/import/es2015/di/forward_ref.js +3 -3
- package/import/es2015/di/injection_token.js +18 -11
- package/import/es2015/di/injector_compatibility.js +19 -10
- package/import/es2015/di/injector_token.js +3 -3
- package/import/es2015/di/interface/defs.js +21 -12
- package/import/es2015/di/interface/provider.js +3 -1
- package/import/es2015/di/null_injector.js +3 -3
- package/import/es2015/di/provider_collection.js +196 -1
- package/import/es2015/di/r3_injector.js +25 -22
- package/import/es2015/error_details_base_url.js +19 -0
- package/import/es2015/errors.js +42 -0
- package/import/es2015/interface/type.js +14 -1
- package/import/es2015/render3/definition_factory.js +2 -3
- package/import/es2015/render3/errors_di.js +2 -3
- package/import/es2015/render3/instructions/di.js +0 -7
- package/import/es2015/render3/util/stringify_utils.js +5 -5
- package/import/es2015/util/array_utils.js +0 -7
- package/import/es2015/util/decorators.js +24 -1
- package/import/es2015/util/empty.js +4 -0
- package/import/es2015/util/stringify.js +5 -5
- package/import/fesm2015/index.js +416 -155
- package/import/typings/di/forward_ref.d.ts +1 -1
- package/import/typings/di/injectable.d.ts +4 -3
- package/import/typings/di/injection_token.d.ts +21 -6
- package/import/typings/di/injector.d.ts +16 -0
- package/import/typings/di/injector_compatibility.d.ts +11 -5
- package/import/typings/di/injector_token.d.ts +2 -2
- package/import/typings/di/interface/defs.d.ts +15 -8
- package/import/typings/di/interface/provider.d.ts +60 -0
- package/import/typings/di/null_injector.d.ts +1 -1
- package/import/typings/di/provider_collection.d.ts +54 -1
- package/import/typings/di/provider_token.d.ts +2 -2
- package/import/typings/di/r3_injector.d.ts +3 -8
- package/import/typings/error_details_base_url.d.ts +19 -0
- package/import/typings/errors.d.ts +89 -0
- package/import/typings/interface/type.d.ts +45 -0
- package/import/typings/render3/errors_di.d.ts +7 -0
- package/import/typings/render3/instructions/di.d.ts +0 -7
- package/import/typings/util/array_utils.d.ts +15 -7
- package/import/typings/util/decorators.d.ts +2 -1
- package/import/typings/util/empty.d.ts +1 -0
- package/package.json +1 -1
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { EMPTY_ARRAY } from '../util/empty';
|
|
9
9
|
import { stringify } from '../util/stringify';
|
|
10
|
+
import { importProvidersFrom } from './provider_collection';
|
|
10
11
|
import { getNullInjector, R3Injector } from './r3_injector';
|
|
11
12
|
/**
|
|
12
13
|
* Create a new `Injector` which is configured using a `defType` of `InjectorType<any>`s.
|
|
@@ -24,7 +25,10 @@ export function createInjector(defType, parent = null, additionalProviders = nul
|
|
|
24
25
|
* should be resolved at a later point by calling `_resolveInjectorDefTypes`.
|
|
25
26
|
*/
|
|
26
27
|
export function createInjectorWithoutInjectorInstances(defType, parent = null, additionalProviders = null, name, scopes = new Set()) {
|
|
27
|
-
const providers = [
|
|
28
|
+
const providers = [
|
|
29
|
+
additionalProviders || EMPTY_ARRAY,
|
|
30
|
+
importProvidersFrom(defType),
|
|
31
|
+
];
|
|
28
32
|
name = name || (typeof defType === 'object' ? undefined : stringify(defType));
|
|
29
33
|
return new R3Injector(providers, parent || getNullInjector(), name || null, scopes);
|
|
30
34
|
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
-
import { getClosureSafeProperty } from
|
|
9
|
-
import { stringify } from
|
|
8
|
+
import { getClosureSafeProperty } from '../util/property';
|
|
9
|
+
import { stringify } from '../util/stringify';
|
|
10
10
|
const __forward_ref__ = getClosureSafeProperty({
|
|
11
11
|
__forward_ref__: getClosureSafeProperty,
|
|
12
12
|
});
|
|
@@ -47,7 +47,7 @@ export function resolveForwardRef(type) {
|
|
|
47
47
|
}
|
|
48
48
|
/** Checks whether a function is wrapped by a `forwardRef`. */
|
|
49
49
|
export function isForwardRef(fn) {
|
|
50
|
-
return (typeof fn ===
|
|
50
|
+
return (typeof fn === 'function' &&
|
|
51
51
|
fn.hasOwnProperty(__forward_ref__) &&
|
|
52
52
|
fn.__forward_ref__ === forwardRef);
|
|
53
53
|
}
|
|
@@ -14,11 +14,11 @@ import { ɵɵdefineInjectable } from './interface/defs';
|
|
|
14
14
|
* parameterized type.
|
|
15
15
|
*
|
|
16
16
|
* `InjectionToken` is parameterized on `T` which is the type of object which will be returned by
|
|
17
|
-
* the `Injector`. This provides additional level of type safety.
|
|
17
|
+
* the `Injector`. This provides an additional level of type safety.
|
|
18
18
|
*
|
|
19
19
|
* ```
|
|
20
20
|
* interface MyInterface {...}
|
|
21
|
-
*
|
|
21
|
+
* const myInterface = injector.get(new InjectionToken<MyInterface>('SomeToken'));
|
|
22
22
|
* // myInterface is inferred to be MyInterface.
|
|
23
23
|
* ```
|
|
24
24
|
*
|
|
@@ -26,14 +26,18 @@ import { ɵɵdefineInjectable } from './interface/defs';
|
|
|
26
26
|
* (possibly by creating) a default value of the parameterized type `T`. This sets up the
|
|
27
27
|
* `InjectionToken` using this factory as a provider as if it was defined explicitly in the
|
|
28
28
|
* application's root injector. If the factory function, which takes zero arguments, needs to inject
|
|
29
|
-
* dependencies, it can do so using the `inject` function.
|
|
29
|
+
* dependencies, it can do so using the `inject` function.
|
|
30
|
+
* As you can see in the Tree-shakable InjectionToken example below.
|
|
30
31
|
*
|
|
31
32
|
* Additionally, if a `factory` is specified you can also specify the `providedIn` option, which
|
|
32
|
-
* overrides the above behavior and marks the token as belonging to a particular `@NgModule
|
|
33
|
-
* mentioned above, `'root'` is the default value for
|
|
33
|
+
* overrides the above behavior and marks the token as belonging to a particular `@NgModule` (note:
|
|
34
|
+
* this option is now deprecated). As mentioned above, `'root'` is the default value for
|
|
35
|
+
* `providedIn`.
|
|
36
|
+
*
|
|
37
|
+
* The `providedIn: NgModule` and `providedIn: 'any'` options are deprecated.
|
|
34
38
|
*
|
|
35
39
|
* @usageNotes
|
|
36
|
-
* ### Basic
|
|
40
|
+
* ### Basic Examples
|
|
37
41
|
*
|
|
38
42
|
* ### Plain InjectionToken
|
|
39
43
|
*
|
|
@@ -47,15 +51,18 @@ import { ɵɵdefineInjectable } from './interface/defs';
|
|
|
47
51
|
* @publicApi
|
|
48
52
|
*/
|
|
49
53
|
export class InjectionToken {
|
|
54
|
+
/**
|
|
55
|
+
* @param _desc Description for the token,
|
|
56
|
+
* used only for debugging purposes,
|
|
57
|
+
* it should but does not need to be unique
|
|
58
|
+
* @param options Options for the token's usage, as described above
|
|
59
|
+
*/
|
|
50
60
|
constructor(_desc, options) {
|
|
51
61
|
this._desc = _desc;
|
|
62
|
+
/** @internal */
|
|
63
|
+
this.ngMetadataName = 'InjectionToken';
|
|
52
64
|
this.ɵprov = undefined;
|
|
53
65
|
if (typeof options == 'number') {
|
|
54
|
-
// (typeof ngDevMode === "undefined" || ngDevMode) &&
|
|
55
|
-
// assertLessThan(options, 0, "Only negative numbers are supported here");
|
|
56
|
-
// // This is a special hack to assign __NG_ELEMENT_ID__ to this instance.
|
|
57
|
-
// // See `InjectorMarkers`
|
|
58
|
-
// (this as any).__NG_ELEMENT_ID__ = options;
|
|
59
66
|
}
|
|
60
67
|
else if (options !== undefined) {
|
|
61
68
|
this.ɵprov = ɵɵdefineInjectable({
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { RuntimeError } from '../errors';
|
|
9
9
|
import { stringify } from '../util/stringify';
|
|
10
10
|
import { resolveForwardRef } from './forward_ref';
|
|
11
|
-
import { injectRootLimpMode } from './inject_switch';
|
|
11
|
+
import { getInjectImplementation, injectRootLimpMode } from './inject_switch';
|
|
12
12
|
import { InjectFlags, } from './interface/injector';
|
|
13
13
|
const _THROW_IF_NOT_FOUND = {};
|
|
14
14
|
export const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
|
|
@@ -23,10 +23,6 @@ const NG_TOKEN_PATH = 'ngTokenPath';
|
|
|
23
23
|
const NEW_LINE = /\n/gm;
|
|
24
24
|
const NO_NEW_LINE = 'ɵ';
|
|
25
25
|
export const SOURCE = '__source';
|
|
26
|
-
export const USE_VALUE = getClosureSafeProperty({
|
|
27
|
-
provide: String,
|
|
28
|
-
useValue: getClosureSafeProperty,
|
|
29
|
-
});
|
|
30
26
|
/**
|
|
31
27
|
* Current injector value used by `inject`.
|
|
32
28
|
* - `undefined`: it is an error to call `inject`
|
|
@@ -41,7 +37,7 @@ export function setCurrentInjector(injector) {
|
|
|
41
37
|
}
|
|
42
38
|
export function injectInjectorOnly(token, flags = InjectFlags.Default) {
|
|
43
39
|
if (_currentInjector === undefined) {
|
|
44
|
-
throw new
|
|
40
|
+
throw new RuntimeError(-203 /* RuntimeErrorCode.MISSING_INJECTION_CONTEXT */, null);
|
|
45
41
|
}
|
|
46
42
|
else if (_currentInjector === null) {
|
|
47
43
|
return injectRootLimpMode(token, undefined, flags);
|
|
@@ -51,7 +47,19 @@ export function injectInjectorOnly(token, flags = InjectFlags.Default) {
|
|
|
51
47
|
}
|
|
52
48
|
}
|
|
53
49
|
export function ɵɵinject(token, flags = InjectFlags.Default) {
|
|
54
|
-
return injectInjectorOnly(resolveForwardRef(token), flags);
|
|
50
|
+
return (getInjectImplementation() || injectInjectorOnly)(resolveForwardRef(token), flags);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Throws an error indicating that a factory function could not be generated by the compiler for a
|
|
54
|
+
* particular class.
|
|
55
|
+
*
|
|
56
|
+
* The name of the class is not mentioned here, but will be in the generated factory function name
|
|
57
|
+
* and thus in the stack trace.
|
|
58
|
+
*
|
|
59
|
+
* @codeGenApi
|
|
60
|
+
*/
|
|
61
|
+
export function ɵɵinvalidFactoryDep(index) {
|
|
62
|
+
throw new RuntimeError(202 /* RuntimeErrorCode.INVALID_FACTORY_DEPENDENCY */, null);
|
|
55
63
|
}
|
|
56
64
|
/**
|
|
57
65
|
* Injects a token from the currently active injector.
|
|
@@ -66,7 +74,7 @@ export function ɵɵinject(token, flags = InjectFlags.Default) {
|
|
|
66
74
|
* @param token A token that represents a dependency that should be injected.
|
|
67
75
|
* @param flags Optional flags that control how injection is executed.
|
|
68
76
|
* The flags correspond to injection strategies that can be specified with
|
|
69
|
-
* parameter decorators `@Host`, `@Self`, `@
|
|
77
|
+
* parameter decorators `@Host`, `@Self`, `@SkipSelf`, and `@Optional`.
|
|
70
78
|
* @returns the injected value if operation is successful, `null` otherwise.
|
|
71
79
|
* @throws if called outside of a supported context.
|
|
72
80
|
*
|
|
@@ -130,6 +138,7 @@ export function convertToBitFlags(flags) {
|
|
|
130
138
|
// `InjectOptions` to `InjectFlags`.
|
|
131
139
|
return (0 /* InternalInjectFlags.Default */ | // comment to force a line break in the formatter
|
|
132
140
|
(flags.optional && 8 /* InternalInjectFlags.Optional */) |
|
|
141
|
+
0 |
|
|
133
142
|
(flags.self && 2 /* InternalInjectFlags.Self */) |
|
|
134
143
|
(flags.skipSelf &&
|
|
135
144
|
4 /* InternalInjectFlags.SkipSelf */));
|
|
@@ -140,7 +149,7 @@ export function injectArgs(types) {
|
|
|
140
149
|
const arg = resolveForwardRef(types[i]);
|
|
141
150
|
if (Array.isArray(arg)) {
|
|
142
151
|
if (arg.length === 0) {
|
|
143
|
-
throw new
|
|
152
|
+
throw new RuntimeError(900 /* RuntimeErrorCode.INVALID_DIFFER_INPUT */, null);
|
|
144
153
|
}
|
|
145
154
|
let type = undefined;
|
|
146
155
|
let flags = InjectFlags.Default;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
-
import { InjectionToken } from
|
|
8
|
+
import { InjectionToken } from './injection_token';
|
|
9
9
|
/**
|
|
10
10
|
* An InjectionToken that gets the current `Injector` for `createInjector()`-style injectors.
|
|
11
11
|
*
|
|
@@ -14,8 +14,8 @@ import { InjectionToken } from "./injection_token";
|
|
|
14
14
|
*
|
|
15
15
|
* @publicApi
|
|
16
16
|
*/
|
|
17
|
-
export const INJECTOR = new InjectionToken(
|
|
18
|
-
//
|
|
17
|
+
export const INJECTOR = new InjectionToken('INJECTOR',
|
|
18
|
+
// Disable tslint because this is const enum which gets inlined not top level prop access.
|
|
19
19
|
// tslint:disable-next-line: no-toplevel-property-access
|
|
20
20
|
-1 /* InjectorMarkers.Injector */ // Special value used by Ivy to identify `Injector`.
|
|
21
21
|
);
|
|
@@ -58,7 +58,10 @@ export function ɵɵdefineInjector(options) {
|
|
|
58
58
|
* @param type A type which may have its own (non-inherited) `ɵprov`.
|
|
59
59
|
*/
|
|
60
60
|
export function getInjectableDef(type) {
|
|
61
|
-
return getOwnDefinition(type, NG_PROV_DEF);
|
|
61
|
+
return getOwnDefinition(type, NG_PROV_DEF) || null;
|
|
62
|
+
}
|
|
63
|
+
export function isInjectable(type) {
|
|
64
|
+
return getInjectableDef(type) !== null;
|
|
62
65
|
}
|
|
63
66
|
/**
|
|
64
67
|
* Return definition only if it is defined directly on `type` and is not inherited from a base
|
|
@@ -67,9 +70,6 @@ export function getInjectableDef(type) {
|
|
|
67
70
|
function getOwnDefinition(type, field) {
|
|
68
71
|
return type.hasOwnProperty(field) ? type[field] : null;
|
|
69
72
|
}
|
|
70
|
-
export const NG_PROV_DEF = getClosureSafeProperty({
|
|
71
|
-
ɵprov: getClosureSafeProperty,
|
|
72
|
-
});
|
|
73
73
|
/**
|
|
74
74
|
* Read the injectable def (`ɵprov`) for `type` or read the `ɵprov` from one of its ancestors.
|
|
75
75
|
*
|
|
@@ -79,22 +79,15 @@ export const NG_PROV_DEF = getClosureSafeProperty({
|
|
|
79
79
|
* scenario if we find the `ɵprov` on an ancestor only.
|
|
80
80
|
*/
|
|
81
81
|
export function getInheritedInjectableDef(type) {
|
|
82
|
-
const def = type && (type[NG_PROV_DEF] ||
|
|
82
|
+
const def = type && (type[NG_PROV_DEF] || null);
|
|
83
83
|
if (def) {
|
|
84
84
|
const typeName = getTypeName(type);
|
|
85
|
-
// TODO(FW-1307): Re-add ngDevMode when closure can handle it
|
|
86
|
-
// ngDevMode &&
|
|
87
|
-
console.warn(`DEPRECATED: DI is instantiating a token "${typeName}" that inherits its @Injectable decorator but does not provide one itself.\n` +
|
|
88
|
-
`This will become an error in a future version of Angular. Please add @Injectable() to the "${typeName}" class.`);
|
|
89
85
|
return def;
|
|
90
86
|
}
|
|
91
87
|
else {
|
|
92
88
|
return null;
|
|
93
89
|
}
|
|
94
90
|
}
|
|
95
|
-
export const NG_INJECTABLE_DEF = getClosureSafeProperty({
|
|
96
|
-
ngInjectableDef: getClosureSafeProperty,
|
|
97
|
-
});
|
|
98
91
|
/** Gets the name of a type, accounting for some cross-browser differences. */
|
|
99
92
|
function getTypeName(type) {
|
|
100
93
|
// `Function.prototype.name` behaves differently between IE and other browsers. In most browsers
|
|
@@ -109,3 +102,19 @@ function getTypeName(type) {
|
|
|
109
102
|
const match = ('' + type).match(/^function\s*([^\s(]+)/);
|
|
110
103
|
return match === null ? '' : match[1];
|
|
111
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Read the injector def type in a way which is immune to accidentally reading inherited value.
|
|
107
|
+
*
|
|
108
|
+
* @param type type which may have an injector def (`ɵinj`)
|
|
109
|
+
*/
|
|
110
|
+
export function getInjectorDef(type) {
|
|
111
|
+
return type && (type.hasOwnProperty(NG_INJ_DEF) || false)
|
|
112
|
+
? type[NG_INJ_DEF]
|
|
113
|
+
: null;
|
|
114
|
+
}
|
|
115
|
+
export const NG_PROV_DEF = getClosureSafeProperty({
|
|
116
|
+
ɵprov: getClosureSafeProperty,
|
|
117
|
+
});
|
|
118
|
+
export const NG_INJ_DEF = getClosureSafeProperty({
|
|
119
|
+
ɵinj: getClosureSafeProperty,
|
|
120
|
+
});
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
-
import { stringify } from
|
|
9
|
-
import { THROW_IF_NOT_FOUND } from
|
|
8
|
+
import { stringify } from '../util/stringify';
|
|
9
|
+
import { THROW_IF_NOT_FOUND } from './injector_compatibility';
|
|
10
10
|
export class NullInjector {
|
|
11
11
|
get(token, notFoundValue = THROW_IF_NOT_FOUND) {
|
|
12
12
|
if (notFoundValue === THROW_IF_NOT_FOUND) {
|
|
13
13
|
const error = new Error(`NullInjectorError: No provider for ${stringify(token)}!`);
|
|
14
|
-
error.name =
|
|
14
|
+
error.name = 'NullInjectorError';
|
|
15
15
|
throw error;
|
|
16
16
|
}
|
|
17
17
|
return notFoundValue;
|
|
@@ -5,8 +5,90 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
+
import { getFactoryDef } from '../render3/definition_factory';
|
|
9
|
+
import { deepForEach } from '../util/array_utils';
|
|
10
|
+
import { EMPTY_ARRAY } from '../util/empty';
|
|
8
11
|
import { getClosureSafeProperty } from '../util/property';
|
|
9
12
|
import { resolveForwardRef } from './forward_ref';
|
|
13
|
+
import { ENVIRONMENT_INITIALIZER } from './initializer_token';
|
|
14
|
+
import { ɵɵinject as inject } from './injector_compatibility';
|
|
15
|
+
import { getInjectorDef, } from './interface/defs';
|
|
16
|
+
import { isEnvironmentProviders, } from './interface/provider';
|
|
17
|
+
import { INJECTOR_DEF_TYPES } from './internal_tokens';
|
|
18
|
+
/**
|
|
19
|
+
* Wrap an array of `Provider`s into `EnvironmentProviders`, preventing them from being accidentally
|
|
20
|
+
* referenced in `@Component in a component injector.
|
|
21
|
+
*/
|
|
22
|
+
export function makeEnvironmentProviders(providers) {
|
|
23
|
+
return {
|
|
24
|
+
ɵproviders: providers,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Collects providers from all NgModules and standalone components, including transitively imported
|
|
29
|
+
* ones.
|
|
30
|
+
*
|
|
31
|
+
* Providers extracted via `importProvidersFrom` are only usable in an application injector or
|
|
32
|
+
* another environment injector (such as a route injector). They should not be used in component
|
|
33
|
+
* providers.
|
|
34
|
+
*
|
|
35
|
+
* More information about standalone components can be found in [this
|
|
36
|
+
* guide](guide/standalone-components).
|
|
37
|
+
*
|
|
38
|
+
* @usageNotes
|
|
39
|
+
* The results of the `importProvidersFrom` call can be used in the `bootstrapApplication` call:
|
|
40
|
+
*
|
|
41
|
+
* ```typescript
|
|
42
|
+
* await bootstrapApplication(RootComponent, {
|
|
43
|
+
* providers: [
|
|
44
|
+
* importProvidersFrom(NgModuleOne, NgModuleTwo)
|
|
45
|
+
* ]
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* You can also use the `importProvidersFrom` results in the `providers` field of a route, when a
|
|
50
|
+
* standalone component is used:
|
|
51
|
+
*
|
|
52
|
+
* ```typescript
|
|
53
|
+
* export const ROUTES: Route[] = [
|
|
54
|
+
* {
|
|
55
|
+
* path: 'foo',
|
|
56
|
+
* providers: [
|
|
57
|
+
* importProvidersFrom(NgModuleOne, NgModuleTwo)
|
|
58
|
+
* ],
|
|
59
|
+
* component: YourStandaloneComponent
|
|
60
|
+
* }
|
|
61
|
+
* ];
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @returns Collected providers from the specified list of types.
|
|
65
|
+
* @publicApi
|
|
66
|
+
*/
|
|
67
|
+
export function importProvidersFrom(...sources) {
|
|
68
|
+
return {
|
|
69
|
+
ɵproviders: internalImportProvidersFrom(true, sources),
|
|
70
|
+
ɵfromNgModule: true,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
export function internalImportProvidersFrom(checkForStandaloneCmp, ...sources) {
|
|
74
|
+
const providersOut = [];
|
|
75
|
+
const dedup = new Set(); // already seen types
|
|
76
|
+
let injectorTypesWithProviders;
|
|
77
|
+
// Collect all providers from `ModuleWithProviders` types.
|
|
78
|
+
if (injectorTypesWithProviders !== undefined) {
|
|
79
|
+
processInjectorTypesWithProviders(injectorTypesWithProviders, providersOut);
|
|
80
|
+
}
|
|
81
|
+
return providersOut;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Collects all providers from the list of `ModuleWithProviders` and appends them to the provided
|
|
85
|
+
* array.
|
|
86
|
+
*/
|
|
87
|
+
function processInjectorTypesWithProviders(typesWithProviders, providersOut) {
|
|
88
|
+
for (let i = 0; i < typesWithProviders.length; i++) {
|
|
89
|
+
const { ngModule, providers } = typesWithProviders[i];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
10
92
|
/**
|
|
11
93
|
* The logic visits an `InjectorType`, an `InjectorTypeWithProviders`, or a standalone
|
|
12
94
|
* `ComponentType`, and all of its transitive providers and collects providers.
|
|
@@ -23,11 +105,124 @@ export function walkProviderTree(container, providersOut, parents, dedup) {
|
|
|
23
105
|
// The actual type which had the definition. Usually `container`, but may be an unwrapped type
|
|
24
106
|
// from `InjectorTypeWithProviders`.
|
|
25
107
|
let defType = null;
|
|
26
|
-
|
|
108
|
+
let injDef = getInjectorDef(container);
|
|
109
|
+
const cmpDef = !injDef && null;
|
|
110
|
+
if (!injDef && !cmpDef) {
|
|
111
|
+
// `container` is not an injector type or a component type. It might be:
|
|
112
|
+
// * An `InjectorTypeWithProviders` that wraps an injector type.
|
|
113
|
+
// * A standalone directive or pipe that got pulled in from a standalone component's
|
|
114
|
+
// dependencies.
|
|
115
|
+
// Try to unwrap it as an `InjectorTypeWithProviders` first.
|
|
116
|
+
const ngModule = container.ngModule;
|
|
117
|
+
injDef = getInjectorDef(ngModule);
|
|
118
|
+
if (injDef) {
|
|
119
|
+
defType = ngModule;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Not a component or injector type, so ignore it.
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (cmpDef && !cmpDef.standalone) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
defType = container;
|
|
131
|
+
}
|
|
132
|
+
// Check for circular dependencies.
|
|
133
|
+
if (false) {
|
|
134
|
+
}
|
|
27
135
|
// Check for multiple imports of the same module
|
|
136
|
+
const isDuplicate = dedup.has(defType);
|
|
137
|
+
if (cmpDef) {
|
|
138
|
+
if (isDuplicate) {
|
|
139
|
+
// This component definition has already been processed.
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
dedup.add(defType);
|
|
143
|
+
if (cmpDef.dependencies) {
|
|
144
|
+
const deps = typeof cmpDef.dependencies === 'function'
|
|
145
|
+
? cmpDef.dependencies()
|
|
146
|
+
: cmpDef.dependencies;
|
|
147
|
+
for (const dep of deps) {
|
|
148
|
+
walkProviderTree(dep, providersOut, parents, dedup);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else if (injDef) {
|
|
153
|
+
// First, include providers from any imports.
|
|
154
|
+
if (injDef.imports != null && !isDuplicate) {
|
|
155
|
+
// Before processing defType's imports, add it to the set of parents. This way, if it ends
|
|
156
|
+
// up deeply importing itself, this can be detected.
|
|
157
|
+
// Add it to the set of dedups. This way we can detect multiple imports of the same module
|
|
158
|
+
dedup.add(defType);
|
|
159
|
+
let importTypesWithProviders;
|
|
160
|
+
try {
|
|
161
|
+
deepForEach(injDef.imports, (imported) => {
|
|
162
|
+
if (walkProviderTree(imported, providersOut, parents, dedup)) {
|
|
163
|
+
importTypesWithProviders || (importTypesWithProviders = []);
|
|
164
|
+
// If the processed import is an injector type with providers, we store it in the
|
|
165
|
+
// list of import types with providers, so that we can process those afterwards.
|
|
166
|
+
importTypesWithProviders.push(imported);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
// Remove it from the parents set when finished.
|
|
172
|
+
}
|
|
173
|
+
// Imports which are declared with providers (TypeWithProviders) need to be processed
|
|
174
|
+
// after all imported modules are processed. This is similar to how View Engine
|
|
175
|
+
// processes/merges module imports in the metadata resolver. See: FW-1349.
|
|
176
|
+
if (importTypesWithProviders !== undefined) {
|
|
177
|
+
processInjectorTypesWithProviders(importTypesWithProviders, providersOut);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (!isDuplicate) {
|
|
181
|
+
// Track the InjectorType and add a provider for it.
|
|
182
|
+
// It's important that this is done after the def's imports.
|
|
183
|
+
const factory = getFactoryDef(defType) || (() => new defType());
|
|
184
|
+
// Append extra providers to make more info available for consumers (to retrieve an injector
|
|
185
|
+
// type), as well as internally (to calculate an injection scope correctly and eagerly
|
|
186
|
+
// instantiate a `defType` when an injector is created).
|
|
187
|
+
providersOut.push(
|
|
188
|
+
// Provider to create `defType` using its factory.
|
|
189
|
+
{ provide: defType, useFactory: factory, deps: EMPTY_ARRAY },
|
|
190
|
+
// Make this `defType` available to an internal logic that calculates injector scope.
|
|
191
|
+
{ provide: INJECTOR_DEF_TYPES, useValue: defType, multi: true },
|
|
192
|
+
// Provider to eagerly instantiate `defType` via `ENVIRONMENT_INITIALIZER`.
|
|
193
|
+
{
|
|
194
|
+
provide: ENVIRONMENT_INITIALIZER,
|
|
195
|
+
useValue: () => inject(defType),
|
|
196
|
+
multi: true,
|
|
197
|
+
} //
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
// Next, include providers listed on the definition itself.
|
|
201
|
+
const defProviders = injDef.providers;
|
|
202
|
+
if (defProviders != null && !isDuplicate) {
|
|
203
|
+
const injectorType = container;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
// Should not happen, but just in case.
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
28
210
|
return (defType !== container &&
|
|
29
211
|
container.providers !== undefined);
|
|
30
212
|
}
|
|
213
|
+
function deepForEachProvider(providers, fn) {
|
|
214
|
+
for (let provider of providers) {
|
|
215
|
+
if (isEnvironmentProviders(provider)) {
|
|
216
|
+
provider = provider.ɵproviders;
|
|
217
|
+
}
|
|
218
|
+
if (Array.isArray(provider)) {
|
|
219
|
+
deepForEachProvider(provider, fn);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
fn(provider);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
31
226
|
export const USE_VALUE = getClosureSafeProperty({
|
|
32
227
|
provide: String,
|
|
33
228
|
useValue: getClosureSafeProperty,
|
|
@@ -5,20 +5,23 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
+
import { RuntimeError } from '../errors';
|
|
8
9
|
import { getFactoryDef } from '../render3/definition_factory';
|
|
9
10
|
import { newArray } from '../util/array_utils';
|
|
10
11
|
import { EMPTY_ARRAY } from '../util/empty';
|
|
11
12
|
import { stringify } from '../util/stringify';
|
|
12
13
|
import { resolveForwardRef } from './forward_ref';
|
|
13
14
|
import { ENVIRONMENT_INITIALIZER } from './initializer_token';
|
|
15
|
+
import { setInjectImplementation } from './inject_switch';
|
|
14
16
|
import { InjectionToken } from './injection_token';
|
|
15
|
-
import { catchInjectorError, convertToBitFlags, injectArgs, NG_TEMP_TOKEN_PATH, setCurrentInjector, THROW_IF_NOT_FOUND,
|
|
17
|
+
import { catchInjectorError, convertToBitFlags, injectArgs, NG_TEMP_TOKEN_PATH, setCurrentInjector, THROW_IF_NOT_FOUND, ɵɵinject, } from './injector_compatibility';
|
|
16
18
|
import { INJECTOR } from './injector_token';
|
|
17
|
-
import { setInjectImplementation } from './inject_switch';
|
|
18
19
|
import { getInheritedInjectableDef, getInjectableDef, } from './interface/defs';
|
|
19
20
|
import { InjectFlags } from './interface/injector';
|
|
21
|
+
import { isEnvironmentProviders, } from './interface/provider';
|
|
20
22
|
import { INJECTOR_DEF_TYPES } from './internal_tokens';
|
|
21
23
|
import { NullInjector } from './null_injector';
|
|
24
|
+
import { isExistingProvider, isFactoryProvider, isTypeProvider, isValueProvider, } from './provider_collection';
|
|
22
25
|
import { INJECTOR_SCOPE } from './scope';
|
|
23
26
|
/**
|
|
24
27
|
* Marker which indicates that a value has not yet been created from the factory function.
|
|
@@ -203,6 +206,8 @@ export class R3Injector extends EnvironmentInjector {
|
|
|
203
206
|
const previousInjectImplementation = setInjectImplementation(undefined);
|
|
204
207
|
try {
|
|
205
208
|
const initializers = this.get(ENVIRONMENT_INITIALIZER.multi, EMPTY_ARRAY, InjectFlags.Self);
|
|
209
|
+
if (false) {
|
|
210
|
+
}
|
|
206
211
|
for (const initializer of initializers) {
|
|
207
212
|
initializer();
|
|
208
213
|
}
|
|
@@ -222,7 +227,7 @@ export class R3Injector extends EnvironmentInjector {
|
|
|
222
227
|
}
|
|
223
228
|
assertNotDestroyed() {
|
|
224
229
|
if (this._destroyed) {
|
|
225
|
-
throw new
|
|
230
|
+
throw new RuntimeError(205 /* RuntimeErrorCode.INJECTOR_ALREADY_DESTROYED */, null);
|
|
226
231
|
}
|
|
227
232
|
}
|
|
228
233
|
/**
|
|
@@ -243,6 +248,8 @@ export class R3Injector extends EnvironmentInjector {
|
|
|
243
248
|
let multiRecord = this.records.get(token);
|
|
244
249
|
if (multiRecord) {
|
|
245
250
|
// It has. Throw a nice error if
|
|
251
|
+
if (false) {
|
|
252
|
+
}
|
|
246
253
|
}
|
|
247
254
|
else {
|
|
248
255
|
multiRecord = makeRecord(undefined, NOT_YET, true);
|
|
@@ -254,11 +261,15 @@ export class R3Injector extends EnvironmentInjector {
|
|
|
254
261
|
}
|
|
255
262
|
else {
|
|
256
263
|
const existing = this.records.get(token);
|
|
264
|
+
if (false) {
|
|
265
|
+
}
|
|
257
266
|
}
|
|
258
267
|
this.records.set(token, record);
|
|
259
268
|
}
|
|
260
269
|
hydrate(token, record) {
|
|
261
|
-
if (
|
|
270
|
+
if (false) {
|
|
271
|
+
}
|
|
272
|
+
else if (record.value === NOT_YET) {
|
|
262
273
|
record.value = CIRCULAR;
|
|
263
274
|
record.value = record.factory();
|
|
264
275
|
}
|
|
@@ -292,21 +303,21 @@ function injectableDefOrInjectorDefFactory(token) {
|
|
|
292
303
|
// InjectionTokens should have an injectable def (ɵprov) and thus should be handled above.
|
|
293
304
|
// If it's missing that, it's an error.
|
|
294
305
|
if (token instanceof InjectionToken) {
|
|
295
|
-
throw new
|
|
306
|
+
throw new RuntimeError(204 /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */, null);
|
|
296
307
|
}
|
|
297
308
|
// Undecorated types can sometimes be created if they have no constructor arguments.
|
|
298
309
|
if (token instanceof Function) {
|
|
299
310
|
return getUndecoratedInjectableFactory(token);
|
|
300
311
|
}
|
|
301
312
|
// There was no way to resolve a factory for this token.
|
|
302
|
-
throw new
|
|
313
|
+
throw new RuntimeError(204 /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */, null);
|
|
303
314
|
}
|
|
304
315
|
function getUndecoratedInjectableFactory(token) {
|
|
305
316
|
// If the token has parameters then it has dependencies that we cannot resolve implicitly.
|
|
306
317
|
const paramLength = token.length;
|
|
307
318
|
if (paramLength > 0) {
|
|
308
319
|
const args = newArray(paramLength, '?');
|
|
309
|
-
throw new
|
|
320
|
+
throw new RuntimeError(204 /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */, null);
|
|
310
321
|
}
|
|
311
322
|
// The constructor function appears to have no parameters.
|
|
312
323
|
// This might be because it inherits from a super-class. In which case, use an injectable
|
|
@@ -337,6 +348,8 @@ function providerToRecord(provider) {
|
|
|
337
348
|
*/
|
|
338
349
|
export function providerToFactory(provider, ngModuleType, providers) {
|
|
339
350
|
let factory = undefined;
|
|
351
|
+
if (false) {
|
|
352
|
+
}
|
|
340
353
|
if (isTypeProvider(provider)) {
|
|
341
354
|
const unwrappedProvider = resolveForwardRef(provider);
|
|
342
355
|
return (getFactoryDef(unwrappedProvider) ||
|
|
@@ -356,9 +369,8 @@ export function providerToFactory(provider, ngModuleType, providers) {
|
|
|
356
369
|
const classRef = resolveForwardRef(provider &&
|
|
357
370
|
(provider.useClass ||
|
|
358
371
|
provider.provide));
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
// }
|
|
372
|
+
if (false) {
|
|
373
|
+
}
|
|
362
374
|
if (hasDeps(provider)) {
|
|
363
375
|
factory = () => new classRef(...injectArgs(provider.deps));
|
|
364
376
|
}
|
|
@@ -376,18 +388,6 @@ function makeRecord(factory, value, multi = false) {
|
|
|
376
388
|
multi: multi ? [] : undefined,
|
|
377
389
|
};
|
|
378
390
|
}
|
|
379
|
-
function isValueProvider(value) {
|
|
380
|
-
return value !== null && typeof value == 'object' && USE_VALUE in value;
|
|
381
|
-
}
|
|
382
|
-
function isExistingProvider(value) {
|
|
383
|
-
return !!(value && value.useExisting);
|
|
384
|
-
}
|
|
385
|
-
function isFactoryProvider(value) {
|
|
386
|
-
return !!(value && value.useFactory);
|
|
387
|
-
}
|
|
388
|
-
export function isTypeProvider(value) {
|
|
389
|
-
return typeof value === 'function';
|
|
390
|
-
}
|
|
391
391
|
function hasDeps(value) {
|
|
392
392
|
return !!value.deps;
|
|
393
393
|
}
|
|
@@ -405,6 +405,9 @@ function forEachSingleProvider(providers, fn) {
|
|
|
405
405
|
if (Array.isArray(provider)) {
|
|
406
406
|
forEachSingleProvider(provider, fn);
|
|
407
407
|
}
|
|
408
|
+
else if (provider && isEnvironmentProviders(provider)) {
|
|
409
|
+
forEachSingleProvider(provider.ɵproviders, fn);
|
|
410
|
+
}
|
|
408
411
|
else {
|
|
409
412
|
fn(provider);
|
|
410
413
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Base URL for the error details page.
|
|
10
|
+
*
|
|
11
|
+
* Keep this constant in sync across:
|
|
12
|
+
* - packages/compiler-cli/src/ngtsc/diagnostics/src/error_details_base_url.ts
|
|
13
|
+
* - packages/core/src/error_details_base_url.ts
|
|
14
|
+
*/
|
|
15
|
+
export const ERROR_DETAILS_PAGE_BASE_URL = 'https://angular.io/errors';
|
|
16
|
+
/**
|
|
17
|
+
* URL for the XSS security documentation.
|
|
18
|
+
*/
|
|
19
|
+
export const XSS_SECURITY_URL = 'https://g.co/ng/security#xss';
|