diff options
| author | Misko Hevery | 2011-08-12 14:32:25 -0700 | 
|---|---|---|
| committer | Igor Minar | 2011-08-14 21:32:15 -0700 | 
| commit | 34f174066f1aa70dba0f97942580082169348200 (patch) | |
| tree | 98dc485ab2963109689bc6fef89cf7123690b4e6 /src/Scope.js | |
| parent | 530dc412c4d4700268e52920e6114f7941171706 (diff) | |
| download | angular.js-34f174066f1aa70dba0f97942580082169348200.tar.bz2 | |
refactor(scope): non-recursive $digest method
Diffstat (limited to 'src/Scope.js')
| -rw-r--r-- | src/Scope.js | 87 | 
1 files changed, 47 insertions, 40 deletions
| diff --git a/src/Scope.js b/src/Scope.js index 244bd7c4..b50d6273 100644 --- a/src/Scope.js +++ b/src/Scope.js @@ -317,60 +317,67 @@ Scope.prototype = {         expect(scope.counter).toEqual(1);       </pre>     * -   * @returns {number} number of {@link angular.scope.$watch listeners} which fired. -   *     */    $digest: function() { -    var child, -        watch, value, last, -        watchers = this.$$watchers, -        asyncQueue = this.$$asyncQueue, -        length, count = 0, -        dirtyCount, ttl = 100, -        recheck = !this.$parent || !this.$parent.$$phase; +    var watch, value, last, next, +        watchers, +        asyncQueue, +        length, +        dirty, ttl = 100, +        scope;      if (this.$$phase) {        throw Error(this.$$phase + ' already in progress');      } -    this.$$phase = '$digest';      do { -      while(asyncQueue.length) { -        try { -          this.$eval(asyncQueue.shift()); -        } catch (e) { -          this.$service('$exceptionHandler')(e); -        } -      } -      dirtyCount = 0; -      if (watchers) { -        // process our watches -        length = watchers.length; -        while (length--) { + +      dirty = false; +      scope = this; +      do { +        scope.$$phase = '$digest'; +        asyncQueue = scope.$$asyncQueue; +        while(asyncQueue.length) {            try { -            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(this)) !== (last = watch.last) && !equals(value, last)) { -              dirtyCount++; -              watch.fn(this, watch.last = copy(value), last); -            } +            scope.$eval(asyncQueue.shift());            } catch (e) { -            this.$service('$exceptionHandler')(e); +            scope.$service('$exceptionHandler')(e);            }          } -      } -      child = this.$$childHead; -      while(child) { -        dirtyCount += child.$digest(); -        child = child.$$nextSibling; -      } -      count += dirtyCount; +        if (watchers = scope.$$watchers) { +          // process our watches +          length = watchers.length; +          while (length--) { +            try { +              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(scope)) !== (last = watch.last) && !equals(value, last)) { +                dirty = true; +                watch.fn(scope, watch.last = copy(value), last); +              } +            } catch (e) { +              scope.$service('$exceptionHandler')(e); +            } +          } +        } + + +        scope.$$phase = null; +        // find the next scope in traversal. +        if (!(next = scope.$$childHead || scope.$$nextSibling) && scope !== this) { +          do { +            scope = scope.$parent; +            if (scope == this || (next = scope.$$nextSibling)) { +              break; +            } +          } while (scope !== this); +        } +      } while (scope = next); +        if(!(ttl--)) {          throw Error('100 $digest() iterations reached. Aborting!');        } -    } while (recheck && dirtyCount); -    this.$$phase = null; -    return count; +    } while (dirty);    },    /** | 
