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

Commit 91bb499

Browse files
committed
perf($interpolate): provide a simplified result for constant expressions
1 parent 7d70dcd commit 91bb499

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

benchmarks/largetable-bp/main.html

+8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<div>interpolation + fnInvocation: <input type="radio" ng-model="benchmarkType" value="interpolationFn"></div>
2020
<div>ngBind + filter: <input type="radio" ng-model="benchmarkType" value="ngBindFilter"></div>
2121
<div>interpolation + filter: <input type="radio" ng-model="benchmarkType" value="interpolationFilter"></div>
22+
<div>ngModel: <input type="radio" ng-model="benchmarkType" value="ngModel"></div>
2223

2324
<ng-switch on="benchmarkType">
2425
<baseline-binding-table ng-switch-when="baselineBinding">
@@ -77,6 +78,13 @@ <h2>interpolation with filter</h2>
7778
<span ng-repeat="column in row">{{column.i | noop}}:{{column.j | noop}}|</span>
7879
</div>
7980
</div>
81+
<div ng-switch-when="ngModel">
82+
<h2>ngModels</h2>
83+
<div ng-repeat="row in data">
84+
<input type="text" ng-model="row.i" name="constName" />
85+
<input type="text" ng-model="row.j" />
86+
</div>
87+
</div>
8088
</ng-switch>
8189
</div>
8290
</div>

src/ng/interpolate.js

+26
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,19 @@ function $InterpolateProvider() {
8888
return '\\\\\\' + ch;
8989
}
9090

91+
//TODO: this is the same as the constantWatchDelegate in parse.js
92+
function constantWatchDelegate(scope, listener, objectEquality, constantInterp) {
93+
var unwatch;
94+
return unwatch = scope.$watch(function constantInterpolateWatch(scope) {
95+
return constantInterp(scope);
96+
}, function constantInterpolateListener(value, old, scope) {
97+
if (isFunction(listener)) {
98+
listener.apply(this, arguments);
99+
}
100+
unwatch();
101+
}, objectEquality);
102+
}
103+
91104
/**
92105
* @ngdoc service
93106
* @name $interpolate
@@ -183,6 +196,19 @@ function $InterpolateProvider() {
183196
* - `context`: evaluation context for all expressions embedded in the interpolated text
184197
*/
185198
function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
199+
// Provide a quick exit and simplified result function for text with no interpolation
200+
if (!text.length || text.indexOf(startSymbol) === -1) {
201+
var constantInterp;
202+
if (!mustHaveExpression) {
203+
var unescapedText = unescapeText(text);
204+
constantInterp = function constantInterpolationFn() { return unescapedText; };
205+
constantInterp.exp = text;
206+
constantInterp.expressions = [];
207+
constantInterp.$$watchDelegate = constantWatchDelegate;
208+
}
209+
return constantInterp;
210+
}
211+
186212
allOrNothing = !!allOrNothing;
187213
var startIndex,
188214
endIndex,

test/ng/interpolateSpec.js

+23
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,28 @@ describe('$interpolate', function() {
125125

126126
expect($rootScope.$countWatchers()).toBe(0);
127127
}));
128+
129+
it('should stop watching strings with no expressions after first execution',
130+
inject(function($interpolate, $rootScope) {
131+
var spy = jasmine.createSpy();
132+
$rootScope.$watch($interpolate('foo'), spy);
133+
$rootScope.$digest();
134+
expect(($rootScope.$$watchers || []).length).toBe(0);
135+
expect(spy).toHaveBeenCalledWith('foo', 'foo', $rootScope);
136+
expect(spy.calls.length).toBe(1);
137+
})
138+
);
139+
140+
it('should stop watching strings with only constant expressions after first execution',
141+
inject(function($interpolate, $rootScope) {
142+
var spy = jasmine.createSpy();
143+
$rootScope.$watch($interpolate('foo {{42}}'), spy);
144+
$rootScope.$digest();
145+
expect(($rootScope.$$watchers || []).length).toBe(0);
146+
expect(spy).toHaveBeenCalledWith('foo 42', 'foo 42', $rootScope);
147+
expect(spy.calls.length).toBe(1);
148+
})
149+
);
128150
});
129151

130152
describe('interpolation escaping', function() {
@@ -135,6 +157,7 @@ describe('$interpolate', function() {
135157

136158

137159
it('should support escaping interpolation signs', inject(function($interpolate) {
160+
expect($interpolate('\\{\\{')(obj)).toBe('{{');
138161
expect($interpolate('{{foo}} \\{\\{bar\\}\\}')(obj)).toBe('Hello {{bar}}');
139162
expect($interpolate('\\{\\{foo\\}\\} {{bar}}')(obj)).toBe('{{foo}} World');
140163
}));

0 commit comments

Comments
 (0)