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

Commit eb47e91

Browse files
committed
perf($parse): remove getterFn wrapper for internal use
1 parent c074181 commit eb47e91

File tree

2 files changed

+42
-28
lines changed

2 files changed

+42
-28
lines changed

src/ng/parse.js

+41-27
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,21 @@ function ensureSafeFunction(obj, fullExpression) {
8080
}
8181
}
8282

83+
//Keyword constants
84+
var CONSTANTS = createMap();
85+
forEach({
86+
'null':function(){return null;},
87+
'true':function(){return true;},
88+
'false':function(){return false;},
89+
'undefined':function(){}
90+
}, function(constFunc, name) {
91+
constFunc.constant = constFunc.literal = constFunc.$$parseShared = true;
92+
CONSTANTS[name] = constFunc;
93+
});
94+
95+
//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter
8396
var OPERATORS = extend(createMap(), {
8497
/* jshint bitwise : false */
85-
'null':function(){return null;},
86-
'true':function(){return true;},
87-
'false':function(){return false;},
88-
undefined:noop,
8998
'+':function(self, locals, a,b){
9099
a=a(self, locals); b=b(self, locals);
91100
if (isDefined(a)) {
@@ -305,30 +314,11 @@ Lexer.prototype = {
305314
}
306315
}
307316

308-
309-
var token = {
317+
this.tokens.push({
310318
index: start,
311-
text: ident
312-
};
313-
314-
var fn = OPERATORS[ident];
315-
316-
if (fn) {
317-
token.fn = fn;
318-
token.constant = true;
319-
} else {
320-
var getter = getterFn(ident, this.options, parserText);
321-
// TODO(perf): consider exposing the getter reference
322-
token.fn = extend(function $parsePathGetter(self, locals) {
323-
return getter(self, locals);
324-
}, {
325-
assign: function(self, value) {
326-
return setter(self, ident, value, parserText);
327-
}
328-
});
329-
}
330-
331-
this.tokens.push(token);
319+
text: ident,
320+
fn: CONSTANTS[ident] || getterFn(ident, this.options, parserText)
321+
});
332322

333323
if (methodName) {
334324
this.tokens.push({
@@ -397,6 +387,7 @@ var Parser = function (lexer, $filter, options) {
397387
Parser.ZERO = extend(function () {
398388
return 0;
399389
}, {
390+
$$parseShared: true,
400391
constant: true
401392
});
402393

@@ -935,9 +926,14 @@ function getterFn(path, options, fullExp) {
935926
var evaledFnGetter = new Function('s', 'l', code); // s=scope, l=locals
936927
/* jshint +W054 */
937928
evaledFnGetter.toString = valueFn(code);
929+
evaledFnGetter.assign = function(self, value) {
930+
return setter(self, path, value, path);
931+
};
932+
938933
fn = evaledFnGetter;
939934
}
940935

936+
fn.$$parseShared = true;
941937
getterFnCache[path] = fn;
942938
return fn;
943939
}
@@ -1005,6 +1001,21 @@ function $ParseProvider() {
10051001
this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
10061002
$parseOptions.csp = $sniffer.csp;
10071003

1004+
function wrapSharedExpression(exp) {
1005+
var wrapped = exp;
1006+
1007+
if (exp.$$parseShared) {
1008+
wrapped = function $parseWrapper(self, locals) {
1009+
return exp(self, locals);
1010+
};
1011+
wrapped.literal = exp.literal;
1012+
wrapped.constant = exp.constant;
1013+
wrapped.assign = exp.assign;
1014+
}
1015+
1016+
return wrapped;
1017+
}
1018+
10081019
return function $parse(exp, interceptorFn) {
10091020
var parsedExpression, oneTime, cacheKey;
10101021

@@ -1027,6 +1038,9 @@ function $ParseProvider() {
10271038
if (parsedExpression.constant) {
10281039
parsedExpression.$$watchDelegate = constantWatchDelegate;
10291040
} else if (oneTime) {
1041+
//oneTime is not part of the exp passed to the Parser so we may have to
1042+
//wrap the parsedExpression before adding a $$watchDelegate
1043+
parsedExpression = wrapSharedExpression(parsedExpression);
10301044
parsedExpression.$$watchDelegate = parsedExpression.literal ?
10311045
oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;
10321046
}

test/ng/parseSpec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ describe('parser', function() {
722722
scope.$eval('a.toString.constructor = 1', scope);
723723
}).toThrowMinErr(
724724
'$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
725-
'Expression: a.toString.constructor = 1');
725+
'Expression: a.toString.constructor');
726726
});
727727

728728

0 commit comments

Comments
 (0)