Index: TODO =================================================================== diff -u -r9a0b8bb0992be0561d8187c275fc1d9b7e0bbcd0 -r8c4e49a8486b47ce8caa35e9e48343accc7f2764 --- TODO (.../TODO) (revision 9a0b8bb0992be0561d8187c275fc1d9b7e0bbcd0) +++ TODO (.../TODO) (revision 8c4e49a8486b47ce8caa35e9e48343accc7f2764) @@ -3731,6 +3731,9 @@ - make time of the definition of a method independent on the number of defined instances (unless, when filters are defined) +nsf.c: +- fixed bug with recursive aliases +- extended regression test ======================================================================== Release Baustellen: Index: generic/nsf.c =================================================================== diff -u -rcd10a7994e42a39768ddc585f81690a26a124dd5 -r8c4e49a8486b47ce8caa35e9e48343accc7f2764 --- generic/nsf.c (.../nsf.c) (revision cd10a7994e42a39768ddc585f81690a26a124dd5) +++ generic/nsf.c (.../nsf.c) (revision 8c4e49a8486b47ce8caa35e9e48343accc7f2764) @@ -2,8 +2,8 @@ * nsf.c -- * * Basic Machinery of the Next Scripting Framework, a Tcl based framework - * for supporting language oriented programming. - * For Details, see http://next-scripting.org/ + * for supporting language oriented programming. For Details, see + * http://next-scripting.org/ * * Copyright (C) 1999-2011 Gustaf Neumann (a) (b) * Copyright (C) 1999-2007 Uwe Zdun (a) (b) @@ -9315,8 +9315,8 @@ * these elements takes care that the cmdPtr is deleted on a pop * operation (although we do a Tcl_DeleteCommandFromToken() below. */ - /*fprintf(stderr, "methodName %s FOUND deleted object with cmd %p my cscPtr %p\n", - methodName, cmd, cscPtr);*/ + fprintf(stderr, "methodName %s found DELETED object with cmd %p my cscPtr %p\n", + methodName, cmd, cscPtr); assert(cscPtr->cmdPtr == cmd); Tcl_DeleteCommandFromToken(interp, cmd); if (cscPtr->cl) { @@ -9473,6 +9473,7 @@ tcd->object = object; assert((CmdIsProc(cmd) == 0)); cscPtr->flags |= NSF_CSC_CALL_IS_TRANSPARENT; + } else if (cp == (ClientData)NSF_CMD_NONLEAF_METHOD) { cp = clientData; assert((CmdIsProc(cmd) == 0)); @@ -9487,8 +9488,8 @@ CscListAdd(interp, cscPtr); - /*fprintf(stderr, "cmdMethodDispatch %s.%s, nothing stacked, objflags %.6x\n", - ObjectName(object), methodName, object->flags); */ + /* fprintf(stderr, "cmdMethodDispatch %p %s.%s, nothing stacked, objflags %.6x\n", + cmd, ObjectName(object), methodName, object->flags); */ return CmdMethodDispatch(clientData, interp, objc, objv, object, cmd, NULL); } @@ -9907,7 +9908,8 @@ /* * If no fully qualified method name/filter/mixin was found then perform - * ordinary method lookup. + * ordinary method lookup. First, try to resolve the method name as a + * per-object method. */ if (likely(cmd == NULL)) { @@ -9933,13 +9935,16 @@ /* do we have an object-specific proc? */ if (object->nsPtr && (flags & (NSF_CM_NO_OBJECT_METHOD|NSF_CM_SYSTEM_METHOD)) == 0) { cmd = FindMethod(object->nsPtr, methodName); - /*fprintf(stderr, "lookup for proc in obj %p method %s nsPtr %p => %p\n", - object, methodName, object->nsPtr, cmd);*/ + /*fprintf(stderr, "lookup for per-object method in obj %p method %s nsPtr %p" + " => %p objProc %p\n", + object, methodName, object->nsPtr, cmd, + cmd ? ((Command *)cmd)->objProc : NULL);*/ if (cmd) { if ((flags & (NSF_CM_LOCAL_METHOD|NSF_CM_IGNORE_PERMISSIONS)) == 0 && (Tcl_Command_flags(cmd) & NSF_CMD_CALL_PRIVATE_METHOD)) { cmd = NULL; } else { + NsfMethodObjSet(interp, methodObj, &NsfObjectMethodObjType, object, nsfObjectMethodEpoch, cmd, NULL, flags); @@ -9956,7 +9961,7 @@ #endif if (likely(cmd == NULL)) { - /* check for a method inherited from a class */ + /* check for an instance method */ NsfClass *currentClass = object->cl; NsfMethodContext *mcPtr = methodObj->internalRep.twoPtrValue.ptr1; int nsfInstanceMethodEpoch = rst->instanceMethodEpoch; @@ -15352,6 +15357,9 @@ assert(self == GetSelfObj(interp)); + /*fprintf(stderr, "NsfProcAliasMethod aliasedCmd %p epoch %p\n", + tcd->aliasedCmd, Tcl_Command_cmdEpoch(tcd->aliasedCmd));*/ + if (Tcl_Command_cmdEpoch(tcd->aliasedCmd)) { NsfObject *defObject = tcd->class ? &(tcd->class->object) : self; Tcl_Obj **listElements, *entryObj, *targetObj; @@ -15381,14 +15389,25 @@ * version. */ cmd = Tcl_GetCommandFromObj(interp, targetObj); + if (cmd) { + cmd = GetOriginalCommand(cmd); + fprintf(stderr, "cmd %p epoch %d deleted %.6x\n", + cmd, + Tcl_Command_cmdEpoch(cmd), + Tcl_Command_flags(cmd) & CMD_IS_DELETED); + if (Tcl_Command_flags(cmd) & CMD_IS_DELETED) { + cmd = NULL; + } + } if (cmd == NULL) { int result = NsfPrintError(interp, "target \"%s\" of alias %s apparently disappeared", ObjStr(targetObj), methodName); DECR_REF_COUNT(entryObj); return result; } - cmd = GetOriginalCommand(cmd); + assert(Tcl_Command_objProc(cmd)); + NsfCommandRelease(tcd->aliasedCmd); tcd->objProc = Tcl_Command_objProc(cmd); tcd->aliasedCmd = cmd; @@ -18151,6 +18170,7 @@ cmd = GetOriginalCommand(cmd); objProc = Tcl_Command_objProc(cmd); + assert(objProc); /* objProc is either ... Index: tests/alias.test =================================================================== diff -u -r9a0b8bb0992be0561d8187c275fc1d9b7e0bbcd0 -r8c4e49a8486b47ce8caa35e9e48343accc7f2764 --- tests/alias.test (.../alias.test) (revision 9a0b8bb0992be0561d8187c275fc1d9b7e0bbcd0) +++ tests/alias.test (.../alias.test) (revision 8c4e49a8486b47ce8caa35e9e48343accc7f2764) @@ -763,4 +763,23 @@ # Recreation of the alias, must free refcount to the old object ? {::o alias X ::baff::child} "::o::X" -} \ No newline at end of file +} + +# +# Testing cylcic alias +# +nx::Test case cyclic-alias { + nx::Object create o { + set handle [:public method foo {} {return 1}] + # we can define currently the recursive definition + ? [list [:] public alias foo $handle] "::o::foo" + } + # at runtime, we get an exception + ? {o foo} {target "::o::foo" of alias foo apparently disappeared} + + # test indirect case + set handle1 [o public method foo {} {return 1}] + set handle2 [o public alias bar $handle1] + set handle3 [o public alias foo $handle2] + ? {o foo} {target "::o::bar" of alias foo apparently disappeared} +}