Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 48697a2

Browse files
committed
refactor(injector): turn scope into a service
- turn scope into a $rootScope service. - injector is now a starting point for creating angular application. - added inject() method which wraps jasmine its/beforeEach/afterEach, and which allows configuration and injection of services. - refactor tests to use inject() where possible BREAK: - removed angular.scope() method
1 parent 93b777c commit 48697a2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+3114
-3199
lines changed

example/personalLog/test/personalLogSpec.js

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

44
function createNotesCtrl() {
5-
var scope = angular.scope();
6-
scope.$cookies = scope.$service('$cookies');
5+
var injector = angular.injector();
6+
var scope = injector('$rootScope');
7+
scope.$cookies = injector('$cookies');
78
return scope.$new(example.personalLog.LogCtrl);
89
}
910

src/Angular.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,8 +952,12 @@ function angularInit(config, document){
952952
var autobind = config.autobind;
953953

954954
if (autobind) {
955-
var element = isString(autobind) ? document.getElementById(autobind) : document;
956-
compile(element)().$apply();
955+
var element = isString(autobind) ? document.getElementById(autobind) : document,
956+
injector = createInjector(),
957+
scope = injector('$rootScope');
958+
959+
compile(element)(scope);
960+
scope.$apply();
957961
}
958962
}
959963

