feat(core): Adds DI support for providedIn: 'platform'|'any'
(#32154)
Extend the vocabulary of the `providedIn` to also include `'platform'` and `'any'`` scope. ``` @Injectable({ providedId: 'platform', // tree shakable injector for platform injector }) class MyService {...} ``` PR Close #32154
This commit is contained in:
@ -8,6 +8,7 @@
|
||||
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {Attribute, ChangeDetectorRef, Component, Directive, ElementRef, EventEmitter, Host, HostBinding, INJECTOR, Inject, Injectable, InjectionToken, Injector, Input, LOCALE_ID, ModuleWithProviders, NgModule, Optional, Output, Pipe, PipeTransform, Self, SkipSelf, TemplateRef, ViewChild, ViewContainerRef, forwardRef, ɵDEFAULT_LOCALE_ID as DEFAULT_LOCALE_ID} from '@angular/core';
|
||||
import {ɵINJECTOR_SCOPE} from '@angular/core/src/core';
|
||||
import {ViewRef} from '@angular/core/src/render3/view_ref';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {ivyEnabled, onlyInIvy} from '@angular/private/testing';
|
||||
@ -866,6 +867,37 @@ describe('di', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tree shakable injectors', () => {
|
||||
it('should support tree shakable injectors scopes', () => {
|
||||
@Injectable({providedIn: 'any'})
|
||||
class AnyService {
|
||||
constructor(public injector: Injector) {}
|
||||
}
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
class RootService {
|
||||
constructor(public injector: Injector) {}
|
||||
}
|
||||
|
||||
@Injectable({providedIn: 'platform'})
|
||||
class PlatformService {
|
||||
constructor(public injector: Injector) {}
|
||||
}
|
||||
|
||||
const testBedInjector: Injector = TestBed.get(Injector);
|
||||
const childInjector = Injector.create([], testBedInjector);
|
||||
|
||||
const anyService = childInjector.get(AnyService);
|
||||
expect(anyService.injector).toBe(childInjector);
|
||||
|
||||
const rootService = childInjector.get(RootService);
|
||||
expect(rootService.injector.get(ɵINJECTOR_SCOPE)).toBe('root');
|
||||
|
||||
const platformService = childInjector.get(PlatformService);
|
||||
expect(platformService.injector.get(ɵINJECTOR_SCOPE)).toBe('platform');
|
||||
});
|
||||
});
|
||||
|
||||
describe('service injection', () => {
|
||||
|
||||
it('should create instance even when no injector present', () => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
[
|
||||
{
|
||||
"name": "APP_ROOT"
|
||||
"name": "INJECTOR_SCOPE"
|
||||
},
|
||||
{
|
||||
"name": "CIRCULAR"
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {NgModuleRef} from '@angular/core';
|
||||
import {NgModuleRef, ɵINJECTOR_SCOPE as INJECTOR_SCOPE} from '@angular/core';
|
||||
import {InjectFlags, inject} from '@angular/core/src/di';
|
||||
import {Injector} from '@angular/core/src/di/injector';
|
||||
import {INJECTOR} from '@angular/core/src/di/injector_compatibility';
|
||||
@ -16,8 +16,6 @@ import {moduleDef} from '@angular/core/src/view/ng_module';
|
||||
import {createNgModuleRef} from '@angular/core/src/view/refs';
|
||||
import {tokenKey} from '@angular/core/src/view/util';
|
||||
|
||||
import {APP_ROOT} from '../../src/di/scope';
|
||||
|
||||
class Foo {}
|
||||
|
||||
class MyModule {}
|
||||
@ -133,7 +131,7 @@ function makeFactoryProviders(
|
||||
function makeModule(modules: any[], providers: NgModuleProviderDef[]): NgModuleDefinition {
|
||||
const providersByKey: {[key: string]: NgModuleProviderDef} = {};
|
||||
providers.forEach(provider => providersByKey[tokenKey(provider.token)] = provider);
|
||||
return {factory: null, providers, providersByKey, modules, isRoot: true};
|
||||
return {factory: null, providers, providersByKey, modules, scope: 'root'};
|
||||
}
|
||||
|
||||
describe('NgModuleRef_ injector', () => {
|
||||
@ -273,19 +271,24 @@ describe('NgModuleRef_ injector', () => {
|
||||
};
|
||||
}
|
||||
|
||||
it('sets isRoot to `true` when APP_ROOT is `true`', () => {
|
||||
const def = moduleDef([createProvider(APP_ROOT, true)]);
|
||||
expect(def.isRoot).toBe(true);
|
||||
it('sets scope to `root` when INJECTOR_SCOPE is `root`', () => {
|
||||
const def = moduleDef([createProvider(INJECTOR_SCOPE, 'root')]);
|
||||
expect(def.scope).toBe('root');
|
||||
});
|
||||
|
||||
it('sets isRoot to `false` when APP_ROOT is absent', () => {
|
||||
it('sets scope to `platform` when INJECTOR_SCOPE is `platform`', () => {
|
||||
const def = moduleDef([createProvider(INJECTOR_SCOPE, 'platform')]);
|
||||
expect(def.scope).toBe('platform');
|
||||
});
|
||||
|
||||
it('sets scope to `null` when INJECTOR_SCOPE is absent', () => {
|
||||
const def = moduleDef([]);
|
||||
expect(def.isRoot).toBe(false);
|
||||
expect(def.scope).toBe(null);
|
||||
});
|
||||
|
||||
it('sets isRoot to `false` when APP_ROOT is `false`', () => {
|
||||
const def = moduleDef([createProvider(APP_ROOT, false)]);
|
||||
expect(def.isRoot).toBe(false);
|
||||
it('sets isRoot to `null` when INJECTOR_SCOPE is `null`', () => {
|
||||
const def = moduleDef([createProvider(INJECTOR_SCOPE, null)]);
|
||||
expect(def.scope).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user