mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 07:40:22 +00:00
feta(scope): watch object refference or equality
Breaks: Must set $watch equality to true for the old behavior
This commit is contained in:
parent
ffa8441886
commit
d6e3e1baab
3 changed files with 46 additions and 26 deletions
|
|
@ -592,7 +592,7 @@ function classDirective(name, selector) {
|
|||
if (isObject(newVal) && !isArray(newVal))
|
||||
newVal = map(newVal, function(v, k) { if (v) return k });
|
||||
if (newVal) element.addClass(isArray(newVal) ? newVal.join(' ') : newVal); }
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -837,7 +837,7 @@ var ngStyleDirective = valueFn(function(scope, element, attr) {
|
|||
forEach(oldStyles, function(val, style) { element.css(style, '');});
|
||||
}
|
||||
if (newStyles) element.css(newStyles);
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,15 @@
|
|||
* event processing life-cycle. See {@link guide/dev_guide.scopes developer guide on scopes}.
|
||||
*/
|
||||
function $RootScopeProvider(){
|
||||
var TTL = 10;
|
||||
|
||||
this.ttl = function(value) {
|
||||
if (arguments.length) {
|
||||
TTL = value;
|
||||
}
|
||||
return TTL;
|
||||
}
|
||||
|
||||
this.$get = ['$injector', '$exceptionHandler', '$parse',
|
||||
function( $injector, $exceptionHandler, $parse) {
|
||||
|
||||
|
|
@ -248,9 +257,11 @@ function $RootScopeProvider(){
|
|||
*
|
||||
* - `string`: Evaluated as {@link guide/dev_guide.expressions expression}
|
||||
* - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.
|
||||
*
|
||||
* @param {boolean=} objectEquality Compare object for equality rather then for refference.
|
||||
* @returns {function()} Returns a deregistration function for this listener.
|
||||
*/
|
||||
$watch: function(watchExp, listener) {
|
||||
$watch: function(watchExp, listener, objectEquality) {
|
||||
var scope = this,
|
||||
get = compileToFn(watchExp, 'watch'),
|
||||
array = scope.$$watchers,
|
||||
|
|
@ -258,7 +269,8 @@ function $RootScopeProvider(){
|
|||
fn: listener,
|
||||
last: initWatchVal,
|
||||
get: get,
|
||||
exp: watchExp
|
||||
exp: watchExp,
|
||||
eq: !!objectEquality
|
||||
};
|
||||
|
||||
// in the case user pass string, we need to compile it, do we really need this ?
|
||||
|
|
@ -332,7 +344,7 @@ function $RootScopeProvider(){
|
|||
watchers,
|
||||
asyncQueue,
|
||||
length,
|
||||
dirty, ttl = 100,
|
||||
dirty, ttl = TTL,
|
||||
next, current, target = this,
|
||||
watchLog = [],
|
||||
logIdx, logMsg;
|
||||
|
|
@ -359,9 +371,13 @@ function $RootScopeProvider(){
|
|||
watch = watchers[length];
|
||||
// Most common watches are on primitives, in which case we can short
|
||||
// circuit it with === operator, only when === fails do we use .equals
|
||||
if ((value = watch.get(current)) !== (last = watch.last) && !equals(value, last)) {
|
||||
if ((value = watch.get(current)) !== (last = watch.last) &&
|
||||
!(watch.eq
|
||||
? equals(value, last)
|
||||
: (typeof value == 'number' && typeof last == 'number'
|
||||
&& isNaN(value) && isNaN(last)))) {
|
||||
dirty = true;
|
||||
watch.last = copy(value);
|
||||
watch.last = watch.eq ? copy(value) : value;
|
||||
watch.fn(value, ((last === initWatchVal) ? value : last), current);
|
||||
if (ttl < 5) {
|
||||
logIdx = 4 - ttl;
|
||||
|
|
@ -390,7 +406,7 @@ function $RootScopeProvider(){
|
|||
} while ((current = next));
|
||||
|
||||
if(dirty && !(ttl--)) {
|
||||
throw Error('100 $digest() iterations reached. Aborting!\n' +
|
||||
throw Error(TTL + ' $digest() iterations reached. Aborting!\n' +
|
||||
'Watchers fired in the last 5 iterations: ' + toJson(watchLog));
|
||||
}
|
||||
} while (dirty || asyncQueue.length);
|
||||
|
|
|
|||
|
|
@ -189,22 +189,26 @@ describe('Scope', function() {
|
|||
}));
|
||||
|
||||
|
||||
it('should prevent infinite recursion and print watcher expression',inject(
|
||||
function($rootScope) {
|
||||
$rootScope.$watch('a', function() {$rootScope.b++;});
|
||||
$rootScope.$watch('b', function() {$rootScope.a++;});
|
||||
$rootScope.a = $rootScope.b = 0;
|
||||
it('should prevent infinite recursion and print watcher expression',function() {
|
||||
module(function($rootScopeProvider) {
|
||||
$rootScopeProvider.ttl(100);
|
||||
});
|
||||
inject(function($rootScope) {
|
||||
$rootScope.$watch('a', function() {$rootScope.b++;});
|
||||
$rootScope.$watch('b', function() {$rootScope.a++;});
|
||||
$rootScope.a = $rootScope.b = 0;
|
||||
|
||||
expect(function() {
|
||||
$rootScope.$digest();
|
||||
}).toThrow('100 $digest() iterations reached. Aborting!\n'+
|
||||
'Watchers fired in the last 5 iterations: ' +
|
||||
'[["a; newVal: 96; oldVal: 95","b; newVal: 97; oldVal: 96"],' +
|
||||
'["a; newVal: 97; oldVal: 96","b; newVal: 98; oldVal: 97"],' +
|
||||
'["a; newVal: 98; oldVal: 97","b; newVal: 99; oldVal: 98"],' +
|
||||
'["a; newVal: 99; oldVal: 98","b; newVal: 100; oldVal: 99"],' +
|
||||
'["a; newVal: 100; oldVal: 99","b; newVal: 101; oldVal: 100"]]');
|
||||
}));
|
||||
expect(function() {
|
||||
$rootScope.$digest();
|
||||
}).toThrow('100 $digest() iterations reached. Aborting!\n'+
|
||||
'Watchers fired in the last 5 iterations: ' +
|
||||
'[["a; newVal: 96; oldVal: 95","b; newVal: 97; oldVal: 96"],' +
|
||||
'["a; newVal: 97; oldVal: 96","b; newVal: 98; oldVal: 97"],' +
|
||||
'["a; newVal: 98; oldVal: 97","b; newVal: 99; oldVal: 98"],' +
|
||||
'["a; newVal: 99; oldVal: 98","b; newVal: 100; oldVal: 99"],' +
|
||||
'["a; newVal: 100; oldVal: 99","b; newVal: 101; oldVal: 100"]]');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should prevent infinite recursion and print print watcher function name or body',
|
||||
|
|
@ -241,11 +245,11 @@ describe('Scope', function() {
|
|||
$rootScope.$watch('a', function(value) {
|
||||
log +='.';
|
||||
expect(value).toBe($rootScope.a);
|
||||
});
|
||||
}, true);
|
||||
$rootScope.$watch('b', function(value) {
|
||||
log +='!';
|
||||
expect(value).toBe($rootScope.b);
|
||||
});
|
||||
}, true);
|
||||
$rootScope.$digest();
|
||||
log = '';
|
||||
|
||||
|
|
@ -331,7 +335,7 @@ describe('Scope', function() {
|
|||
$rootScope.$watch(function() { return undefined;}, logger);
|
||||
$rootScope.$watch(function() { return '';}, logger);
|
||||
$rootScope.$watch(function() { return false;}, logger);
|
||||
$rootScope.$watch(function() { return {};}, logger);
|
||||
$rootScope.$watch(function() { return {};}, logger, true);
|
||||
$rootScope.$watch(function() { return 23;}, logger);
|
||||
|
||||
$rootScope.$digest();
|
||||
|
|
|
|||
Loading…
Reference in a new issue