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

Commit e8d7496

Browse files
committed
perf($parse): improve performance of assignment expressions
There was a ~5% improvement in the added `parsed-expressions-bp/assignment` benchmark (which only contains assignment expressions). In real-world applications, the time spent in assignment expressions will be a tiny fragment of the overall processing time, though. Closes #14957
1 parent 49f0777 commit e8d7496

File tree

3 files changed

+57
-35
lines changed

3 files changed

+57
-35
lines changed

benchmarks/parsed-expressions-bp/app.js

+9-10
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ app.directive('bmPeWatch', function() {
2323
return function($scope, $element, $attrs) {
2424
$scope.$watch($attrs.bmPeWatch, function(val) {
2525
$element.text(val);
26-
2726
});
2827
};
2928
}
@@ -55,19 +54,19 @@ app.controller('DataController', function($scope, $rootScope) {
5554

5655
var star = '*';
5756

58-
$scope.func = function() { return star;};
57+
$scope.func = function() { return star; };
5958

6059
for (var i = 0; i < totalRows; i++) {
6160
data.push({
6261
index: i,
63-
odd: i % 2 === 0,
64-
even: i % 2 === 1,
65-
str0: "foo-" + Math.random() * Date.now(),
66-
str1: "bar-" + Math.random() * Date.now(),
67-
str2: "baz-" + Math.random() * Date.now(),
68-
num0: Math.random() * Date.now(),
69-
num1: Math.random() * Date.now(),
70-
num2: Math.random() * Date.now(),
62+
odd: i % 2 === 0,
63+
even: i % 2 === 1,
64+
str0: 'foo-' + Math.random() * Date.now(),
65+
str1: 'bar-' + Math.random() * Date.now(),
66+
str2: 'baz-' + Math.random() * Date.now(),
67+
num0: Math.random() * Date.now(),
68+
num1: Math.random() * Date.now(),
69+
num2: Math.random() * Date.now(),
7170
date0: new Date(Math.random() * Date.now()),
7271
date1: new Date(Math.random() * Date.now()),
7372
date2: new Date(Math.random() * Date.now()),

benchmarks/parsed-expressions-bp/main.html

+17
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@
5252
<label for="functionCalls">Function calls</label>
5353
</li>
5454

55+
<li>
56+
<input type="radio" ng-model="expressionType" value="assignment" id="assignment">
57+
<label for="assignment">Assignment</label>
58+
</li>
59+
5560
<li>
5661
<input type="radio" ng-model="expressionType" value="objectLiterals" id="objectLiterals">
5762
<label for="objectLiterals">Object Literals</label>
@@ -197,6 +202,18 @@
197202
<span bm-pe-watch="row.func(row.func(), row.func())"></span>
198203
</li>
199204

205+
<li ng-switch-when="assignment" ng-repeat="(rowIdx, row) in ::data">
206+
<span bm-pe-watch="row.foo = row.str0"></span>
207+
<span bm-pe-watch="row.obj.foo = row.str1"></span>
208+
<span bm-pe-watch="row.obj.obj.foo = row.str2"></span>
209+
<span bm-pe-watch="row['bar'] = row.num0"></span>
210+
<span bm-pe-watch="row.obj['bar'] = row.num1"></span>
211+
<span bm-pe-watch="row.obj.obj['bar'] = row.num2"></span>
212+
<span bm-pe-watch="row[0] = row.date0"></span>
213+
<span bm-pe-watch="row.obj[0] = row.date1"></span>
214+
<span bm-pe-watch="row.obj.obj[0] = row.date2"></span>
215+
</li>
216+
200217
<li ng-switch-when="objectLiterals" ng-repeat="(rowIdx, row) in ::data">
201218
<span bm-pe-watch-literal="{foo: rowIdx}"></span>
202219
<span bm-pe-watch-literal="{foo: row, bar: rowIdx}"></span>

src/ng/parse.js

+31-25
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,25 @@
1313

1414
var $parseMinErr = minErr('$parse');
1515

16+
var ARRAY_CTOR = [].constructor;
17+
var BOOLEAN_CTOR = (false).constructor;
18+
var FUNCTION_CTOR = Function.constructor;
19+
var NUMBER_CTOR = (0).constructor;
20+
var OBJECT_CTOR = {}.constructor;
21+
var STRING_CTOR = ''.constructor;
22+
var ARRAY_CTOR_PROTO = ARRAY_CTOR.prototype;
23+
var BOOLEAN_CTOR_PROTO = BOOLEAN_CTOR.prototype;
24+
var FUNCTION_CTOR_PROTO = FUNCTION_CTOR.prototype;
25+
var NUMBER_CTOR_PROTO = NUMBER_CTOR.prototype;
26+
var OBJECT_CTOR_PROTO = OBJECT_CTOR.prototype;
27+
var STRING_CTOR_PROTO = STRING_CTOR.prototype;
28+
29+
var CALL = FUNCTION_CTOR_PROTO.call;
30+
var APPLY = FUNCTION_CTOR_PROTO.apply;
31+
var BIND = FUNCTION_CTOR_PROTO.bind;
32+
33+
var objectValueOf = OBJECT_CTOR_PROTO.valueOf;
34+
1635
// Sandboxing Angular Expressions
1736
// ------------------------------
1837
// Angular expressions are generally considered safe because these expressions only have direct
@@ -93,10 +112,6 @@ function ensureSafeObject(obj, fullExpression) {
93112
return obj;
94113
}
95114

96-
var CALL = Function.prototype.call;
97-
var APPLY = Function.prototype.apply;
98-
var BIND = Function.prototype.bind;
99-
100115
function ensureSafeFunction(obj, fullExpression) {
101116
if (obj) {
102117
if (obj.constructor === obj) {
@@ -113,25 +128,18 @@ function ensureSafeFunction(obj, fullExpression) {
113128

114129
function ensureSafeAssignContext(obj, fullExpression) {
115130
if (obj) {
116-
var booleanConstructor = (false).constructor;
117-
var numberConstructor = (0).constructor;
118-
var stringConstructor = ''.constructor;
119-
var objectConstructor = {}.constructor;
120-
var arrayConstructor = [].constructor;
121-
var functionConstructor = Function.constructor;
122-
123-
if (obj === booleanConstructor ||
124-
obj === numberConstructor ||
125-
obj === stringConstructor ||
126-
obj === objectConstructor ||
127-
obj === arrayConstructor ||
128-
obj === functionConstructor ||
129-
obj === booleanConstructor.prototype ||
130-
obj === numberConstructor.prototype ||
131-
obj === stringConstructor.prototype ||
132-
obj === objectConstructor.prototype ||
133-
obj === arrayConstructor.prototype ||
134-
obj === functionConstructor.prototype) {
131+
if (obj === ARRAY_CTOR ||
132+
obj === BOOLEAN_CTOR ||
133+
obj === FUNCTION_CTOR ||
134+
obj === NUMBER_CTOR ||
135+
obj === OBJECT_CTOR ||
136+
obj === STRING_CTOR ||
137+
obj === ARRAY_CTOR_PROTO ||
138+
obj === BOOLEAN_CTOR_PROTO ||
139+
obj === FUNCTION_CTOR_PROTO ||
140+
obj === NUMBER_CTOR_PROTO ||
141+
obj === OBJECT_CTOR_PROTO ||
142+
obj === STRING_CTOR_PROTO) {
135143
throw $parseMinErr('isecaf',
136144
'Assigning to a constructor or its prototype is disallowed! Expression: {0}',
137145
fullExpression);
@@ -1794,8 +1802,6 @@ function isPossiblyDangerousMemberName(name) {
17941802
return name === 'constructor';
17951803
}
17961804

1797-
var objectValueOf = Object.prototype.valueOf;
1798-
17991805
function getValueOf(value) {
18001806
return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);
18011807
}

0 commit comments

Comments
 (0)