1
1
/**
2
- * @license scalyr v1.0.2
2
+ * @license scalyr v1.0.3
3
3
* (c) 2013 Scalyr, Inc. http://scalyr.com
4
4
* License: MIT
5
5
*/
@@ -352,9 +352,10 @@ function defineScalyrAngularModule(moduleName, dependencies) {
352
352
*
353
353
* slyEvaluateOnlyWhen: A directive that prevents updating / evaluating
354
354
* all bindings for the current element and its children unless
355
- * the expression has changed values. It currently assumes the
355
+ * the expression has changed values. If new children are added, they
356
+ * are always evaluated at least once. It currently assumes the
356
357
* expression evaluates to an object and detects changes only by
357
- * a change in object reference.
358
+ * a change in object reference.
358
359
*
359
360
* slyAlwaysEvaluate: Can only be used in conjunction with the
360
361
* slyEvaluateOnlyWhen directive. This directive will ensure that
@@ -419,7 +420,7 @@ defineScalyrAngularModule('slyEvaluate', ['gatedScope'])
419
420
// be gated.
420
421
return isNull ( alwaysEvaluateString ) ||
421
422
! ( isStringNonempty ( watchExpression ) && ( watchExpression . indexOf ( alwaysEvaluateString ) >= 0 ) ) ;
422
- } ) ;
423
+ } , true /* Evaluate any newly added watchers when they are added */ ) ;
423
424
} ,
424
425
} ;
425
426
} ,
@@ -755,6 +756,7 @@ defineScalyrAngularModule('gatedScope', [])
755
756
result . $$parentGatingFunction = this . $$gatingFunction ;
756
757
result . $$shouldGateFunction = this . $$shouldGateFunction ;
757
758
result . $$gatedWatchers = [ ] ;
759
+ result . $$cleanUpQueue = this . $$cleanUpQueue ;
758
760
759
761
return result ;
760
762
} ;
@@ -786,6 +788,14 @@ defineScalyrAngularModule('gatedScope', [])
786
788
if ( watch . gatingFunction !== targetGatingFunction )
787
789
continue ;
788
790
791
+ // Since we are about to execute the watcher as part of a digestGated
792
+ // call, we can remove it from the normal digest queue if it was placed
793
+ // there because the watcher was added after the gate function's first
794
+ // evaluation.
795
+ if ( watch && ! isNull ( watch . cleanUp ) ) {
796
+ watch . cleanUp ( ) ;
797
+ watch . cleanUp = null ;
798
+ }
789
799
// Most common watches are on primitives, in which case we can short
790
800
// circuit it with === operator, only when === fails do we use .equals
791
801
if ( watch && ( value = watch . get ( current ) ) !== ( last = watch . last ) &&
@@ -820,6 +830,8 @@ defineScalyrAngularModule('gatedScope', [])
820
830
}
821
831
} while ( ( current = next ) ) ;
822
832
833
+ // Mark that this gating function has digested all children.
834
+ targetGatingFunction . hasDigested = true ;
823
835
return dirty ;
824
836
} ;
825
837
@@ -844,11 +856,38 @@ defineScalyrAngularModule('gatedScope', [])
844
856
var result = scopePrototype . $watch . call ( this , watchExpression , listener , objectEquality ) ;
845
857
this . $$watchers = tmp ;
846
858
this . $$gatedWatchers [ 0 ] . gatingFunction = this . $$gatingFunction ;
859
+ this . $$gatedWatchers [ 0 ] . cleanUp = null ;
847
860
848
861
// We know that the last field of the watcher object will be set to initWatchVal, so we
849
862
// grab it here.
850
863
initWatchVal = this . $$gatedWatchers [ 0 ] . last ;
864
+ var watch = this . $$gatedWatchers [ 0 ] ;
865
+
866
+ // We should make sure the watch expression gets evaluated fully on at least one
867
+ // digest cycle even if the gate function is now closed if requested by the gating function's
868
+ // value for shouldEvalNewWatchers. We do this by adding in normal watcher that will execute
869
+ // the watcher we just added and remove itself after the digest cycle completes.
870
+ if ( this . $$gatingFunction . shouldEvalNewWatchers && this . $$gatingFunction . hasDigested ) {
871
+ var self = this ;
872
+ watch . cleanUp = scopePrototype . $watch . call ( self , function ( ) {
873
+ if ( ! isNull ( watch . cleanUp ) ) {
874
+ self . $$cleanUpQueue . unshift ( watch . cleanUp ) ;
875
+ watch . cleanUp = null ;
876
+ }
877
+ var value ;
878
+ var last = initWatchVal ;
851
879
880
+ if ( watch && ( value = watch . get ( self ) ) !== ( last = watch . last ) &&
881
+ ! ( watch . eq
882
+ ? areEqual ( value , last )
883
+ : ( typeof value == 'number' && typeof last == 'number'
884
+ && isNaN ( value ) && isNaN ( last ) ) ) ) {
885
+ watch . last = watch . eq ? copy ( value ) : value ;
886
+ watch . fn ( value , ( ( last === initWatchVal ) ? value : last ) , self ) ;
887
+ }
888
+ return watch . last ;
889
+ } ) ;
890
+ }
852
891
return result ;
853
892
} else {
854
893
return scopePrototype . $watch . call ( this , watchExpression , listener , objectEquality ) ;
@@ -871,8 +910,8 @@ defineScalyrAngularModule('gatedScope', [])
871
910
// functions and should be evaluated at all. However, if a caller is invoking
872
911
// $digest on a particular scope, we assume the caller is doing that because it
873
912
// knows the watchers should be evaluated.
913
+ var dirty = false ;
874
914
if ( ! isNull ( this . $$parentGatingFunction ) && this . $$parentGatingFunction ( ) ) {
875
- var dirty = false ;
876
915
var ttl = 5 ;
877
916
do {
878
917
dirty = this . $digestGated ( this . $$parentGatingFunction ) ;
@@ -884,7 +923,19 @@ defineScalyrAngularModule('gatedScope', [])
884
923
}
885
924
} while ( dirty ) ;
886
925
}
887
- return scopePrototype . $digest . call ( this ) || dirty ;
926
+
927
+ dirty = scopePrototype . $digest . call ( this ) || dirty ;
928
+
929
+ var cleanUpQueue = this . $$cleanUpQueue ;
930
+
931
+ while ( cleanUpQueue . length )
932
+ try {
933
+ cleanUpQueue . shift ( ) ( ) ;
934
+ } catch ( e ) {
935
+ $exceptionHandler ( e ) ;
936
+ }
937
+
938
+ return dirty ;
888
939
}
889
940
890
941
/**
@@ -901,8 +952,13 @@ defineScalyrAngularModule('gatedScope', [])
901
952
* a new watcher will be gated using gatingFunction. It is evaluated with the
902
953
* arguments to $watch and should return true if the watcher created by those
903
954
* arguments should be gated
955
+ * @param {Boolean } shouldEvalNewWatchers If true, if a watcher is added
956
+ * after the gating function has returned true on a previous digest cycle, the
957
+ * the new watcher will be evaluated on the next digest cycle even if the
958
+ * gating function is currently return false.
904
959
*/
905
- methodsToAdd . $addWatcherGate = function ( gatingFunction , shouldGateFunction ) {
960
+ methodsToAdd . $addWatcherGate = function ( gatingFunction , shouldGateFunction ,
961
+ shouldEvalNewWatchers ) {
906
962
var changeCount = 0 ;
907
963
var self = this ;
908
964
@@ -918,30 +974,36 @@ defineScalyrAngularModule('gatedScope', [])
918
974
// true (which we can tell if the watcher we register here is evaluated), then
919
975
// we always evaluate our watcher until our gating function returns true.
920
976
var hasNestedGates = ! isNull ( this . $$gatingFunction ) ;
921
- var promotedWatcher = null ;
922
-
923
- this . $watch ( function ( ) {
924
- if ( gatingFunction ( ) ) {
925
- if ( self . $digestGated ( gatingFunction ) )
926
- ++ changeCount ;
927
- } else if ( hasNestedGates && isNull ( promotedWatcher ) ) {
928
- promotedWatcher = scopePrototype . $watch . call ( self , function ( ) {
929
- if ( gatingFunction ( ) ) {
930
- promotedWatcher ( ) ;
931
- promotedWatcher = null ;
932
- if ( self . $digestGated ( gatingFunction ) )
933
- ++ changeCount ;
934
- }
935
- return changeCount ;
936
- } ) ;
937
- }
938
- return changeCount ;
939
- } ) ;
977
+
978
+ ( function ( ) {
979
+ var promotedWatcher = null ;
980
+
981
+ self . $watch ( function ( ) {
982
+ if ( gatingFunction ( ) ) {
983
+ if ( self . $digestGated ( gatingFunction ) )
984
+ ++ changeCount ;
985
+ } else if ( hasNestedGates && isNull ( promotedWatcher ) ) {
986
+ promotedWatcher = scopePrototype . $watch . call ( self , function ( ) {
987
+ if ( gatingFunction ( ) ) {
988
+ promotedWatcher ( ) ;
989
+ promotedWatcher = null ;
990
+ if ( self . $digestGated ( gatingFunction ) )
991
+ ++ changeCount ;
992
+ }
993
+ return changeCount ;
994
+ } ) ;
995
+ }
996
+ return changeCount ;
997
+ } ) ;
998
+ } ) ( ) ;
940
999
941
1000
942
1001
if ( isUndefined ( shouldGateFunction ) )
943
1002
shouldGateFunction = null ;
1003
+ if ( isUndefined ( shouldEvalNewWatchers ) )
1004
+ shouldEvalNewWatchers = false ;
944
1005
this . $$gatingFunction = gatingFunction ;
1006
+ this . $$gatingFunction . shouldEvalNewWatchers = shouldEvalNewWatchers ;
945
1007
this . $$shouldGateFunction = shouldGateFunction ;
946
1008
} ;
947
1009
@@ -957,6 +1019,7 @@ defineScalyrAngularModule('gatedScope', [])
957
1019
$rootScope . $$parentGatingFunction = null ;
958
1020
$rootScope . $$shouldGateFunction = null ;
959
1021
$rootScope . $$gatedWatchers = [ ] ;
1022
+ $rootScope . $$cleanUpQueue = [ ] ;
960
1023
961
1024
return $rootScope ;
962
1025
} ] ) ;
0 commit comments