Skip to content

Commit ed36b9d

Browse files
committed
refactor(injector): switch to injector 2.0 introduce modules
1 parent c925f8a commit ed36b9d

30 files changed

+239
-333
lines changed

example/personalLog/test/personalLogSpec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ describe('example.personalLog.LogCtrl', function() {
22
var logCtrl;
33

44
function createNotesCtrl() {
5-
var injector = angular.injector();
5+
var injector = angular.injector('NG');
66
var scope = injector('$rootScope');
77
scope.$cookies = injector('$cookies');
88
return scope.$new(example.personalLog.LogCtrl);
@@ -121,4 +121,4 @@ describe('example.personalLog.LogCtrl', function() {
121121
expect(logCtrl.$cookies.logs).not.toBeDefined();
122122
});
123123
});
124-
});
124+
});

src/Angular.js

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ var _undefined = undefined,
100100

101101
/** @name angular */
102102
angular = window[$angular] || (window[$angular] = {}),
103+
angularModules = angular.modules || (angular.modules = {}),
103104
/** @name angular.markup */
104105
angularTextMarkup = extensionMap(angular, 'markup'),
105106
/** @name angular.attrMarkup */
@@ -274,6 +275,7 @@ function inherit(parent, extra) {
274275
</pre>
275276
*/
276277
function noop() {}
278+
noop.$inject = [];
277279

278280

279281
/**
@@ -292,6 +294,7 @@ function noop() {}
292294
</pre>
293295
*/
294296
function identity($) {return $;}
297+
identity.$inject = [];
295298

296299

297300
function valueFn(value) {return function() {return value;};}
@@ -945,14 +948,20 @@ function encodeUriQuery(val, pctEncodeSpaces) {
945948
*/
946949
function angularInit(config, document){
947950
var autobind = config.autobind;
948-
951+
949952
if (autobind) {
950-
var element = isString(autobind) ? document.getElementById(autobind) : document,
951-
injector = createInjector(angularService),
952-
scope = injector('$rootScope');
953-
954-
injector('$compile')(element)(scope);
955-
scope.$apply();
953+
var modules = [ngModule];
954+
forEach((config.modules || '').split(','), function(module){
955+
module = trim(module);
956+
if (module) {
957+
modules.push(module);
958+
}
959+
});
960+
createInjector(modules, angularModules)(['$rootScope', '$compile', function(scope, compile){
961+
scope.$apply(function(){
962+
compile(isString(autobind) ? document.getElementById(autobind) : document)(scope);
963+
});
964+
}]);
956965
}
957966
}
958967

@@ -1017,13 +1026,11 @@ function assertArgFn(arg, name) {
10171026

10181027
function publishExternalAPI(angular){
10191028
extend(angular, {
1020-
// disabled for now until we agree on public name
1021-
//'annotate': annotate,
10221029
'copy': copy,
10231030
'extend': extend,
10241031
'equals': equals,
10251032
'forEach': forEach,
1026-
'injector': createInjector,
1033+
'injector': function(){ return createInjector(arguments, angularModules); },
10271034
'noop':noop,
10281035
'bind':bind,
10291036
'toJson': toJson,
@@ -1041,6 +1048,15 @@ function publishExternalAPI(angular){
10411048
'lowercase': lowercase,
10421049
'uppercase': uppercase
10431050
});
1051+
1052+
angularModules.NG = ngModule;
1053+
}
1054+
1055+
ngModule.$inject = ['$provide'];
1056+
function ngModule($provide) {
1057+
forEach(angularService, function(factory, name){
1058+
$provide.factory(name, factory);
1059+
});
10441060
}
10451061

10461062

src/Injector.js

Lines changed: 33 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -22,108 +22,16 @@
2222
* The injector function also has these properties:
2323
*
2424
* * An `invoke` property which can be used to invoke methods with dependency-injected arguments.
25-
* `injector.invoke(self, fn, curryArgs)`
25+
* `injector.invoke(self, fn, locals)`
2626
* * `self` - The "`this`" to be used when invoking the function.
2727
* * `fn` - The function to be invoked. The function may have the `$inject` property that
2828
* lists the set of arguments which should be auto-injected.
2929
* (see {@link guide/dev_guide.di dependency injection}).
30-
* * `curryArgs(array)` - Optional array of arguments to pass to the function
31-
* invocation after the injection arguments (also known as curry arguments or currying).
30+
* * `locals(array)` - Optional array of arguments to pass to the function
31+
* invocation after the injection arguments.
3232
* * An `eager` property which is used to initialize the eager services.
3333
* `injector.eager()`
3434
*/
35-
function createInjector(factories) {
36-
var instanceCache = {
37-
$injector: injector
38-
};
39-
factories = factories || angularService;
40-
41-
injector.invoke = invoke;
42-
43-
forEach(factories, function(factory, name){
44-
if (factory.$eager)
45-
injector(name);
46-
});
47-
return instanceCache.$injector;
48-
49-
function injector(serviceId, path){
50-
if (typeof serviceId == 'string') {
51-
if (!(serviceId in instanceCache)) {
52-
var factory = factories[serviceId];
53-
path = path || [];
54-
path.unshift(serviceId);
55-
if (!factory) throw Error("Unknown provider for '" + path.join("' <- '") + "'.");
56-
inferInjectionArgs(factory);
57-
instanceCache[serviceId] = invoke(null, factory, [], path);
58-
path.shift();
59-
}
60-
return instanceCache[serviceId];
61-
} else {
62-
return invoke(null, serviceId, path);
63-
}
64-
}
65-
66-
function invoke(self, fn, args, path){
67-
args = args || [];
68-
var injectNames;
69-
var i;
70-
if (typeof fn == 'function') {
71-
injectNames = fn.$inject || [];
72-
i = injectNames.length;
73-
} else if (fn instanceof Array) {
74-
injectNames = fn;
75-
i = injectNames.length;
76-
fn = injectNames[--i];
77-
}
78-
assertArgFn(fn, 'fn');
79-
while(i--) {
80-
args.unshift(injector(injectNames[i], path));
81-
}
82-
return fn.apply(self, args);
83-
}
84-
}
85-
86-
/**
87-
* THIS IS NOT PUBLIC DOC YET!
88-
*
89-
* @name angular.annotate
90-
* @function
91-
*
92-
* @description
93-
* Annotate the function with injection arguments. This is equivalent to setting the `$inject`
94-
* property as described in {@link guide.di dependency injection}.
95-
*
96-
* <pre>
97-
* var MyController = angular.annotate('$location', function($location){ ... });
98-
* </pre>
99-
*
100-
* is the same as
101-
*
102-
* <pre>
103-
* var MyController = function($location){ ... };
104-
* MyController.$inject = ['$location'];
105-
* </pre>
106-
*
107-
* @param {String|Array} serviceName... zero or more service names to inject into the
108-
* `annotatedFunction`.
109-
* @param {function} annotatedFunction function to annotate with `$inject`
110-
* functions.
111-
* @returns {function} `annotatedFunction`
112-
*/
113-
function annotate(services, fn) {
114-
if (services instanceof Array) {
115-
fn.$inject = services;
116-
return fn;
117-
} else {
118-
var i = 0,
119-
length = arguments.length - 1, // last one is the destination function
120-
$inject = arguments[length].$inject = [];
121-
for (; i < length; i++) {
122-
$inject.push(arguments[i]);
123-
}
124-
return arguments[length]; // return the last one
125-
}
126-
}
12735

12836
function angularServiceInject(name, fn, inject, eager) {
12937
angularService(name, fn, {$inject:inject, $eager:eager});
@@ -156,22 +64,16 @@ function inferInjectionArgs(fn) {
15664
}
15765

15866
///////////////////////////////////////
159-
function createInjector2(modulesToLoad, moduleRegistry) {
67+
function createInjector(modulesToLoad, moduleRegistry) {
16068
var cache = {},
16169
$injector = internalInjector(cache),
16270
providerSuffix = 'Provider',
16371
providerSuffixLength = providerSuffix.length;
16472

165-
function $provide(name) {
166-
var provider = cache['#' + name + providerSuffix];
167-
if (provider) {
168-
return provider;
169-
} else {
170-
throw Error("No provider for: " + name);
171-
}
172-
}
73+
value('$injector', $injector);
74+
value('$provide', {service: service, factory: factory, value: value});
17375

174-
$provide.service = function(name, provider) {
76+
function service(name, provider) {
17577
if (isFunction(provider)){
17678
provider = $injector.instantiate(provider);
17779
}
@@ -180,11 +82,8 @@ function createInjector2(modulesToLoad, moduleRegistry) {
18082
}
18183
cache['#' + name + providerSuffix] = provider;
18284
};
183-
$provide.factory = function(name, factoryFn) { $provide.service(name, { $get:factoryFn }); };
184-
$provide.value = function(name, value) { $provide.factory(name, valueFn(value)); };
185-
186-
$provide.value('$injector', $injector);
187-
$provide.value('$provide', $provide);
85+
function factory(name, factoryFn) { service(name, { $get:factoryFn }); };
86+
function value(name, value) { factory(name, valueFn(value)); };
18887

18988
function internalInjector(cache) {
19089
var path = [];
@@ -194,9 +93,10 @@ function createInjector2(modulesToLoad, moduleRegistry) {
19493
case 'function':
19594
return invoke(null, value);
19695
case 'string':
197-
var instanceKey = '#' + value;
198-
if (cache[instanceKey]) {
199-
return cache[instanceKey];
96+
var instanceKey = '#' + value,
97+
instance = cache[instanceKey];
98+
if (instance !== undefined || cache.hasOwnProperty(instanceKey)) {
99+
return instance;
200100
}
201101
try {
202102
path.unshift(value);
@@ -219,28 +119,32 @@ function createInjector2(modulesToLoad, moduleRegistry) {
219119
}
220120
}
221121

222-
function invoke(self, fn){
122+
function invoke(self, fn, locals){
223123
var args = [],
224124
$inject,
225-
length;
226125

227-
switch(typeof fn){
228-
case 'function':
229-
$inject = inferInjectionArgs(fn);
126+
length,
127+
key;
128+
129+
if (fn instanceof Function) {
130+
$inject = inferInjectionArgs(fn);
131+
length = $inject.length;
132+
} else {
133+
if (fn instanceof Array) {
134+
$inject = fn;
230135
length = $inject.length;
231-
break;
232-
case 'object':
233-
if (typeof fn.length == 'number') {
234-
$inject = fn;
235-
length = $inject.length;
236-
fn = $inject[--length];
237-
}
238-
default:
239-
assertArgFn(fn, 'fn');
240-
};
136+
fn = $inject[--length];
137+
}
138+
assertArgFn(fn, 'fn');
139+
}
241140

242141
while(length--) {
243-
args.unshift(injector($inject[length], path));
142+
key = $inject[length];
143+
args.unshift(
144+
locals && locals.hasOwnProperty(key)
145+
? locals[key]
146+
: injector($inject[length], path)
147+
);
244148
}
245149

246150
switch (self ? -1 : args.length) {

src/scenario/Runner.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ angular.scenario.Runner.prototype.createSpecRunner_ = function(scope) {
163163
*/
164164
angular.scenario.Runner.prototype.run = function(application) {
165165
var self = this;
166-
var $root = angular.injector()('$rootScope');
166+
var $root = angular.injector('NG')('$rootScope');
167167
angular.extend($root, this);
168168
angular.forEach(angular.scenario.Runner.prototype, function(fn, name) {
169169
$root[name] = angular.bind(self, fn);

src/scenario/dsl.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,25 +103,25 @@ angular.scenario.dsl('browser', function() {
103103

104104
api.url = function() {
105105
return this.addFutureAction('$location.url()', function($window, $document, done) {
106-
done(null, $window.angular.injector()('$location').url());
106+
done(null, $window.angular.injector('NG')('$location').url());
107107
});
108108
};
109109

110110
api.path = function() {
111111
return this.addFutureAction('$location.path()', function($window, $document, done) {
112-
done(null, $window.angular.injector()('$location').path());
112+
done(null, $window.angular.injector('NG')('$location').path());
113113
});
114114
};
115115

116116
api.search = function() {
117117
return this.addFutureAction('$location.search()', function($window, $document, done) {
118-
done(null, $window.angular.injector()('$location').search());
118+
done(null, $window.angular.injector('NG')('$location').search());
119119
});
120120
};
121121

122122
api.hash = function() {
123123
return this.addFutureAction('$location.hash()', function($window, $document, done) {
124-
done(null, $window.angular.injector()('$location').hash());
124+
done(null, $window.angular.injector('NG')('$location').hash());
125125
});
126126
};
127127

src/service/compiler.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ angularServiceInject('$compile', function($injector, $exceptionHandler, $textMar
2222

2323
Template.prototype = {
2424
link: function(element, scope) {
25-
var childScope = scope;
25+
var childScope = scope,
26+
locals = {$element: element};
2627
if (this.newScope) {
2728
childScope = isFunction(this.newScope) ? scope.$new(this.newScope(scope)) : scope.$new();
2829
element.data($$scope, childScope);
2930
}
3031
forEach(this.linkFns, function(fn) {
3132
try {
32-
childScope.$service.invoke(childScope, fn, [element]);
33+
$injector.invoke(childScope, fn, locals);
3334
} catch (e) {
3435
$exceptionHandler(e);
3536
}
@@ -54,6 +55,10 @@ angularServiceInject('$compile', function($injector, $exceptionHandler, $textMar
5455

5556
addLinkFn:function(linkingFn) {
5657
if (linkingFn) {
58+
//TODO(misko): temporary hack.
59+
if (isFunction(linkingFn) && !linkingFn.$inject) {
60+
linkingFn.$inject = ['$element'];
61+
}
5762
this.linkFns.push(linkingFn);
5863
}
5964
},

0 commit comments

Comments
 (0)