@@ -80,12 +80,21 @@ function ensureSafeFunction(obj, fullExpression) {
80
80
}
81
81
}
82
82
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 ( constantGetter , name ) {
91
+ constantGetter . constant = constantGetter . literal = constantGetter . sharedGetter = true ;
92
+ CONSTANTS [ name ] = constantGetter ;
93
+ } ) ;
94
+
95
+ //Operators - will be wrapped by binaryFn/unaryFn/assignment/filter
83
96
var OPERATORS = extend ( createMap ( ) , {
84
97
/* jshint bitwise : false */
85
- 'null' :function ( ) { return null ; } ,
86
- 'true' :function ( ) { return true ; } ,
87
- 'false' :function ( ) { return false ; } ,
88
- undefined :noop ,
89
98
'+' :function ( self , locals , a , b ) {
90
99
a = a ( self , locals ) ; b = b ( self , locals ) ;
91
100
if ( isDefined ( a ) ) {
@@ -305,30 +314,11 @@ Lexer.prototype = {
305
314
}
306
315
}
307
316
308
-
309
- var token = {
317
+ this . tokens . push ( {
310
318
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 , expression ) ;
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 , expression ) ;
327
- }
328
- } ) ;
329
- }
330
-
331
- this . tokens . push ( token ) ;
319
+ text : ident ,
320
+ fn : CONSTANTS [ ident ] || getterFn ( ident , this . options , expression )
321
+ } ) ;
332
322
333
323
if ( methodName ) {
334
324
this . tokens . push ( {
@@ -397,6 +387,7 @@ var Parser = function (lexer, $filter, options) {
397
387
Parser . ZERO = extend ( function ( ) {
398
388
return 0 ;
399
389
} , {
390
+ sharedGetter : true ,
400
391
constant : true
401
392
} ) ;
402
393
@@ -935,9 +926,14 @@ function getterFn(path, options, fullExp) {
935
926
var evaledFnGetter = new Function ( 's' , 'l' , code ) ; // s=scope, l=locals
936
927
/* jshint +W054 */
937
928
evaledFnGetter . toString = valueFn ( code ) ;
929
+ evaledFnGetter . assign = function ( self , value ) {
930
+ return setter ( self , path , value , path ) ;
931
+ } ;
932
+
938
933
fn = evaledFnGetter ;
939
934
}
940
935
936
+ fn . sharedGetter = true ;
941
937
getterFnCache [ path ] = fn ;
942
938
return fn ;
943
939
}
@@ -1004,6 +1000,21 @@ function $ParseProvider() {
1004
1000
this . $get = [ '$filter' , '$sniffer' , function ( $filter , $sniffer ) {
1005
1001
$parseOptions . csp = $sniffer . csp ;
1006
1002
1003
+ function wrapSharedExpression ( exp ) {
1004
+ var wrapped = exp ;
1005
+
1006
+ if ( exp . sharedGetter ) {
1007
+ wrapped = function $parseWrapper ( self , locals ) {
1008
+ return exp ( self , locals ) ;
1009
+ } ;
1010
+ wrapped . literal = exp . literal ;
1011
+ wrapped . constant = exp . constant ;
1012
+ wrapped . assign = exp . assign ;
1013
+ }
1014
+
1015
+ return wrapped ;
1016
+ }
1017
+
1007
1018
return function $parse ( exp , interceptorFn ) {
1008
1019
var parsedExpression , oneTime , cacheKey ;
1009
1020
@@ -1026,6 +1037,9 @@ function $ParseProvider() {
1026
1037
if ( parsedExpression . constant ) {
1027
1038
parsedExpression . $$watchDelegate = constantWatchDelegate ;
1028
1039
} else if ( oneTime ) {
1040
+ //oneTime is not part of the exp passed to the Parser so we may have to
1041
+ //wrap the parsedExpression before adding a $$watchDelegate
1042
+ parsedExpression = wrapSharedExpression ( parsedExpression ) ;
1029
1043
parsedExpression . $$watchDelegate = parsedExpression . literal ?
1030
1044
oneTimeLiteralWatchDelegate : oneTimeWatchDelegate ;
1031
1045
}
0 commit comments