Index: generic/nsf.c =================================================================== diff -u -r47f388cda74f1b4656389d4129b96435034ac4a4 -red5cc784dfa9e971fd124701a7bdfb9d609512a5 --- generic/nsf.c (.../nsf.c) (revision 47f388cda74f1b4656389d4129b96435034ac4a4) +++ generic/nsf.c (.../nsf.c) (revision ed5cc784dfa9e971fd124701a7bdfb9d609512a5) @@ -18663,13 +18663,15 @@ * *---------------------------------------------------------------------- */ -static int InvokeShadowedProc(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Command cmd, ParseContext *pcPtr, +static int InvokeShadowedProc(Tcl_Interp *interp, Tcl_Obj *procNameObj, + Tcl_Command cmd, ParseContext *pcPtr, struct Tcl_Time *trtPtr, unsigned int cmdFlags, - Tcl_Namespace *execNsPtr) + Tcl_Namespace *execNsPtr) nonnull(1) nonnull(2) nonnull(4) nonnull(3) nonnull(4) nonnull(5); static int -InvokeShadowedProc(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Command cmd, ParseContext *pcPtr, +InvokeShadowedProc(Tcl_Interp *interp, Tcl_Obj *procNameObj, + Tcl_Command cmd, ParseContext *pcPtr, struct Tcl_Time *trtPtr, unsigned int cmdFlags, Tcl_Namespace *execNsPtr) { Tcl_Obj *const *objv; @@ -18697,33 +18699,6 @@ * slightly adapted to remove object dependencies. */ - if (Tcl_Command_cmdEpoch(cmd) != 0) { -#if 1 - /* - * It seems, as someone messed around with the shadowed proc. For now, we - * give up. - */ - return NsfPrintError(interp, "command '%s' is epoched", fullMethodName); -#else - /* - * We must refetch the command ... - */ - cmd = Tcl_GetCommandFromObj(interp, procNameObj); - if (unlikely(cmd == NULL)) { - return NsfPrintError(interp, "cannot lookup command '%s'", fullMethodName); - } - if (unlikely(!CmdIsProc(cmd))) { - return NsfPrintError(interp, "command '%s' is not a proc", fullMethodName); - } - /* - * ... and update the refCounts and cmd in ClientData - */ - NsfCommandRelease(tcd->cmd); - tcd->cmd = cmd; - NsfCommandPreserve(tcd->cmd); -#endif - } - procPtr = (Proc *)Tcl_Command_objClientData(cmd); result = TclPushStackFrame(interp, &framePtr, execNsPtr /* procPtr->cmdPtr->nsPtr */, @@ -18870,11 +18845,41 @@ trt.usec = 0; } #endif - + if ((cmdFlags & NSF_CMD_DEPRECATED_METHOD) != 0u) { NsfDeprecatedCmd(interp, "proc", ObjStr(objv[0]), ""); } + + if ((((unsigned int)Tcl_Command_flags(tcd->cmd) & CMD_IS_DELETED) == 0u) || + Tcl_Command_cmdEpoch(tcd->cmd) != 0) { + /* + * It seems, as the cached command was deleted (e.g., rename), or someone + * messed around with the shadowed proc. + * + * We must refetch the command ... + */ + + Tcl_Command newCmdPtr = Tcl_GetCommandFromObj(interp, tcd->procName); + + if (unlikely(newCmdPtr == NULL)) { + return NsfPrintError(interp, "cannot lookup command '%s'", + ObjStr(tcd->procName)); + } + + if (unlikely(!CmdIsProc(newCmdPtr))) { + return NsfPrintError(interp, "command '%s' is not a proc", + ObjStr(tcd->procName)); + } + + /* + * ... and update the refCounts and cmd in ClientData + */ + NsfCommandRelease(tcd->cmd); + tcd->cmd = newCmdPtr; + NsfCommandPreserve(tcd->cmd); + } + result = InvokeShadowedProc(interp, tcd->procName, tcd->cmd, pcPtr, &trt, cmdFlags, Tcl_Command_nsPtr(cmd)); Index: tests/nsf-cmd.test =================================================================== diff -u -r47f388cda74f1b4656389d4129b96435034ac4a4 -red5cc784dfa9e971fd124701a7bdfb9d609512a5 --- tests/nsf-cmd.test (.../nsf-cmd.test) (revision 47f388cda74f1b4656389d4129b96435034ac4a4) +++ tests/nsf-cmd.test (.../nsf-cmd.test) (revision ed5cc784dfa9e971fd124701a7bdfb9d609512a5) @@ -511,7 +511,12 @@ } -nx::test case nsf-proc-rename { +# to-dos: +# - basic rename-delete +# - rename chain +# - interp hide/expose + +nx::test case nsf-proc-rename-redefine { namespace eval ::ns1 {} nsf::proc ns1::foo { @@ -531,7 +536,30 @@ namespace delete ::ns1 } +nx::test case nsf-proc-rename-redefine-call { + namespace eval ::ns1 {} + + nsf::proc ns1::foo { + {-x:required} + } { return 1-$x } + ? {ns1::foo -x ok} 1-ok + + rename ns1::foo ns1::foo.orig + + nsf::proc ns1::foo { + {-x:required} + } { return 2-$x } + + ? {ns1::foo -x ok} 2-ok + + ? {ns1::foo.orig -x ok} 2-ok; # should be 1-ok! + + namespace delete ::ns1 +} + + + # # Local variables: # mode: tcl