Index: generic/nsf.c =================================================================== diff -u -re75f57c39bdc5455b65317013ed58d2db8d22dbd -r6b039871ad08a490bb975e3ddd713177f6dd9ea9 --- generic/nsf.c (.../nsf.c) (revision e75f57c39bdc5455b65317013ed58d2db8d22dbd) +++ generic/nsf.c (.../nsf.c) (revision 6b039871ad08a490bb975e3ddd713177f6dd9ea9) @@ -13925,17 +13925,30 @@ /*fprintf(stderr, "MethodProperty, ParamDefsGet cmd %p paramDefs %p returns %p\n", cmd, paramDefs, paramDefs?paramDefs->returns:NULL);*/ - if (paramDefs == NULL) { - paramDefs = ParamDefsNew(); - ParamDefsStore(interp, cmd, paramDefs); - /*fprintf(stderr, "new param defs %p for cmd %p %s\n", paramDefs, cmd, methodName);*/ - } - objPtr = methodproperty == MethodpropertySlotobjIdx ? ¶mDefs->slotObj : ¶mDefs->returns; if (valueObj == NULL) { - /* must be a returns query */ - Tcl_SetObjResult(interp, *objPtr ? *objPtr : NsfGlobalObjs[NSF_EMPTY]); + /* a query for "returns" or "slotobj" */ + Tcl_Obj *resultObj; + + if (paramDefs == NULL) { + resultObj = NsfGlobalObjs[NSF_EMPTY]; + } else { + objPtr = methodproperty == MethodpropertySlotobjIdx ? ¶mDefs->slotObj : ¶mDefs->returns; + resultObj = *objPtr ? *objPtr : NsfGlobalObjs[NSF_EMPTY]; + } + Tcl_SetObjResult(interp, resultObj); + } else { + /* setting "returns" or "slotobj" */ const char *valueString = ObjStr(valueObj); + + if (paramDefs == NULL) { + /* acquire new paramDefs */ + paramDefs = ParamDefsNew(); + ParamDefsStore(interp, cmd, paramDefs); + /*fprintf(stderr, "new param defs %p for cmd %p %s\n", paramDefs, cmd, methodName);*/ + } + objPtr = methodproperty == MethodpropertySlotobjIdx ? ¶mDefs->slotObj : ¶mDefs->returns; + /* Set a new value; if there is already a value, free it */ if (*objPtr) { DECR_REF_COUNT(*objPtr); Index: tests/returns.test =================================================================== diff -u -re75f57c39bdc5455b65317013ed58d2db8d22dbd -r6b039871ad08a490bb975e3ddd713177f6dd9ea9 --- tests/returns.test (.../returns.test) (revision e75f57c39bdc5455b65317013ed58d2db8d22dbd) +++ tests/returns.test (.../returns.test) (revision 6b039871ad08a490bb975e3ddd713177f6dd9ea9) @@ -354,14 +354,21 @@ Test case empty-paramdefs-robustedness { ::nx::Object create ku { - # Condition 1: An empty or checker-free parameter spec! + # 1: Create an empty or checker-free parameter spec :method foo {} {;} - # Condition 2: A call to ::nsf::methodproperty which acquires a - # NsfParamDefs - ::nsf::methodproperty [::nx::current] foo returns; # a returns query - # At this point, we find a NsfParamDefs structure with an empty set - # of params! Subsequent references to paramDefs->paramsPtr in - # e.g. ListCmdParams() would crash ... if not trapped appropriately. - ? [list [::nx::current] info method parameter foo] ""; # boom! + ? [:info method parameter foo] "" + # 2: A call to ::nsf::methodproperty which might require NsfParamDefs + ? [list ::nsf::methodproperty [::nx::current] foo returns] "" + # 3: Check, if "info method parameter" still works + ? [:info method parameter foo] "" + ? [list ::nsf::methodproperty [::nx::current] foo returns] "" + # 4: Set methodproperty to some value and check again + ::nsf::methodproperty [::nx::current] foo returns int + ? [list ::nsf::methodproperty [::nx::current] foo returns] "int" + ? [:info method parameter foo] "" + # 5: Reset methodproperty and query again + ::nsf::methodproperty [::nx::current] foo returns "" + ? [list ::nsf::methodproperty [::nx::current] foo returns] "" + ? [:info method parameter foo] "" } } \ No newline at end of file