Interpreter: Fix delegate through try_table (#9234)

When an exception is delegated to an outer scope via legacy
try-delegate, the interpreter would previously fail to propagate it
through try_table to the delegate target.
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 8f79022..d5e358a 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -4963,6 +4963,12 @@
     try {
       return self()->visit(curr->body);
     } catch (const WasmException& e) {
+      // If delegation is in progress, try_table cannot be the target of a
+      // legacy try-delegate, so don't handle it and just rethrow.
+      if (scope->currDelegateTarget.is()) {
+        throw;
+      }
+
       auto exnData = e.exn.getExnData();
       for (size_t i = 0; i < curr->catchTags.size(); i++) {
         auto catchTag = curr->catchTags[i];
diff --git a/test/lit/exec/eh-legacy.wast b/test/lit/exec/eh-legacy.wast
index 6a95652..3c03550 100644
--- a/test/lit/exec/eh-legacy.wast
+++ b/test/lit/exec/eh-legacy.wast
@@ -47,6 +47,46 @@
       )
     )
   )
+
+  ;; CHECK:      [fuzz-exec] export try-delegate-caller-through-try_table
+  ;; CHECK-NEXT: [exception thrown: e-i32 5]
+  (func $try-delegate-caller-through-try_table (export "try-delegate-caller-through-try_table")
+    ;; Delegation to the caller should bypass an intermediate try_table.
+    (block $catch
+      (try_table (catch_all $catch)
+        (try
+          (do
+            (throw $e-i32 (i32.const 5))
+          )
+          (delegate 1)
+        )
+      )
+    )
+  )
+
+  ;; CHECK:      [fuzz-exec] export try-delegate-try-through-try_table
+  ;; CHECK-NEXT: [fuzz-exec] note result: try-delegate-try-through-try_table => 6
+  (func $try-delegate-try-through-try_table (export "try-delegate-try-through-try_table") (result i32)
+    ;; Delegation to an outer try should also bypass an intermediate try_table.
+    (try $l0 (result i32)
+      (do
+        (block $catch
+          (try_table (catch_all $catch)
+            (try
+              (do
+                (throw $e-i32 (i32.const 6))
+              )
+              (delegate $l0)
+            )
+          )
+        )
+        (i32.const 0)
+      )
+      (catch $e-i32
+        (pop i32)
+      )
+    )
+  )
 )
 ;; CHECK:      [fuzz-exec] export throw
 ;; CHECK-NEXT: [exception thrown: e-i32 1]
@@ -58,7 +98,15 @@
 
 ;; CHECK:      [fuzz-exec] export try-delegate
 ;; CHECK-NEXT: [exception thrown: e-i32 4]
+
+;; CHECK:      [fuzz-exec] export try-delegate-caller-through-try_table
+;; CHECK-NEXT: [exception thrown: e-i32 5]
+
+;; CHECK:      [fuzz-exec] export try-delegate-try-through-try_table
+;; CHECK-NEXT: [fuzz-exec] note result: try-delegate-try-through-try_table => 6
 ;; CHECK-NEXT: [fuzz-exec] comparing catchless-try
 ;; CHECK-NEXT: [fuzz-exec] comparing throw
 ;; CHECK-NEXT: [fuzz-exec] comparing try-catch
 ;; CHECK-NEXT: [fuzz-exec] comparing try-delegate
+;; CHECK-NEXT: [fuzz-exec] comparing try-delegate-caller-through-try_table
+;; CHECK-NEXT: [fuzz-exec] comparing try-delegate-try-through-try_table