Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 1caf0b6

Browse files
committed
fix($parse): evaluate once simple expressions in interpolations
For simple expressions without filters that have a stateless interceptor then handle the 2nd phase parse evaluation using `inputs`. TL;DR This fixes the issue that interpolated simple expressions were evaluated twice within one digest loop. Long version, things happen in the following order: * There was an overhaul on $interpolate, this overhaul changed $parse and incorporated the concept of an interceptor. * Optimization on $parse landed so expressions that have filters without parameters (or the parameters are constants) would be evaluated in 2 phases, first to evaluate the expression sans the filter evaluation and then with the filter evaluation. This also used interceptors [the second evaluation issue was added here] * More optimizations on $parse landed and now expressions could be evaluated in 2 phases. One to get all the possible values that could change (lets call this state), the state was checked by $watch to know if an expression changed. The second to continue the evaluation (as long as this state is provided). This, once again, used interceptors The last change, was supposed to fix the issue, but there was an assumption in the existing code that the code would always generate the 2 phases functions, but that is not true. If the expression is simple enough (just like the one in your case) then the 2-phase evaluations functions are not generated. In this case, if a stateless interceptor was added (just like what $interpolate adds) then the state was not used and you see the function being evaluated twice. This explains why, if you change the expression from `Hello {{log('A')}} {{log('B')}}!` to `Hello {{log('A') + ' ' + log('B')}}!`, then the repetition is not there. Closes #12983 Closes #13002
1 parent 9f716dd commit 1caf0b6

File tree

2 files changed

+11
-1
lines changed

2 files changed

+11
-1
lines changed

src/ng/parse.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1906,13 +1906,14 @@ function $ParseProvider() {
19061906
function addInterceptor(parsedExpression, interceptorFn) {
19071907
if (!interceptorFn) return parsedExpression;
19081908
var watchDelegate = parsedExpression.$$watchDelegate;
1909+
var useInputs = false;
19091910

19101911
var regularWatch =
19111912
watchDelegate !== oneTimeLiteralWatchDelegate &&
19121913
watchDelegate !== oneTimeWatchDelegate;
19131914

19141915
var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) {
1915-
var value = parsedExpression(scope, locals, assign, inputs);
1916+
var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs);
19161917
return interceptorFn(value, scope, locals);
19171918
} : function oneTimeInterceptedExpression(scope, locals, assign, inputs) {
19181919
var value = parsedExpression(scope, locals, assign, inputs);
@@ -1930,6 +1931,7 @@ function $ParseProvider() {
19301931
// If there is an interceptor, but no watchDelegate then treat the interceptor like
19311932
// we treat filters - it is assumed to be a pure function unless flagged with $stateful
19321933
fn.$$watchDelegate = inputsWatchDelegate;
1934+
useInputs = !parsedExpression.inputs;
19331935
fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];
19341936
}
19351937

test/ng/compileSpec.js

+8
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,14 @@ describe('$compile', function() {
947947
expect(child).toHaveClass('log'); // merged from replace directive template
948948
}));
949949

950+
it('should interpolate the values once per digest',
951+
inject(function($compile, $rootScope, log) {
952+
element = $compile('<div>{{log("A")}} foo {{::log("B")}}</div>')($rootScope);
953+
$rootScope.log = log;
954+
$rootScope.$digest();
955+
expect(log).toEqual('A; B; A; B');
956+
}));
957+
950958
it('should update references to replaced jQuery context', function() {
951959
module(function($compileProvider) {
952960
$compileProvider.directive('foo', function() {

0 commit comments

Comments
 (0)