feat: tree-shakeable providers API updates (#22655)
Rename @Injectable({scope -> providedIn}). Instead of {providedIn: APP_ROOT_SCOPE}, accept {providedIn: 'root'}. Also, {providedIn: null} implies the injectable should not be added to any scope. PR Close #22655
This commit is contained in:

committed by
Kara Erickson

parent
21e44c6ba9
commit
db56836425
@ -7,12 +7,13 @@
|
||||
*/
|
||||
|
||||
import {resolveForwardRef} from '../di/forward_ref';
|
||||
import {InjectableDef} from '../di/injectable';
|
||||
import {InjectFlags, Injector, setCurrentInjector} from '../di/injector';
|
||||
import {APP_ROOT_SCOPE} from '../di/scope';
|
||||
import {APP_ROOT} from '../di/scope';
|
||||
import {NgModuleRef} from '../linker/ng_module_factory';
|
||||
import {stringify} from '../util';
|
||||
|
||||
import {DepDef, DepFlags, InjectableDef, NgModuleData, NgModuleDefinition, NgModuleProviderDef, NodeFlags} from './types';
|
||||
import {DepDef, DepFlags, NgModuleData, NgModuleDefinition, NgModuleProviderDef, NodeFlags} from './types';
|
||||
import {splitDepsDsl, tokenKey} from './util';
|
||||
|
||||
const UNDEFINED_VALUE = new Object();
|
||||
@ -20,12 +21,6 @@ const UNDEFINED_VALUE = new Object();
|
||||
const InjectorRefTokenKey = tokenKey(Injector);
|
||||
const NgModuleRefTokenKey = tokenKey(NgModuleRef);
|
||||
|
||||
export function injectableDef(scope: any, factory: () => any): InjectableDef {
|
||||
return {
|
||||
scope, factory,
|
||||
};
|
||||
}
|
||||
|
||||
export function moduleProvideDef(
|
||||
flags: NodeFlags, token: any, value: any,
|
||||
deps: ([DepFlags, any] | any)[]): NgModuleProviderDef {
|
||||
@ -47,7 +42,7 @@ export function moduleDef(providers: NgModuleProviderDef[]): NgModuleDefinition
|
||||
let isRoot: boolean = false;
|
||||
for (let i = 0; i < providers.length; i++) {
|
||||
const provider = providers[i];
|
||||
if (provider.token === APP_ROOT_SCOPE) {
|
||||
if (provider.token === APP_ROOT) {
|
||||
isRoot = true;
|
||||
}
|
||||
if (provider.flags & NodeFlags.TypeNgModule) {
|
||||
@ -103,7 +98,7 @@ export function resolveNgModuleDep(
|
||||
}
|
||||
return providerInstance === UNDEFINED_VALUE ? undefined : providerInstance;
|
||||
} else if (depDef.token.ngInjectableDef && targetsModule(data, depDef.token.ngInjectableDef)) {
|
||||
const injectableDef = depDef.token.ngInjectableDef as InjectableDef;
|
||||
const injectableDef = depDef.token.ngInjectableDef as InjectableDef<any>;
|
||||
const key = tokenKey;
|
||||
const index = data._providers.length;
|
||||
data._def.providersByKey[depDef.tokenKey] = {
|
||||
@ -129,9 +124,9 @@ function moduleTransitivelyPresent(ngModule: NgModuleData, scope: any): boolean
|
||||
return ngModule._def.modules.indexOf(scope) > -1;
|
||||
}
|
||||
|
||||
function targetsModule(ngModule: NgModuleData, def: InjectableDef): boolean {
|
||||
return def.scope != null && (moduleTransitivelyPresent(ngModule, def.scope) ||
|
||||
def.scope === APP_ROOT_SCOPE && ngModule._def.isRoot);
|
||||
function targetsModule(ngModule: NgModuleData, def: InjectableDef<any>): boolean {
|
||||
return def.providedIn != null && (moduleTransitivelyPresent(ngModule, def.providedIn) ||
|
||||
def.providedIn === 'root' && ngModule._def.isRoot);
|
||||
}
|
||||
|
||||
function _createProviderInstance(ngModule: NgModuleData, providerDef: NgModuleProviderDef): any {
|
||||
|
@ -8,13 +8,14 @@
|
||||
|
||||
import {isDevMode} from '../application_ref';
|
||||
import {DebugElement, DebugNode, EventListener, getDebugNode, indexDebugNode, removeDebugNodeFromIndex} from '../debug/debug_node';
|
||||
import {Injector} from '../di';
|
||||
import {InjectableType, Injector} from '../di';
|
||||
import {ErrorHandler} from '../error_handler';
|
||||
import {ComponentFactory} from '../linker/component_factory';
|
||||
import {NgModuleRef} from '../linker/ng_module_factory';
|
||||
import {Renderer2, RendererFactory2, RendererStyleFlags2, RendererType2} from '../render/api';
|
||||
import {Sanitizer} from '../sanitization/security';
|
||||
import {Type} from '../type';
|
||||
import {tokenKey} from '../view/util';
|
||||
|
||||
import {isViewDebugError, viewDestroyedError, viewWrappedDebugError} from './errors';
|
||||
import {resolveDep} from './provider';
|
||||
@ -162,10 +163,15 @@ function debugCreateNgModuleRef(
|
||||
}
|
||||
|
||||
const providerOverrides = new Map<any, ProviderOverride>();
|
||||
const providerOverridesWithScope = new Map<InjectableType<any>, ProviderOverride>();
|
||||
const viewDefOverrides = new Map<any, ViewDefinition>();
|
||||
|
||||
function debugOverrideProvider(override: ProviderOverride) {
|
||||
providerOverrides.set(override.token, override);
|
||||
if (typeof override.token === 'function' && override.token.ngInjectableDef &&
|
||||
typeof override.token.ngInjectableDef.providedIn === 'function') {
|
||||
providerOverridesWithScope.set(override.token as InjectableType<any>, override);
|
||||
}
|
||||
}
|
||||
|
||||
function debugOverrideComponentView(comp: any, compFactory: ComponentFactory<any>) {
|
||||
@ -176,6 +182,7 @@ function debugOverrideComponentView(comp: any, compFactory: ComponentFactory<any
|
||||
|
||||
function debugClearOverrides() {
|
||||
providerOverrides.clear();
|
||||
providerOverridesWithScope.clear();
|
||||
viewDefOverrides.clear();
|
||||
}
|
||||
|
||||
@ -266,6 +273,14 @@ function applyProviderOverridesToNgModule(def: NgModuleDefinition): NgModuleDefi
|
||||
hasDeprecatedOverrides = hasDeprecatedOverrides || override.deprecatedBehavior;
|
||||
}
|
||||
});
|
||||
def.modules.forEach(module => {
|
||||
providerOverridesWithScope.forEach((override, token) => {
|
||||
if (token.ngInjectableDef.providedIn === module) {
|
||||
hasOverrides = true;
|
||||
hasDeprecatedOverrides = hasDeprecatedOverrides || override.deprecatedBehavior;
|
||||
}
|
||||
});
|
||||
});
|
||||
return {hasOverrides, hasDeprecatedOverrides};
|
||||
}
|
||||
|
||||
@ -285,6 +300,23 @@ function applyProviderOverridesToNgModule(def: NgModuleDefinition): NgModuleDefi
|
||||
provider.value = override.value;
|
||||
}
|
||||
}
|
||||
if (providerOverridesWithScope.size > 0) {
|
||||
let moduleSet = new Set<any>(def.modules);
|
||||
providerOverridesWithScope.forEach((override, token) => {
|
||||
if (moduleSet.has(token.ngInjectableDef.providedIn)) {
|
||||
let provider = {
|
||||
token: token,
|
||||
flags:
|
||||
override.flags | (hasDeprecatedOverrides ? NodeFlags.LazyProvider : NodeFlags.None),
|
||||
deps: splitDepsDsl(override.deps),
|
||||
value: override.value,
|
||||
index: def.providers.length,
|
||||
};
|
||||
def.providers.push(provider);
|
||||
def.providersByKey[tokenKey(token)] = provider;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,11 +297,6 @@ export const enum DepFlags {
|
||||
Value = 1 << 3,
|
||||
}
|
||||
|
||||
export interface InjectableDef {
|
||||
scope: any;
|
||||
factory: () => any;
|
||||
}
|
||||
|
||||
export interface TextDef { prefix: string; }
|
||||
|
||||
export interface QueryDef {
|
||||
|
Reference in New Issue
Block a user