fix(ivy): properly tree-shake away StaticInjector (#30219)
Ivy uses R3Injector, but we are currently pulling in both the StaticInjector (View Engine injector) and the R3Injector when running with Ivy. This commit adds an ivy switch so calling Injector.create() pulls in the correct implementation of the injector depending on whether you are using VE or Ivy. This saves us about 3KB in the bundle. PR Close #30219
This commit is contained in:
parent
b1506a3271
commit
7d6f4885b2
|
@ -21,7 +21,7 @@
|
|||
"master": {
|
||||
"uncompressed": {
|
||||
"runtime": 1440,
|
||||
"main": 149205,
|
||||
"main": 146225,
|
||||
"polyfills": 43567
|
||||
}
|
||||
}
|
||||
|
|
|
@ -291,4 +291,6 @@ export {
|
|||
|
||||
export {createInjector as ɵcreateInjector} from './di/r3_injector';
|
||||
|
||||
export {INJECTOR_IMPL__POST_R3__ as ɵINJECTOR_IMPL__POST_R3__} from './di/injector';
|
||||
|
||||
// clang-format on
|
||||
|
|
|
@ -17,8 +17,8 @@ export {InjectFlags} from './interface/injector';
|
|||
export {ɵɵdefineInjectable, 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, inject} from './injector_compatibility';
|
||||
export {Injector} from './injector';
|
||||
export {ɵɵinject, inject, INJECTOR} from './injector_compatibility';
|
||||
export {ReflectiveInjector} from './reflective_injector';
|
||||
export {StaticProvider, ValueProvider, ConstructorSansProvider, ExistingProvider, FactoryProvider, Provider, TypeProvider, ClassProvider} from './interface/provider';
|
||||
export {ResolvedReflectiveFactory, ResolvedReflectiveProvider} from './reflective_provider';
|
||||
|
|
|
@ -7,48 +7,29 @@
|
|||
*/
|
||||
|
||||
import {Type} from '../interface/type';
|
||||
import {getClosureSafeProperty} from '../util/property';
|
||||
import {stringify} from '../util/stringify';
|
||||
|
||||
import {resolveForwardRef} from './forward_ref';
|
||||
import {InjectionToken} from './injection_token';
|
||||
import {ɵɵinject} from './injector_compatibility';
|
||||
import {INJECTOR, NG_TEMP_TOKEN_PATH, NullInjector, THROW_IF_NOT_FOUND, USE_VALUE, catchInjectorError, formatError, ɵɵ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';
|
||||
import {createInjector} from './r3_injector';
|
||||
|
||||
export const SOURCE = '__source';
|
||||
const _THROW_IF_NOT_FOUND = new Object();
|
||||
export const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
|
||||
|
||||
/**
|
||||
* 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`.
|
||||
);
|
||||
|
||||
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 INJECTOR_IMPL__PRE_R3__(
|
||||
providers: StaticProvider[], parent: Injector | undefined, name: string) {
|
||||
return new StaticInjector(providers, parent, name);
|
||||
}
|
||||
|
||||
export function INJECTOR_IMPL__POST_R3__(
|
||||
providers: StaticProvider[], parent: Injector | undefined, name: string) {
|
||||
return createInjector({name: name}, parent, providers, name);
|
||||
}
|
||||
|
||||
export const INJECTOR_IMPL = INJECTOR_IMPL__PRE_R3__;
|
||||
|
||||
/**
|
||||
* Concrete injectors implement this interface.
|
||||
*
|
||||
|
@ -66,7 +47,7 @@ export class NullInjector implements Injector {
|
|||
* @publicApi
|
||||
*/
|
||||
export abstract class Injector {
|
||||
static THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
|
||||
static THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND;
|
||||
static NULL: Injector = new NullInjector();
|
||||
|
||||
/**
|
||||
|
@ -100,9 +81,9 @@ export abstract class Injector {
|
|||
options: StaticProvider[]|{providers: StaticProvider[], parent?: Injector, name?: string},
|
||||
parent?: Injector): Injector {
|
||||
if (Array.isArray(options)) {
|
||||
return new StaticInjector(options, parent);
|
||||
return INJECTOR_IMPL(options, parent, '');
|
||||
} else {
|
||||
return new StaticInjector(options.providers, options.parent, options.name || null);
|
||||
return INJECTOR_IMPL(options.providers, options.parent, options.name || '');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,10 +110,7 @@ const CIRCULAR = IDENT;
|
|||
const MULTI_PROVIDER_FN = function(): any[] {
|
||||
return Array.prototype.slice.call(arguments);
|
||||
};
|
||||
export const USE_VALUE =
|
||||
getClosureSafeProperty<ValueProvider>({provide: String, useValue: getClosureSafeProperty});
|
||||
const NG_TOKEN_PATH = 'ngTokenPath';
|
||||
export const NG_TEMP_TOKEN_PATH = 'ngTempTokenPath';
|
||||
|
||||
const enum OptionFlags {
|
||||
Optional = 1 << 0,
|
||||
CheckSelf = 1 << 1,
|
||||
|
@ -140,7 +118,6 @@ const enum OptionFlags {
|
|||
Default = CheckSelf | CheckParent
|
||||
}
|
||||
const NULL_INJECTOR = Injector.NULL;
|
||||
const NEW_LINE = /\n/gm;
|
||||
const NO_NEW_LINE = 'ɵ';
|
||||
|
||||
export class StaticInjector implements Injector {
|
||||
|
@ -377,38 +354,6 @@ function computeDeps(provider: StaticProvider): DependencyRecord[] {
|
|||
return deps;
|
||||
}
|
||||
|
||||
export function catchInjectorError(
|
||||
e: any, token: any, injectorErrorName: string, source: string | null): never {
|
||||
const tokenPath: any[] = e[NG_TEMP_TOKEN_PATH];
|
||||
if (token[SOURCE]) {
|
||||
tokenPath.unshift(token[SOURCE]);
|
||||
}
|
||||
e.message = formatError('\n' + e.message, tokenPath, injectorErrorName, source);
|
||||
e[NG_TOKEN_PATH] = tokenPath;
|
||||
e[NG_TEMP_TOKEN_PATH] = null;
|
||||
throw e;
|
||||
}
|
||||
|
||||
function formatError(
|
||||
text: string, obj: any, injectorErrorName: string, source: string | null = null): string {
|
||||
text = text && text.charAt(0) === '\n' && text.charAt(1) == NO_NEW_LINE ? text.substr(2) : text;
|
||||
let context = stringify(obj);
|
||||
if (obj instanceof Array) {
|
||||
context = obj.map(stringify).join(' -> ');
|
||||
} else if (typeof obj === 'object') {
|
||||
let parts = <string[]>[];
|
||||
for (let key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
let value = obj[key];
|
||||
parts.push(
|
||||
key + ':' + (typeof value === 'string' ? JSON.stringify(value) : stringify(value)));
|
||||
}
|
||||
}
|
||||
context = `{${parts.join(', ')}}`;
|
||||
}
|
||||
return `${injectorErrorName}${source ? '(' + source + ')' : ''}[${context}]: ${text.replace(NEW_LINE, '\n ')}`;
|
||||
}
|
||||
|
||||
function staticError(text: string, obj: any): Error {
|
||||
return new Error(formatError(text, obj, 'StaticInjectorError'));
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
import {Type} from '../interface/type';
|
||||
import {getClosureSafeProperty} from '../util/property';
|
||||
import {stringify} from '../util/stringify';
|
||||
|
||||
import {resolveForwardRef} from './forward_ref';
|
||||
|
@ -14,10 +15,36 @@ 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 = new Object();
|
||||
export const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
|
||||
|
||||
export const NG_TEMP_TOKEN_PATH = 'ngTempTokenPath';
|
||||
const NG_TOKEN_PATH = 'ngTokenPath';
|
||||
const NEW_LINE = /\n/gm;
|
||||
const NO_NEW_LINE = 'ɵ';
|
||||
export const SOURCE = '__source';
|
||||
|
||||
export const USE_VALUE =
|
||||
getClosureSafeProperty<ValueProvider>({provide: String, useValue: getClosureSafeProperty});
|
||||
|
||||
/**
|
||||
* Current injector value used by `inject`.
|
||||
* - `undefined`: it is an error to call `inject`
|
||||
|
@ -166,3 +193,52 @@ export function injectArgs(types: (Type<any>| InjectionToken<any>| any[])[]): an
|
|||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
|
||||
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];
|
||||
if (token[SOURCE]) {
|
||||
tokenPath.unshift(token[SOURCE]);
|
||||
}
|
||||
e.message = formatError('\n' + e.message, tokenPath, injectorErrorName, source);
|
||||
e[NG_TOKEN_PATH] = tokenPath;
|
||||
e[NG_TEMP_TOKEN_PATH] = null;
|
||||
throw e;
|
||||
}
|
||||
|
||||
export function formatError(
|
||||
text: string, obj: any, injectorErrorName: string, source: string | null = null): string {
|
||||
text = text && text.charAt(0) === '\n' && text.charAt(1) == NO_NEW_LINE ? text.substr(2) : text;
|
||||
let context = stringify(obj);
|
||||
if (obj instanceof Array) {
|
||||
context = obj.map(stringify).join(' -> ');
|
||||
} else if (typeof obj === 'object') {
|
||||
let parts = <string[]>[];
|
||||
for (let key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
let value = obj[key];
|
||||
parts.push(
|
||||
key + ':' + (typeof value === 'string' ? JSON.stringify(value) : stringify(value)));
|
||||
}
|
||||
}
|
||||
context = `{${parts.join(', ')}}`;
|
||||
}
|
||||
return `${injectorErrorName}${source ? '(' + source + ')' : ''}[${context}]: ${text.replace(NEW_LINE, '\n ')}`;
|
||||
}
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
|
||||
import {OnDestroy} from '../interface/lifecycle_hooks';
|
||||
import {Type} from '../interface/type';
|
||||
import {throwCyclicDependencyError, throwInvalidProviderError, throwMixedMultiProviderError} from '../render3/errors';
|
||||
import {stringify} from '../util/stringify';
|
||||
|
||||
import {resolveForwardRef} from './forward_ref';
|
||||
import {InjectionToken} from './injection_token';
|
||||
import {INJECTOR, Injector, NG_TEMP_TOKEN_PATH, NullInjector, USE_VALUE, catchInjectorError} from './injector';
|
||||
import {injectArgs, setCurrentInjector, ɵɵinject} from './injector_compatibility';
|
||||
import {Injector} from './injector';
|
||||
import {INJECTOR, NG_TEMP_TOKEN_PATH, NullInjector, THROW_IF_NOT_FOUND, USE_VALUE, catchInjectorError, injectArgs, setCurrentInjector, ɵɵinject} from './injector_compatibility';
|
||||
import {InjectableType, InjectorType, InjectorTypeWithProviders, getInjectableDef, getInjectorDef, ɵɵInjectableDef} from './interface/defs';
|
||||
import {InjectFlags} from './interface/injector';
|
||||
import {ClassProvider, ConstructorProvider, ExistingProvider, FactoryProvider, StaticClassProvider, StaticProvider, TypeProvider, ValueProvider} from './interface/provider';
|
||||
|
@ -131,7 +132,7 @@ export class R3Injector {
|
|||
this.injectorDefTypes.forEach(defType => this.get(defType));
|
||||
|
||||
// Source name, used for debugging
|
||||
this.source = source || (def instanceof Array ? null : stringify(def));
|
||||
this.source = source || (typeof def === 'object' ? null : stringify(def));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,7 +158,7 @@ export class R3Injector {
|
|||
}
|
||||
|
||||
get<T>(
|
||||
token: Type<T>|InjectionToken<T>, notFoundValue: any = Injector.THROW_IF_NOT_FOUND,
|
||||
token: Type<T>|InjectionToken<T>, notFoundValue: any = THROW_IF_NOT_FOUND,
|
||||
flags = InjectFlags.Default): T {
|
||||
this.assertNotDestroyed();
|
||||
// Set the injection context.
|
||||
|
@ -208,6 +209,12 @@ export class R3Injector {
|
|||
}
|
||||
}
|
||||
|
||||
toString() {
|
||||
const tokens = <string[]>[], records = this.records;
|
||||
records.forEach((v, token) => tokens.push(stringify(token)));
|
||||
return `R3Injector[${tokens.join(', ')}]`;
|
||||
}
|
||||
|
||||
private assertNotDestroyed(): void {
|
||||
if (this._destroyed) {
|
||||
throw new Error('Injector has already been destroyed.');
|
||||
|
@ -242,7 +249,8 @@ export class R3Injector {
|
|||
(ngModule === undefined) ? (defOrWrappedDef as InjectorType<any>) : ngModule;
|
||||
|
||||
// Check for circular dependencies.
|
||||
if (ngDevMode && parents.indexOf(defType) !== -1) {
|
||||
// TODO(FW-1307): Re-add ngDevMode when closure can handle it
|
||||
if (parents.indexOf(defType) !== -1) {
|
||||
const defName = stringify(defType);
|
||||
throw new Error(
|
||||
`Circular dependency in DI detected for type ${defName}. Dependency path: ${parents.map(defType => stringify(defType)).join(' > ')} > ${defName}.`);
|
||||
|
@ -278,7 +286,8 @@ export class R3Injector {
|
|||
if (def.imports != null && !isDuplicate) {
|
||||
// Before processing defType's imports, add it to the set of parents. This way, if it ends
|
||||
// up deeply importing itself, this can be detected.
|
||||
ngDevMode && parents.push(defType);
|
||||
// TODO(FW-1307): Re-add ngDevMode when closure can handle it
|
||||
parents.push(defType);
|
||||
// Add it to the set of dedups. This way we can detect multiple imports of the same module
|
||||
dedupStack.push(defType);
|
||||
|
||||
|
@ -287,7 +296,8 @@ export class R3Injector {
|
|||
def.imports, imported => this.processInjectorType(imported, parents, dedupStack));
|
||||
} finally {
|
||||
// Remove it from the parents set when finished.
|
||||
ngDevMode && parents.pop();
|
||||
// TODO(FW-1307): Re-add ngDevMode when closure can handle it
|
||||
parents.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,7 +335,7 @@ export class R3Injector {
|
|||
if (multiRecord) {
|
||||
// It has. Throw a nice error if
|
||||
if (multiRecord.multi === undefined) {
|
||||
throw new Error(`Mixed multi-provider for ${token}.`);
|
||||
throwMixedMultiProviderError();
|
||||
}
|
||||
} else {
|
||||
multiRecord = makeRecord(undefined, NOT_YET, true);
|
||||
|
@ -337,7 +347,7 @@ export class R3Injector {
|
|||
} else {
|
||||
const existing = this.records.get(token);
|
||||
if (existing && existing.multi !== undefined) {
|
||||
throw new Error(`Mixed multi-provider for ${stringify(token)}`);
|
||||
throwMixedMultiProviderError();
|
||||
}
|
||||
}
|
||||
this.records.set(token, record);
|
||||
|
@ -345,7 +355,7 @@ export class R3Injector {
|
|||
|
||||
private hydrate<T>(token: Type<T>|InjectionToken<T>, record: Record<T>): T {
|
||||
if (record.value === CIRCULAR) {
|
||||
throw new Error(`Cannot instantiate cyclic dependency! ${stringify(token)}`);
|
||||
throwCyclicDependencyError(stringify(token));
|
||||
} else if (record.value === NOT_YET) {
|
||||
record.value = CIRCULAR;
|
||||
record.value = record.factory !();
|
||||
|
@ -421,14 +431,7 @@ export function providerToFactory(
|
|||
provider &&
|
||||
((provider as StaticClassProvider | ClassProvider).useClass || provider.provide));
|
||||
if (!classRef) {
|
||||
let ngModuleDetail = '';
|
||||
if (ngModuleType && providers) {
|
||||
const providerDetail = providers.map(v => v == provider ? '?' + provider + '?' : '...');
|
||||
ngModuleDetail =
|
||||
` - only instances of Provider and Type are allowed, got: [${providerDetail.join(', ')}]`;
|
||||
}
|
||||
throw new Error(
|
||||
`Invalid provider for the NgModule '${stringify(ngModuleType)}'` + ngModuleDetail);
|
||||
throwInvalidProviderError(ngModuleType, providers, provider);
|
||||
}
|
||||
if (hasDeps(provider)) {
|
||||
factory = () => new (classRef)(...injectArgs(provider.deps));
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Injector, THROW_IF_NOT_FOUND} from './injector';
|
||||
import {Injector} from './injector';
|
||||
import {THROW_IF_NOT_FOUND} from './injector_compatibility';
|
||||
import {Provider} from './interface/provider';
|
||||
import {Self, SkipSelf} from './metadata';
|
||||
import {cyclicDependencyError, instantiationError, noProviderError, outOfBoundsError} from './reflective_errors';
|
||||
|
|
|
@ -6,8 +6,12 @@
|
|||
* 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 {InjectorType} from '../di/interface/defs';
|
||||
import {stringify} from '../util/stringify';
|
||||
|
||||
import {TNode} from './interfaces/node';
|
||||
|
||||
|
||||
/** Called when directives inject each other (creating a circular dependency) */
|
||||
export function throwCyclicDependencyError(token: any): never {
|
||||
throw new Error(`Cannot instantiate cyclic dependency! ${token}`);
|
||||
|
@ -31,3 +35,20 @@ export function throwErrorIfNoChangesMode(
|
|||
// TODO: include debug context
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
export function throwMixedMultiProviderError() {
|
||||
throw new Error(`Cannot mix multi providers and regular providers`);
|
||||
}
|
||||
|
||||
export function throwInvalidProviderError(
|
||||
ngModuleType?: InjectorType<any>, providers?: any[], provider?: any) {
|
||||
let ngModuleDetail = '';
|
||||
if (ngModuleType && providers) {
|
||||
const providerDetail = providers.map(v => v == provider ? '?' + provider + '?' : '...');
|
||||
ngModuleDetail =
|
||||
` - only instances of Provider and Type are allowed, got: [${providerDetail.join(', ')}]`;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Invalid provider for the NgModule '${stringify(ngModuleType)}'` + ngModuleDetail);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {INJECTOR, Injector} from '../di/injector';
|
||||
import {Injector} from '../di/injector';
|
||||
import {INJECTOR} from '../di/injector_compatibility';
|
||||
import {InjectFlags} from '../di/interface/injector';
|
||||
import {StaticProvider} from '../di/interface/provider';
|
||||
import {R3Injector, createInjector} from '../di/r3_injector';
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
*/
|
||||
|
||||
import {resolveForwardRef} from '../di/forward_ref';
|
||||
import {INJECTOR, Injector} from '../di/injector';
|
||||
import {setCurrentInjector} from '../di/injector_compatibility';
|
||||
import {Injector} from '../di/injector';
|
||||
import {INJECTOR, setCurrentInjector} from '../di/injector_compatibility';
|
||||
import {getInjectableDef, ɵɵInjectableDef} from '../di/interface/defs';
|
||||
import {APP_ROOT} from '../di/scope';
|
||||
import {NgModuleRef} from '../linker/ng_module_factory';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import {WrappedValue, devModeEqual} from '../change_detection/change_detection';
|
||||
import {SOURCE} from '../di/injector';
|
||||
import {SOURCE} from '../di/injector_compatibility';
|
||||
import {ViewEncapsulation} from '../metadata/view';
|
||||
import {RendererType2} from '../render/api';
|
||||
import {looseIdentical} from '../util/comparison';
|
||||
|
|
|
@ -5,21 +5,12 @@
|
|||
{
|
||||
"name": "CIRCULAR"
|
||||
},
|
||||
{
|
||||
"name": "CIRCULAR"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY"
|
||||
},
|
||||
{
|
||||
"name": "EMPTY_ARRAY"
|
||||
},
|
||||
{
|
||||
"name": "EmptyErrorImpl"
|
||||
},
|
||||
{
|
||||
"name": "IDENT"
|
||||
},
|
||||
{
|
||||
"name": "INJECTOR"
|
||||
},
|
||||
|
@ -32,12 +23,6 @@
|
|||
{
|
||||
"name": "InjectionToken"
|
||||
},
|
||||
{
|
||||
"name": "Injector"
|
||||
},
|
||||
{
|
||||
"name": "MULTI_PROVIDER_FN"
|
||||
},
|
||||
{
|
||||
"name": "NEW_LINE"
|
||||
},
|
||||
|
@ -62,9 +47,6 @@
|
|||
{
|
||||
"name": "NULL_INJECTOR"
|
||||
},
|
||||
{
|
||||
"name": "NULL_INJECTOR"
|
||||
},
|
||||
{
|
||||
"name": "NullInjector"
|
||||
},
|
||||
|
@ -93,7 +75,7 @@
|
|||
"name": "SkipSelf"
|
||||
},
|
||||
{
|
||||
"name": "StaticInjector"
|
||||
"name": "THROW_IF_NOT_FOUND"
|
||||
},
|
||||
{
|
||||
"name": "USE_VALUE"
|
||||
|
@ -101,9 +83,6 @@
|
|||
{
|
||||
"name": "UnsubscriptionErrorImpl"
|
||||
},
|
||||
{
|
||||
"name": "_THROW_IF_NOT_FOUND"
|
||||
},
|
||||
{
|
||||
"name": "__forward_ref__"
|
||||
},
|
||||
|
@ -122,9 +101,6 @@
|
|||
{
|
||||
"name": "catchInjectorError"
|
||||
},
|
||||
{
|
||||
"name": "computeDeps"
|
||||
},
|
||||
{
|
||||
"name": "couldBeInjectableType"
|
||||
},
|
||||
|
@ -194,38 +170,29 @@
|
|||
{
|
||||
"name": "makeRecord"
|
||||
},
|
||||
{
|
||||
"name": "multiProviderMixError"
|
||||
},
|
||||
{
|
||||
"name": "providerToFactory"
|
||||
},
|
||||
{
|
||||
"name": "providerToRecord"
|
||||
},
|
||||
{
|
||||
"name": "recursivelyProcessProviders"
|
||||
},
|
||||
{
|
||||
"name": "resolveForwardRef"
|
||||
},
|
||||
{
|
||||
"name": "resolveProvider"
|
||||
},
|
||||
{
|
||||
"name": "resolveToken"
|
||||
},
|
||||
{
|
||||
"name": "setCurrentInjector"
|
||||
},
|
||||
{
|
||||
"name": "staticError"
|
||||
},
|
||||
{
|
||||
"name": "stringify"
|
||||
},
|
||||
{
|
||||
"name": "tryResolveToken"
|
||||
"name": "throwCyclicDependencyError"
|
||||
},
|
||||
{
|
||||
"name": "throwInvalidProviderError"
|
||||
},
|
||||
{
|
||||
"name": "throwMixedMultiProviderError"
|
||||
},
|
||||
{
|
||||
"name": "ɵɵdefineInjectable"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import {Inject, InjectionToken, Injector, Optional, Self, SkipSelf, forwardRef} from '@angular/core';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
import {ivyEnabled, modifiedInIvy} from '@angular/private/testing';
|
||||
|
||||
import {stringify} from '../../src/util/stringify';
|
||||
|
||||
|
@ -86,7 +87,7 @@ function factoryFn(a: any){}
|
|||
{provide: 'provider10', useValue: 1}
|
||||
];
|
||||
|
||||
describe(`StaticInjector`, () => {
|
||||
modifiedInIvy('Ivy uses R3Injector').describe(`StaticInjector`, () => {
|
||||
|
||||
it('should instantiate a class without dependencies', () => {
|
||||
const injector = Injector.create([Engine.PROVIDER]);
|
||||
|
@ -413,9 +414,11 @@ function factoryFn(a: any){}
|
|||
[{provide: Car, useFactory: (e: Engine) => new Car(e), deps: [[Engine, new Self()]]}],
|
||||
parent);
|
||||
|
||||
const injectorName = ivyEnabled ? `R3Injector` : `StaticInjector`;
|
||||
|
||||
expect(() => child.get(Car))
|
||||
.toThrowError(
|
||||
`StaticInjectorError[${stringify(Car)} -> ${stringify(Engine)}]: \n` +
|
||||
`${injectorName}Error[${stringify(Car)} -> ${stringify(Engine)}]: \n` +
|
||||
' NullInjectorError: No provider for Engine!');
|
||||
});
|
||||
});
|
||||
|
@ -472,8 +475,11 @@ function factoryFn(a: any){}
|
|||
|
||||
describe('displayName', () => {
|
||||
it('should work', () => {
|
||||
const ivyError = `R3Injector[Engine, BrokenEngine, InjectionToken INJECTOR]`;
|
||||
const viewEngineError =
|
||||
`StaticInjector[Injector, InjectionToken INJECTOR, Engine, BrokenEngine]`;
|
||||
expect(Injector.create([Engine.PROVIDER, {provide: BrokenEngine, useValue: null}]).toString())
|
||||
.toEqual('StaticInjector[Injector, InjectionToken INJECTOR, Engine, BrokenEngine]');
|
||||
.toEqual(ivyEnabled ? ivyError : viewEngineError);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
import {NgModuleRef} from '@angular/core';
|
||||
import {InjectFlags, inject} from '@angular/core/src/di';
|
||||
import {INJECTOR, Injector} from '@angular/core/src/di/injector';
|
||||
import {Injector} from '@angular/core/src/di/injector';
|
||||
import {INJECTOR} from '@angular/core/src/di/injector_compatibility';
|
||||
import {ɵɵInjectableDef, ɵɵdefineInjectable} 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';
|
||||
|
|
|
@ -232,10 +232,7 @@ function bootstrap(
|
|||
]).then(null, (e: Error) => {
|
||||
let errorMsg: string;
|
||||
if (ivyEnabled) {
|
||||
errorMsg = `R3InjectorError(TestModule)[IDontExist]: \n` +
|
||||
' StaticInjectorError(TestModule)[IDontExist]: \n' +
|
||||
' StaticInjectorError(Platform: core)[IDontExist]: \n' +
|
||||
' NullInjectorError: No provider for IDontExist!';
|
||||
errorMsg = `R3InjectorError(TestModule)[IDontExist -> IDontExist -> IDontExist]: \n`;
|
||||
} else {
|
||||
errorMsg = `StaticInjectorError(TestModule)[CustomCmp -> IDontExist]: \n` +
|
||||
' StaticInjectorError(Platform: core)[CustomCmp -> IDontExist]: \n' +
|
||||
|
|
Loading…
Reference in New Issue