feat($injector): print caller name in "unknown provider" errors (when available)

NGEUROPE!!!!!

Closes #8135
Closes #9721
This commit is contained in:
Olivier Combe
2014-10-21 13:48:22 +02:00
committed by Caitlin Potter
parent 7c6be43e83
commit 013b522c9e
2 changed files with 31 additions and 9 deletions

View File

@@ -179,6 +179,7 @@ function annotate(fn, strictDi, name) {
* Return an instance of the service.
*
* @param {string} name The name of the instance to retrieve.
* @param {string} caller An optional string to provide the origin of the function call for error messages.
* @return {*} The instance.
*/
@@ -629,14 +630,17 @@ function createInjector(modulesToLoad, strictDi) {
}
},
providerInjector = (providerCache.$injector =
createInternalInjector(providerCache, function() {
createInternalInjector(providerCache, function(serviceName, caller) {
if (angular.isString(caller)) {
path.push(caller);
}
throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
})),
instanceCache = {},
instanceInjector = (instanceCache.$injector =
createInternalInjector(instanceCache, function(servicename) {
var provider = providerInjector.get(servicename + providerSuffix);
return instanceInjector.invoke(provider.$get, provider, undefined, servicename);
createInternalInjector(instanceCache, function(serviceName, caller) {
var provider = providerInjector.get(serviceName + providerSuffix, caller);
return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
}));
@@ -671,7 +675,7 @@ function createInjector(modulesToLoad, strictDi) {
function enforceReturnValue(name, factory) {
return function enforcedReturnValue() {
var result = instanceInjector.invoke(factory, this, undefined, name);
var result = instanceInjector.invoke(factory, this);
if (isUndefined(result)) {
throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
}
@@ -766,7 +770,7 @@ function createInjector(modulesToLoad, strictDi) {
function createInternalInjector(cache, factory) {
function getService(serviceName) {
function getService(serviceName, caller) {
if (cache.hasOwnProperty(serviceName)) {
if (cache[serviceName] === INSTANTIATING) {
throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
@@ -777,7 +781,7 @@ function createInjector(modulesToLoad, strictDi) {
try {
path.unshift(serviceName);
cache[serviceName] = INSTANTIATING;
return cache[serviceName] = factory(serviceName);
return cache[serviceName] = factory(serviceName, caller);
} catch (err) {
if (cache[serviceName] === INSTANTIATING) {
delete cache[serviceName];
@@ -809,7 +813,7 @@ function createInjector(modulesToLoad, strictDi) {
args.push(
locals && locals.hasOwnProperty(key)
? locals[key]
: getService(key)
: getService(key, serviceName)
);
}
if (isArray(fn)) {

View File

@@ -4,12 +4,14 @@ describe('injector', function() {
var providers;
var injector;
var providerInjector;
var controllerProvider;
beforeEach(module(function($provide, $injector) {
beforeEach(module(function($provide, $injector, $controllerProvider) {
providers = function(name, factory, annotations) {
$provide.factory(name, extend(factory, annotations || {}));
};
providerInjector = $injector;
controllerProvider = $controllerProvider;
}));
beforeEach(inject(function($injector) {
injector = $injector;
@@ -74,6 +76,22 @@ describe('injector', function() {
});
it('should provide the caller name if given', function(done) {
expect(function() {
injector.get('idontexist', 'callerName');
}).toThrowMinErr("$injector", "unpr", "Unknown provider: idontexistProvider <- idontexist <- callerName");
});
it('should provide the caller name for controllers', function(done) {
controllerProvider.register('myCtrl', function(idontexist) {});
var $controller = injector.get('$controller');
expect(function() {
$controller('myCtrl', {$scope: {}});
}).toThrowMinErr("$injector", "unpr", "Unknown provider: idontexistProvider <- idontexist <- myCtrl");
});
it('should not corrupt the cache when an object fails to get instantiated', function() {
expect(function() {
injector.get('idontexist');