Skip to content
Permalink
Browse files

fix($parse): call once stable bind-once expressions with filter

When an expression has the following:
- Bind-once
- A stateless filter at the end
- Optionally an expression interceptor

Then call the filter once.

Closes: #14583
Closes: #14589
  • Loading branch information
lgalfaso committed May 11, 2016
1 parent 5d1e15c commit 3b5751dce8d6c699dc76e47cfa544c30b38b9771
Showing with 26 additions and 7 deletions.
  1. +14 −7 src/ng/parse.js
  2. +12 −0 test/ng/parseSpec.js
@@ -2050,14 +2050,20 @@ function $ParseProvider() {
}, listener, objectEquality, prettyPrintExpression);
}

function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {
function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {
var unwatch, lastValue;
return unwatch = scope.$watch(function oneTimeWatch(scope) {
if (parsedExpression.inputs) {
return unwatch = inputsWatchDelegate(scope, oneTimeListener, objectEquality, parsedExpression, prettyPrintExpression);
} else {
return unwatch = scope.$watch(oneTimeWatch, oneTimeListener, objectEquality);
}
function oneTimeWatch(scope) {
return parsedExpression(scope);
}, function oneTimeListener(value, old, scope) {
}
function oneTimeListener(value, old, scope) {
lastValue = value;
if (isFunction(listener)) {
listener.apply(this, arguments);
listener(value, old, scope);
}
if (isDefined(value)) {
scope.$$postDigest(function() {
@@ -2066,7 +2072,7 @@ function $ParseProvider() {
}
});
}
}, objectEquality);
}
}

function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {
@@ -2076,7 +2082,7 @@ function $ParseProvider() {
}, function oneTimeListener(value, old, scope) {
lastValue = value;
if (isFunction(listener)) {
listener.call(this, value, old, scope);
listener(value, old, scope);
}
if (isAllDefined(value)) {
scope.$$postDigest(function() {
@@ -2123,14 +2129,15 @@ function $ParseProvider() {
};

// Propagate $$watchDelegates other then inputsWatchDelegate
useInputs = !parsedExpression.inputs;
if (parsedExpression.$$watchDelegate &&
parsedExpression.$$watchDelegate !== inputsWatchDelegate) {
fn.$$watchDelegate = parsedExpression.$$watchDelegate;
fn.inputs = parsedExpression.inputs;
} else if (!interceptorFn.$stateful) {
// If there is an interceptor, but no watchDelegate then treat the interceptor like
// we treat filters - it is assumed to be a pure function unless flagged with $stateful
fn.$$watchDelegate = inputsWatchDelegate;
useInputs = !parsedExpression.inputs;
fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];
}

@@ -3232,6 +3232,18 @@ describe('parser', function() {
expect(fn()).toEqual(undefined);
}));

it('should invoke a stateless filter once when the parsed expression has an interceptor',
inject(function($parse, $rootScope) {
var countFilter = jasmine.createSpy();
var interceptor = jasmine.createSpy();
countFilter.and.returnValue(1);
$filterProvider.register('count', valueFn(countFilter));
$rootScope.foo = function() { return 1; };
$rootScope.$watch($parse(':: foo() | count', interceptor));
$rootScope.$digest();
expect(countFilter.calls.count()).toBe(1);
}));

describe('literal expressions', function() {
it('should mark an empty expressions as literal', inject(function($parse) {
expect($parse('').literal).toBe(true);

0 comments on commit 3b5751d

Please sign in to comment.
You can’t perform that action at this time.