aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Minar2012-01-21 00:01:44 -0800
committerIgor Minar2012-01-23 22:33:28 -0800
commit7da2bdb82a72dffc8c72c1becf6f62aae52d32ce (patch)
tree72abcd1baeb8ee026f8f30843ce2b9d7edf2b27e
parented78f0d830b22eb8f280e841cde6287b678fc914 (diff)
downloadangular.js-7da2bdb82a72dffc8c72c1becf6f62aae52d32ce.tar.bz2
fix(scope): support watching functions
currently we run into infinite digest if a function is being watched as an expression. This is because we generate bound function wrapper when the watch is processed via parser. I'm not too keen on the solution because it relies on the unbound fn that is being exposed for other reasons, but I can't think of a better way to deal with this right now
-rw-r--r--src/Angular.js39
-rw-r--r--test/service/scopeSpec.js16
2 files changed, 37 insertions, 18 deletions
diff --git a/src/Angular.js b/src/Angular.js
index 3f272ec2..17ede3aa 100644
--- a/src/Angular.js
+++ b/src/Angular.js
@@ -655,28 +655,31 @@ function equals(o1, o2) {
if (o1 === null || o2 === null) return false;
if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
- if (t1 == t2 && t1 == 'object') {
- if (isArray(o1)) {
- if ((length = o1.length) == o2.length) {
- for(key=0; key<length; key++) {
- if (!equals(o1[key], o2[key])) return false;
+ if (t1 == t2) {
+ if (t1 == 'object') {
+ if (isArray(o1)) {
+ if ((length = o1.length) == o2.length) {
+ for(key=0; key<length; key++) {
+ if (!equals(o1[key], o2[key])) return false;
+ }
+ return true;
}
- return true;
- }
- } else {
- if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;
- keySet = {};
- for(key in o1) {
- if (key.charAt(0) !== '$' && !isFunction(o1[key]) && !equals(o1[key], o2[key])) {
- return false;
+ } else {
+ if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;
+ keySet = {};
+ for(key in o1) {
+ if (key.charAt(0) !== '$' && !isFunction(o1[key]) && !equals(o1[key], o2[key])) {
+ return false;
+ }
+ keySet[key] = true;
}
- keySet[key] = true;
- }
- for(key in o2) {
- if (!keySet[key] && key.charAt(0) !== '$' && !isFunction(o2[key])) return false;
+ for(key in o2) {
+ if (!keySet[key] && key.charAt(0) !== '$' && !isFunction(o2[key])) return false;
+ }
+ return true;
}
- return true;
}
+ if (t1 == 'function' && o1.$unboundFn) return o1.$unboundFn === o2.$unboundFn;
}
return false;
}
diff --git a/test/service/scopeSpec.js b/test/service/scopeSpec.js
index 30805684..b1b870f4 100644
--- a/test/service/scopeSpec.js
+++ b/test/service/scopeSpec.js
@@ -248,6 +248,22 @@ describe('Scope', function() {
}));
+ it('should watch functions', function() {
+ module(provideLog);
+ inject(function($rootScope, log) {
+ $rootScope.fn = function() {return 'a'};
+ $rootScope.$watch('fn', function(scope, fn) {
+ log(fn());
+ });
+ $rootScope.$digest();
+ expect(log).toEqual('a');
+ $rootScope.fn = function() {return 'b'};
+ $rootScope.$digest();
+ expect(log).toEqual('a; b');
+ })
+ });
+
+
it('should prevent $digest recursion', inject(function($rootScope) {
var callCount = 0;
$rootScope.$watch('name', function() {