From 0477bfc8ed4f3a3cd2f7a43fe4ff8e604c2edb7c Mon Sep 17 00:00:00 2001
From: thekiba
Date: Wed, 10 Apr 2019 14:42:41 +0300
Subject: [PATCH] fix(core): make injector.get() return default value with
InjectFlags.Self flag on (#27739)
Fixes #27729
PR Close #27739
---
packages/core/src/di/injector.ts | 4 +++
packages/core/src/di/r3_injector.ts | 7 ++++-
packages/core/test/di/static_injector_spec.ts | 31 ++++++++++++++++++-
3 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/packages/core/src/di/injector.ts b/packages/core/src/di/injector.ts
index 02ecfd46e6..6efee5d6f7 100644
--- a/packages/core/src/di/injector.ts
+++ b/packages/core/src/di/injector.ts
@@ -342,6 +342,10 @@ function resolveToken(
}
} else if (!(flags & InjectFlags.Self)) {
value = parent.get(token, notFoundValue, InjectFlags.Default);
+ } else if (!(flags & InjectFlags.Optional)) {
+ value = Injector.NULL.get(token, notFoundValue);
+ } else {
+ value = Injector.NULL.get(token, typeof notFoundValue !== 'undefined' ? notFoundValue : null);
}
return value;
}
diff --git a/packages/core/src/di/r3_injector.ts b/packages/core/src/di/r3_injector.ts
index df5be04609..f944eab19b 100644
--- a/packages/core/src/di/r3_injector.ts
+++ b/packages/core/src/di/r3_injector.ts
@@ -197,7 +197,12 @@ export class R3Injector {
// Select the next injector based on the Self flag - if self is set, the next injector is
// the NullInjector, otherwise it's the parent.
const nextInjector = !(flags & InjectFlags.Self) ? this.parent : getNullInjector();
- return nextInjector.get(token, flags & InjectFlags.Optional ? null : notFoundValue);
+ // Set the notFoundValue based on the Optional flag - if optional is set and notFoundValue
+ // is undefined, the value is null, otherwise it's the notFoundValue.
+ notFoundValue = (flags & InjectFlags.Optional) && notFoundValue === THROW_IF_NOT_FOUND ?
+ null :
+ notFoundValue;
+ return nextInjector.get(token, notFoundValue);
} catch (e) {
if (e.name === 'NullInjectorError') {
const path: any[] = e[NG_TEMP_TOKEN_PATH] = e[NG_TEMP_TOKEN_PATH] || [];
diff --git a/packages/core/test/di/static_injector_spec.ts b/packages/core/test/di/static_injector_spec.ts
index 6d4920006e..7ca5da9ef7 100644
--- a/packages/core/test/di/static_injector_spec.ts
+++ b/packages/core/test/di/static_injector_spec.ts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {Inject, InjectionToken, Injector, Optional, Self, SkipSelf, forwardRef} from '@angular/core';
+import {Inject, InjectFlags, 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';
@@ -421,6 +421,35 @@ function factoryFn(a: any){}
`${injectorName}Error[${stringify(Car)} -> ${stringify(Engine)}]: \n` +
' NullInjectorError: No provider for Engine!');
});
+
+ it('should return a default value when not requested provider on self', () => {
+ const car = new SportsCar(new Engine());
+ const injector = Injector.create([]);
+ expect(injector.get(Car, null, InjectFlags.Self)).toBeNull();
+ expect(injector.get(Car, car, InjectFlags.Self)).toBe(car);
+ });
+
+ it('should return a default value when not requested provider on self and optional', () => {
+ const flags = InjectFlags.Self | InjectFlags.Optional;
+ const injector = Injector.create([]);
+ expect(injector.get(Car, null, InjectFlags.Self)).toBeNull();
+ expect(injector.get(Car, 0, flags)).toBe(0);
+ });
+
+ it(`should return null when not requested provider on self and optional`, () => {
+ const flags = InjectFlags.Self | InjectFlags.Optional;
+ const injector = Injector.create([]);
+ expect(injector.get(Car, undefined, flags)).toBeNull();
+ });
+
+ it('should throw error when not requested provider on self', () => {
+ const injector = Injector.create([]);
+ const injectorName = ivyEnabled ? `R3Injector` : `StaticInjector`;
+ expect(() => injector.get(Car, undefined, InjectFlags.Self))
+ .toThrowError(
+ `${injectorName}Error[${stringify(Car)}]: \n` +
+ ` NullInjectorError: No provider for ${stringify(Car)}!`);
+ });
});
describe('default', () => {