Index: generic/predefined.h =================================================================== diff -u -r7c5c045a38db603c9a506d17a29403065256a845 -rf9807b1cea03590c9573b5a521760538d53ee90f --- generic/predefined.h (.../predefined.h) (revision 7c5c045a38db603c9a506d17a29403065256a845) +++ generic/predefined.h (.../predefined.h) (revision f9807b1cea03590c9573b5a521760538d53ee90f) @@ -232,7 +232,7 @@ "lappend methods $m}\n" "error \"Method '$method' unknown for slot [::xotcl::self]; valid are: {[lsort $methods]]}\"}\n" "::xotcl::Slot public method destroy {} {\n" -"if {${.domain} ne \"\"} {\n" +"if {${.domain} ne \"\" && [::xotcl::is ${.domain} object]} {\n" "${.domain} __invalidateobjectparameter}\n" "next}\n" "::xotcl::Slot method init {args} {\n" Index: generic/predefined.xotcl =================================================================== diff -u -rd70c849219212800fa401c2227796b9a63eadcaf -rf9807b1cea03590c9573b5a521760538d53ee90f --- generic/predefined.xotcl (.../predefined.xotcl) (revision d70c849219212800fa401c2227796b9a63eadcaf) +++ generic/predefined.xotcl (.../predefined.xotcl) (revision f9807b1cea03590c9573b5a521760538d53ee90f) @@ -460,7 +460,7 @@ } ::xotcl::Slot public method destroy {} { - if {${.domain} ne ""} { + if {${.domain} ne "" && [::xotcl::is ${.domain} object]} { ${.domain} __invalidateobjectparameter } next Index: generic/xotcl.c =================================================================== diff -u -re2bce71b86e234dd095039949f8e7dbbb4a4620e -rf9807b1cea03590c9573b5a521760538d53ee90f --- generic/xotcl.c (.../xotcl.c) (revision e2bce71b86e234dd095039949f8e7dbbb4a4620e) +++ generic/xotcl.c (.../xotcl.c) (revision f9807b1cea03590c9573b5a521760538d53ee90f) @@ -2421,22 +2421,26 @@ oid = obj->id; if (obj->teardown && oid) { - Tcl_Obj *savedObjResult = Tcl_GetObjResult(interp); - /*int flags = obj->flags;*/ - INCR_REF_COUNT(savedObjResult); + /* PrimitiveDestroy() has to be before DeleteCommandFromToken(), + otherwise e.g. unset traces on this object cannot be executed + from Tcl. We make sure via refcounting that the object structure + is kept until after DeleteCommandFromToken(). + */ + obj->refCount ++; + PrimitiveDestroy((ClientData) obj); if (!(obj->flags & XOTCL_CMD_NOT_FOUND)) { + Tcl_Obj *savedObjResult = Tcl_GetObjResult(interp); + INCR_REF_COUNT(savedObjResult); + /*fprintf(stderr, " before DeleteCommandFromToken %p %.6x\n", oid, ((Command*)oid)->flags);*/ Tcl_DeleteCommandFromToken(interp, oid); /* this can change the result */ /*fprintf(stderr, " after DeleteCommandFromToken %p %.6x\n", oid, ((Command*)oid)->flags);*/ Tcl_SetObjResult(interp, savedObjResult); + DECR_REF_COUNT(savedObjResult); } - - PrimitiveDestroy((ClientData) obj); - /*fprintf(stderr, "CallStackDoDestroy after primitiveDestroy of obj %p flags %.6x\n", - obj, flags);*/ - DECR_REF_COUNT(savedObjResult); + XOTclCleanupObject(obj); } } @@ -5911,7 +5915,7 @@ if (filterStackPushed && obj->filterStack) FilterStackPop(obj); - + XOTclCleanupObject(obj); DECR_REF_COUNT(cmdName); /* must be after last dereferencing of obj */ return result; @@ -11799,22 +11803,26 @@ static int XOTclODestroyMethod(Tcl_Interp *interp, XOTclObject *obj) { PRINTOBJ("XOTclODestroyMethod", obj); + + /*fprintf(stderr,"XOTclODestroyMethod %p %s flags %.6x activation %d cmd %p cmd->flags %.6x\n", + obj, ((Command*)obj->id)->flags == 0 ? objectName(obj) : "(deleted)", + obj->flags, obj->activationCount, obj->id, ((Command*)obj->id)->flags); */ + /* * XOTCL_DESTROY_CALLED might be set already be callDestroyMethod(), * the implicit destroy calls. It is necessary to set it here for * the explicit destroy calls in the script, which reach the * Object->destroy. */ - /*fprintf(stderr,"XOTclODestroyMethod %p flags %.6x activation %d cmd %p cmd->flags %.6x\n", - obj, obj->flags, obj->activationCount, obj->id, ((Command*)obj->id)->flags); */ if ((obj->flags & XOTCL_DESTROY_CALLED) == 0) { obj->flags |= XOTCL_DESTROY_CALLED; } if ((obj->flags & XOTCL_DURING_DELETE) == 0) { int result; - /*fprintf(stderr, " call dealloc on %p %s\n", obj, objectName(obj));*/ + /*fprintf(stderr, " call dealloc on %p %s\n", obj, + ((Command*)obj->id)->flags == 0 ? objectName(obj) : "(deleted)");*/ result = XOTclCallMethodWithArgs((ClientData)obj->cl, interp, XOTclGlobalObjects[XOTE_DEALLOC], obj->cmdName, @@ -12395,21 +12403,21 @@ } -static int XOTclCDeallocMethod(Tcl_Interp *interp, XOTclClass *cl, Tcl_Obj *object) { - XOTclObject *delobj; +static int XOTclCDeallocMethod(Tcl_Interp *interp, XOTclClass *cl, Tcl_Obj *obj) { + XOTclObject *delobject; XOTclRuntimeState *rst = RUNTIME_STATE(interp); rst->deallocCalled = 1; - /*fprintf(stderr, "XOTclCDeallocMethod obj %p\n",object);*/ - - if (GetObjectFromObj(interp, object, &delobj) != TCL_OK) { - fprintf(stderr, "obj %s does not exist\n", ObjStr(object)); + /*fprintf(stderr, "XOTclCDeallocMethod obj %p %s\n",obj, ObjStr(obj));*/ + + if (GetObjectFromObj(interp, obj, &delobject) != TCL_OK) { + fprintf(stderr, "XOTcl object %s does not exist\n", ObjStr(obj)); return XOTclVarErrMsg(interp, "Can't destroy object ", - ObjStr(object), " that does not exist.", (char *) NULL); + ObjStr(obj), " that does not exist.", (char *) NULL); } - return DoDealloc(interp, delobj); + return DoDealloc(interp, delobject); } static int XOTclCNewMethod(Tcl_Interp *interp, XOTclClass *cl, XOTclObject *withChildof, Index: tests/destroytest.xotcl =================================================================== diff -u -rf3cbadd6d76459cc00032877fa905bb618e9f780 -rf9807b1cea03590c9573b5a521760538d53ee90f --- tests/destroytest.xotcl (.../destroytest.xotcl) (revision f3cbadd6d76459cc00032877fa905bb618e9f780) +++ tests/destroytest.xotcl (.../destroytest.xotcl) (revision f9807b1cea03590c9573b5a521760538d53ee90f) @@ -1,13 +1,8 @@ package require XOTcl -puts stderr XXXX===1 xotcl::use xotcl1 -puts stderr XXXX===2 - package require xotcl::test -puts stderr XXXX===3 - proc ? {cmd expected {msg ""}} { set count 10 if {$msg ne ""} { @@ -238,7 +233,6 @@ ? {namespace exists ::test::C} 0 "$::case namespace ::test::C still exists after proc" ? {namespace exists ::test} 0 "$::case parent ::test namespace still exists after proc" ? {namespace exists ::xotcl::classes::test::C} 0 "$::case namespace ::xotcl::classes::test::C still exists after proc" -puts stderr XXXXX3 # # namespace delete: tcl delays delete until the namespace is not @@ -248,9 +242,7 @@ set case "delete parent namespace (2)" namespace eval ::test { ? {namespace exists test::C} 0 "exists test::C" - puts stderr AAA Class C -superclass O - puts stderr BBB C instproc destroy {} {incr ::firstDestroy; puts stderr " *** [self] destroy block"} C instproc foo {} { puts stderr "==== $::case [self]" @@ -262,7 +254,7 @@ # here. Is there a bug with nsPtr->activationCount # #? "[self] set x" 1 "$::case can still access [self]" - puts stderr "BBB" + puts stderr "BBBB" puts stderr "???? [self] exists [Object isobject [self]]" ? "Object isobject [self]" 0 "$::case object still exists in proc";# WHY? puts stderr "???? [self] exists [Object isobject [self]]" @@ -276,7 +268,6 @@ ? {Object isobject test::c1} 0 "$::case object still exists after proc" ? "set ::firstDestroy" 1 "$::case, firstDestroy called" ? "set ::ObjectDestroy" 0 "$::case, ObjectDestroy called" ;# toplevel destroy was blocked -puts stderr =============OK_STILL-after-61 # # controlled namespace delete: xotcl has its own namespace cleanup, @@ -296,15 +287,14 @@ puts stderr "AAAA [self] exists [Object isobject [self]]" my set x 1 #? "[self] set x" 1 "$::case can still access [self]" - puts stderr "BBB" + puts stderr "BBBB" ? {Object isobject ::o::c1} 0 "$::case object still exists in proc" ? "set ::firstDestroy" 1 "$::case, firstDestroy called" ? "set ::ObjectDestroy" 1 "$::case, ObjectDestroy called" } C o::c1 -puts stderr =====OK1 o::c1 foo -puts stderr =====OK-DONE + puts stderr ======[Object isobject ::o::c1] ? {Object isobject ::o::c1} 0 "$::case object o::c1 still exists after proc" ? {Object isobject o} 0 "$::case object o still exists after proc" Index: tests/speedtest.xotcl =================================================================== diff -u -r217d826e64107056ae97176552cae3c776991b9e -rf9807b1cea03590c9573b5a521760538d53ee90f --- tests/speedtest.xotcl (.../speedtest.xotcl) (revision 217d826e64107056ae97176552cae3c776991b9e) +++ tests/speedtest.xotcl (.../speedtest.xotcl) (revision f9807b1cea03590c9573b5a521760538d53ee90f) @@ -54,11 +54,17 @@ info exists v } C instproc existsViaExistsMethod {} { - my exists v + [self] exists v } C instproc existsViaMyExistsMethod {} { my exists v } +C instproc existsViaDotExistsMethod {} { + .exists v +} +C instproc existsViaResolver {} { + info exists .v +} C instproc notExistsViaInstvar {} { my instvar xxx info exists xxx @@ -200,6 +206,8 @@ Test new -cmd {c existsViaMyInstvar} Test new -cmd {c existsViaExistsMethod} Test new -cmd {c existsViaMyExistsMethod} +Test new -cmd {c existsViaDotExistsMethod} +Test new -cmd {c existsViaResolver} Test new -cmd {c exists v} Test new -cmd {c notExistsViaInstvar} -expected 0 Test new -cmd {c notExistsViaExistsMethod} -expected 0 Index: tests/testo.xotcl =================================================================== diff -u -r217d826e64107056ae97176552cae3c776991b9e -rf9807b1cea03590c9573b5a521760538d53ee90f --- tests/testo.xotcl (.../testo.xotcl) (revision 217d826e64107056ae97176552cae3c776991b9e) +++ tests/testo.xotcl (.../testo.xotcl) (revision f9807b1cea03590c9573b5a521760538d53ee90f) @@ -470,7 +470,7 @@ # if {[$obj set scalar] != $n} then { - error "FAILED [self] - scalar" + error "FAILED [self] - scalar [$obj set scalar] != $n" } $obj unset scalar @@ -501,11 +501,11 @@ avar2 proc trace {var ops} { my instvar $var ::trace variable $var $ops "avar2 traceproc" - #::trace variable $var $ops "traceproc" + #puts stderr "::trace variable $var $ops avar2 traceproc" } avar2 proc traceproc {maj min op} { - set majTmp [namespace tail "$maj"] + set majTmp [namespace tail $maj] #puts stderr ...TRACE global trail; lappend trail [list $majTmp $min $op] } @@ -527,11 +527,9 @@ avar2 set array($i) [avar2 set scalar$i] lappend guide [list array $i w] } - - if {$guide != $trail} then { + if {$guide != $trail} then { error "FAILED [self] - trace: expected $guide, got $trail" } - # # destroy must trigger unset traces # @@ -541,7 +539,9 @@ for {set i 0} {$i < $n} {incr i} { lappend guide [list scalar$i {} u] } + avar2 killSelf + if {[lsort $guide] != [lsort $trail]} then { error "FAILED [self] - trace: expected $guide, got $trail" } Index: tests/testx.xotcl =================================================================== diff -u -re2bce71b86e234dd095039949f8e7dbbb4a4620e -rf9807b1cea03590c9573b5a521760538d53ee90f --- tests/testx.xotcl (.../testx.xotcl) (revision e2bce71b86e234dd095039949f8e7dbbb4a4620e) +++ tests/testx.xotcl (.../testx.xotcl) (revision f9807b1cea03590c9573b5a521760538d53ee90f) @@ -1742,7 +1742,6 @@ puts stderr "### heritage: [a0 info precedence]" a0 parametercmd f6 - puts stderr OK ::errorCheck [a0 procsearch f1] "::A instproc f1" procsearch-1 ::errorCheck [a0 procsearch f2] "::A instforward f2" procsearch-2 @@ -2623,15 +2622,6 @@ "tclProc--tclProc"\ "object hierarchy copy" -#todo REMOVE ME - Class DestroyWatch - DestroyWatch instproc destroy args { - puts stderr "[self] destroy" - next - } - ::xotcl::Class instmixin DestroyWatch -### until here - Class O O x Index: tests/varresolutiontest.xotcl =================================================================== diff -u -r217d826e64107056ae97176552cae3c776991b9e -rf9807b1cea03590c9573b5a521760538d53ee90f --- tests/varresolutiontest.xotcl (.../varresolutiontest.xotcl) (revision 217d826e64107056ae97176552cae3c776991b9e) +++ tests/varresolutiontest.xotcl (.../varresolutiontest.xotcl) (revision f9807b1cea03590c9573b5a521760538d53ee90f) @@ -190,7 +190,7 @@ # we do not have to recreate bar, compiled var persists, # change must be detected C create c1 -puts stderr "after recreate" +#puts stderr "after recreate" ? {catch {c1 bar}} "1" "compiled var y should not exist" ? {c1 info vars} "x" c1 destroy @@ -241,9 +241,7 @@ set .z 100 } ? {c1 info vars} "" -puts call-foo c1 foo -puts call-foo-done ? {c1 info vars} "a z" @@ -312,7 +310,6 @@ ? {::xotcl::Object isobject ::c} 1 ? {::c info hasnamespace} 0 -puts [::c Set w 2] ? {::c Set w 2; expr {[::c Set w] == $::w}} 0 ? {::c Unset w; info exists ::w} 1 ? {::c Set tmpArray(key) value2; expr {[::c Set tmpArray(key)] == $::tmpArray(key)}} 0