diff --git a/src/loader.js b/src/loader.js index 02a2e2d66c43..a6c14f54ae9d 100644 --- a/src/loader.js +++ b/src/loader.js @@ -146,7 +146,7 @@ function setupModuleLoader(window) { * @description * See {@link auto.$provide#provider $provide.provider()}. */ - provider: invokeLater('$provide', 'provider'), + provider: invokeLaterAndSetModuleName('$provide', 'provider'), /** * @ngdoc method @@ -157,7 +157,7 @@ function setupModuleLoader(window) { * @description * See {@link auto.$provide#factory $provide.factory()}. */ - factory: invokeLater('$provide', 'factory'), + factory: invokeLaterAndSetModuleName('$provide', 'factory'), /** * @ngdoc method @@ -168,7 +168,7 @@ function setupModuleLoader(window) { * @description * See {@link auto.$provide#service $provide.service()}. */ - service: invokeLater('$provide', 'service'), + service: invokeLaterAndSetModuleName('$provide', 'service'), /** * @ngdoc method @@ -203,7 +203,7 @@ function setupModuleLoader(window) { * @description * See {@link auto.$provide#decorator $provide.decorator()}. */ - decorator: invokeLater('$provide', 'decorator'), + decorator: invokeLaterAndSetModuleName('$provide', 'decorator'), /** * @ngdoc method @@ -237,7 +237,7 @@ function setupModuleLoader(window) { * See {@link ng.$animateProvider#register $animateProvider.register()} and * {@link ngAnimate ngAnimate module} for more information. */ - animation: invokeLater('$animateProvider', 'register'), + animation: invokeLaterAndSetModuleName('$animateProvider', 'register'), /** * @ngdoc method @@ -255,7 +255,7 @@ function setupModuleLoader(window) { * (`myapp_subsection_filterx`). * */ - filter: invokeLater('$filterProvider', 'register'), + filter: invokeLaterAndSetModuleName('$filterProvider', 'register'), /** * @ngdoc method @@ -267,7 +267,7 @@ function setupModuleLoader(window) { * @description * See {@link ng.$controllerProvider#register $controllerProvider.register()}. */ - controller: invokeLater('$controllerProvider', 'register'), + controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'), /** * @ngdoc method @@ -280,7 +280,7 @@ function setupModuleLoader(window) { * @description * See {@link ng.$compileProvider#directive $compileProvider.directive()}. */ - directive: invokeLater('$compileProvider', 'directive'), + directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'), /** * @ngdoc method @@ -330,6 +330,19 @@ function setupModuleLoader(window) { return moduleInstance; }; } + + /** + * @param {string} provider + * @param {string} method + * @returns {angular.Module} + */ + function invokeLaterAndSetModuleName(provider, method) { + return function(recipeName, factoryFunction) { + if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name; + invokeQueue.push([provider, method, arguments]); + return moduleInstance; + }; + } }); }; }); diff --git a/src/ng/compile.js b/src/ng/compile.js index 140e5b61559c..150d8992f4c0 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -852,6 +852,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (isObject(bindings.isolateScope)) { directive.$$isolateBindings = bindings.isolateScope; } + directive.$$moduleName = directiveFactory.$$moduleName; directives.push(directive); } catch (e) { $exceptionHandler(e); @@ -2300,11 +2301,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return a.index - b.index; } - function assertNoDuplicate(what, previousDirective, directive, element) { + + function wrapModuleNameIfDefined(moduleName) { + return moduleName ? + (' (module: ' + moduleName + ')') : + ''; + } + if (previousDirective) { - throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}', - previousDirective.name, directive.name, what, startingTag(element)); + throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}', + previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName), + directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element)); } } diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 27e5dcb3c8a0..98d84af884af 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -2514,6 +2514,70 @@ describe('$compile', function() { ); }); }); + + describe('multidir isolated scope error messages', function() { + angular.module('fakeIsoledScopeModule', []) + .directive('fakeScope', function(log) { + return { + scope: true, + restrict: 'CA', + compile: function() { + return {pre: function(scope, element) { + log(scope.$id); + expect(element.data('$scope')).toBe(scope); + }}; + } + }; + }) + .directive('fakeIScope', function(log) { + return { + scope: {}, + restrict: 'CA', + compile: function() { + return function(scope, element) { + iscope = scope; + log(scope.$id); + expect(element.data('$isolateScopeNoTemplate')).toBe(scope); + }; + } + }; + }); + + beforeEach(module('fakeIsoledScopeModule', function() { + directive('anonymModuleScopeDirective', function(log) { + return { + scope: true, + restrict: 'CA', + compile: function() { + return {pre: function(scope, element) { + log(scope.$id); + expect(element.data('$scope')).toBe(scope); + }}; + } + }; + }); + })); + + it('should add module name to multidir isolated scope message if directive defined through module', inject( + function($rootScope, $compile) { + expect(function() { + $compile('
'); + }).toThrowMinErr('$compile', 'multidir', + 'Multiple directives [fakeIScope (module: fakeIsoledScopeModule), fakeScope (module: fakeIsoledScopeModule)] ' + + 'asking for new/isolated scope on: