Index: TODO =================================================================== diff -u -r0378d1c22ef6e05c54af07058a0315d7a9f20cab -r7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3 --- TODO (.../TODO) (revision 0378d1c22ef6e05c54af07058a0315d7a9f20cab) +++ TODO (.../TODO) (revision 7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3) @@ -3394,6 +3394,8 @@ * allow protected and private methods to be used as filters * added regression tests * some cleanup in regression tests + * added support for calling private methods via -local and filters + * extended regression test for private + filters TODO: - fix interp.test for tcl 8.6 @@ -3405,7 +3407,6 @@ * tests for private + mixins * tests for object-specific private methods * flag "-local" in dispatch is maybe confusing - * -local and filter - nx: * maybe provide a replacement for -attributes, but without the magic variable. Index: generic/nsf.c =================================================================== diff -u -r0378d1c22ef6e05c54af07058a0315d7a9f20cab -r7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3 --- generic/nsf.c (.../nsf.c) (revision 0378d1c22ef6e05c54af07058a0315d7a9f20cab) +++ generic/nsf.c (.../nsf.c) (revision 7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3) @@ -7644,13 +7644,17 @@ *currentCmd = NULL; - /* Ensure that the filter order is not invalid, otherwise compute order - FilterComputeDefined(interp, object); - */ + /* + * Ensure that the filter order is not invalid, otherwise compute order + * FilterComputeDefined(interp, object); + */ assert(object->flags & NSF_FILTER_ORDER_VALID); + cmdList = SeekCurrent(object->filterStack->currentCmdPtr, object->filterOrder); while (cmdList) { + /*fprintf(stderr, "FilterSearchProc found %s\n", + Tcl_GetCommandName(interp, (Tcl_Command)cmdList->cmdPtr));*/ if (Tcl_Command_cmdEpoch(cmdList->cmdPtr)) { cmdList = cmdList->nextPtr; } else if (FilterActiveOnObj(interp, object, cmdList->cmdPtr)) { @@ -10037,10 +10041,6 @@ NsfStackDump(interp); #endif -#ifdef CALLSTACK_TRACE - NsfCallStackDump(interp); -#endif - if (objc > 1) { /* * Normal dispatch; we must not use NSF_CSC_IMMEDIATE here, @@ -12418,8 +12418,8 @@ object->filterStack->currentCmdPtr) { *cmdPtr = FilterSearchProc(interp, object, currentCmdPtr, clPtr); - /*fprintf(stderr, "EndOfChain? cmd=%p\n",*cmdPtr);*/ - /* NsfCallStackDump(interp); NsfStackDump(interp);*/ + /*fprintf(stderr, "FilterSearchProc returned cmd %p\n", *cmdPtr); + NsfShowStack(interp);*/ if (*cmdPtr == NULL) { if (cscPtr->frameType == NSF_CSC_TYPE_ACTIVE_FILTER) { @@ -12468,8 +12468,6 @@ } } - - /*fprintf(stderr, "nextsearch: object %s nsPtr %p endOfChain %d\n", ObjectName(object), object->nsPtr, endOfChain);*/ @@ -12489,6 +12487,7 @@ } else if (object->nsPtr) { *cmdPtr = FindMethod(object->nsPtr, *methodNamePtr); if (*cmdPtr && (Tcl_Command_flags(*cmdPtr) & NSF_CMD_CALL_PRIVATE_METHOD)) { + /*fprintf(stderr, "NEXT found private cmd %s => %p\n", *methodNamePtr, *cmdPtr);*/ *cmdPtr = NULL; } } else { @@ -12498,8 +12497,8 @@ *cmdPtr = NULL; } - /*fprintf(stderr, "NEXT methodName %s *clPtr %p %s *cmd %p\n", - *methodNamePtr, *clPtr, ClassName((*clPtr)), *cmdPtr); */ + /*fprintf(stderr, "NEXT methodName %s *clPtr %p %s *cmd %p cscPtr->flags %.6x\n", + *methodNamePtr, *clPtr, ClassName((*clPtr)), *cmdPtr, cscPtr->flags); */ if (!*cmdPtr) { NsfClasses *pl = ComputeOrder(object->cl, object->cl->order, Super); @@ -12518,9 +12517,13 @@ } /* - * Search for a further class method + * Search for a further class method. When we are called from an active + * filter and the call had the -local flag set, then allow to call private methods. */ - *clPtr = SearchPLMethod(pl, *methodNamePtr, cmdPtr, NSF_CMD_CALL_PRIVATE_METHOD); + *clPtr = SearchPLMethod(pl, *methodNamePtr, cmdPtr, + ((cscPtr->flags & NSF_CM_LOCAL_METHOD) && + cscPtr->frameType == NSF_CSC_TYPE_ACTIVE_FILTER) + ? 0 : NSF_CMD_CALL_PRIVATE_METHOD); } else { *clPtr = NULL; Index: generic/nsf.h =================================================================== diff -u -race51b03d7e2b835c6867943f49c6ad5fa4c1b65 -r7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3 --- generic/nsf.h (.../nsf.h) (revision ace51b03d7e2b835c6867943f49c6ad5fa4c1b65) +++ generic/nsf.h (.../nsf.h) (revision 7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3) @@ -102,7 +102,6 @@ /* turn tracing output on/off #define NSFOBJ_TRACE 1 -#define CALLSTACK_TRACE 1 #define NAMESPACE_TRACE 1 #define OBJDELETION_TRACE 1 #define STACK_TRACE 1 Index: generic/nsfInt.h =================================================================== diff -u -rb57f4b6701eadc6f177da91291638d26da3322ba -r7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3 --- generic/nsfInt.h (.../nsfInt.h) (revision b57f4b6701eadc6f177da91291638d26da3322ba) +++ generic/nsfInt.h (.../nsfInt.h) (revision 7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3) @@ -700,7 +700,6 @@ #define NSF_CSC_FILTER_STACK_PUSHED 0x008000 #define NSF_CSC_METHOD_IS_UNKNOWN 0x010000 #define NSF_CSC_CALL_IS_TRANSPARENT 0x020000 -#define NSF_CSC_COPY_FLAGS (NSF_CSC_MIXIN_STACK_PUSHED|NSF_CSC_FILTER_STACK_PUSHED|NSF_CSC_IMMEDIATE|NSF_CSC_CALL_IS_TRANSPARENT|NSF_CSC_FORCE_FRAME) /* flags for call method */ #define NSF_CM_NO_UNKNOWN 0x000001 @@ -711,6 +710,8 @@ #define NSF_CM_LOCAL_METHOD 0x000020 #define NSF_CM_INTRINSIC_METHOD 0x000040 +#define NSF_CSC_COPY_FLAGS (NSF_CSC_MIXIN_STACK_PUSHED|NSF_CSC_FILTER_STACK_PUSHED|NSF_CSC_IMMEDIATE|NSF_CSC_CALL_IS_TRANSPARENT|NSF_CSC_FORCE_FRAME|NSF_CM_LOCAL_METHOD) + #define NSF_VAR_TRIGGER_TRACE 1 #define NSF_VAR_REQUIRE_DEFINED 2 #define NSF_VAR_ISARRAY 4 Index: generic/nsfStack.c =================================================================== diff -u -rf177b4dbbb589f91704b1acb8dfbd91fc076335a -r7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3 --- generic/nsfStack.c (.../nsfStack.c) (revision f177b4dbbb589f91704b1acb8dfbd91fc076335a) +++ generic/nsfStack.c (.../nsfStack.c) (revision 7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3) @@ -79,21 +79,22 @@ Tcl_CallFrame_objc(framePtr) ? ObjStr(Tcl_CallFrame_objv(framePtr)[0]) : "(null)"); }*/ framePtr = (Tcl_CallFrame *)Tcl_Interp_framePtr(interp); + fprintf(stderr, "... varFrame flags clientData lvl ns\n"); for (; framePtr; framePtr = Tcl_CallFrame_callerPtr(framePtr)) { int frameFlags = Tcl_CallFrame_isProcCallFrame(framePtr); NsfCallStackContent *cscPtr = (frameFlags & (FRAME_IS_NSF_METHOD|FRAME_IS_NSF_CMETHOD)) ? ((NsfCallStackContent *)Tcl_CallFrame_clientData(framePtr)) : NULL; - fprintf(stderr, "... var frame %p flags %.6x cd %p lvl %d ns %p %s ov %s %d", + fprintf(stderr, "... %16p %.6x %16p %3d %16p %s ov %s %d", framePtr, frameFlags, Tcl_CallFrame_clientData(framePtr), Tcl_CallFrame_level(framePtr), Tcl_CallFrame_nsPtr(framePtr), Tcl_CallFrame_nsPtr(framePtr)->fullName, 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 (%s.%p %s)\n", + fprintf(stderr, " csc %p frameType %.4x flags %.6x (%s.%p %s)\n", cscPtr, cscPtr ? cscPtr->frameType : -1, cscPtr ? cscPtr->flags : -1, Index: nxsh.in =================================================================== diff -u -r0f3ecd0524a309ace0729dbfeb5f299f8bf7a250 -r7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3 --- nxsh.in (.../nxsh.in) (revision 0f3ecd0524a309ace0729dbfeb5f299f8bf7a250) +++ nxsh.in (.../nxsh.in) (revision 7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3) @@ -36,6 +36,6 @@ set argv [lreplace $argv 0 0] incr argc -1 if {[catch [list source $argv0] errorMsg]} { - return -level 1 $errorMsg + return -code error -level 1 $errorMsg } } Index: tests/protected.test =================================================================== diff -u -r0378d1c22ef6e05c54af07058a0315d7a9f20cab -r7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3 --- tests/protected.test (.../protected.test) (revision 0378d1c22ef6e05c54af07058a0315d7a9f20cab) +++ tests/protected.test (.../protected.test) (revision 7b8ab056c2dafa49164db2e9ccddd9cb6d5b6fb3) @@ -259,7 +259,51 @@ ? {c1 foo} "c1.baz" } +# +# Check local + filter +# +nx::Test case local+filter { + nx::Class create C { + :method f1 args { return "f1 [next]" } + :public method foo {} { return "C.foo [nsf::my -local bar]"} + :private method bar {} { return "bar"} + :public method baz {} { return "C.baz [next]"} + } + nx::Class create D -superclass C { + :public method baz {} { return "D.baz [next]"} + } + D create d1 + ? {d1 baz} "D.baz C.baz " + ? {d1 foo} "C.foo bar" + ? {d1 bar} "::d1: unable to dispatch method 'bar'" + + # add a filter; be sure that we still can call the private -local + # method + d1 filter add f1 + ? {d1 baz} "f1 D.baz C.baz " + ? {d1 foo} "f1 C.foo f1 bar" + ? {d1 bar} "::d1: unable to dispatch method 'bar'" + + # remove the filter + d1 filter "" + # define call to private method via method handle + C public method foo {} { return "C.foo [[self] [C info method handle bar]]"} + + # the behavior without filter, should be like above + ? {d1 baz} "D.baz C.baz " + ? {d1 foo} "C.foo bar" + ? {d1 bar} "::d1: unable to dispatch method 'bar'" + + # add a filter; be sure that we still can call the private method + d1 filter add f1 + ? {d1 baz} "f1 D.baz C.baz " + ? {d1 foo} "f1 C.foo f1 bar" + ? {d1 bar} "::d1: unable to dispatch method 'bar'" +} + + + # # test private #