Index: TODO =================================================================== diff -u -r3cc93845be8bba214f09b9c6ec29e48de99175ff -r7d197d8e8a9ad6229c2aa8a11111118f5cab26b6 --- TODO (.../TODO) (revision 3cc93845be8bba214f09b9c6ec29e48de99175ff) +++ TODO (.../TODO) (revision 7d197d8e8a9ad6229c2aa8a11111118f5cab26b6) @@ -3480,6 +3480,7 @@ - nsf.c: * minor cleanup * added regression tests + * fixed recration of object alias with a alias to a different cmd TODO: Index: generic/nsf.c =================================================================== diff -u -r3cc93845be8bba214f09b9c6ec29e48de99175ff -r7d197d8e8a9ad6229c2aa8a11111118f5cab26b6 --- generic/nsf.c (.../nsf.c) (revision 3cc93845be8bba214f09b9c6ec29e48de99175ff) +++ generic/nsf.c (.../nsf.c) (revision 7d197d8e8a9ad6229c2aa8a11111118f5cab26b6) @@ -17629,10 +17629,11 @@ Tcl_ObjCmdProc *objProc, *newObjProc = NULL; Tcl_CmdDeleteProc *deleteProc = NULL; AliasCmdClientData *tcd = NULL; /* make compiler happy */ - Tcl_Command cmd, newCmd = NULL; + Tcl_Command cmd, oldCmd, newCmd = NULL; Tcl_Namespace *nsPtr; int flags, result; NsfClass *cl = (withPer_object || ! NsfObjectIsClass(object)) ? NULL : (NsfClass *)object; + NsfObject *oldTargetObject, *newTargetObject; cmd = Tcl_GetCommandFromObj(interp, cmdName); if (cmd == NULL) { @@ -17665,26 +17666,50 @@ newObjProc = NsfObjscopedMethod; } - if (CmdIsNsfObject(cmd)) { - Tcl_Command oldCmd; - Tcl_Namespace *lookupNsPtr; - NsfObject *oldTargetObject, *newTargetObject; - - newTargetObject = (NsfObject *)Tcl_Command_objClientData(cmd); - assert(newTargetObject); + /* + * We need to perform a defensive lookup of a previously defined + * object-alias under the given methodName. + */ + nsPtr = cl ? cl->nsPtr : object->nsPtr; + oldCmd = nsPtr ? FindMethod(nsPtr, methodName) : NULL; + newTargetObject = NsfGetObjectFromCmdPtr(cmd); + if (oldCmd != NULL) { + oldTargetObject = NsfGetObjectFromCmdPtr(oldCmd); + /*fprintf(stderr, "oldTargetObject %p flags %.6x newTargetObject %p\n", + oldTargetObject, oldTargetObject ? oldTargetObject->flags : 0, newTargetObject);*/ /* - * We need to perform a defensive lookup of a previously defined - * object-alias under the given methodName. + * The old target object might be already stale (i.e. destroyed, but kept + * alive by the reference counter). In this case, we have to decrement the + * object reference counter and release this object here. + * + * nx::Object create ::x + * nx::Object create ::o {:alias X ::x} + * + * Destroy the object and create it new + * + * x destroy + * nx::Object create ::x + * + * The recreation of the alias has to decrement the reference counter on + * the old object ::x + * + * o alias X ::x + * + * The test below is exactly the same as for invokes on destroyed aliased + * objects in ObjectDispatchCsc(). */ - lookupNsPtr = cl ? cl->nsPtr : object->nsPtr; - oldCmd = lookupNsPtr ? FindMethod(lookupNsPtr, methodName) : NULL; - if (oldCmd != NULL) { - oldTargetObject = NsfGetObjectFromCmdPtr(oldCmd); - } else { - oldTargetObject = NULL; + if (oldTargetObject != NULL && oldTargetObject != newTargetObject) { + assert(oldTargetObject->refCount > 0); + /*fprintf(stderr, "--- releasing old target object %p refCount %d\n", + oldTargetObject, oldTargetObject->refCount);*/ + AliasDeleteObjectReference(interp, oldCmd); } + } else { + oldTargetObject = NULL; + } + if (newTargetObject) { /* * Bump the object reference counter when the new target object is * different from the old one. Note, that the old target object might be @@ -17707,34 +17732,6 @@ /*fprintf(stderr, "--- don't incr refcount on obj %p %s\n", newTargetObject, ObjectName(newTargetObject));*/ } - - /* - * The old target object might be already stale (i.e. destroyed, but kept - * alive by the reference counter). In this case, we have to decrement the - * object reference counter and release this object here. - * - * nx::Object create ::x - * nx::Object create ::o {:alias X ::x} - * - * Destroy the object and create it new - * - * x destroy - * nx::Object create ::x - * - * The recreation of the alias has to decrement the reference counter on - * the old object ::x - * - * o alias X ::x - * - * The test below is exactly the same as for invokes on destroyed aliased - * objects in ObjectDispatchCsc(). - */ - if (oldTargetObject != NULL && oldTargetObject->flags & NSF_DELETED) { - /*fprintf(stderr, "--- releasing destroyed object %p refCount %d\n", - oldTargetObject, oldTargetObject->refCount);*/ - assert(oldTargetObject->refCount > 0); - AliasDeleteObjectReference(interp, oldCmd); - } } else if (CmdIsProc(cmd)) { /* Index: tests/alias.test =================================================================== diff -u -r3cc93845be8bba214f09b9c6ec29e48de99175ff -r7d197d8e8a9ad6229c2aa8a11111118f5cab26b6 --- tests/alias.test (.../alias.test) (revision 3cc93845be8bba214f09b9c6ec29e48de99175ff) +++ tests/alias.test (.../alias.test) (revision 7d197d8e8a9ad6229c2aa8a11111118f5cab26b6) @@ -671,7 +671,10 @@ # Testing aliases to objects and reference counting. # Check the effects via MEM_COUNT... # -nx::Test case refcount-object-alias-recreate { +nx::Test case refcount-object-alias-recreate1 { + # + # alias recreate with the same object + # nx::Object create ::x nx::Object create ::o { @@ -682,6 +685,20 @@ } } +nx::Test case refcount-object-alias-recreate2 { + # + # alias recreate with a proc + # + nx::Object create ::x + ::proc ::y {} {} + nx::Object create ::o { + :alias X ::x + ? {o info method definition X} "::o protected alias X ::x" + :alias X ::y + ? {o info method definition X} "::o protected alias X ::y" + } +} + nx::Test case refount-destroy-delete1 { nx::Object create ::x nx::Object create ::o {:alias X ::x} Index: tests/contains.test =================================================================== diff -u -rb4266efa283e86989f6f09f3938f41f173580400 -r7d197d8e8a9ad6229c2aa8a11111118f5cab26b6 --- tests/contains.test (.../contains.test) (revision b4266efa283e86989f6f09f3938f41f173580400) +++ tests/contains.test (.../contains.test) (revision 7d197d8e8a9ad6229c2aa8a11111118f5cab26b6) @@ -95,7 +95,7 @@ #puts stderr =====3 } -#puts ====NX +puts ====NX package forget nx package req nx @@ -104,10 +104,6 @@ package forget XOTcl package require XOTcl -######################################################################## -# trigger the call of "cleanup" to work via method dispatch -::xotcl::Object create o1 -o1 proc cleanup {} {return} ######################################################################## # @@ -121,6 +117,10 @@ ? {set ::errorMsg} {class "::C0" has a different object system as class "::nx::Object"} ::nx::Class create C1 -superclass ::nx::Object +# trigger the call of "cleanup" to work via method dispatch +::xotcl::Object create o1 +o1 proc cleanup {} {puts stderr "CLEANUP"; return} + #C0 create c0 #C0 create c0 C1 create c1