src/AngularPublic.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ extend(angular, {
1515
// disabled for now until we agree on public name
1616
//'annotate': annotate,
1717
'compile': compile,
18-
'scope': createScope,
1918
'copy': copy,
2019
'extend': extend,
2120
'equals': equals,

src/Compiler.js

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,10 @@ Template.prototype = {
102102
*
103103
*
104104
* @param {string|DOMElement} element Element or HTML to compile into a template function.
105-
* @returns {function([scope][, cloneAttachFn])} a template function which is used to bind template
105+
* @returns {function(scope[, cloneAttachFn])} a template function which is used to bind template
106106
* (a DOM element/tree) to a scope. Where:
107107
*
108-
* * `scope` - A {@link angular.scope Scope} to bind to. If none specified, then a new
109-
* root scope is created.
108+
* * `scope` - A {@link angular.scope Scope} to bind to.
110109
* * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
111110
* `template` and call the `cloneAttachFn` function allowing the caller to attach the
112111
* cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
@@ -115,9 +114,8 @@ Template.prototype = {
115114
* * `clonedElement` - is a clone of the original `element` passed into the compiler.
116115
* * `scope` - is the current scope with which the linking function is working with.
117116
*
118-
* Calling the template function returns the scope to which the element is bound to. It is either
119-
* the same scope as the one passed into the template function, or if none were provided it's the
120-
* newly create scope.
117+
* Calling the template function returns the element of the template. It is either the original element
118+
* passed in, or the clone of the element if the `cloneAttachFn` is provided.
121119
*
122120
* It is important to understand that the returned scope is "linked" to the view DOM, but no linking
123121
* (instance) functions registered by {@link angular.directive directives} or
@@ -133,8 +131,8 @@ Template.prototype = {
133131
* - If you are not asking the linking function to clone the template, create the DOM element(s)
134132
* before you send them to the compiler and keep this reference around.
135133
* <pre>
136-
* var view = angular.element('<p>{{total}}</p>'),
137-
* scope = angular.compile(view)();
134+
* var scope = angular.injector()('$rootScope');
135+
* var element = angular.compile('<p>{{total}}</p>')(scope);
138136
* </pre>
139137
*
140138
* - if on the other hand, you need the element to be cloned, the view reference from the original
@@ -208,17 +206,17 @@ Compiler.prototype = {
208206
}
209207
template = this.templatize(templateElement, index) || new Template();
210208
return function(scope, cloneConnectFn){
209+
assertArg(scope, 'scope');
211210
// important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
212211
// and sometimes changes the structure of the DOM.
213212
var element = cloneConnectFn
214213
? JQLitePrototype.clone.call(templateElement) // IMPORTANT!!!
215214
: templateElement;
216-
scope = scope || createScope();
217215
element.data($$scope, scope);
218216
scope.$element = element;
219217
(cloneConnectFn||noop)(element, scope);
220218
template.link(element, scope);
221-
return scope;
219+
return element;
222220
};
223221
},
224222

src/Injector.js

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,11 @@
99
* Creates an injector function that can be used for retrieving services as well as for
1010
* dependency injection (see {@link guide/dev_guide.di dependency injection}).
1111
*
12-
* Angular creates an injector automatically for the root scope and it is available as the
13-
* {@link angular.scope.$service $service} property. Creating an injector doesn't automatically
14-
* create all of the `$eager` {@link angular.service services}. You have to call `injector.eager()`
15-
* to initialize them.
12+
* Creating an injector doesn't automatically create all of the `$eager`
13+
* {@link angular.service services}. You have to call `injector.eager()` to initialize them.
1614
*
17-
* @param {Object=} [factoryScope={}] The `this` for the service factory function.
1815
* @param {Object.<string, function()>=} [factories=angular.service] Map of the service factory
1916
* functions.
20-
* @param {Object.<string, function()>=} [instanceCache={}] Place where instances of services are
21-
* saved for reuse. Can also be used to override services specified by `serviceFactory`
22-
* (useful in tests).
2317
* @returns {function()} Injector function:
2418
*
2519
* * `injector(serviceName)`:
@@ -38,30 +32,24 @@
3832
* * An `eager` property which is used to initialize the eager services.
3933
* `injector.eager()`
4034
*/
41-
function createInjector(factoryScope, factories, instanceCache) {
35+
function createInjector(factories) {
36+
var instanceCache = {$injector: injector};
4237
factories = factories || angularService;
43-
instanceCache = instanceCache || {};
44-
factoryScope = factoryScope || {};
45-
injector.invoke = invoke;
4638

47-
injector.eager = function() {
48-
forEach(factories, function(factory, name){
49-
if (factory.$eager)
50-
injector(name);
39+
injector.invoke = invoke;
5140

52-
if (factory.$creation)
53-
throw new Error("Failed to register service '" + name +
54-
"': $creation property is unsupported. Use $eager:true or see release notes.");
55-
});
56-
};
41+
forEach(factories, function(factory, name){
42+
if (factory.$eager)
43+
injector(name);
44+
});
5745
return injector;
5846

5947
function injector(value){
6048
if (!(value in instanceCache)) {
6149
var factory = factories[value];
62-
if (!factory) throw Error("Unknown provider for '"+value+"'.");
50+
if (!factory) throw Error("Unknown provider for '" + value + "'.");
6351
inferInjectionArgs(factory);
64-
instanceCache[value] = invoke(factoryScope, factory);
52+
instanceCache[value] = invoke(null, factory);
6553
}
6654
return instanceCache[value];
6755
}

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.scope();
166+
var $root = angular.injector()('$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.scope().$service('$location').url());
106+
done(null, $window.angular.injector()('$location').url());
107107
});
108108
};
109109

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

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

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

src/service/cookies.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@
1313
*
1414
* @example
1515
*/
16-
angularServiceInject('$cookies', function($browser) {
17-
var rootScope = this,
18-
cookies = {},
16+
angularServiceInject('$cookies', function($rootScope, $browser) {
17+
var cookies = {},
1918
lastCookies = {},
2019
lastBrowserCookies,
2120
runEval = false;
@@ -27,7 +26,7 @@ angularServiceInject('$cookies', function($browser) {
2726
lastBrowserCookies = currentCookies;
2827
copy(currentCookies, lastCookies);
2928
copy(currentCookies, cookies);
30-
if (runEval) rootScope.$apply();
29+
if (runEval) $rootScope.$apply();
3130
}
3231
})();
3332

@@ -36,7 +35,7 @@ angularServiceInject('$cookies', function($browser) {
3635
//at the end of each eval, push cookies
3736
//TODO: this should happen before the "delayed" watches fire, because if some cookies are not
3837
// strings or browser refuses to store some cookies, we update the model in the push fn.
39-
this.$watch(push);
38+
$rootScope.$watch(push);
4039

4140
return cookies;
4241

@@ -90,4 +89,4 @@ angularServiceInject('$cookies', function($browser) {
9089
}
9190
}
9291
}
93-
}, ['$browser']);
92+
}, ['$rootScope', '$browser']);

src/service/defer.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,10 @@
2828
* @param {*} deferId Token returned by the `$defer` function.
2929
* @returns {boolean} Returns `true` if the task hasn't executed yet and was successfuly canceled.
3030
*/
31-
angularServiceInject('$defer', function($browser) {
32-
var scope = this;
33-
31+
angularServiceInject('$defer', function($rootScope, $browser) {
3432
function defer(fn, delay) {
3533
return $browser.defer(function() {
36-
scope.$apply(fn);
34+
$rootScope.$apply(fn);
3735
}, delay);
3836
}
3937

@@ -42,4 +40,4 @@ angularServiceInject('$defer', function($browser) {
4240
};
4341

4442
return defer;
45-
}, ['$browser']);
43+
}, ['$rootScope', '$browser']);

src/service/formFactory.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
</doc:scenario>
9797
</doc:example>
9898
*/
99-
angularServiceInject('$formFactory', function() {
99+
angularServiceInject('$formFactory', function($rootScope) {
100100

101101

102102
/**
@@ -109,7 +109,7 @@ angularServiceInject('$formFactory', function() {
109109
* Each application ({@link guide/dev_guide.scopes.internals root scope}) gets a root form which
110110
* is the top-level parent of all forms.
111111
*/
112-
formFactory.rootForm = formFactory(this);
112+
formFactory.rootForm = formFactory($rootScope);
113113

114114

115115
/**
@@ -132,7 +132,7 @@ angularServiceInject('$formFactory', function() {
132132
return (parent || formFactory.rootForm).$new(FormController);
133133
}
134134

135-
});
135+
}, ['$rootScope']);
136136

137137
function propertiesUpdate(widget) {
138138
widget.$valid = !(widget.$invalid =

src/service/location.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,8 @@ function locationGetterSetter(property, preprocess) {
419419
*
420420
* For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular Services: Using $location}
421421
*/
422-
angularServiceInject('$location', function($browser, $sniffer, $locationConfig, $document) {
423-
var scope = this, currentUrl,
422+
angularServiceInject('$location', function($rootScope, $browser, $sniffer, $locationConfig, $document) {
423+
var currentUrl,
424424
basePath = $browser.baseHref() || '/',
425425
pathPrefix = pathPrefixFromBase(basePath),
426426
hashPrefix = $locationConfig.hashPrefix || '',
@@ -464,7 +464,7 @@ angularServiceInject('$location', function($browser, $sniffer, $locationConfig,
464464
href = href.indexOf(pathPrefix) === 0 ? href.substr(pathPrefix.length) : href;
465465

466466
currentUrl.url(href);
467-
scope.$apply();
467+
$rootScope.$apply();
468468
event.preventDefault();
469469
// hack to work around FF6 bug 684208 when scenario runner clicks on links
470470
window.angular['ff-684208-preventDefault'] = true;
@@ -482,16 +482,16 @@ angularServiceInject('$location', function($browser, $sniffer, $locationConfig,
482482
$browser.onUrlChange(function(newUrl) {
483483
if (currentUrl.absUrl() != newUrl) {
484484
currentUrl.$$parse(newUrl);
485-
scope.$apply();
485+
$rootScope.$apply();
486486
}
487487
});
488488

489489
// update browser
490490
var changeCounter = 0;
491-
scope.$watch(function() {
491+
$rootScope.$watch(function() {
492492
if ($browser.url() != currentUrl.absUrl()) {
493493
changeCounter++;
494-
scope.$evalAsync(function() {
494+
$rootScope.$evalAsync(function() {
495495
$browser.url(currentUrl.absUrl(), currentUrl.$$replace);
496496
currentUrl.$$replace = false;
497497
});
@@ -501,7 +501,7 @@ angularServiceInject('$location', function($browser, $sniffer, $locationConfig,
501501
});
502502

503503
return currentUrl;
504-
}, ['$browser', '$sniffer', '$locationConfig', '$document']);
504+
}, ['$rootScope', '$browser', '$sniffer', '$locationConfig', '$document']);
505505

506506

507507
angular.service('$locationConfig', function() {

src/service/route.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
</doc:scenario>
6363
</doc:example>
6464
*/
65-
angularServiceInject('$route', function($location, $routeParams) {
65+
angularServiceInject('$route', function($rootScope, $location, $routeParams) {
6666
/**
6767
* @ngdoc event
6868
* @name angular.service.$route#$beforeRouteChange
@@ -112,8 +112,7 @@ angularServiceInject('$route', function($location, $routeParams) {
112112

113113
var routes = {},
114114
matcher = switchRouteMatcher,
115-
parentScope = this,
116-
rootScope = this,
115+
parentScope = $rootScope,
117116
dirty = 0,
118117
forceReload = false,
119118
$route = {
@@ -220,7 +219,7 @@ angularServiceInject('$route', function($location, $routeParams) {
220219
}
221220
};
222221

223-
this.$watch(function() { return dirty + $location.url(); }, updateRoute);
222+
$rootScope.$watch(function() { return dirty + $location.url(); }, updateRoute);
224223

225224
return $route;
226225

@@ -262,7 +261,7 @@ angularServiceInject('$route', function($location, $routeParams) {
262261
last.scope && last.scope.$emit('$routeUpdate');
263262
} else {
264263
forceReload = false;
265-
rootScope.$broadcast('$beforeRouteChange', next, last);
264+
$rootScope.$broadcast('$beforeRouteChange', next, last);
266265
last && last.scope && last.scope.$destroy();
267266
$route.current = next;
268267
if (next) {
@@ -280,7 +279,7 @@ angularServiceInject('$route', function($location, $routeParams) {
280279
next.scope = parentScope.$new(Controller);
281280
}
282281
}
283-
rootScope.$broadcast('$afterRouteChange', next, last);
282+
$rootScope.$broadcast('$afterRouteChange', next, last);
284283
}
285284
}
286285

@@ -323,4 +322,4 @@ angularServiceInject('$route', function($location, $routeParams) {
323322
}
324323

325324

326-
}, ['$location', '$routeParams']);
325+
}, ['$rootScope', '$location', '$routeParams']);

0 commit comments

Comments
 (0)