Index: generic/nsf.c =================================================================== diff -u -r404b55935a5b1650bed72125c793906f44074533 -r2c338821c949f8eb468c54a537d96a1d90b55805 --- generic/nsf.c (.../nsf.c) (revision 404b55935a5b1650bed72125c793906f44074533) +++ generic/nsf.c (.../nsf.c) (revision 2c338821c949f8eb468c54a537d96a1d90b55805) @@ -18472,21 +18472,32 @@ FindSelfNext(Tcl_Interp *interp) { NsfCallStackContent *cscPtr; int result; - + Tcl_CallFrame *framePtr; + nonnull_assert(interp != NULL); - cscPtr = CallStackGetTopFrame0(interp); + cscPtr = CallStackGetTopFrame(interp, &framePtr); + if (unlikely(cscPtr == NULL)) { result = NsfPrintError(interp, "called outside NSF scope"); } else { Tcl_Command cmd = NULL, currentCmd = NULL; - const char *methodName; + const char *lookupMethodName = NULL, *methodName; + int isEnsemble = (cscPtr->frameType & NSF_CSC_TYPE_ENSEMBLE) != 0u; Tcl_ResetResult(interp); methodName = Tcl_GetCommandName(interp, cscPtr->cmdPtr); - if (methodName == NULL) { + if (isEnsemble) { + NsfCallStackContent *cscPtr1; + cscPtr1 = CallStackFindEnsembleCsc(framePtr, &framePtr); + lookupMethodName = MethodName(cscPtr1->objv[0]); + } else { + lookupMethodName = methodName; + } + + if (lookupMethodName == NULL) { /* * In case, we do not find the command, we return OK. Why? */ @@ -18496,9 +18507,10 @@ NsfClass *cl = cscPtr->cl; NsfObject *object = cscPtr->self; - result = NextSearchMethod(object, interp, cscPtr, &cl, &methodName, &cmd, + result = NextSearchMethod(object, interp, cscPtr, &cl, &lookupMethodName, &cmd, &isMixinEntry, &isFilterEntry, &endOfFilterChain, ¤tCmd); if (cmd != NULL) { + methodName = isEnsemble ? ObjStr(NsfMethodNamePath(interp, framePtr, methodName)) : lookupMethodName; Tcl_SetObjResult(interp, MethodHandleObj((cl != NULL) ? (NsfObject *)cl : object, cl == NULL, methodName)); } Index: tests/submethods.test =================================================================== diff -u -r2a10ca191c0d398430ad7b6b86bf0714a141e089 -r2c338821c949f8eb468c54a537d96a1d90b55805 --- tests/submethods.test (.../submethods.test) (revision 2a10ca191c0d398430ad7b6b86bf0714a141e089) +++ tests/submethods.test (.../submethods.test) (revision 2c338821c949f8eb468c54a537d96a1d90b55805) @@ -911,10 +911,36 @@ ? {b x s} $sc } +nx::test case ensemble-callstack-introspection { + set ::body { + return [list [current nextmethod] {*}[next]] + } + + nx::Class create A { + set ::handle [:method "i s" args $::body] + } + + nx::Class create B -superclasses A { + :public method "i s" args $::body + :create b + } + + ? {b eval { :i s }} {{::nsf::classes::A::i s} {}} + ? {::nsf::cmd::info args [lindex [b eval { :i s }] 0]} "args" + ? {::nsf::cmd::info definitionhandle [lindex [b eval { :i s }] 0]} $::handle + ? {::nsf::cmd::info body [lindex [b eval { :i s }] 0]} $::body + ? {b i s} {{::nsf::classes::A::i s} {}}; + ? {::nsf::cmd::info args [lindex [b i s] 0]} "args" + ? {::nsf::cmd::info definitionhandle [lindex [b i s] 0]} $::handle + ? {::nsf::cmd::info body [lindex [b i s] 0]} $::body + + unset -nocomplain ::handle + unset -nocomplain ::body +} + # # Local variables: # mode: tcl # tcl-indent-level: 2 # indent-tabs-mode: nil # End: -