@@ -878,6 +878,10 @@ function setter(obj, path, setValue, fullExp, options) {
878
878
879
879
var getterFnCache = { } ;
880
880
881
+ function isPossiblyDangerousMemberName ( name ) {
882
+ return name == 'constructor' ;
883
+ }
884
+
881
885
/**
882
886
* Implementation of the "Black Hole" variant from:
883
887
* - http://jsperf.com/angularjs-parse-getter/4
@@ -889,29 +893,37 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
889
893
ensureSafeMemberName ( key2 , fullExp ) ;
890
894
ensureSafeMemberName ( key3 , fullExp ) ;
891
895
ensureSafeMemberName ( key4 , fullExp ) ;
896
+ var eso = function ( o ) {
897
+ return ensureSafeObject ( o , fullExp ) ;
898
+ } ;
899
+ var eso0 = isPossiblyDangerousMemberName ( key0 ) ? eso : identity ;
900
+ var eso1 = isPossiblyDangerousMemberName ( key1 ) ? eso : identity ;
901
+ var eso2 = isPossiblyDangerousMemberName ( key2 ) ? eso : identity ;
902
+ var eso3 = isPossiblyDangerousMemberName ( key3 ) ? eso : identity ;
903
+ var eso4 = isPossiblyDangerousMemberName ( key4 ) ? eso : identity ;
892
904
893
905
return ! options . unwrapPromises
894
906
? function cspSafeGetter ( scope , locals ) {
895
907
var pathVal = ( locals && locals . hasOwnProperty ( key0 ) ) ? locals : scope ;
896
908
897
909
if ( pathVal == null ) return pathVal ;
898
- pathVal = pathVal [ key0 ] ;
910
+ pathVal = eso0 ( pathVal [ key0 ] ) ;
899
911
900
912
if ( ! key1 ) return pathVal ;
901
913
if ( pathVal == null ) return undefined ;
902
- pathVal = pathVal [ key1 ] ;
914
+ pathVal = eso1 ( pathVal [ key1 ] ) ;
903
915
904
916
if ( ! key2 ) return pathVal ;
905
917
if ( pathVal == null ) return undefined ;
906
- pathVal = pathVal [ key2 ] ;
918
+ pathVal = eso2 ( pathVal [ key2 ] ) ;
907
919
908
920
if ( ! key3 ) return pathVal ;
909
921
if ( pathVal == null ) return undefined ;
910
- pathVal = pathVal [ key3 ] ;
922
+ pathVal = eso3 ( pathVal [ key3 ] ) ;
911
923
912
924
if ( ! key4 ) return pathVal ;
913
925
if ( pathVal == null ) return undefined ;
914
- pathVal = pathVal [ key4 ] ;
926
+ pathVal = eso4 ( pathVal [ key4 ] ) ;
915
927
916
928
return pathVal ;
917
929
}
@@ -921,72 +933,78 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
921
933
922
934
if ( pathVal == null ) return pathVal ;
923
935
924
- pathVal = pathVal [ key0 ] ;
936
+ pathVal = eso0 ( pathVal [ key0 ] ) ;
925
937
if ( pathVal && pathVal . then ) {
926
938
promiseWarning ( fullExp ) ;
927
939
if ( ! ( "$$v" in pathVal ) ) {
928
940
promise = pathVal ;
929
941
promise . $$v = undefined ;
930
- promise . then ( function ( val ) { promise . $$v = val ; } ) ;
942
+ promise . then ( function ( val ) { promise . $$v = eso0 ( val ) ; } ) ;
931
943
}
932
- pathVal = pathVal . $$v ;
944
+ pathVal = eso0 ( pathVal . $$v ) ;
933
945
}
934
946
935
947
if ( ! key1 ) return pathVal ;
936
948
if ( pathVal == null ) return undefined ;
937
- pathVal = pathVal [ key1 ] ;
949
+ pathVal = eso1 ( pathVal [ key1 ] ) ;
938
950
if ( pathVal && pathVal . then ) {
939
951
promiseWarning ( fullExp ) ;
940
952
if ( ! ( "$$v" in pathVal ) ) {
941
953
promise = pathVal ;
942
954
promise . $$v = undefined ;
943
- promise . then ( function ( val ) { promise . $$v = val ; } ) ;
955
+ promise . then ( function ( val ) { promise . $$v = eso1 ( val ) ; } ) ;
944
956
}
945
- pathVal = pathVal . $$v ;
957
+ pathVal = eso1 ( pathVal . $$v ) ;
946
958
}
947
959
948
960
if ( ! key2 ) return pathVal ;
949
961
if ( pathVal == null ) return undefined ;
950
- pathVal = pathVal [ key2 ] ;
962
+ pathVal = eso2 ( pathVal [ key2 ] ) ;
951
963
if ( pathVal && pathVal . then ) {
952
964
promiseWarning ( fullExp ) ;
953
965
if ( ! ( "$$v" in pathVal ) ) {
954
966
promise = pathVal ;
955
967
promise . $$v = undefined ;
956
- promise . then ( function ( val ) { promise . $$v = val ; } ) ;
968
+ promise . then ( function ( val ) { promise . $$v = eso2 ( val ) ; } ) ;
957
969
}
958
- pathVal = pathVal . $$v ;
970
+ pathVal = eso2 ( pathVal . $$v ) ;
959
971
}
960
972
961
973
if ( ! key3 ) return pathVal ;
962
974
if ( pathVal == null ) return undefined ;
963
- pathVal = pathVal [ key3 ] ;
975
+ pathVal = eso3 ( pathVal [ key3 ] ) ;
964
976
if ( pathVal && pathVal . then ) {
965
977
promiseWarning ( fullExp ) ;
966
978
if ( ! ( "$$v" in pathVal ) ) {
967
979
promise = pathVal ;
968
980
promise . $$v = undefined ;
969
- promise . then ( function ( val ) { promise . $$v = val ; } ) ;
981
+ promise . then ( function ( val ) { promise . $$v = eso3 ( val ) ; } ) ;
970
982
}
971
- pathVal = pathVal . $$v ;
983
+ pathVal = eso3 ( pathVal . $$v ) ;
972
984
}
973
985
974
986
if ( ! key4 ) return pathVal ;
975
987
if ( pathVal == null ) return undefined ;
976
- pathVal = pathVal [ key4 ] ;
988
+ pathVal = eso4 ( pathVal [ key4 ] ) ;
977
989
if ( pathVal && pathVal . then ) {
978
990
promiseWarning ( fullExp ) ;
979
991
if ( ! ( "$$v" in pathVal ) ) {
980
992
promise = pathVal ;
981
993
promise . $$v = undefined ;
982
- promise . then ( function ( val ) { promise . $$v = val ; } ) ;
994
+ promise . then ( function ( val ) { promise . $$v = eso4 ( val ) ; } ) ;
983
995
}
984
- pathVal = pathVal . $$v ;
996
+ pathVal = eso4 ( pathVal . $$v ) ;
985
997
}
986
998
return pathVal ;
987
999
} ;
988
1000
}
989
1001
1002
+ function getterFnWithExtraArgs ( fn , fullExpression ) {
1003
+ return function ( s , l ) {
1004
+ return fn ( s , l , promiseWarning , ensureSafeObject , fullExpression ) ;
1005
+ } ;
1006
+ }
1007
+
990
1008
function getterFn ( path , options , fullExp ) {
991
1009
// Check whether the cache has this getter already.
992
1010
// We can use hasOwnProperty directly on the cache because we ensure,
@@ -1019,35 +1037,45 @@ function getterFn(path, options, fullExp) {
1019
1037
}
1020
1038
} else {
1021
1039
var code = 'var p;\n' ;
1040
+ var needsEnsureSafeObject = false ;
1022
1041
forEach ( pathKeys , function ( key , index ) {
1023
1042
ensureSafeMemberName ( key , fullExp ) ;
1024
- code += 'if(s == null) return undefined;\n' +
1025
- 's=' + ( index
1043
+ var lookupJs = ( index
1026
1044
// we simply dereference 's' on any .dot notation
1027
1045
? 's'
1028
1046
// but if we are first then we check locals first, and if so read it first
1029
- : '((k&&k.hasOwnProperty("' + key + '"))?k:s)' ) + '["' + key + '"]' + ';\n' +
1030
- ( options . unwrapPromises
1031
- ? 'if (s && s.then) {\n' +
1047
+ : '((l&&l.hasOwnProperty("' + key + '"))?l:s)' ) + '["' + key + '"]' ;
1048
+ var wrapWithEso = isPossiblyDangerousMemberName ( key ) ;
1049
+ if ( wrapWithEso ) {
1050
+ lookupJs = 'eso(' + lookupJs + ', fe)' ;
1051
+ needsEnsureSafeObject = true ;
1052
+ }
1053
+ code += 'if(s == null) return undefined;\n' +
1054
+ 's=' + lookupJs + ';\n' ;
1055
+ if ( options . unwrapPromises ) {
1056
+ code += 'if (s && s.then) {\n' +
1032
1057
' pw("' + fullExp . replace ( / ( [ " \r \n ] ) / g, '\\$1' ) + '");\n' +
1033
1058
' if (!("$$v" in s)) {\n' +
1034
1059
' p=s;\n' +
1035
1060
' p.$$v = undefined;\n' +
1036
- ' p.then(function(v) {p.$$v=v ;});\n' +
1061
+ ' p.then(function(v) {p.$$v=' + ( wrapWithEso ? 'eso(v)' : 'v' ) + ' ;});\n' +
1037
1062
'}\n' +
1038
- ' s=s.$$v\n' +
1039
- '}\n'
1040
- : '' ) ;
1063
+ ' s=' + ( wrapWithEso ? 'eso(s.$$v)' : 's.$$v' ) + '\n' +
1064
+ '}\n' ;
1065
+
1066
+ }
1041
1067
} ) ;
1042
1068
code += 'return s;' ;
1043
1069
1044
1070
/* jshint -W054 */
1045
- var evaledFnGetter = new Function ( 's' , 'k' , 'pw' , code ) ; // s=scope, k=locals, pw=promiseWarning
1071
+ // s=scope, l=locals, pw=promiseWarning, eso=ensureSafeObject, fe=fullExpression
1072
+ var evaledFnGetter = new Function ( 's' , 'l' , 'pw' , 'eso' , 'fe' , code ) ;
1046
1073
/* jshint +W054 */
1047
1074
evaledFnGetter . toString = valueFn ( code ) ;
1048
- fn = options . unwrapPromises ? function ( scope , locals ) {
1049
- return evaledFnGetter ( scope , locals , promiseWarning ) ;
1050
- } : evaledFnGetter ;
1075
+ if ( needsEnsureSafeObject || options . unwrapPromises ) {
1076
+ evaledFnGetter = getterFnWithExtraArgs ( evaledFnGetter , fullExp ) ;
1077
+ }
1078
+ fn = evaledFnGetter ;
1051
1079
}
1052
1080
1053
1081
// Only cache the value if it's not going to mess up the cache object
0 commit comments