authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-10-07 22:48:56-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-07 22:48:56-07:00
logc001e191a19db32199ad75ccea219f729f9db7c4
tree05dce05522d5a41fff2abeb706c11722a2556988
parent6c1ce06996979fcfe120ec8c8cb4f78a5c8a7365
signature Signed by PGP key B5690EEEBB952194

fix(mobile): collect UI runtime garbage on iOS memory warnings (#16296)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

2 files changed, 27 insertions(+), 0 deletions(-)

apps/mobile/src/App.tsx+3
...@@ -23,6 +23,7 @@ import { appAtomRegistry } from "./state/atom-registry";...@@ -23,6 +23,7 @@ import { appAtomRegistry } from "./state/atom-registry";
23import { OverlayPortalHost } from "./components/OverlayPortal";23import { OverlayPortalHost } from "./components/OverlayPortal";
24import { shouldHandleAppLink } from "./lib/appLinking";24import { shouldHandleAppLink } from "./lib/appLinking";
25import { useMobileNavigationTheme } from "./lib/useMobileNavigationTheme";25import { useMobileNavigationTheme } from "./lib/useMobileNavigationTheme";
26import { useUiRuntimeMemoryWarningGc } from "./lib/useUiRuntimeMemoryWarningGc";
26import { SubscriptionUsageCoordinator } from "./widgets/SubscriptionUsageCoordinator";27import { SubscriptionUsageCoordinator } from "./widgets/SubscriptionUsageCoordinator";
27import { VoiceInputProvider } from "./features/voice-input/VoiceInputProvider";28import { VoiceInputProvider } from "./features/voice-input/VoiceInputProvider";
28import { GlobalVoiceInputControl } from "./features/voice-input/GlobalVoiceInputControl";29import { GlobalVoiceInputControl } from "./features/voice-input/GlobalVoiceInputControl";
...@@ -57,6 +58,8 @@ function SplashScreenCoordinator() {...@@ -57,6 +58,8 @@ function SplashScreenCoordinator() {
57}58}
5859
59export default function App() {60export default function App() {
61 useUiRuntimeMemoryWarningGc();
62
60 return (63 return (
61 <RegistryContext.Provider value={appAtomRegistry}>64 <RegistryContext.Provider value={appAtomRegistry}>
62 <CloudAuthProvider>65 <CloudAuthProvider>
apps/mobile/src/lib/useUiRuntimeMemoryWarningGc.ts created+24
...@@ -0,0 +1,24 @@
1import { useEffect } from "react";
2import { AppState } from "react-native";
3import { scheduleOnUI } from "react-native-worklets";
4
5function collectUiRuntimeGarbage() {
6 "worklet";
7 // Hermes exposes `gc` on the worklets UI runtime; skip quietly on runtimes that do not.
8 const gc = (globalThis as { gc?: () => void }).gc;
9 if (typeof gc === "function") gc();
10}
11
12/**
13 * React Native only collects the main JS runtime on an iOS memory warning. The
14 * worklets UI runtime is a separate Hermes heap that holds native shadow nodes and
15 * serializables alive until its own GC runs, so collect it on the same warning.
16 */
17export function useUiRuntimeMemoryWarningGc() {
18 useEffect(() => {
19 const subscription = AppState.addEventListener("memoryWarning", () => {
20 scheduleOnUI(collectUiRuntimeGarbage);
21 });
22 return () => subscription.remove();
23 }, []);
24}