@@ -1104,6 +1104,90 @@ func TestBeginRescueTypedUnknownTypeFailsCompile(t *testing.T) {
11041104 }
11051105}
11061106
1107+ func TestBeginRescueReraisePreservesStack (t * testing.T ) {
1108+ script := compileScript (t , `
1109+ def inner()
1110+ assert false, "boom"
1111+ end
1112+
1113+ def middle()
1114+ begin
1115+ inner()
1116+ rescue(AssertionError)
1117+ raise
1118+ end
1119+ end
1120+
1121+ def outer()
1122+ middle()
1123+ end
1124+
1125+ def catches_reraise()
1126+ begin
1127+ middle()
1128+ rescue(AssertionError)
1129+ "caught"
1130+ end
1131+ end
1132+
1133+ def raise_outside()
1134+ raise
1135+ end
1136+
1137+ def raise_new_message()
1138+ raise "custom boom"
1139+ end
1140+ ` )
1141+
1142+ if got := callFunc (t , script , "catches_reraise" , nil ); ! got .Equal (NewString ("caught" )) {
1143+ t .Fatalf ("catches_reraise mismatch: %v" , got )
1144+ }
1145+
1146+ _ , err := script .Call (context .Background (), "outer" , nil , CallOptions {})
1147+ if err == nil || ! strings .Contains (err .Error (), "boom" ) {
1148+ t .Fatalf ("expected reraise error, got %v" , err )
1149+ }
1150+ var rtErr * RuntimeError
1151+ if ! errors .As (err , & rtErr ) {
1152+ t .Fatalf ("expected RuntimeError, got %T" , err )
1153+ }
1154+ if rtErr .Type != runtimeErrorTypeAssertion {
1155+ t .Fatalf ("expected assertion error type %s, got %s" , runtimeErrorTypeAssertion , rtErr .Type )
1156+ }
1157+ if len (rtErr .Frames ) < 4 {
1158+ t .Fatalf ("expected at least 4 frames, got %d" , len (rtErr .Frames ))
1159+ }
1160+ if rtErr .Frames [0 ].Function != "inner" {
1161+ t .Fatalf ("expected inner frame first, got %s" , rtErr .Frames [0 ].Function )
1162+ }
1163+ if rtErr .Frames [1 ].Function != "inner" {
1164+ t .Fatalf ("expected inner call site second, got %s" , rtErr .Frames [1 ].Function )
1165+ }
1166+ if rtErr .Frames [2 ].Function != "middle" {
1167+ t .Fatalf ("expected middle frame third, got %s" , rtErr .Frames [2 ].Function )
1168+ }
1169+ if rtErr .Frames [3 ].Function != "outer" {
1170+ t .Fatalf ("expected outer frame fourth, got %s" , rtErr .Frames [3 ].Function )
1171+ }
1172+
1173+ _ , err = script .Call (context .Background (), "raise_outside" , nil , CallOptions {})
1174+ if err == nil || ! strings .Contains (err .Error (), "raise used outside of rescue" ) {
1175+ t .Fatalf ("expected raise outside rescue error, got %v" , err )
1176+ }
1177+
1178+ _ , err = script .Call (context .Background (), "raise_new_message" , nil , CallOptions {})
1179+ if err == nil || ! strings .Contains (err .Error (), "custom boom" ) {
1180+ t .Fatalf ("expected raise message error, got %v" , err )
1181+ }
1182+ var raisedErr * RuntimeError
1183+ if ! errors .As (err , & raisedErr ) {
1184+ t .Fatalf ("expected RuntimeError, got %T" , err )
1185+ }
1186+ if raisedErr .Type != runtimeErrorTypeBase {
1187+ t .Fatalf ("expected runtime error type %s, got %s" , runtimeErrorTypeBase , raisedErr .Type )
1188+ }
1189+ }
1190+
11071191func TestLoopControlBreakAndNext (t * testing.T ) {
11081192 script := compileScript (t , `
11091193 def for_break()
0 commit comments