From e641d0c5e9b4fcbbef5dbfeb30fd72ade3163ae9 Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Thu, 3 Aug 2017 01:04:37 -0700 Subject: [PATCH] perf($rootScope): allow $watchCollection use of expression input watching By adding a $$pure flag to the $watchCollectionInterceptor to shallow watch all inputs regardless of type when watching an object/array literal. --- src/ng/parse.js | 9 +++++++-- src/ng/rootScope.js | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ng/parse.js b/src/ng/parse.js index f173eed527d8..9f8621440cf3 100644 --- a/src/ng/parse.js +++ b/src/ng/parse.js @@ -1944,6 +1944,7 @@ function $ParseProvider() { return second(first(value)); } chainedInterceptor.$stateful = first.$stateful || second.$stateful; + chainedInterceptor.$$pure = first.$$pure && second.$$pure; return chainedInterceptor; } @@ -1979,14 +1980,18 @@ function $ParseProvider() { // If the expression itself has no inputs then use the full expression as an input. if (!interceptorFn.$stateful) { useInputs = !parsedExpression.inputs; - fn.inputs = (parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression]).map(function(e) { + fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression]; + + if (!interceptorFn.$$pure) { + fn.inputs = fn.inputs.map(function(e) { // Remove the isPure flag of inputs when it is not absolute because they are now wrapped in a - // potentially non-pure interceptor function. + // non-pure interceptor function. if (e.isPure === PURITY_RELATIVE) { return function depurifier(s) { return e(s); }; } return e; }); + } } return addWatchDelegate(fn); diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js index bb7f83b42462..5bb68c732846 100644 --- a/src/ng/rootScope.js +++ b/src/ng/rootScope.js @@ -581,7 +581,11 @@ function $RootScopeProvider() { * de-registration function is executed, the internal watch operation is terminated. */ $watchCollection: function(obj, listener) { - $watchCollectionInterceptor.$stateful = true; + // Mark the interceptor as + // ... $$pure when literal since the instance will change when any input changes + $watchCollectionInterceptor.$$pure = $parse(obj).literal; + // ... $stateful when non-literal since we must read the state of the collection + $watchCollectionInterceptor.$stateful = !$watchCollectionInterceptor.$$pure; var self = this; // the current value, updated on each dirty-check run