fix(injector): invoke config blocks for module after all providers

This change ensures that a module's config blocks are always invoked after all of its providers are
registered.

BREAKING CHANGE:

Previously, config blocks would be able to control behaviour of provider registration, due to being
invoked prior to provider registration. Now, provider registration always occurs prior to configuration
for a given module, and therefore config blocks are not able to have any control over a providers
registration.

Example:

Previously, the following:

   angular.module('foo', [])
     .provider('$rootProvider', function() {
       this.$get = function() { ... }
     })
     .config(function($rootProvider) {
       $rootProvider.dependentMode = "B";
     })
     .provider('$dependentProvider', function($rootProvider) {
       if ($rootProvider.dependentMode === "A") {
         this.$get = function() {
           // Special mode!
         }
       } else {
         this.$get = function() {
           // something else
         }
       }
     });

would have "worked", meaning behaviour of the config block between the registration of "$rootProvider"
and "$dependentProvider" would have actually accomplished something and changed the behaviour of the
app. This is no longer possible within a single module.

Fixes #7139
Closes #7147
This commit is contained in:
Caitlin Potter
2014-04-17 10:11:28 -04:00
parent 924ee6db06
commit c0b4e2db9c
4 changed files with 47 additions and 12 deletions

View File

@@ -308,6 +308,29 @@ describe('injector', function() {
expect(log).toEqual('abABCD');
});
it('should execute own config blocks after all own providers are invoked', function() {
var log = '';
angular.module('a', ['b'])
.config(function($aProvider) {
log += 'aConfig;';
})
.provider('$a', function() {
log += '$aProvider;';
this.$get = function() {};
});
angular.module('b', [])
.config(function($bProvider) {
log += 'bConfig;';
})
.provider('$b', function() {
log += '$bProvider;';
this.$get = function() {};
});
createInjector(['a']);
expect(log).toBe('$bProvider;bConfig;$aProvider;aConfig;');
});
describe('$provide', function() {
it('should throw an exception if we try to register a service called "hasOwnProperty"', function() {

View File

@@ -46,7 +46,6 @@ describe('module loader', function() {
expect(myModule.requires).toEqual(['other']);
expect(myModule._invokeQueue).toEqual([
['$provide', 'constant', ['abc', 123] ],
['$injector', 'invoke', ['config'] ],
['$provide', 'provider', ['sk', 'sv'] ],
['$provide', 'factory', ['fk', 'fv'] ],
['$provide', 'service', ['a', 'aa'] ],
@@ -54,6 +53,9 @@ describe('module loader', function() {
['$filterProvider', 'register', ['f', 'ff'] ],
['$compileProvider', 'directive', ['d', 'dd'] ],
['$controllerProvider', 'register', ['ctrl', 'ccc']],
]);
expect(myModule._configBlocks).toEqual([
['$injector', 'invoke', ['config'] ],
['$injector', 'invoke', ['init2'] ]
]);
expect(myModule._runBlocks).toEqual(['runBlock']);