aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2021-07-08 22:15:07 +1000
committerSteve Bennett <steveb@workware.net.au>2021-07-08 22:36:50 +1000
commit500866719dde1cb03d87b550cc8998b31d9e1316 (patch)
tree32dbb05cdf3318090ff697790c3139ad8dbbbf92
parent40298deee7cd1e72cb5e34ef98e07bc6adff2573 (diff)
downloadjimtcl-500866719dde1cb03d87b550cc8998b31d9e1316.zip
jimtcl-500866719dde1cb03d87b550cc8998b31d9e1316.tar.gz
jimtcl-500866719dde1cb03d87b550cc8998b31d9e1316.tar.bz2
collect: correctly handle references as globally scoped names
When a reference is used as a command name (e.g. in oo.tcl) it is created in the global namespace as ::<reference... The current check for references that are commands with a reference count of 1 doesn't take this into account so these references were not being garbage collected. Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r--jim.c14
-rw-r--r--tests/alias.test17
2 files changed, 28 insertions, 3 deletions
diff --git a/jim.c b/jim.c
index cfc0f8f..f339758 100644
--- a/jim.c
+++ b/jim.c
@@ -5505,6 +5505,14 @@ int Jim_Collect(Jim_Interp *interp)
continue;
}
+ /* If the string is ::<reference we need to skip over the :: when doing the
+ * comparison
+ */
+ if (str[0] == ':' && str[1] == ':') {
+ str +=2;
+ len -= 2;
+ }
+
/* Extract references from the object string repr. */
while (1) {
int i;
@@ -5526,9 +5534,9 @@ int Jim_Collect(Jim_Interp *interp)
/* Ok, a reference for the given ID
* was found. Mark it. */
- /* But if this is a command in the command table with refCount 1
- * don't mark it since it can be deleted.
- */
+ /* But if this is a command in the command table with refCount 1
+ * don't mark it since it can be deleted.
+ */
if (p == str && objPtr->refCount == 1 && Jim_FindHashEntry(&interp->commands, objPtr)) {
#ifdef JIM_DEBUG_GC
printf("No MARK: %lu - command with refcount=1\n", id);
diff --git a/tests/alias.test b/tests/alias.test
index 00870d1..9ad2dfd 100644
--- a/tests/alias.test
+++ b/tests/alias.test
@@ -265,4 +265,21 @@ test upcall-1.6 {delete local command with upcall} -body {
rename a c
} -returnCodes error -result {can't rename local command "a"}
+test collect-1.1 {ensure globally scoped references are deleted} {
+ collect
+ set result {}
+
+ # Create a globally scoped reference as a function name
+ set a ::[ref testfunction -]
+ proc $a {} { return 3 }
+ lappend result [$a]
+ # It shouldn't be collected
+ lappend result [collect]
+ lappend result [$a]
+ unset a
+ # Now it should be collected
+ lappend result [collect]
+ set result
+} {3 0 3 1}
+
testreport