From e88dfb734a64aad4dbd402642816781b0e1725ec Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Sat, 12 Nov 2011 15:23:30 -0800 Subject: refactor(injector): $injector is no longer a function. - $injector('abc') -> $injector.get('abc'); - $injector(fn) -> $injector.invoke(null, fn); --- src/Angular.js | 14 +-- src/Injector.js | 209 +++++++++++++++++++++----------------------- src/angular-mocks.js | 2 +- src/scenario/Application.js | 2 +- src/scenario/Runner.js | 2 +- src/scenario/dsl.js | 8 +- src/service/compiler.js | 3 +- src/service/filter.js | 2 +- 8 files changed, 118 insertions(+), 124 deletions(-) (limited to 'src') diff --git a/src/Angular.js b/src/Angular.js index 6ee51c57..9c506d78 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -849,12 +849,14 @@ function angularInit(config, document){ function bootstrap(element, modules) { modules = modules || []; modules.unshift(ngModule); - createInjector(modules, angularModule)(['$rootScope', '$compile', '$injector', function(scope, compile, injector){ - scope.$apply(function() { - element.data('$injector', injector); - compile(element)(scope); - }); - }]); + createInjector(modules, angularModule).invoke(null, + ['$rootScope', '$compile', '$injector', function(scope, compile, injector){ + scope.$apply(function() { + element.data('$injector', injector); + compile(element)(scope); + }); + }] + ); } function angularJsConfig(document) { diff --git a/src/Injector.js b/src/Injector.js index fb64abd1..1db79eb8 100644 --- a/src/Injector.js +++ b/src/Injector.js @@ -22,7 +22,7 @@ * * // use the injector to kick of your application * // use the type inference to auto inject arguments, or use implicit injection - * $injector(function($rootScope, $compile, $document){ + * $injector.invoke(null, function($rootScope, $compile, $document){ * $compile($document)($rootScope); * $rootScope.$digest(); * }); @@ -60,21 +60,22 @@ function inferInjectionArgs(fn) { /////////////////////////////////////// /** - * @ngdoc function + * @ngdoc object * @name angular.module.AUTO.$injector * @function * * @description * - * `$injector` function is used to retrieve object instances. Object instances are defined by - * {@link angular.module.AUTO.$provide provider}. + * `$injector` is used to retrieve object instances as defined by + * {@link angular.module.AUTO.$provide provider}, instantiate types, invoke methods, + * and load modules. * * The following always holds true: * *
* var $injector = angular.injector();
- * expect($injector('$injector')).toBe($injector);
- * expect($injector(function($injector){
+ * expect($injector.get('$injector')).toBe($injector);
+ * expect($injector.invoke(null, function($injector){
* return $injector;
* }).toBe($injector);
*
@@ -108,14 +109,6 @@ function inferInjectionArgs(fn) {
*
* ## Inline
* As an array of injection names, where the last item in the array is the function to call.
- *
- * @param {string, function()} argument If the `argument` is:
- *
- * - `string`: Retrieve an instance of a named object. If object does not exist, use the provider to create
- * a new instance. Calling the method repeatedly with the same name will always return the same
- * instance.
- * - `function`: Invoke the function. This is a short hand for `$injector.`{@link #invoke invoke(null, argument)}.
- * @return the object instance or the return value of the invoked function.
*/
/**
@@ -261,113 +254,116 @@ function inferInjectionArgs(fn) {
function createInjector(modulesToLoad, moduleRegistry) {
var cache = {},
- $injector = internalInjector(cache),
providerSuffix = 'Provider',
- providerSuffixLength = providerSuffix.length;
+ providerSuffixLength = providerSuffix.length,
+ path = [],
+ $injector;
+
+ value('$injector', $injector = {
+ get: getService,
+ invoke: invoke,
+ instantiate: instantiate,
+ loadModule: loadModule
+ });
+ value('$provide', {
+ service: service,
+ factory: factory,
+ value: value
+ });
+
+ loadModule(modulesToLoad);
+
+ return $injector;
- value('$injector', $injector);
- value('$provide', {service: service, factory: factory, value: value});
+ ////////////////////////////////////
function service(name, provider) {
if (isFunction(provider)){
- provider = $injector.instantiate(provider);
+ provider = instantiate(provider);
}
if (!provider.$get) {
throw Error('Providers must define $get factory method.');
}
cache['#' + name + providerSuffix] = provider;
- };
- function factory(name, factoryFn) { service(name, { $get:factoryFn }); };
- function value(name, value) { factory(name, valueFn(value)); };
-
- function internalInjector(cache) {
- var path = [];
-
- function injector(value) {
- switch(typeof value) {
- case 'function':
- return invoke(null, value);
- case 'string':
- var instanceKey = '#' + value,
- instance = cache[instanceKey];
- if (instance !== undefined || cache.hasOwnProperty(instanceKey)) {
- return instance;
- }
- try {
- path.unshift(value);
- var providerKey = instanceKey + providerSuffix,
- provider = cache[providerKey];
- if (provider) {
- return cache[instanceKey] = invoke(provider, provider.$get);
- } else {
- throw Error("Unknown provider for '" + path.join("' <- '") + "'.");
- }
- } finally {
- path.shift();
- }
- case 'object':
- if (isArray(value)) {
- return invoke(null, value);
- }
- default:
- throw Error('Injector expects name or function.');
- }
- }
+ }
- function invoke(self, fn, locals){
- var args = [],
- $inject,
+ function factory(name, factoryFn) { service(name, { $get:factoryFn }); }
- length,
- key;
+ function value(name, value) { factory(name, valueFn(value)); }
- if (typeof fn == 'function') {
- $inject = inferInjectionArgs(fn);
- length = $inject.length;
+ function getService(value) {
+ if (typeof value !== 'string') {
+ throw Error('Service name expected');
+ }
+ var instanceKey = '#' + value,
+ instance = cache[instanceKey];
+ if (instance !== undefined || cache.hasOwnProperty(instanceKey)) {
+ return instance;
+ }
+ try {
+ path.unshift(value);
+ var providerKey = instanceKey + providerSuffix,
+ provider = cache[providerKey];
+ if (provider) {
+ return cache[instanceKey] = invoke(provider, provider.$get);
} else {
- if (isArray(fn)) {
- $inject = fn;
- length = $inject.length;
- fn = $inject[--length];
- }
- assertArgFn(fn, 'fn');
+ throw Error("Unknown provider for '" + path.join("' <- '") + "'.");
}
+ } finally {
+ path.shift();
+ }
+ }
- while(length--) {
- key = $inject[length];
- args.unshift(
- locals && locals.hasOwnProperty(key)
- ? locals[key]
- : injector($inject[length], path)
- );
+ function invoke(self, fn, locals){
+ var args = [],
+ $inject,
+ length,
+ key;
+
+ if (typeof fn == 'function') {
+ $inject = inferInjectionArgs(fn);
+ length = $inject.length;
+ } else {
+ if (isArray(fn)) {
+ $inject = fn;
+ length = $inject.length;
+ fn = $inject[--length];
}
+ assertArgFn(fn, 'fn');
+ }
- switch (self ? -1 : args.length) {
- case 0: return fn();
- case 1: return fn(args[0]);
- case 2: return fn(args[0], args[1]);
- case 3: return fn(args[0], args[1], args[2]);
- case 4: return fn(args[0], args[1], args[2], args[3]);
- case 5: return fn(args[0], args[1], args[2], args[3], args[4]);
- case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);
- case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
- case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
- case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
- case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
- default: return fn.apply(self, args);
- }
- };
-
- injector.invoke = invoke;
- injector.instantiate = function(Type, locals){
- var Constructor = function(){},
- instance;
- Constructor.prototype = Type.prototype;
- instance = new Constructor();
- return invoke(instance, Type, locals) || instance;
- };
- injector.loadModule = loadModule;
- return injector;
+ while(length--) {
+ key = $inject[length];
+ args.unshift(
+ locals && locals.hasOwnProperty(key)
+ ? locals[key]
+ : getService($inject[length], path)
+ );
+ }
+
+ // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke
+ switch (self ? -1 : args.length) {
+ case 0: return fn();
+ case 1: return fn(args[0]);
+ case 2: return fn(args[0], args[1]);
+ case 3: return fn(args[0], args[1], args[2]);
+ case 4: return fn(args[0], args[1], args[2], args[3]);
+ case 5: return fn(args[0], args[1], args[2], args[3], args[4]);
+ case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);
+ case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+ case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
+ case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
+ default: return fn.apply(self, args);
+ }
+ }
+
+ function instantiate(Type, locals){
+ var Constructor = function(){},
+ instance;
+ Constructor.prototype = Type.prototype;
+ instance = new Constructor();
+ return invoke(instance, Type, locals) || instance;
}
function loadModule(modulesToLoad){
@@ -380,15 +376,10 @@ function createInjector(modulesToLoad, moduleRegistry) {
}
}
if (isFunction(module) || isArray(module)) {
- $injector(module);
+ invoke(null, module);
} else {
assertArgFn(module, 'module');
}
});
}
-
-
- loadModule(modulesToLoad);
-
- return $injector;
}
diff --git a/src/angular-mocks.js b/src/angular-mocks.js
index ae0ba65e..f5907a42 100644
--- a/src/angular-mocks.js
+++ b/src/angular-mocks.js
@@ -783,7 +783,7 @@ window.jasmine && (function(window){
return function(){
var injector = this.$injector;
if (!injector) {
- injector = this.$injector = angular.injector('ng', 'ngMock');
+ injector = this.$injector = angular.injector('ng', 'ngMock');
}
for(var i = 0, ii = blockFns.length; i < ii; i++) {
injector.invoke(this, blockFns[i]);
diff --git a/src/scenario/Application.js b/src/scenario/Application.js
index f4f4b974..5e7b8370 100644
--- a/src/scenario/Application.js
+++ b/src/scenario/Application.js
@@ -92,7 +92,7 @@ angular.scenario.Application.prototype.executeAction = function(action) {
}
var element = $window.angular.element($window.document);
var $injector = element.inheritedData('$injector');
- $injector(function($browser){
+ $injector.invoke(null, function($browser){
$browser.notifyWhenNoOutstandingRequests(function() {
action.call(self, $window, _jQuery($window.document));
});
diff --git a/src/scenario/Runner.js b/src/scenario/Runner.js
index 5839fae0..aeb5196a 100644
--- a/src/scenario/Runner.js
+++ b/src/scenario/Runner.js
@@ -163,7 +163,7 @@ angular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {
*/
angular.scenario.Runner.prototype.run = function(application) {
var self = this;
- var $root = angular.injector('ng')('$rootScope');
+ var $root = angular.injector('ng').get('$rootScope');
angular.extend($root, this);
angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {
$root[name] = angular.bind(self, fn);
diff --git a/src/scenario/dsl.js b/src/scenario/dsl.js
index 8963f889..12cbdb21 100644
--- a/src/scenario/dsl.js
+++ b/src/scenario/dsl.js
@@ -103,25 +103,25 @@ angular.scenario.dsl('browser', function() {
api.url = function() {
return this.addFutureAction('$location.url()', function($window, $document, done) {
- done(null, $window.angular.injector('ng')('$location').url());
+ done(null, $window.angular.injector('ng').get('$location').url());
});
};
api.path = function() {
return this.addFutureAction('$location.path()', function($window, $document, done) {
- done(null, $window.angular.injector('ng')('$location').path());
+ done(null, $window.angular.injector('ng').get('$location').path());
});
};
api.search = function() {
return this.addFutureAction('$location.search()', function($window, $document, done) {
- done(null, $window.angular.injector('ng')('$location').search());
+ done(null, $window.angular.injector('ng').get('$location').search());
});
};
api.hash = function() {
return this.addFutureAction('$location.hash()', function($window, $document, done) {
- done(null, $window.angular.injector('ng')('$location').hash());
+ done(null, $window.angular.injector('ng').get('$location').hash());
});
};
diff --git a/src/service/compiler.js b/src/service/compiler.js
index 781d7b3a..3464a1a0 100644
--- a/src/service/compiler.js
+++ b/src/service/compiler.js
@@ -143,7 +143,8 @@ function $CompileProvider(){
* - If you are not asking the linking function to clone the template, create the DOM element(s)
* before you send them to the compiler and keep this reference around.
*
- * var scope = angular.injector('ng')(function($rootScope, $compile){
+ * var $injector = angular.injector('ng');
+ * var scope = $injector.invoke(null, function($rootScope, $compile){
* var element = $compile('{{total}}
')($rootScope);
* });
*
diff --git a/src/service/filter.js b/src/service/filter.js
index 4c43be00..dd97851b 100644
--- a/src/service/filter.js
+++ b/src/service/filter.js
@@ -85,7 +85,7 @@ function $FilterProvider($provide) {
this.$get = ['$injector', function($injector) {
return function(name) {
- return $injector(name + suffix);
+ return $injector.get(name + suffix);
}
}];
--
cgit v1.2.3