diff options
Diffstat (limited to 'src/ng')
| -rw-r--r-- | src/ng/rootScope.js | 51 | 
1 files changed, 43 insertions, 8 deletions
| diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js index 2bb965bb..ce0f8ad5 100644 --- a/src/ng/rootScope.js +++ b/src/ng/rootScope.js @@ -398,30 +398,40 @@ function $RootScopeProvider(){         *    {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the         *    collection will trigger a call to the `listener`.         * -       * @param {function(newCollection, oldCollection, scope)} listener a callback function that is -       *    fired with both the `newCollection` and `oldCollection` as parameters. -       *    The `newCollection` object is the newly modified data obtained from the `obj` expression -       *    and the `oldCollection` object is a copy of the former collection data. -       *    The `scope` refers to the current scope. +       * @param {function(newCollection, oldCollection, scope)} listener a callback function called +       *    when a change is detected. +       *    - The `newCollection` object is the newly modified data obtained from the `obj` expression +       *    - The `oldCollection` object is a copy of the former collection data. +       *      Due to performance considerations, the`oldCollection` value is computed only if the +       *      `listener` function declares two or more arguments. +       *    - The `scope` argument refers to the current scope.         *         * @returns {function()} Returns a de-registration function for this listener. When the         *    de-registration function is executed, the internal watch operation is terminated.         */        $watchCollection: function(obj, listener) {          var self = this; -        var oldValue; +        // the current value, updated on each dirty-check run          var newValue; +        // a shallow copy of the newValue from the last dirty-check run, +        // updated to match newValue during dirty-check run +        var oldValue; +        // a shallow copy of the newValue from when the last change happened +        var veryOldValue; +        // only track veryOldValue if the listener is asking for it +        var trackVeryOldValue = (listener.length > 1);          var changeDetected = 0;          var objGetter = $parse(obj);          var internalArray = [];          var internalObject = {}; +        var initRun = true;          var oldLength = 0;          function $watchCollectionWatch() {            newValue = objGetter(self);            var newLength, key; -          if (!isObject(newValue)) { +          if (!isObject(newValue)) { // if primitive              if (oldValue !== newValue) {                oldValue = newValue;                changeDetected++; @@ -487,7 +497,32 @@ function $RootScopeProvider(){          }          function $watchCollectionAction() { -          listener(newValue, oldValue, self); +          if (initRun) { +            initRun = false; +            listener(newValue, newValue, self); +          } else { +            listener(newValue, veryOldValue, self); +          } + +          // make a copy for the next time a collection is changed +          if (trackVeryOldValue) { +            if (!isObject(newValue)) { +              //primitive +              veryOldValue = newValue; +            } else if (isArrayLike(newValue)) { +              veryOldValue = new Array(newValue.length); +              for (var i = 0; i < newValue.length; i++) { +                veryOldValue[i] = newValue[i]; +              } +            } else { // if object +              veryOldValue = {}; +              for (var key in newValue) { +                if (hasOwnProperty.call(newValue, key)) { +                  veryOldValue[key] = newValue[key]; +                } +              } +            } +          }          }          return this.$watch($watchCollectionWatch, $watchCollectionAction); | 
