Fossil SCM
Make sure that TH1 variables get removed from the call frame upon being unset.
Commit
fa17f1ce3a8915d5c26c1c7e736cc7a0033a3b8d
Parent
5a9f9ba61dd6a36…
2 files changed
+7
-3
+5
M
src/th.c
+7
-3
| --- src/th.c | ||
| +++ src/th.c | ||
| @@ -1079,11 +1079,11 @@ | ||
| 1079 | 1079 | if( isGlobal ){ |
| 1080 | 1080 | while( pFrame->pCaller ) pFrame = pFrame->pCaller; |
| 1081 | 1081 | } |
| 1082 | 1082 | |
| 1083 | 1083 | pEntry = Th_HashFind(interp, pFrame->paVar, zOuter, nOuter, create); |
| 1084 | - assert(pEntry || !create); | |
| 1084 | + assert(pEntry || create<=0); | |
| 1085 | 1085 | if( !pEntry ){ |
| 1086 | 1086 | goto no_such_var; |
| 1087 | 1087 | } |
| 1088 | 1088 | |
| 1089 | 1089 | pValue = (Th_Variable *)pEntry->pData; |
| @@ -1253,17 +1253,21 @@ | ||
| 1253 | 1253 | pValue = thFindValue(interp, zVar, nVar, 0, 1, 0); |
| 1254 | 1254 | if( !pValue ){ |
| 1255 | 1255 | return TH_ERROR; |
| 1256 | 1256 | } |
| 1257 | 1257 | |
| 1258 | - Th_Free(interp, pValue->zData); | |
| 1259 | - pValue->zData = 0; | |
| 1258 | + if( pValue->zData ){ | |
| 1259 | + Th_Free(interp, pValue->zData); | |
| 1260 | + pValue->zData = 0; | |
| 1261 | + } | |
| 1260 | 1262 | if( pValue->pHash ){ |
| 1261 | 1263 | Th_HashIterate(interp, pValue->pHash, thFreeVariable, (void *)interp); |
| 1262 | 1264 | Th_HashDelete(interp, pValue->pHash); |
| 1263 | 1265 | pValue->pHash = 0; |
| 1264 | 1266 | } |
| 1267 | + | |
| 1268 | + thFindValue(interp, zVar, nVar, -1, 1, 1); /* Finally, delete from frame */ | |
| 1265 | 1269 | return TH_OK; |
| 1266 | 1270 | } |
| 1267 | 1271 | |
| 1268 | 1272 | /* |
| 1269 | 1273 | ** Return an allocated buffer containing a copy of string (z, n). The |
| 1270 | 1274 |
| --- src/th.c | |
| +++ src/th.c | |
| @@ -1079,11 +1079,11 @@ | |
| 1079 | if( isGlobal ){ |
| 1080 | while( pFrame->pCaller ) pFrame = pFrame->pCaller; |
| 1081 | } |
| 1082 | |
| 1083 | pEntry = Th_HashFind(interp, pFrame->paVar, zOuter, nOuter, create); |
| 1084 | assert(pEntry || !create); |
| 1085 | if( !pEntry ){ |
| 1086 | goto no_such_var; |
| 1087 | } |
| 1088 | |
| 1089 | pValue = (Th_Variable *)pEntry->pData; |
| @@ -1253,17 +1253,21 @@ | |
| 1253 | pValue = thFindValue(interp, zVar, nVar, 0, 1, 0); |
| 1254 | if( !pValue ){ |
| 1255 | return TH_ERROR; |
| 1256 | } |
| 1257 | |
| 1258 | Th_Free(interp, pValue->zData); |
| 1259 | pValue->zData = 0; |
| 1260 | if( pValue->pHash ){ |
| 1261 | Th_HashIterate(interp, pValue->pHash, thFreeVariable, (void *)interp); |
| 1262 | Th_HashDelete(interp, pValue->pHash); |
| 1263 | pValue->pHash = 0; |
| 1264 | } |
| 1265 | return TH_OK; |
| 1266 | } |
| 1267 | |
| 1268 | /* |
| 1269 | ** Return an allocated buffer containing a copy of string (z, n). The |
| 1270 |
| --- src/th.c | |
| +++ src/th.c | |
| @@ -1079,11 +1079,11 @@ | |
| 1079 | if( isGlobal ){ |
| 1080 | while( pFrame->pCaller ) pFrame = pFrame->pCaller; |
| 1081 | } |
| 1082 | |
| 1083 | pEntry = Th_HashFind(interp, pFrame->paVar, zOuter, nOuter, create); |
| 1084 | assert(pEntry || create<=0); |
| 1085 | if( !pEntry ){ |
| 1086 | goto no_such_var; |
| 1087 | } |
| 1088 | |
| 1089 | pValue = (Th_Variable *)pEntry->pData; |
| @@ -1253,17 +1253,21 @@ | |
| 1253 | pValue = thFindValue(interp, zVar, nVar, 0, 1, 0); |
| 1254 | if( !pValue ){ |
| 1255 | return TH_ERROR; |
| 1256 | } |
| 1257 | |
| 1258 | if( pValue->zData ){ |
| 1259 | Th_Free(interp, pValue->zData); |
| 1260 | pValue->zData = 0; |
| 1261 | } |
| 1262 | if( pValue->pHash ){ |
| 1263 | Th_HashIterate(interp, pValue->pHash, thFreeVariable, (void *)interp); |
| 1264 | Th_HashDelete(interp, pValue->pHash); |
| 1265 | pValue->pHash = 0; |
| 1266 | } |
| 1267 | |
| 1268 | thFindValue(interp, zVar, nVar, -1, 1, 1); /* Finally, delete from frame */ |
| 1269 | return TH_OK; |
| 1270 | } |
| 1271 | |
| 1272 | /* |
| 1273 | ** Return an allocated buffer containing a copy of string (z, n). The |
| 1274 |
+5
| --- test/th1.test | ||
| +++ test/th1.test | ||
| @@ -147,5 +147,10 @@ | ||
| 147 | 147 | |
| 148 | 148 | ############################################################################### |
| 149 | 149 | |
| 150 | 150 | fossil test-th-eval "unset var" |
| 151 | 151 | test th1-unset-2 {$RESULT eq {TH_ERROR: no such variable: var}} |
| 152 | + | |
| 153 | +############################################################################### | |
| 154 | + | |
| 155 | +fossil test-th-eval "set var 1; unset var; unset var" | |
| 156 | +test th1-unset-3 {$RESULT eq {TH_ERROR: no such variable: var}} | |
| 152 | 157 |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -147,5 +147,10 @@ | |
| 147 | |
| 148 | ############################################################################### |
| 149 | |
| 150 | fossil test-th-eval "unset var" |
| 151 | test th1-unset-2 {$RESULT eq {TH_ERROR: no such variable: var}} |
| 152 |
| --- test/th1.test | |
| +++ test/th1.test | |
| @@ -147,5 +147,10 @@ | |
| 147 | |
| 148 | ############################################################################### |
| 149 | |
| 150 | fossil test-th-eval "unset var" |
| 151 | test th1-unset-2 {$RESULT eq {TH_ERROR: no such variable: var}} |
| 152 | |
| 153 | ############################################################################### |
| 154 | |
| 155 | fossil test-th-eval "set var 1; unset var; unset var" |
| 156 | test th1-unset-3 {$RESULT eq {TH_ERROR: no such variable: var}} |
| 157 |