@@ -1042,3 +1042,186 @@ moduleFor(
1042
1042
}
1043
1043
}
1044
1044
) ;
1045
+
1046
+ class LazyObject {
1047
+ value = 123 ;
1048
+
1049
+ @computed ( '_value' )
1050
+ get value ( ) {
1051
+ return get ( this , '_value' ) ;
1052
+ }
1053
+
1054
+ set value ( value ) {
1055
+ set ( this , '_value' , value ) ;
1056
+ }
1057
+
1058
+ static create ( ) {
1059
+ let obj = new LazyObject ( ) ;
1060
+
1061
+ // ensure a tag exists for the value computed
1062
+ get ( obj , 'value' ) ;
1063
+
1064
+ return obj ;
1065
+ }
1066
+ }
1067
+
1068
+ moduleFor (
1069
+ 'computed - lazy dependencies' ,
1070
+ class extends AbstractTestCase {
1071
+ '@test computed properties with lazy dependencies work as expected' ( assert ) {
1072
+ let calledCount = 0 ;
1073
+ let lazyObject = LazyObject . create ( ) ;
1074
+
1075
+ class ObjectWithLazyDep {
1076
+ @computed ( 'lazyObject.value' )
1077
+ get someProp ( ) {
1078
+ return ++ calledCount ;
1079
+ }
1080
+
1081
+ @computed ( 'otherProp' )
1082
+ get lazyObject ( ) {
1083
+ return lazyObject ;
1084
+ }
1085
+ }
1086
+
1087
+ let obj = new ObjectWithLazyDep ( ) ;
1088
+
1089
+ // Get someProp and setup the lazy dependency
1090
+ assert . equal ( obj . someProp , 1 , 'called the first time' ) ;
1091
+ assert . equal ( obj . someProp , 1 , 'returned cached value the second time' ) ;
1092
+
1093
+ // Finish the lazy dependency
1094
+ assert . equal ( obj . lazyObject . value , 123 , 'lazyObject returns expected value' ) ;
1095
+ assert . equal (
1096
+ obj . someProp ,
1097
+ 1 ,
1098
+ 'someProp was not dirtied by propB being calculated for the first time'
1099
+ ) ;
1100
+
1101
+ set ( lazyObject , 'value' , 456 ) ;
1102
+ assert . equal ( obj . someProp , 2 , 'someProp dirtied by lazyObject.value changing' ) ;
1103
+
1104
+ set ( lazyObject , 'value' , 789 ) ;
1105
+ assert . equal (
1106
+ obj . someProp ,
1107
+ 3 ,
1108
+ 'someProp still dirtied by otherProp when lazyObject.value is dirty'
1109
+ ) ;
1110
+ }
1111
+
1112
+ '@test computed properties with lazy dependencies do not dirty until dependencies have been read at least once' (
1113
+ assert
1114
+ ) {
1115
+ let calledCount = 0 ;
1116
+ let lazyObject = LazyObject . create ( ) ;
1117
+
1118
+ class ObjectWithLazyDep {
1119
+ @computed ( 'lazyObject.value' )
1120
+ get someProp ( ) {
1121
+ return ++ calledCount ;
1122
+ }
1123
+
1124
+ @computed ( 'otherProp' )
1125
+ get lazyObject ( ) {
1126
+ return lazyObject ;
1127
+ }
1128
+ }
1129
+
1130
+ let obj = new ObjectWithLazyDep ( ) ;
1131
+
1132
+ assert . equal ( obj . someProp , 1 , 'called the first time' ) ;
1133
+ assert . equal ( obj . someProp , 1 , 'returned cached value the second time' ) ;
1134
+
1135
+ // dirty the object value before the dependency has been finished
1136
+ set ( lazyObject , 'value' , 456 ) ;
1137
+
1138
+ assert . equal ( obj . lazyObject . value , 456 , 'propB returns expected value' ) ;
1139
+ assert . equal (
1140
+ obj . someProp ,
1141
+ 1 ,
1142
+ 'someProp was not dirtied by propB being dirtied before it has been calculated'
1143
+ ) ;
1144
+ }
1145
+
1146
+ '@test computed properties with lazy dependencies work correctly if lazy dependency is more recent' (
1147
+ assert
1148
+ ) {
1149
+ let calledCount = 0 ;
1150
+ let lazyObject = LazyObject . create ( ) ;
1151
+
1152
+ class ObjectWithLazyDep {
1153
+ @computed ( 'lazyObject.value' )
1154
+ get someProp ( ) {
1155
+ return ++ calledCount ;
1156
+ }
1157
+
1158
+ @computed ( 'otherProp' )
1159
+ get lazyObject ( ) {
1160
+ return lazyObject ;
1161
+ }
1162
+ }
1163
+
1164
+ let obj = new ObjectWithLazyDep ( ) ;
1165
+
1166
+ set ( lazyObject , 'value' , 456 ) ;
1167
+
1168
+ assert . equal ( obj . someProp , 1 , 'called the first time' ) ;
1169
+ assert . equal ( obj . someProp , 1 , 'returned cached value the second time' ) ;
1170
+
1171
+ assert . equal ( obj . lazyObject . value , 456 , 'lazyObject returns expected value' ) ;
1172
+
1173
+ assert . equal (
1174
+ obj . someProp ,
1175
+ 1 ,
1176
+ 'someProp was not dirtied by lazyObject being dirtied before it has been calculated'
1177
+ ) ;
1178
+ }
1179
+ }
1180
+ ) ;
1181
+
1182
+ moduleFor (
1183
+ 'computed - observer interop' ,
1184
+ class extends AbstractTestCase {
1185
+ async '@test observers that do not consume computed properties still work' ( assert ) {
1186
+ assert . expect ( 2 ) ;
1187
+
1188
+ class Foo {
1189
+ otherProp = 123 ;
1190
+
1191
+ @computed ( 'otherProp' )
1192
+ get someProp ( ) {
1193
+ return this . otherProp ;
1194
+ }
1195
+ }
1196
+
1197
+ let foo = new Foo ( ) ;
1198
+
1199
+ addObserver (
1200
+ foo ,
1201
+ 'otherProp' ,
1202
+ foo ,
1203
+ ( ) => assert . ok ( true , 'otherProp observer called when it was changed' ) ,
1204
+ false
1205
+ ) ;
1206
+
1207
+ addObserver (
1208
+ foo ,
1209
+ 'someProp' ,
1210
+ foo ,
1211
+ ( ) => assert . ok ( false , 'someProp observer called when it was not changed' ) ,
1212
+ false
1213
+ ) ;
1214
+
1215
+ set ( foo , 'otherProp' , 456 ) ;
1216
+
1217
+ await runLoopSettled ( ) ;
1218
+
1219
+ assert . equal ( get ( foo , 'someProp' ) , 456 , '' ) ;
1220
+
1221
+ addObserver ( foo , 'anotherProp' , foo , ( ) => { } , false ) ;
1222
+ set ( foo , 'anotherProp' , 123 ) ;
1223
+
1224
+ await runLoopSettled ( ) ;
1225
+ }
1226
+ }
1227
+ ) ;
0 commit comments