Index: TODO =================================================================== diff -u -r7413d266916a491ff674489513351c89987366d7 -r6d831cc09c3eea83a17baa5ef05dfeb79b05836e --- TODO (.../TODO) (revision 7413d266916a491ff674489513351c89987366d7) +++ TODO (.../TODO) (revision 6d831cc09c3eea83a17baa5ef05dfeb79b05836e) @@ -3842,22 +3842,23 @@ In addition, the new approach is faster. - eliminating obsolete flag NSF_CSC_CALL_IS_TRANSPARENT +- use alias-stubs for aliases pointing to objects. This allows + us to distinguish between cases, where an object is dispatchable + due to the alias or due to allowmethoddispatch (when the object + happens to be a subobject and has therefore its cmd in the same + namespace). The semantics are now: + - aliases to objects are always dispatchable, no matter, how + allowmethoddispatch is set. + - direct subobjects of objects are currently on dispatchable + when allowmethoddispatch is set. Note, that this could + be seen as a method-property of the method-name, which + could be made "private" as well to avoud such dispatches. + ======================================================================== TODO: +- corollary: for complete configurability of method dispatch, we would + need as well a 3rd object-property: restrict-dispatch-to-object-methods -- make an additional attempt to use aliases instead of direct - object dispatches in ensembles - reconsider whether it is worth the effort. - -- also aliasMethods pointing to objects require that these objects - have allowmethoddispatch, since this is an object property - (not an alias property). - * contra: might be unexpected - * pro: if we keep the logic of ensemble methods with the per-object - methods, and/or the keepcallerself, it make sense to avoid mixing - interpretations from the point of view of different objects - - corollary: for complete configurability of method dispatch, we would - need as well a 3rd object-property: restrict-dispatch-to-object-methods - - pertaining allowmethoddispatch and keepcallerself in serializer - setting of allowmethoddispatch in XOTcl is weak, since set over constructor, which migh be overwritten by application classes Index: generic/nsf.c =================================================================== diff -u -r7413d266916a491ff674489513351c89987366d7 -r6d831cc09c3eea83a17baa5ef05dfeb79b05836e --- generic/nsf.c (.../nsf.c) (revision 7413d266916a491ff674489513351c89987366d7) +++ generic/nsf.c (.../nsf.c) (revision 6d831cc09c3eea83a17baa5ef05dfeb79b05836e) @@ -2121,7 +2121,7 @@ if (cmd) { *cmdPtr = cmd; - return NsfGetObjectFromCmdPtr(cmd); + return NsfGetObjectFromCmdPtr(GetOriginalCommand(cmd)); } return NULL; } @@ -2201,9 +2201,9 @@ int containsSpace; Tcl_Command cmd; - /* - fprintf(stderr,"methodName '%s' comp %d type %s\n", - methodName, strchr(methodName, ' ')>0, methodObj->typePtr ? methodObj->typePtr->name : "(none)");*/ + + /*fprintf(stderr,"methodName '%s' comp %d type %s\n", + methodName, strchr(methodName, ' ')>0, methodObj->typePtr ? methodObj->typePtr->name : "(none)");*/ if (methodObj->typePtr == Nsf_OT_listType) { int length; @@ -17138,8 +17138,10 @@ } case InfomethodsubcmdSubmethodsIdx: { - if (CmdIsNsfObject(cmd)) { - NsfObject *subObject = NsfGetObjectFromCmdPtr(cmd); + Tcl_Command origCmd = GetOriginalCommand(cmd); + + if (CmdIsNsfObject(origCmd)) { + NsfObject *subObject = NsfGetObjectFromCmdPtr(origCmd); if (subObject) { return ListDefinedMethods(interp, subObject, NULL, 1 /* per-object */, NSF_METHODTYPE_ALL, CallprotectionAllIdx, 0); @@ -17570,6 +17572,7 @@ hPtr = Tcl_CreateHashEntry(tablePtr, pattern, NULL); if (hPtr) { NsfObject *childObject; + Tcl_Command origCmd; key = Tcl_GetHashKey(tablePtr, hPtr); cmd = (Tcl_Command)Tcl_GetHashValue(hPtr); @@ -17583,15 +17586,20 @@ * Aliased objects methods return 1 but lookup from cmd returns * NULL. Below, we are just interested on true subobjects. */ - childObject = isObject ? NsfGetObjectFromCmdPtr(cmd) : NULL; + origCmd = GetOriginalCommand(cmd); + childObject = isObject ? NsfGetObjectFromCmdPtr(origCmd) : NULL; if (childObject) { if (withPath) { return TCL_OK; } - if ((childObject->flags & NSF_ALLOW_METHOD_DISPATCH ) == 0) { + /* + * Treat aliased object dispatch different from direct object + * dispatches. + */ + if (cmd == origCmd && (childObject->flags & NSF_ALLOW_METHOD_DISPATCH ) == 0) { /*fprintf(stderr, "no method dispatch allowed on child %s\n", ObjectName(childObject));*/ return TCL_OK; } @@ -17623,6 +17631,7 @@ hPtr; hPtr = Tcl_NextHashEntry(&hSrch)) { NsfObject *childObject; + Tcl_Command origCmd; key = Tcl_GetHashKey(tablePtr, hPtr); cmd = (Tcl_Command)Tcl_GetHashValue(hPtr); @@ -17633,7 +17642,8 @@ * Aliased objects methods return 1 but lookup from cmd returns * NULL. Below, we are just interested on true subobjects. */ - childObject = isObject ? NsfGetObjectFromCmdPtr(cmd) : NULL; + origCmd = GetOriginalCommand(cmd); + childObject = isObject ? NsfGetObjectFromCmdPtr(origCmd) : NULL; if (childObject) { if (withPath) { @@ -17667,7 +17677,11 @@ continue; } - if ((childObject->flags & NSF_ALLOW_METHOD_DISPATCH ) == 0) { + /* + * Treat aliased object dispatch different from direct object + * dispatches. + */ + if (cmd == origCmd && (childObject->flags & NSF_ALLOW_METHOD_DISPATCH ) == 0) { /*fprintf(stderr, "no method dispatch allowed on child %s\n", ObjectName(childObject));*/ continue; } @@ -18788,7 +18802,7 @@ newObjProc = NsfProcAliasMethod; } // TODO: for forcing redirectors on objects, do something like - //newObjProc = NsfProcAliasMethod; + newObjProc = NsfProcAliasMethod; /* * The new alias is pointing to an nsf object. In case no aliasMethod is @@ -23094,9 +23108,11 @@ if (subcmd == InfomethodsubcmdHandleIdx) { subcmd = InfomethodsubcmdDefinitionhandleIdx; } + /*fprintf(stderr, "NsfClassInfoMethodMethod object %p regObject %p defObject %p %s fromClass %d cmd %p method %s\n", &class->object, regObject, defObject, ObjectName(defObject), fromClassNS, cmd, methodName1);*/ + result = ListMethod(interp, regObject ? regObject : &class->object, defObject ? defObject : &class->object, Index: tests/destroy.test =================================================================== diff -u -r7413d266916a491ff674489513351c89987366d7 -r6d831cc09c3eea83a17baa5ef05dfeb79b05836e --- tests/destroy.test (.../destroy.test) (revision 7413d266916a491ff674489513351c89987366d7) +++ tests/destroy.test (.../destroy.test) (revision 6d831cc09c3eea83a17baa5ef05dfeb79b05836e) @@ -446,10 +446,10 @@ ? {o a info vars} x "query vars via alias" ? {o a set x} 10 "set var via alias" o2 destroy - ? {o a info vars} "Trying to dispatch deleted object via method 'a'" "1st call on deleted object" - ? {o a info vars} "::o: unable to dispatch method 'a'" "2nd call on deleted object" - #? {o a info vars} {target "o2" of alias a apparently disappeared} "1st call on deleted object" - #? {o a info vars} {target "o2" of alias a apparently disappeared} "2nd call on deleted object" + #? {o a info vars} "Trying to dispatch deleted object via method 'a'" "1st call on deleted object" + #? {o a info vars} "::o: unable to dispatch method 'a'" "2nd call on deleted object" + ? {o a info vars} {target "o2" of alias a apparently disappeared} "1st call on deleted object" + ? {o a info vars} {target "o2" of alias a apparently disappeared} "2nd call on deleted object" } Test case deleting-aliased-object2 { @@ -471,10 +471,10 @@ ? {o a set y 1} 1 "set var via alias (on o2)" ? {o a info vars} y "query vars via alias (from o2)" o2 destroy - ? {o a info vars} "Trying to dispatch deleted object via method 'a'" "1st call on deleted object" - ? {o a info vars} "::o: unable to dispatch method 'a'" "2nd call on deleted object" - #? {o a info vars} {target "o2" of alias a apparently disappeared} "1st call on deleted object" - #? {o a info vars} {target "o2" of alias a apparently disappeared} "2nd call on deleted object" + #? {o a info vars} "Trying to dispatch deleted object via method 'a'" "1st call on deleted object" + #? {o a info vars} "::o: unable to dispatch method 'a'" "2nd call on deleted object" + ? {o a info vars} {target "o2" of alias a apparently disappeared} "1st call on deleted object" + ? {o a info vars} {target "o2" of alias a apparently disappeared} "2nd call on deleted object" } set case "deleting object with alias to object" @@ -495,8 +495,8 @@ ::nsf::method::alias o x o3 #o::x destroy o3 destroy -#? {o x foo} {target "o3" of alias x apparently disappeared} -? {o x foo} {Trying to dispatch deleted object via method 'x'} +? {o x foo} {target "o3" of alias x apparently disappeared} +#? {o x foo} {Trying to dispatch deleted object via method 'x'} ? {::nsf::object::exists o3} 0 "aliased object destroyed" o destroy @@ -537,8 +537,8 @@ ? {c1 set B} 2 "call 1st level ok" ? {c1 set A} 3 "call 2nd level ok" o destroy - ? {c1 b} "Trying to dispatch deleted object via method 'b'" "call via alias to deleted object" - #? {c1 b} {target "o" of alias b apparently disappeared} "call via alias to deleted object" + #? {c1 b} "Trying to dispatch deleted object via method 'b'" "call via alias to deleted object" + ? {c1 b} {target "o" of alias b apparently disappeared} "call via alias to deleted object" } # Index: tests/info-method.test =================================================================== diff -u -r7413d266916a491ff674489513351c89987366d7 -r6d831cc09c3eea83a17baa5ef05dfeb79b05836e --- tests/info-method.test (.../info-method.test) (revision 7413d266916a491ff674489513351c89987366d7) +++ tests/info-method.test (.../info-method.test) (revision 6d831cc09c3eea83a17baa5ef05dfeb79b05836e) @@ -180,9 +180,16 @@ } :public alias soAlias ::o::sub } + # + # per default, we see just the alias + # ? {o info methods} "soAlias" ? {o info method type soAlias} "alias" + # + # if allowmethoddispatch is turned on, we see the alias and the + # submethod name + # nsf::object::property ::o::sub allowmethoddispatch on ? {o info methods} "soAlias sub" ? {o info method type sub} "object" @@ -198,12 +205,14 @@ :public alias i ::I :create c1 } - ? {C info methods i} "" - ? {c1 info lookup methods i} "" - #? {C info methods i} "i" - #? {c1 info lookup methods i} "i" - #? {C info methods *i} "i" - #? {c1 info lookup methods *i} "i" + # + # We see the alias to the object, no matter whether + # allowmethoddispatch on the target is turned on or off. + # + ? {C info methods i} "i" + ? {c1 info lookup methods i} "i" + ? {C info methods *i} "i" + ? {c1 info lookup methods *i} "i" ::nsf::object::property ::I allowmethoddispatch 1 ? {C info methods i} "i" Index: tests/interp.test =================================================================== diff -u -r8da343e4eb0b6166a184a0ab8eb7189d97eaff6f -r6d831cc09c3eea83a17baa5ef05dfeb79b05836e --- tests/interp.test (.../interp.test) (revision 8da343e4eb0b6166a184a0ab8eb7189d97eaff6f) +++ tests/interp.test (.../interp.test) (revision 6d831cc09c3eea83a17baa5ef05dfeb79b05836e) @@ -608,7 +608,10 @@ ? {$i eval {dongo bar foo}} OK $i hide x ? {$i hidden} x - ? {$i eval {dongo bar foo}} OK + + #? {$i eval {dongo bar foo}} OK + ? {$i eval {dongo bar foo}} {target "::x" of alias bar apparently disappeared} + ? {$i eval {x foo}} {invalid command name "x"} ? {$i invokehidden x foo} OK $i expose x @@ -618,13 +621,15 @@ $i hide x X ? {$i hidden} X - ? {$i eval {dongo bar foo}} OK + #? {$i eval {dongo bar foo}} OK + ? {$i eval {dongo bar foo}} {target "::x" of alias bar apparently disappeared} ? {$i eval {X foo}} {invalid command name "X"} ? {$i invokehidden X foo} OK $i expose X XX ? {$i hidden} "" - ? {$i eval {dongo bar foo}} OK + #? {$i eval {dongo bar foo}} OK + ? {$i eval {dongo bar foo}} {target "::x" of alias bar apparently disappeared} ? {$i eval {XX foo}} OK #