@@ -38,20 +38,30 @@ var $parseMinErr = minErr('$parse');
38
38
39
39
40
40
function ensureSafeMemberName ( name , fullExpression ) {
41
+ if ( name === "__defineGetter__" || name === "__defineSetter__"
42
+ || name === "__lookupGetter__" || name === "__lookupSetter__"
43
+ || name === "__proto__" ) {
44
+ throw $parseMinErr ( 'isecfld' ,
45
+ 'Attempting to access a disallowed field in Angular expressions! '
46
+ + 'Expression: {0}' , fullExpression ) ;
47
+ }
48
+ return name ;
49
+ }
50
+
51
+ function getStringValue ( name , fullExpression ) {
41
52
// From the JavaScript docs:
42
53
// Property names must be strings. This means that non-string objects cannot be used
43
54
// as keys in an object. Any non-string object, including a number, is typecasted
44
55
// into a string via the toString method.
45
56
//
46
57
// So, to ensure that we are checking the same `name` that JavaScript would use,
47
- // we cast it to a string, if possible
48
- name = ( isObject ( name ) && name . toString ) ? name . toString ( ) : name ;
49
-
50
- if ( name === "__defineGetter__" || name === "__defineSetter__"
51
- || name === "__lookupGetter__" || name === "__lookupSetter__"
52
- || name === "__proto__" ) {
53
- throw $parseMinErr ( 'isecfld' ,
54
- 'Attempting to access a disallowed field in Angular expressions! '
58
+ // we cast it to a string, if possible.
59
+ // Doing `name + ''` can cause a repl error if the result to `toString` is not a string,
60
+ // this is, this will handle objects that misbehave.
61
+ name = name + '' ;
62
+ if ( ! isString ( name ) ) {
63
+ throw $parseMinErr ( 'iseccst' ,
64
+ 'Cannot convert object to primitive value! '
55
65
+ 'Expression: {0}' , fullExpression ) ;
56
66
}
57
67
return name ;
@@ -816,6 +826,7 @@ ASTCompiler.prototype = {
816
826
'ensureSafeMemberName' ,
817
827
'ensureSafeObject' ,
818
828
'ensureSafeFunction' ,
829
+ 'getStringValue' ,
819
830
'ifDefined' ,
820
831
'plus' ,
821
832
'text' ,
@@ -824,6 +835,7 @@ ASTCompiler.prototype = {
824
835
ensureSafeMemberName ,
825
836
ensureSafeObject ,
826
837
ensureSafeFunction ,
838
+ getStringValue ,
827
839
ifDefined ,
828
840
plusFn ,
829
841
expression ) ;
@@ -967,6 +979,7 @@ ASTCompiler.prototype = {
967
979
if ( ast . computed ) {
968
980
right = self . nextId ( ) ;
969
981
self . recurse ( ast . property , right ) ;
982
+ self . getStringValue ( right ) ;
970
983
self . addEnsureSafeMemberName ( right ) ;
971
984
if ( create && create !== 1 ) {
972
985
self . if_ ( self . not ( self . computedMember ( left , right ) ) , self . lazyAssign ( self . computedMember ( left , right ) , '{}' ) ) ;
@@ -1187,6 +1200,10 @@ ASTCompiler.prototype = {
1187
1200
return 'ensureSafeFunction(' + item + ',text)' ;
1188
1201
} ,
1189
1202
1203
+ getStringValue : function ( item ) {
1204
+ this . assign ( item , 'getStringValue(' + item + ',text)' ) ;
1205
+ } ,
1206
+
1190
1207
lazyRecurse : function ( ast , intoId , nameId , recursionFn , create , skipWatchIdCheck ) {
1191
1208
var self = this ;
1192
1209
return function ( ) {
@@ -1561,6 +1578,7 @@ ASTInterpreter.prototype = {
1561
1578
var value ;
1562
1579
if ( lhs != null ) {
1563
1580
rhs = right ( scope , locals , assign , inputs ) ;
1581
+ rhs = getStringValue ( rhs ) ;
1564
1582
ensureSafeMemberName ( rhs , expression ) ;
1565
1583
if ( create && create !== 1 && lhs && ! ( lhs [ rhs ] ) ) {
1566
1584
lhs [ rhs ] = { } ;
0 commit comments