@@ -852,7 +852,8 @@ function setter(obj, path, setValue, fullExp) {
852852 return setValue ;
853853}
854854
855- var getterFnCache = createMap ( ) ;
855+ var getterFnCacheDefault = createMap ( ) ;
856+ var getterFnCacheExpensive = createMap ( ) ;
856857
857858function isPossiblyDangerousMemberName ( name ) {
858859 return name == 'constructor' ;
@@ -863,7 +864,7 @@ function isPossiblyDangerousMemberName(name) {
863864 * - http://jsperf.com/angularjs-parse-getter/4
864865 * - http://jsperf.com/path-evaluation-simplified/7
865866 */
866- function cspSafeGetterFn ( key0 , key1 , key2 , key3 , key4 , fullExp ) {
867+ function cspSafeGetterFn ( key0 , key1 , key2 , key3 , key4 , fullExp , expensiveChecks ) {
867868 ensureSafeMemberName ( key0 , fullExp ) ;
868869 ensureSafeMemberName ( key1 , fullExp ) ;
869870 ensureSafeMemberName ( key2 , fullExp ) ;
@@ -872,11 +873,11 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp) {
872873 var eso = function ( o ) {
873874 return ensureSafeObject ( o , fullExp ) ;
874875 } ;
875- var eso0 = isPossiblyDangerousMemberName ( key0 ) ? eso : identity ;
876- var eso1 = isPossiblyDangerousMemberName ( key1 ) ? eso : identity ;
877- var eso2 = isPossiblyDangerousMemberName ( key2 ) ? eso : identity ;
878- var eso3 = isPossiblyDangerousMemberName ( key3 ) ? eso : identity ;
879- var eso4 = isPossiblyDangerousMemberName ( key4 ) ? eso : identity ;
876+ var eso0 = ( expensiveChecks || isPossiblyDangerousMemberName ( key0 ) ) ? eso : identity ;
877+ var eso1 = ( expensiveChecks || isPossiblyDangerousMemberName ( key1 ) ) ? eso : identity ;
878+ var eso2 = ( expensiveChecks || isPossiblyDangerousMemberName ( key2 ) ) ? eso : identity ;
879+ var eso3 = ( expensiveChecks || isPossiblyDangerousMemberName ( key3 ) ) ? eso : identity ;
880+ var eso4 = ( expensiveChecks || isPossiblyDangerousMemberName ( key4 ) ) ? eso : identity ;
880881
881882 return function cspSafeGetter ( scope , locals ) {
882883 var pathVal = ( locals && locals . hasOwnProperty ( key0 ) ) ? locals : scope ;
@@ -911,23 +912,25 @@ function getterFnWithEnsureSafeObject(fn, fullExpression) {
911912}
912913
913914function getterFn ( path , options , fullExp ) {
915+ var expensiveChecks = options . expensiveChecks ;
916+ var getterFnCache = ( expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault ) ;
914917 var fn = getterFnCache [ path ] ;
915-
916918 if ( fn ) return fn ;
917919
920+
918921 var pathKeys = path . split ( '.' ) ,
919922 pathKeysLength = pathKeys . length ;
920923
921924 // http://jsperf.com/angularjs-parse-getter/6
922925 if ( options . csp ) {
923926 if ( pathKeysLength < 6 ) {
924- fn = cspSafeGetterFn ( pathKeys [ 0 ] , pathKeys [ 1 ] , pathKeys [ 2 ] , pathKeys [ 3 ] , pathKeys [ 4 ] , fullExp ) ;
927+ fn = cspSafeGetterFn ( pathKeys [ 0 ] , pathKeys [ 1 ] , pathKeys [ 2 ] , pathKeys [ 3 ] , pathKeys [ 4 ] , fullExp , expensiveChecks ) ;
925928 } else {
926929 fn = function cspSafeGetter ( scope , locals ) {
927930 var i = 0 , val ;
928931 do {
929932 val = cspSafeGetterFn ( pathKeys [ i ++ ] , pathKeys [ i ++ ] , pathKeys [ i ++ ] , pathKeys [ i ++ ] ,
930- pathKeys [ i ++ ] , fullExp ) ( scope , locals ) ;
933+ pathKeys [ i ++ ] , fullExp , expensiveChecks ) ( scope , locals ) ;
931934
932935 locals = undefined ; // clear after first iteration
933936 scope = val ;
@@ -937,15 +940,18 @@ function getterFn(path, options, fullExp) {
937940 }
938941 } else {
939942 var code = '' ;
940- var needsEnsureSafeObject = false ;
943+ if ( expensiveChecks ) {
944+ code += 's = eso(s, fe);\nl = eso(l, fe);\n' ;
945+ }
946+ var needsEnsureSafeObject = expensiveChecks ;
941947 forEach ( pathKeys , function ( key , index ) {
942948 ensureSafeMemberName ( key , fullExp ) ;
943949 var lookupJs = ( index
944950 // we simply dereference 's' on any .dot notation
945951 ? 's'
946952 // but if we are first then we check locals first, and if so read it first
947953 : '((l&&l.hasOwnProperty("' + key + '"))?l:s)' ) + '.' + key ;
948- if ( isPossiblyDangerousMemberName ( key ) ) {
954+ if ( expensiveChecks || isPossiblyDangerousMemberName ( key ) ) {
949955 lookupJs = 'eso(' + lookupJs + ', fe)' ;
950956 needsEnsureSafeObject = true ;
951957 }
@@ -1030,15 +1036,20 @@ function getValueOf(value) {
10301036 * service.
10311037 */
10321038function $ParseProvider ( ) {
1033- var cache = createMap ( ) ;
1039+ var cacheDefault = createMap ( ) ;
1040+ var cacheExpensive = createMap ( ) ;
10341041
1035- var $parseOptions = {
1036- csp : false
1037- } ;
10381042
10391043
10401044 this . $get = [ '$filter' , '$sniffer' , function ( $filter , $sniffer ) {
1041- $parseOptions . csp = $sniffer . csp ;
1045+ var $parseOptions = {
1046+ csp : $sniffer . csp ,
1047+ expensiveChecks : false
1048+ } ,
1049+ $parseOptionsExpensive = {
1050+ csp : $sniffer . csp ,
1051+ expensiveChecks : true
1052+ } ;
10421053
10431054 function wrapSharedExpression ( exp ) {
10441055 var wrapped = exp ;
@@ -1055,13 +1066,14 @@ function $ParseProvider() {
10551066 return wrapped ;
10561067 }
10571068
1058- return function $parse ( exp , interceptorFn ) {
1069+ return function $parse ( exp , interceptorFn , expensiveChecks ) {
10591070 var parsedExpression , oneTime , cacheKey ;
10601071
10611072 switch ( typeof exp ) {
10621073 case 'string' :
10631074 cacheKey = exp = exp . trim ( ) ;
10641075
1076+ var cache = ( expensiveChecks ? cacheExpensive : cacheDefault ) ;
10651077 parsedExpression = cache [ cacheKey ] ;
10661078
10671079 if ( ! parsedExpression ) {
@@ -1070,8 +1082,9 @@ function $ParseProvider() {
10701082 exp = exp . substring ( 2 ) ;
10711083 }
10721084
1073- var lexer = new Lexer ( $parseOptions ) ;
1074- var parser = new Parser ( lexer , $filter , $parseOptions ) ;
1085+ var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions ;
1086+ var lexer = new Lexer ( parseOptions ) ;
1087+ var parser = new Parser ( lexer , $filter , parseOptions ) ;
10751088 parsedExpression = parser . parse ( exp ) ;
10761089
10771090 if ( parsedExpression . constant ) {
0 commit comments