From 1a99c038a8b8a78a79495df03e081e30c5b5dfe0 Mon Sep 17 00:00:00 2001
From: Galen Warren <galen.warren@coachclientconnect.com>
Date: Sun, 23 Jun 2024 14:07:45 -0400
Subject: [PATCH] feat: fix hang that occurs when hot restarting

---
 CHANGELOG.md                              |  1 +
 lib/src/client/transport/web_streams.dart | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d336d3de..398f2c81 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
 * Remove generated status codes.
 * Remove dependency on `package:archive`.
 * Move `codec.dart`.
+* Work around hang during Flutter hot restart by adding default case handler in _GrpcWebConversionSink.add.
 
 ## 3.2.4
 
diff --git a/lib/src/client/transport/web_streams.dart b/lib/src/client/transport/web_streams.dart
index aba0a7bc..8480ab29 100644
--- a/lib/src/client/transport/web_streams.dart
+++ b/lib/src/client/transport/web_streams.dart
@@ -132,6 +132,16 @@ class _GrpcWebConversionSink implements ChunkedConversionSink<ByteBuffer> {
   void add(ByteBuffer chunk) {
     _chunkOffset = 0;
     final chunkData = chunk.asUint8List();
+    // in flutter web, when a hot-restart is requested, the code can get stuck
+    // in the following loop if there is an active streaming call. the
+    // switch statement is invoked but doesn't match any of the cases. this
+    // presumably has something to do how enums work across isolates.
+    // possibly related to https://github.com/dart-lang/sdk/issues/35626.
+    //
+    // in any case, adding a default handler to the switch statement
+    // causes this loop to end in that case, allowing the old isolate
+    // to shut down and the hot-restart to work properly.
+    processingLoop:
     while (_chunkOffset < chunk.lengthInBytes) {
       switch (_state) {
         case _GrpcWebParseState.init:
@@ -143,6 +153,9 @@ class _GrpcWebConversionSink implements ChunkedConversionSink<ByteBuffer> {
         case _GrpcWebParseState.message:
           _parseMessage(chunkData);
           break;
+        default:
+          // only expected to be hit when hot-restarting, see above
+          break processingLoop;
       }
     }
     _chunkOffset = 0;