diff --git a/src/auto/injector.js b/src/auto/injector.js index 352db5d42a47..0711c562c4cc 100644 --- a/src/auto/injector.js +++ b/src/auto/injector.js @@ -176,6 +176,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. */ @@ -622,14 +623,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); })); @@ -664,7 +668,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); } @@ -759,7 +763,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}', @@ -770,7 +774,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]; @@ -802,7 +806,7 @@ function createInjector(modulesToLoad, strictDi) { args.push( locals && locals.hasOwnProperty(key) ? locals[key] - : getService(key) + : getService(key, serviceName) ); } if (isArray(fn)) { diff --git a/test/auto/injectorSpec.js b/test/auto/injectorSpec.js index ff5dcc1f5654..3b1812904c9e 100644 --- a/test/auto/injectorSpec.js +++ b/test/auto/injectorSpec.js @@ -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');