aboutsummaryrefslogtreecommitdiffstats
path: root/src/service
diff options
context:
space:
mode:
authorMisko Hevery2011-03-23 09:33:29 -0700
committerVojta Jina2011-08-02 01:00:03 +0200
commit8f0dcbab804180828d6859b1340c86cf161209fb (patch)
treed13d47d47a1889cb7c96a87cecacd2e25307d51c /src/service
parent1f4b417184ce53af15474de065400f8a686430c5 (diff)
downloadangular.js-8f0dcbab804180828d6859b1340c86cf161209fb.tar.bz2
feat(scope): new and improved scope implementation
- Speed improvements (about 4x on flush phase) - Memory improvements (uses no function closures) - Break $eval into $apply, $dispatch, $flush - Introduced $watch and $observe Breaks angular.equals() use === instead of == Breaks angular.scope() does not take parent as first argument Breaks scope.$watch() takes scope as first argument Breaks scope.$set(), scope.$get are removed Breaks scope.$config is removed Breaks $route.onChange callback has not "this" bounded
Diffstat (limited to 'src/service')
-rw-r--r--src/service/cookies.js4
-rw-r--r--src/service/defer.js11
-rw-r--r--src/service/invalidWidgets.js4
-rw-r--r--src/service/location.js47
-rw-r--r--src/service/route.js51
-rw-r--r--src/service/updateView.js6
-rw-r--r--src/service/xhr.bulk.js2
7 files changed, 54 insertions, 71 deletions
diff --git a/src/service/cookies.js b/src/service/cookies.js
index d6be1364..74e63679 100644
--- a/src/service/cookies.js
+++ b/src/service/cookies.js
@@ -28,7 +28,7 @@ angularServiceInject('$cookies', function($browser) {
lastBrowserCookies = currentCookies;
copy(currentCookies, lastCookies);
copy(currentCookies, cookies);
- if (runEval) rootScope.$eval();
+ if (runEval) rootScope.$apply();
}
})();
@@ -37,7 +37,7 @@ angularServiceInject('$cookies', function($browser) {
//at the end of each eval, push cookies
//TODO: this should happen before the "delayed" watches fire, because if some cookies are not
// strings or browser refuses to store some cookies, we update the model in the push fn.
- this.$onEval(PRIORITY_LAST, push);
+ this.$observe(push);
return cookies;
diff --git a/src/service/defer.js b/src/service/defer.js
index 551e8bc9..0a69912c 100644
--- a/src/service/defer.js
+++ b/src/service/defer.js
@@ -18,16 +18,11 @@
* @param {function()} fn A function, who's execution should be deferred.
* @param {number=} [delay=0] of milliseconds to defer the function execution.
*/
-angularServiceInject('$defer', function($browser, $exceptionHandler, $updateView) {
+angularServiceInject('$defer', function($browser) {
+ var scope = this;
return function(fn, delay) {
$browser.defer(function() {
- try {
- fn();
- } catch(e) {
- $exceptionHandler(e);
- } finally {
- $updateView();
- }
+ scope.$apply(fn);
}, delay);
};
}, ['$browser', '$exceptionHandler', '$updateView']);
diff --git a/src/service/invalidWidgets.js b/src/service/invalidWidgets.js
index b7ef0b53..7c1b2a9f 100644
--- a/src/service/invalidWidgets.js
+++ b/src/service/invalidWidgets.js
@@ -42,7 +42,7 @@ angularServiceInject("$invalidWidgets", function(){
/* At the end of each eval removes all invalid widgets that are not part of the current DOM. */
- this.$onEval(PRIORITY_LAST, function() {
+ this.$watch(function() {
for(var i = 0; i < invalidWidgets.length;) {
var widget = invalidWidgets[i];
if (isOrphan(widget[0])) {
@@ -56,7 +56,7 @@ angularServiceInject("$invalidWidgets", function(){
/**
- * Traverses DOM element's (widget's) parents and considers the element to be an orphant if one of
+ * Traverses DOM element's (widget's) parents and considers the element to be an orphan if one of
* it's parents isn't the current window.document.
*/
function isOrphan(widget) {
diff --git a/src/service/location.js b/src/service/location.js
index 1889266e..23531140 100644
--- a/src/service/location.js
+++ b/src/service/location.js
@@ -69,18 +69,14 @@ var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+)
</doc:example>
*/
angularServiceInject("$location", function($browser) {
- var scope = this,
- location = {update:update, updateHash: updateHash},
- lastLocation = {};
+ var location = {update: update, updateHash: updateHash};
+ var lastLocation = {}; // last state since last update().
- $browser.onHashChange(function() { //register
+ $browser.onHashChange(bind(this, this.$apply, function() { //register
update($browser.getUrl());
- copy(location, lastLocation);
- scope.$eval();
- })(); //initialize
+ }))(); //initialize
- this.$onEval(PRIORITY_FIRST, sync);
- this.$onEval(PRIORITY_LAST, updateBrowser);
+ this.$watch(sync);
return location;
@@ -94,6 +90,8 @@ angularServiceInject("$location", function($browser) {
*
* @description
* Updates the location object.
+ * Does not immediately update the browser
+ * Browser is updated at the end of $flush()
*
* Does not immediately update the browser. Instead the browser is updated at the end of $eval()
* cycle.
@@ -122,6 +120,8 @@ angularServiceInject("$location", function($browser) {
location.href = composeHref(location);
}
+ $browser.setUrl(location.href);
+ copy(location, lastLocation);
}
/**
@@ -188,34 +188,21 @@ angularServiceInject("$location", function($browser) {
if (!equals(location, lastLocation)) {
if (location.href != lastLocation.href) {
update(location.href);
- return;
- }
- if (location.hash != lastLocation.hash) {
- var hash = parseHash(location.hash);
- updateHash(hash.hashPath, hash.hashSearch);
} else {
- location.hash = composeHash(location);
- location.href = composeHref(location);
+ if (location.hash != lastLocation.hash) {
+ var hash = parseHash(location.hash);
+ updateHash(hash.hashPath, hash.hashSearch);
+ } else {
+ location.hash = composeHash(location);
+ location.href = composeHref(location);
+ }
+ update(location.href);
}
- update(location.href);
}
}
/**
- * If location has changed, update the browser
- * This method is called at the end of $eval() phase
- */
- function updateBrowser() {
- sync();
-
- if ($browser.getUrl() != location.href) {
- $browser.setUrl(location.href);
- copy(location, lastLocation);
- }
- }
-
- /**
* Compose href string from a location object
*
* @param {Object} loc The location object with all properties
diff --git a/src/service/route.js b/src/service/route.js
index 9534968a..e1d0e7be 100644
--- a/src/service/route.js
+++ b/src/service/route.js
@@ -62,7 +62,7 @@
</doc:scenario>
</doc:example>
*/
-angularServiceInject('$route', function(location, $updateView) {
+angularServiceInject('$route', function($location, $updateView) {
var routes = {},
onChange = [],
matcher = switchRouteMatcher,
@@ -207,66 +207,67 @@ angularServiceInject('$route', function(location, $updateView) {
function updateRoute(){
- var childScope, routeParams, pathParams, segmentMatch, key, redir;
+ var selectedRoute, pathParams, segmentMatch, key, redir;
+ if ($route.current && $route.current.scope) {
+ $route.current.scope.$destroy();
+ }
$route.current = null;
+ // Match a route
forEach(routes, function(rParams, rPath) {
if (!pathParams) {
- if (pathParams = matcher(location.hashPath, rPath)) {
- routeParams = rParams;
+ if (pathParams = matcher($location.hashPath, rPath)) {
+ selectedRoute = rParams;
}
}
});
- // "otherwise" fallback
- routeParams = routeParams || routes[null];
+ // No route matched; fallback to "otherwise" route
+ selectedRoute = selectedRoute || routes[null];
- if(routeParams) {
- if (routeParams.redirectTo) {
- if (isString(routeParams.redirectTo)) {
+ if(selectedRoute) {
+ if (selectedRoute.redirectTo) {
+ if (isString(selectedRoute.redirectTo)) {
// interpolate the redirectTo string
redir = {hashPath: '',
- hashSearch: extend({}, location.hashSearch, pathParams)};
+ hashSearch: extend({}, $location.hashSearch, pathParams)};
- forEach(routeParams.redirectTo.split(':'), function(segment, i) {
+ forEach(selectedRoute.redirectTo.split(':'), function(segment, i) {
if (i==0) {
redir.hashPath += segment;
} else {
segmentMatch = segment.match(/(\w+)(.*)/);
key = segmentMatch[1];
- redir.hashPath += pathParams[key] || location.hashSearch[key];
+ redir.hashPath += pathParams[key] || $location.hashSearch[key];
redir.hashPath += segmentMatch[2] || '';
delete redir.hashSearch[key];
}
});
} else {
// call custom redirectTo function
- redir = {hash: routeParams.redirectTo(pathParams, location.hash, location.hashPath,
- location.hashSearch)};
+ redir = {hash: selectedRoute.redirectTo(pathParams, $location.hash, $location.hashPath,
+ $location.hashSearch)};
}
- location.update(redir);
- $updateView(); //TODO this is to work around the $location<=>$browser issues
+ $location.update(redir);
return;
}
- childScope = createScope(parentScope);
- $route.current = extend({}, routeParams, {
- scope: childScope,
- params: extend({}, location.hashSearch, pathParams)
- });
+ $route.current = extend({}, selectedRoute);
+ $route.current.params = extend({}, $location.hashSearch, pathParams);
}
//fire onChange callbacks
- forEach(onChange, parentScope.$tryEval);
+ forEach(onChange, parentScope.$eval, parentScope);
- if (childScope) {
- childScope.$become($route.current.controller);
+ // Create the scope if we have mtched a route
+ if ($route.current) {
+ $route.current.scope = parentScope.$new($route.current.controller);
}
}
- this.$watch(function(){return dirty + location.hash;}, updateRoute);
+ this.$watch(function(){return dirty + $location.hash;}, updateRoute)();
return $route;
}, ['$location', '$updateView']);
diff --git a/src/service/updateView.js b/src/service/updateView.js
index 9ac7c1fb..b51e719b 100644
--- a/src/service/updateView.js
+++ b/src/service/updateView.js
@@ -35,8 +35,8 @@
* without angular knowledge and you may need to call '$updateView()' directly.
*
* Note: if you wish to update the view immediately (without delay), you can do so by calling
- * {@link angular.scope.$eval} at any time from your code:
- * <pre>scope.$root.$eval()</pre>
+ * {@link angular.scope.$apply} at any time from your code:
+ * <pre>scope.$apply()</pre>
*
* In unit-test mode the update is instantaneous and synchronous to simplify writing tests.
*
@@ -47,7 +47,7 @@ function serviceUpdateViewFactory($browser){
var scheduled;
function update(){
scheduled = false;
- rootScope.$eval();
+ rootScope.$flush();
}
return $browser.isMock ? update : function(){
if (!scheduled) {
diff --git a/src/service/xhr.bulk.js b/src/service/xhr.bulk.js
index d7fc7990..816336f8 100644
--- a/src/service/xhr.bulk.js
+++ b/src/service/xhr.bulk.js
@@ -82,6 +82,6 @@ angularServiceInject('$xhr.bulk', function($xhr, $error, $log){
}
});
};
- this.$onEval(PRIORITY_LAST, bulkXHR.flush);
+ this.$observe(bulkXHR.flush);
return bulkXHR;
}, ['$xhr', '$xhr.error', '$log']);