@@ -777,6 +777,61 @@ test "window_closing lifecycle message is ignored in web-url mode without tracke
777777 try std .testing .expect (! should_close );
778778}
779779
780+ test "websocket disconnect schedules close in browser-window mode when last client is gone" {
781+ var gpa = std .heap .GeneralPurposeAllocator (.{}){};
782+ defer _ = gpa .deinit ();
783+
784+ var app = try App .init (gpa .allocator (), .{
785+ .launch_policy = .{ .first = .browser_window , .second = null , .third = null },
786+ });
787+ defer app .deinit ();
788+
789+ var win = try app .newWindow (.{ .title = "WsDisconnectCloseBrowserWindow" });
790+ try win .showHtml ("<html><body>ws-disconnect-close-browser-window</body></html>" );
791+ try app .run ();
792+
793+ win .state ().state_mutex .lock ();
794+ win .state ().runtime_render_state .active_surface = .browser_window ;
795+ win .state ().noteWsDisconnectLocked ("test-disconnect" );
796+ const pending_after_disconnect = win .state ().lifecycle_close_pending ;
797+ const close_immediate = win .state ().close_requested .load (.acquire );
798+ win .state ().state_mutex .unlock ();
799+
800+ try std .testing .expect (pending_after_disconnect );
801+ try std .testing .expect (! close_immediate );
802+
803+ win .state ().state_mutex .lock ();
804+ win .state ().lifecycle_close_deadline_ms = std .time .milliTimestamp () - 1 ;
805+ win .state ().reconcileChildExit (gpa .allocator ());
806+ const should_close = win .state ().close_requested .load (.acquire );
807+ win .state ().state_mutex .unlock ();
808+ try std .testing .expect (should_close );
809+ }
810+
811+ test "websocket disconnect does not close backend in web-url mode" {
812+ var gpa = std .heap .GeneralPurposeAllocator (.{}){};
813+ defer _ = gpa .deinit ();
814+
815+ var app = try App .init (gpa .allocator (), .{
816+ .launch_policy = .{ .first = .web_url , .second = null , .third = null },
817+ });
818+ defer app .deinit ();
819+
820+ var win = try app .newWindow (.{ .title = "WsDisconnectNoCloseWebUrl" });
821+ try win .showHtml ("<html><body>ws-disconnect-no-close-web-url</body></html>" );
822+ try app .run ();
823+
824+ win .state ().state_mutex .lock ();
825+ win .state ().runtime_render_state .active_surface = .web_url ;
826+ win .state ().noteWsDisconnectLocked ("test-disconnect" );
827+ const pending = win .state ().lifecycle_close_pending ;
828+ const should_close = win .state ().close_requested .load (.acquire );
829+ win .state ().state_mutex .unlock ();
830+
831+ try std .testing .expect (! pending );
832+ try std .testing .expect (! should_close );
833+ }
834+
780835test "non-linked tracked browser pid death detaches without close in web mode" {
781836 if (builtin .os .tag != .linux ) return error .SkipZigTest ;
782837
0 commit comments