Index: generic/nsf.c =================================================================== diff -u -r98775245c7eb6eb2662fbccfd9fea1f30bd5f3d8 -rdd76d711addf35ee16af13d4d4a6774a8ebd1795 --- generic/nsf.c (.../nsf.c) (revision 98775245c7eb6eb2662fbccfd9fea1f30bd5f3d8) +++ generic/nsf.c (.../nsf.c) (revision dd76d711addf35ee16af13d4d4a6774a8ebd1795) @@ -15596,10 +15596,24 @@ } } else { /* - * Configure failed, therefore, the object might be in an undefined - * state. To avoid strange errors, we delete the half-baked object. + * Configure failed and might have left the object in a bogus state. To + * avoid strange errors, we delete the half-baked object. */ + + Tcl_Obj *errObj; + + /* + * Preserve the outer error message, calls triggered by + * DispatchDestroyMethod() can cause the interp result to be reset + */ + + errObj = Tcl_GetObjResult(interp); + INCR_REF_COUNT(errObj); + DispatchDestroyMethod(interp, (NsfObject *)object, 0); + + Tcl_SetObjResult(interp, errObj); + DECR_REF_COUNT(errObj); } NsfCleanupObject(object, "obj init"); Index: tests/parameters.test =================================================================== diff -u -r98775245c7eb6eb2662fbccfd9fea1f30bd5f3d8 -rdd76d711addf35ee16af13d4d4a6774a8ebd1795 --- tests/parameters.test (.../parameters.test) (revision 98775245c7eb6eb2662fbccfd9fea1f30bd5f3d8) +++ tests/parameters.test (.../parameters.test) (revision dd76d711addf35ee16af13d4d4a6774a8ebd1795) @@ -2803,4 +2803,37 @@ ? {o eval {info exists :a}} 1 ? {o eval {info exists :assignCalled}} 0; # !!! should be 1 ? {o a} 1 +} + +nx::Test case cmd-error-propagation { + ? {nx::Object new { + error "bow-wow" + }} "bow-wow" + + ? {nx::Object new { + :object method foo {} { + error "bow-wow" + } + :foo + }} "bow-wow" + + ? {nx::Object new { + # Note: Creating a slot causes a destroy() to perform some cascading + # operations which eventually reset the interp result at some + # point. + :object property x + :object method foo {} { error "bow-wow" } + :foo + }} "bow-wow" + + ? {nx::Object new { + :object method destroy {} { + # This (inner) error message is swallowed and written to stderr + # directly. The original (outer) error message is preserved. + error "BOW-WOW" + } + :object method foo {} { error "bow-wow" } + :foo + }} "bow-wow" + } \ No newline at end of file