Index: TODO =================================================================== diff -u -rdfa0f22e1cc0b5d1d9b1f8bcc3ffbccb68737540 -ref1f9efa0bc697404c0aa5322bbd5cc2d7796c2c --- TODO (.../TODO) (revision dfa0f22e1cc0b5d1d9b1f8bcc3ffbccb68737540) +++ TODO (.../TODO) (revision ef1f9efa0bc697404c0aa5322bbd5cc2d7796c2c) @@ -1840,19 +1840,18 @@ - fix bad interaction between filters and cmd name resolvers - output object frame to ease interpretation of [info frame] +- fixed scoping issue, when "-volatile" was used for object creation +- added regression test for interaction between filters and + function resolver (and volatile) +- reactivated new volatile test in destroy.test +- undone temporary fixes for volatile in serializer and nx.tcl + TODO: -- regression test for interaction between filters and function resolver - (when volatile issue is solved) -- reactivate new volatile test in destroy.test - NsColonVarResolver can be optimized: // last case first // why OBJECT? is NSF_CMETHOD used without PROC? -- undo volatile fixes in serializer when volatile is revived. - #set s [:new -childof [::nsf::current object]] - #$s volatile - - "-returns" * leave syntax as is for method? * add flag to alias and forward? Index: generic/nsf.c =================================================================== diff -u -reb0084076a445a9f64bf775b68a120716e3cb516 -ref1f9efa0bc697404c0aa5322bbd5cc2d7796c2c --- generic/nsf.c (.../nsf.c) (revision eb0084076a445a9f64bf775b68a120716e3cb516) +++ generic/nsf.c (.../nsf.c) (revision ef1f9efa0bc697404c0aa5322bbd5cc2d7796c2c) @@ -14800,12 +14800,19 @@ Nsf_PushFrameCsc(interp, cscPtr, framePtr2); if (paramPtr->flags & NSF_ARG_INITCMD) { + /* cscPtr->cmdPtr = NSFindCommand(interp, "::eval"); */ result = Tcl_EvalObjEx(interp, newValue, TCL_EVAL_DIRECT); } else /* must be NSF_ARG_METHOD */ { Tcl_Obj *ov[3]; int oc = 0; + /* + * Mark the current frame as inactive such that e.g. volatile + * does not use this as a base frame, and methods like + * activelevel ignore it. + */ + cscPtr->frameType = NSF_CSC_TYPE_INACTIVE; if (paramPtr->converterArg) { /* if arg= was given, pass it as first argument */ ov[0] = paramPtr->converterArg; @@ -15250,7 +15257,7 @@ fprintf(stderr, "### Can't make objects volatile during shutdown\n"); return NsfVarErrMsg(interp, "Can't make objects volatile during shutdown\n", NULL); } - //NsfShowStack(interp); + CallStackUseActiveFrame(interp, &ctx); vn = NSTail(fullName); Index: generic/nsfStack.c =================================================================== diff -u -r4454585cc13933eceea7815732a3d889e47a0f97 -ref1f9efa0bc697404c0aa5322bbd5cc2d7796c2c --- generic/nsfStack.c (.../nsfStack.c) (revision 4454585cc13933eceea7815732a3d889e47a0f97) +++ generic/nsfStack.c (.../nsfStack.c) (revision ef1f9efa0bc697404c0aa5322bbd5cc2d7796c2c) @@ -89,12 +89,14 @@ Tcl_CallFrame_objc(framePtr) && 0 ? ObjStr(Tcl_CallFrame_objv(framePtr)[0]) : "(null)", Tcl_CallFrame_objc(framePtr) ? Tcl_CallFrame_objc(framePtr) : -1); if (cscPtr) { - fprintf(stderr, " csc %p frameType %.4x callType %.4x (%p %s)\n", + fprintf(stderr, " csc %p frameType %.4x callType %.4x (%s.%p %s)\n", cscPtr, cscPtr ? cscPtr->frameType : -1, cscPtr ? cscPtr->flags : -1, - cscPtr ? cscPtr->self : NULL, - cscPtr ? objectName(cscPtr->self) : ""); + cscPtr ? objectName(cscPtr->self) : "", + cscPtr ? cscPtr->cmdPtr : NULL, + cscPtr ? Tcl_GetCommandName(interp, cscPtr->cmdPtr) : "" + ); } else { fprintf(stderr, " no csc"); if (frameFlags & FRAME_IS_NSF_OBJECT) { @@ -216,16 +218,16 @@ for (; framePtr; framePtr = Tcl_CallFrame_callerPtr(framePtr)) { register int flag = Tcl_CallFrame_isProcCallFrame(framePtr); - if (flag & FRAME_IS_NSF_METHOD) { + if (flag & (FRAME_IS_NSF_METHOD|FRAME_IS_NSF_CMETHOD)) { /* never return an inactive method frame */ if (!(((NsfCallStackContent *)Tcl_CallFrame_clientData(framePtr))->frameType & NSF_CSC_TYPE_INACTIVE)) break; } else { - //if (flag & (FRAME_IS_NSF_CMETHOD|FRAME_IS_NSF_OBJECT)) continue; if (flag & (FRAME_IS_NSF_OBJECT)) continue; - if (flag == 0 || flag & FRAME_IS_PROC) break; + if (flag == 0 || (flag & FRAME_IS_PROC)) break; } } + return framePtr; } @@ -408,7 +410,7 @@ /* search for first active frame and set tcl frame pointers */ for (; varFramePtr; varFramePtr = Tcl_CallFrame_callerPtr(varFramePtr)) { - if (Tcl_CallFrame_isProcCallFrame(varFramePtr) & FRAME_IS_NSF_METHOD/*(FRAME_IS_NSF_METHOD|FRAME_IS_NSF_CMETHOD)*/) { + if (Tcl_CallFrame_isProcCallFrame(varFramePtr) & /*FRAME_IS_NSF_METHOD*/ (FRAME_IS_NSF_METHOD|FRAME_IS_NSF_CMETHOD)) { NsfCallStackContent *cscPtr = (NsfCallStackContent *)Tcl_CallFrame_clientData(varFramePtr); if (!(cscPtr->frameType & NSF_CSC_TYPE_INACTIVE)) { /* we found the highest active frame */ @@ -844,18 +846,7 @@ cscPtr->flags |= NSF_CSC_OBJECT_ACTIVATED; - // TODO /* - * Some csc's are never stacked. We flag this case by setting self - * to NULL. This cscPtr should never appear on the stack. - */ - if (Tcl_Command_objClientData(cmd) == NULL && !(Tcl_Command_flags(cmd) & NSF_CMD_NONLEAF_METHOD)) { - /*fprintf(stderr, "+++ no CscInit needed\n");*/ - //cscPtr->self = NULL; - //return; - } - - /* * track object activations */ object->activationCount ++; Index: library/nx/nx.tcl =================================================================== diff -u -r4454585cc13933eceea7815732a3d889e47a0f97 -ref1f9efa0bc697404c0aa5322bbd5cc2d7796c2c --- library/nx/nx.tcl (.../nx.tcl) (revision 4454585cc13933eceea7815732a3d889e47a0f97) +++ library/nx/nx.tcl (.../nx.tcl) (revision ef1f9efa0bc697404c0aa5322bbd5cc2d7796c2c) @@ -1428,11 +1428,7 @@ Object public method copy newName { if {[string compare [string trimleft $newName :] [string trimleft [::nsf::self] :]]} { - CopyHandler new { - :copy [:uplevel ::nsf::self] [uplevel set newName] - :destroy - } - #[CopyHandler new -volatile] copy [::nsf::self] $newName + [CopyHandler new -volatile] copy [::nsf::self] $newName } } Index: library/serialize/serializer.tcl =================================================================== diff -u -rdfa0f22e1cc0b5d1d9b1f8bcc3ffbccb68737540 -ref1f9efa0bc697404c0aa5322bbd5cc2d7796c2c --- library/serialize/serializer.tcl (.../serializer.tcl) (revision dfa0f22e1cc0b5d1d9b1f8bcc3ffbccb68737540) +++ library/serialize/serializer.tcl (.../serializer.tcl) (revision ef1f9efa0bc697404c0aa5322bbd5cc2d7796c2c) @@ -363,8 +363,8 @@ # don't filter anything during serialization set filterstate [::nsf::configure filter off] - set s [:new -childof [::nsf::current object]] - $s volatile + set s [:new -childof [::nsf::current object] -volatile] + #$s volatile if {[info exists ignoreVarsRE]} {$s ignoreVarsRE $ignoreVarsRE} if {[info exists ignore]} {$s ignore $ignore} @@ -405,15 +405,15 @@ } :class-object method methodSerialize {object method prefix} { - set s [:new -childof [::nsf::current object]] - $s volatile + set s [:new -childof [::nsf::current object] -volatile] + #$s volatile concat $object [$s method-serialize $object $method $prefix] } :public class-object method deepSerialize {-ignoreVarsRE -ignore -map args} { :resetPattern - set s [:new -childof [::nsf::current object]] - $s volatile + set s [:new -childof [::nsf::current object] -volatile] + #$s volatile if {[info exists ignoreVarsRE]} {$s ignoreVarsRE $ignoreVarsRE} if {[info exists ignore]} {$s ignore $ignore} Index: tests/destroy.test =================================================================== diff -u -r3b474e35616c02dbca08b877963c1f5b5adfcd1f -ref1f9efa0bc697404c0aa5322bbd5cc2d7796c2c --- tests/destroy.test (.../destroy.test) (revision 3b474e35616c02dbca08b877963c1f5b5adfcd1f) +++ tests/destroy.test (.../destroy.test) (revision ef1f9efa0bc697404c0aa5322bbd5cc2d7796c2c) @@ -643,15 +643,38 @@ ? [list info command $x] "" "destroy via volatile" - # set x [nx::Class new -volatile { - # :public method bar {} {return 1} - # :public method baz {} {return 2} - # :new { :volatile; :bar; :baz } - # }] + set x [nx::Class new -volatile { + :public method bar {} {return 1} + :public method baz {} {return 2} + :new { :volatile; :bar; :baz } + }] - # ? [list info command $x] "" "destroy via volatile method" + ? [list info command $x] $x "destroy via volatile method" + # create new class and object and cleanup everything + 2 filters + ::nx::Object public method f1 args {next} + ::nx::Object public method f2 args {next} + ::nx::Object filter {f1 f2} + + set x [nx::Class new { + :volatile + :public method bar {} {return 1} + :public method baz {} {return 2} + :new { :volatile; :bar; :baz } + }] + + ? [list info command $x] "" "destroy via volatile + 2 filters" + + set x [nx::Class new -volatile { + :public method bar {} {return 1} + :public method baz {} {return 2} + :new { :volatile; :bar; :baz } + }] + + ? [list info command $x] $x "destroy via volatile method + 2 filters" + + ::nx::Object filter "" } #puts stderr "==== EXIT ===="