@@ -112,7 +112,7 @@ var OPERATORS = extend(createMap(), {
112
112
'/' :function ( self , locals , a , b ) { return a ( self , locals ) / b ( self , locals ) ; } ,
113
113
'%' :function ( self , locals , a , b ) { return a ( self , locals ) % b ( self , locals ) ; } ,
114
114
'^' :function ( self , locals , a , b ) { return a ( self , locals ) ^ b ( self , locals ) ; } ,
115
- '=' :noop ,
115
+ '=' :true ,
116
116
'===' :function ( self , locals , a , b ) { return a ( self , locals ) === b ( self , locals ) ; } ,
117
117
'!==' :function ( self , locals , a , b ) { return a ( self , locals ) !== b ( self , locals ) ; } ,
118
118
'==' :function ( self , locals , a , b ) { return a ( self , locals ) == b ( self , locals ) ; } ,
@@ -125,7 +125,7 @@ var OPERATORS = extend(createMap(), {
125
125
'||' :function ( self , locals , a , b ) { return a ( self , locals ) || b ( self , locals ) ; } ,
126
126
'&' :function ( self , locals , a , b ) { return a ( self , locals ) & b ( self , locals ) ; } ,
127
127
// '|':function(self, locals, a,b){return a|b;},
128
- '|' :function ( self , locals , a , b ) { return b ( self , locals ) ( self , locals , a ( self , locals ) ) ; } ,
128
+ '|' :true ,
129
129
'!' :function ( self , locals , a ) { return ! a ( self , locals ) ; }
130
130
} ) ;
131
131
/* jshint bitwise: true */
@@ -492,23 +492,26 @@ Parser.prototype = {
492
492
return extend ( function ( self , locals ) {
493
493
return fn ( self , locals , right ) ;
494
494
} , {
495
- constant :right . constant
495
+ constant :right . constant ,
496
+ children : [ right ]
496
497
} ) ;
497
498
} ,
498
499
499
500
ternaryFn : function ( left , middle , right ) {
500
501
return extend ( function ( self , locals ) {
501
502
return left ( self , locals ) ? middle ( self , locals ) : right ( self , locals ) ;
502
503
} , {
503
- constant : left . constant && middle . constant && right . constant
504
+ constant : left . constant && middle . constant && right . constant ,
505
+ children : [ left , middle , right ]
504
506
} ) ;
505
507
} ,
506
508
507
509
binaryFn : function ( left , fn , right ) {
508
510
return extend ( function ( self , locals ) {
509
511
return fn ( self , locals , left , right ) ;
510
512
} , {
511
- constant :left . constant && right . constant
513
+ constant :left . constant && right . constant ,
514
+ children : [ left , right ]
512
515
} ) ;
513
516
} ,
514
517
@@ -537,12 +540,12 @@ Parser.prototype = {
537
540
var left = this . expression ( ) ;
538
541
var token ;
539
542
while ( ( token = this . expect ( '|' ) ) ) {
540
- left = this . binaryFn ( left , token . fn , this . filter ( ) ) ;
543
+ left = this . filter ( left ) ;
541
544
}
542
545
return left ;
543
546
} ,
544
547
545
- filter : function ( ) {
548
+ filter : function ( input ) {
546
549
var token = this . expect ( ) ;
547
550
var fn = this . $filter ( token . text ) ;
548
551
var argsFn ;
@@ -556,9 +559,10 @@ Parser.prototype = {
556
559
}
557
560
}
558
561
559
- return valueFn ( function $parseFilter ( self , locals , input ) {
562
+ return extend ( function $parseFilter ( self , locals ) {
563
+ var inputVal = input ( self , locals ) ;
560
564
if ( args ) {
561
- args [ 0 ] = input ;
565
+ args [ 0 ] = inputVal ;
562
566
563
567
var i = argsFn . length ;
564
568
while ( i -- ) {
@@ -568,7 +572,9 @@ Parser.prototype = {
568
572
return fn . apply ( undefined , args ) ;
569
573
}
570
574
571
- return fn ( input ) ;
575
+ return fn ( inputVal ) ;
576
+ } , {
577
+ children : [ input ] . concat ( argsFn || [ ] )
572
578
} ) ;
573
579
} ,
574
580
@@ -586,9 +592,11 @@ Parser.prototype = {
586
592
this . text . substring ( 0 , token . index ) + '] can not be assigned to' , token ) ;
587
593
}
588
594
right = this . ternary ( ) ;
589
- return function $parseAssignment ( scope , locals ) {
595
+ return extend ( function $parseAssignment ( scope , locals ) {
590
596
return left . assign ( scope , right ( scope , locals ) , locals ) ;
591
- } ;
597
+ } , {
598
+ children : [ left , right ]
599
+ } ) ;
592
600
}
593
601
return left ;
594
602
} ,
@@ -688,7 +696,8 @@ Parser.prototype = {
688
696
var o = object ( scope , locals ) ;
689
697
if ( ! o ) object . assign ( scope , o = { } ) ;
690
698
return setter ( o , field , value , parserText ) ;
691
- }
699
+ } ,
700
+ children : [ object , getter ]
692
701
} ) ;
693
702
} ,
694
703
@@ -714,7 +723,8 @@ Parser.prototype = {
714
723
var o = ensureSafeObject ( obj ( self , locals ) , parserText ) ;
715
724
if ( ! o ) obj . assign ( self , o = { } ) ;
716
725
return o [ key ] = value ;
717
- }
726
+ } ,
727
+ children : [ obj , indexFn ]
718
728
} ) ;
719
729
} ,
720
730
@@ -781,24 +791,25 @@ Parser.prototype = {
781
791
return array ;
782
792
} , {
783
793
literal : true ,
784
- constant : allConstant
794
+ constant : allConstant ,
795
+ children : elementFns
785
796
} ) ;
786
797
} ,
787
798
788
799
object : function ( ) {
789
- var keyValues = [ ] ;
800
+ var keys = [ ] , values = [ ] ;
790
801
var allConstant = true ;
791
802
if ( this . peekToken ( ) . text !== '}' ) {
792
803
do {
793
804
if ( this . peek ( '}' ) ) {
794
805
// Support trailing commas per ES5.1.
795
806
break ;
796
807
}
797
- var token = this . expect ( ) ,
798
- key = token . string || token . text ;
808
+ var token = this . expect ( ) ;
809
+ keys . push ( token . string || token . text ) ;
799
810
this . consume ( ':' ) ;
800
811
var value = this . expression ( ) ;
801
- keyValues . push ( { key : key , value : value } ) ;
812
+ values . push ( value ) ;
802
813
if ( ! value . constant ) {
803
814
allConstant = false ;
804
815
}
@@ -808,14 +819,14 @@ Parser.prototype = {
808
819
809
820
return extend ( function $parseObjectLiteral ( self , locals ) {
810
821
var object = { } ;
811
- for ( var i = 0 , ii = keyValues . length ; i < ii ; i ++ ) {
812
- var keyValue = keyValues [ i ] ;
813
- object [ keyValue . key ] = keyValue . value ( self , locals ) ;
822
+ for ( var i = 0 , ii = values . length ; i < ii ; i ++ ) {
823
+ object [ keys [ i ] ] = values [ i ] ( self , locals ) ;
814
824
}
815
825
return object ;
816
826
} , {
817
827
literal : true ,
818
- constant : allConstant
828
+ constant : allConstant ,
829
+ children : values
819
830
} ) ;
820
831
}
821
832
} ;
@@ -1044,6 +1055,9 @@ function $ParseProvider() {
1044
1055
parsedExpression . $$watchDelegate = parsedExpression . literal ?
1045
1056
oneTimeLiteralWatchDelegate : oneTimeWatchDelegate ;
1046
1057
}
1058
+ else if ( parsedExpression . children ) {
1059
+ parsedExpression . $$watchDelegate = childExpressionWatchDelegate ;
1060
+ }
1047
1061
1048
1062
cache [ cacheKey ] = parsedExpression ;
1049
1063
}
@@ -1057,6 +1071,60 @@ function $ParseProvider() {
1057
1071
}
1058
1072
} ;
1059
1073
1074
+ function collectChildExpressions ( e , list ) {
1075
+ if ( e . children ) {
1076
+ for ( var i = 0 , ii = e . children . length ; i < ii ; i ++ ) {
1077
+ var child = e . children [ i ] ;
1078
+ if ( ! child . constant ) {
1079
+ collectChildExpressions ( child , list ) ;
1080
+ }
1081
+ }
1082
+ }
1083
+ else if ( ! e . constant && - 1 === list . indexOf ( e ) ) {
1084
+ list . push ( e ) ;
1085
+ }
1086
+
1087
+ return list ;
1088
+ }
1089
+ function isPrimitive ( o ) {
1090
+ var t ;
1091
+ return null == o || ( t = typeof o ) === "number" || t === "string" || t === "boolean" ;
1092
+ }
1093
+
1094
+ function childExpressionWatchDelegate ( scope , listener , objectEquality , parsedExpression ) {
1095
+ var inputExpressions = collectChildExpressions ( parsedExpression , [ ] ) ;
1096
+
1097
+ var inputs = [ NaN ] ;
1098
+ var lastResult ;
1099
+
1100
+ if ( 1 === inputExpressions . length ) {
1101
+ inputs = inputs [ 0 ] ;
1102
+ inputExpressions = inputExpressions [ 0 ] ;
1103
+ return scope . $watch ( function expressionInputWatch ( scope ) {
1104
+ var newVal = inputExpressions ( scope ) ;
1105
+ if ( newVal !== inputs || ! isPrimitive ( newVal ) ) {
1106
+ lastResult = parsedExpression ( scope ) ;
1107
+ inputs = newVal ;
1108
+ }
1109
+ return lastResult ;
1110
+ } , listener , objectEquality ) ;
1111
+ }
1112
+
1113
+ return scope . $watch ( function expressionInputsWatch ( scope ) {
1114
+ var changed = false ;
1115
+
1116
+ for ( var i = 0 , ii = inputExpressions . length ; i < ii ; i ++ ) {
1117
+ var valI = inputExpressions [ i ] ( scope ) ;
1118
+ changed = changed || valI !== inputs [ i ] || ! isPrimitive ( valI ) ;
1119
+ if ( changed ) {
1120
+ inputs [ i ] = valI ;
1121
+ }
1122
+ }
1123
+
1124
+ return changed ? ( lastResult = parsedExpression ( scope ) ) : lastResult ;
1125
+ } , listener , objectEquality ) ;
1126
+ }
1127
+
1060
1128
function oneTimeWatchDelegate ( scope , listener , objectEquality , parsedExpression ) {
1061
1129
var unwatch , lastValue ;
1062
1130
return unwatch = scope . $watch ( function oneTimeWatch ( scope ) {
0 commit comments