From 4ad927eb74ed9344bd7c4da5652ccfb5c3472a7e Mon Sep 17 00:00:00 2001 From: Alex Rickabaugh Date: Mon, 26 Mar 2018 16:22:46 -0700 Subject: [PATCH] fix: consistently rewrite Injector to INJECTOR In Ivy mode we rewrite references to Injector to INJECTOR in ngInjectableDef, to fix tree-shaking. This changes the rewrite to happen always, even in non-Ivy mode, and makes Angular understand INJECTOR across the board at runtime. --- .../bazel/injectable_def/app/test/app_spec.ts | 26 ++++++++++++++++++- packages/compiler/src/injectable_compiler.ts | 2 +- packages/core/src/di/injector.ts | 2 +- packages/core/src/view/ng_module.ts | 2 ++ packages/core/src/view/provider.ts | 5 +++- 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/packages/compiler-cli/integrationtest/bazel/injectable_def/app/test/app_spec.ts b/packages/compiler-cli/integrationtest/bazel/injectable_def/app/test/app_spec.ts index 4db7761d7e5f0..571252f744734 100644 --- a/packages/compiler-cli/integrationtest/bazel/injectable_def/app/test/app_spec.ts +++ b/packages/compiler-cli/integrationtest/bazel/injectable_def/app/test/app_spec.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {Component, Injectable, NgModule} from '@angular/core'; +import {Component, INJECTOR, Injectable, NgModule} from '@angular/core'; import {TestBed} from '@angular/core/testing'; import {renderModuleFactory} from '@angular/platform-server'; import {BasicAppModuleNgFactory} from 'app_built/src/basic.ngfactory'; @@ -142,4 +142,28 @@ describe('ngInjectableDef Bazel Integration', () => { TestBed.configureTestingModule({}); expect(TestBed.get(Service).value).toEqual(true); }); + + it('NgModule injector understands requests for INJECTABLE', () => { + TestBed.configureTestingModule({ + providers: [{provide: 'foo', useValue: 'bar'}], + }); + expect(TestBed.get(INJECTOR).get('foo')).toEqual('bar'); + }); + + it('Component injector understands requests for INJECTABLE', () => { + @Component({ + selector: 'test-cmp', + template: 'test', + providers: [{provide: 'foo', useValue: 'bar'}], + }) + class TestCmp { + } + + TestBed.configureTestingModule({ + declarations: [TestCmp], + }); + + const fixture = TestBed.createComponent(TestCmp); + expect(fixture.componentRef.injector.get(INJECTOR).get('foo')).toEqual('bar'); + }); }); diff --git a/packages/compiler/src/injectable_compiler.ts b/packages/compiler/src/injectable_compiler.ts index 263a48ef9d773..8677a091fb3e1 100644 --- a/packages/compiler/src/injectable_compiler.ts +++ b/packages/compiler/src/injectable_compiler.ts @@ -63,7 +63,7 @@ export class InjectableCompiler { let tokenExpr: o.Expression; if (typeof token === 'string') { tokenExpr = o.literal(token); - } else if (token === this.tokenInjector && this.alwaysGenerateDef) { + } else if (token === this.tokenInjector) { tokenExpr = o.importExpr(Identifiers.INJECTOR); } else { tokenExpr = ctx.importExpr(token); diff --git a/packages/core/src/di/injector.ts b/packages/core/src/di/injector.ts index 25331a179c849..5d3bf0c1a60f2 100644 --- a/packages/core/src/di/injector.ts +++ b/packages/core/src/di/injector.ts @@ -145,7 +145,7 @@ export class StaticInjector implements Injector { records.set( Injector, {token: Injector, fn: IDENT, deps: EMPTY, value: this, useNew: false}); records.set( - INJECTOR, {token: Injector, fn: IDENT, deps: EMPTY, value: this, useNew: false}); + INJECTOR, {token: INJECTOR, fn: IDENT, deps: EMPTY, value: this, useNew: false}); recursivelyProcessProviders(records, providers); } diff --git a/packages/core/src/view/ng_module.ts b/packages/core/src/view/ng_module.ts index 4fa7615a8b4d2..339a4368f6175 100644 --- a/packages/core/src/view/ng_module.ts +++ b/packages/core/src/view/ng_module.ts @@ -19,6 +19,7 @@ import {splitDepsDsl, tokenKey} from './util'; const UNDEFINED_VALUE = new Object(); const InjectorRefTokenKey = tokenKey(Injector); +const INJECTORRefTokenKey = tokenKey(INJECTOR); const NgModuleRefTokenKey = tokenKey(NgModuleRef); export function moduleProvideDef( @@ -86,6 +87,7 @@ export function resolveNgModuleDep( const tokenKey = depDef.tokenKey; switch (tokenKey) { case InjectorRefTokenKey: + case INJECTORRefTokenKey: case NgModuleRefTokenKey: return data; } diff --git a/packages/core/src/view/provider.ts b/packages/core/src/view/provider.ts index b8a9b7df53be2..dbdc468e5e9f8 100644 --- a/packages/core/src/view/provider.ts +++ b/packages/core/src/view/provider.ts @@ -7,12 +7,13 @@ */ import {ChangeDetectorRef, SimpleChange, SimpleChanges, WrappedValue} from '../change_detection/change_detection'; -import {Injector, resolveForwardRef} from '../di'; +import {INJECTOR, Injector, resolveForwardRef} from '../di'; import {ElementRef} from '../linker/element_ref'; import {TemplateRef} from '../linker/template_ref'; import {ViewContainerRef} from '../linker/view_container_ref'; import {Renderer as RendererV1, Renderer2} from '../render/api'; import {stringify} from '../util'; + import {createChangeDetectorRef, createInjector, createRendererV1} from './refs'; import {BindingDef, BindingFlags, DepDef, DepFlags, NodeDef, NodeFlags, OutputDef, OutputType, ProviderData, QueryValueType, Services, ViewData, ViewFlags, ViewState, asElementData, asProviderData, shouldCallLifecycleInitHook} from './types'; import {calcBindingFlags, checkBinding, dispatchEvent, isComponentView, splitDepsDsl, splitMatchedQueriesDsl, tokenKey, viewParentEl} from './util'; @@ -24,6 +25,7 @@ const ViewContainerRefTokenKey = tokenKey(ViewContainerRef); const TemplateRefTokenKey = tokenKey(TemplateRef); const ChangeDetectorRefTokenKey = tokenKey(ChangeDetectorRef); const InjectorRefTokenKey = tokenKey(Injector); +const INJECTORRefTokenKey = tokenKey(INJECTOR); export function directiveDef( checkIndex: number, flags: NodeFlags, @@ -373,6 +375,7 @@ export function resolveDep( return createChangeDetectorRef(cdView); } case InjectorRefTokenKey: + case INJECTORRefTokenKey: return createInjector(searchView, elDef); default: const providerDef =