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";
2323import { OverlayPortalHost } from "./components/OverlayPortal";
2424import { shouldHandleAppLink } from "./lib/appLinking";
2525import { useMobileNavigationTheme } from "./lib/useMobileNavigationTheme";
26import { useUiRuntimeMemoryWarningGc } from "./lib/useUiRuntimeMemoryWarningGc";
2627import { SubscriptionUsageCoordinator } from "./widgets/SubscriptionUsageCoordinator";
2728import { VoiceInputProvider } from "./features/voice-input/VoiceInputProvider";
2829import { GlobalVoiceInputControl } from "./features/voice-input/GlobalVoiceInputControl";
......@@ -57,6 +58,8 @@ function SplashScreenCoordinator() {
5758}
5859
5960export default function App() {
61 useUiRuntimeMemoryWarningGc();
62
6063 return (
6164 <RegistryContext.Provider value={appAtomRegistry}>
6265 <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}