Skip to content

Commit 0c3b65a

Browse files
committed
perf($parse): use no-proto maps as caches and avoid hasOwnProperty checks
1 parent e43541f commit 0c3b65a

File tree

2 files changed

+18
-29
lines changed

2 files changed

+18
-29
lines changed

src/ng/parse.js

+17-28
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function ensureSafeFunction(obj, fullExpression) {
8080
}
8181
}
8282

83-
var OPERATORS = {
83+
var OPERATORS = extend(createMap(), {
8484
/* jshint bitwise : false */
8585
'null':function(){return null;},
8686
'true':function(){return true;},
@@ -118,7 +118,7 @@ var OPERATORS = {
118118
// '|':function(self, locals, a,b){return a|b;},
119119
'|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},
120120
'!':function(self, locals, a){return !a(self, locals);}
121-
};
121+
});
122122
/* jshint bitwise: true */
123123
var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
124124

@@ -301,9 +301,10 @@ Lexer.prototype = {
301301
text: ident
302302
};
303303

304-
// OPERATORS is our own object so we don't need to use special hasOwnPropertyFn
305-
if (OPERATORS.hasOwnProperty(ident)) {
306-
token.fn = OPERATORS[ident];
304+
var fn = OPERATORS[ident];
305+
306+
if (fn) {
307+
token.fn = fn;
307308
token.constant = true;
308309
} else {
309310
var getter = getterFn(ident, this.options, this.text);
@@ -834,7 +835,7 @@ function setter(obj, path, setValue, fullExp) {
834835
return setValue;
835836
}
836837

837-
var getterFnCache = {};
838+
var getterFnCache = createMap();
838839

839840
/**
840841
* Implementation of the "Black Hole" variant from:
@@ -875,16 +876,12 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp) {
875876
}
876877

877878
function getterFn(path, options, fullExp) {
878-
// Check whether the cache has this getter already.
879-
// We can use hasOwnProperty directly on the cache because we ensure,
880-
// see below, that the cache never stores a path called 'hasOwnProperty'
881-
if (getterFnCache.hasOwnProperty(path)) {
882-
return getterFnCache[path];
883-
}
879+
var fn = getterFnCache[path];
880+
881+
if (fn) return fn;
884882

885883
var pathKeys = path.split('.'),
886-
pathKeysLength = pathKeys.length,
887-
fn;
884+
pathKeysLength = pathKeys.length;
888885

889886
// http://jsperf.com/angularjs-parse-getter/6
890887
if (options.csp) {
@@ -923,11 +920,7 @@ function getterFn(path, options, fullExp) {
923920
fn = evaledFnGetter;
924921
}
925922

926-
// Only cache the value if it's not going to mess up the cache object
927-
// This is more performant that using Object.prototype.hasOwnProperty.call
928-
if (path !== 'hasOwnProperty') {
929-
getterFnCache[path] = fn;
930-
}
923+
getterFnCache[path] = fn;
931924
return fn;
932925
}
933926

@@ -984,7 +977,7 @@ function getterFn(path, options, fullExp) {
984977
* service.
985978
*/
986979
function $ParseProvider() {
987-
var cache = {};
980+
var cache = createMap();
988981

989982
var $parseOptions = {
990983
csp: false
@@ -1001,9 +994,9 @@ function $ParseProvider() {
1001994
case 'string':
1002995
cacheKey = exp = exp.trim();
1003996

1004-
if (cache.hasOwnProperty(cacheKey)) {
1005-
parsedExpression = cache[cacheKey];
1006-
} else {
997+
parsedExpression = cache[cacheKey];
998+
999+
if (!parsedExpression) {
10071000
if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
10081001
oneTime = true;
10091002
exp = exp.substring(2);
@@ -1016,11 +1009,7 @@ function $ParseProvider() {
10161009
if (parsedExpression.constant) parsedExpression.$$watchDelegate = constantWatch;
10171010
else if (oneTime) parsedExpression.$$watchDelegate = oneTimeWatch;
10181011

1019-
if (cacheKey !== 'hasOwnProperty') {
1020-
// Only cache the value if it's not going to mess up the cache object
1021-
// This is more performant that using Object.prototype.hasOwnProperty.call
1022-
cache[cacheKey] = parsedExpression;
1023-
}
1012+
cache[cacheKey] = parsedExpression;
10241013
}
10251014
return addInterceptor(parsedExpression, interceptorFn);
10261015

test/ng/parseSpec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ describe('parser', function() {
55
beforeEach(function() {
66
/* global getterFnCache: true */
77
// clear cache
8-
getterFnCache = {};
8+
getterFnCache = createMap();
99
});
1010

1111

0 commit comments

Comments
 (0)