From d1f1b5eb7d2f9cb2dea8e93a52db1371e84fc328 Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Thu, 22 Oct 2026 12:35:19 -0700 Subject: [PATCH 1/2] Read launchOptions from injection in RCTLinkingManager (#59259) Summary: Synthesize the injected launchOptions property and read getInitialURL state from it instead of self.bridge. Drops the last bridge read in this module along with its direct bridge header import. Changelog: [Internal] Reviewed By: shwanton Differential Revision: D126567470 --- .../Libraries/LinkingIOS/RCTLinkingManager.mm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm index f25ad54a5f4a..76d6f526d9fa 100644 --- a/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm +++ b/packages/react-native/Libraries/LinkingIOS/RCTLinkingManager.mm @@ -8,7 +8,6 @@ #import #import -#import #import #import #import @@ -36,6 +35,8 @@ @implementation RCTLinkingManager RCT_EXPORT_MODULE() +@synthesize launchOptions = _launchOptions; + + (void)postNotificationWithURL:(NSURL *)URL { NSDictionary *payload = @{@"url" : URL.absoluteString}; @@ -207,11 +208,10 @@ - (void)canOpenURL:(NSString *)urlString - (void)getInitialURL:(RCTPromiseResolveBlock)resolve reject:(__unused RCTPromiseRejectBlock)reject { NSURL *initialURL = nil; - if (self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey] != nullptr) { - initialURL = self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]; + if (self.launchOptions[UIApplicationLaunchOptionsURLKey] != nullptr) { + initialURL = self.launchOptions[UIApplicationLaunchOptionsURLKey]; } else { - NSDictionary *userActivityDictionary = - self.bridge.launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey]; + NSDictionary *userActivityDictionary = self.launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey]; if ([userActivityDictionary[UIApplicationLaunchOptionsUserActivityTypeKey] isEqual:NSUserActivityTypeBrowsingWeb]) { initialURL = ((NSUserActivity *)userActivityDictionary[@"UIApplicationLaunchOptionsUserActivityKey"]).webpageURL; } From 5db3081fd0f6b41e1aa31115e54a9c8da405ddb1 Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Thu, 22 Oct 2026 12:35:19 -0700 Subject: [PATCH 2/2] Drop RCTBridge from RCTPerfMonitor (#59258) Summary: Route JS-thread dispatch through the injected dispatchToJSThread block and read the injected performanceLogger. Delete the Views counter, which can only show zero since RCTViewRegistry exposes no enumeration, and reflow the HUD bar. Changelog: [iOS][Removed] - Remove the non-functional Views counter from the PerfMonitor HUD Reviewed By: shwanton Differential Revision: D126567926 --- .../React/CoreModules/RCTPerfMonitor.mm | 66 +++++++------------ 1 file changed, 23 insertions(+), 43 deletions(-) diff --git a/packages/react-native/React/CoreModules/RCTPerfMonitor.mm b/packages/react-native/React/CoreModules/RCTPerfMonitor.mm index c33af88055a0..2bb27c1eaebf 100644 --- a/packages/react-native/React/CoreModules/RCTPerfMonitor.mm +++ b/packages/react-native/React/CoreModules/RCTPerfMonitor.mm @@ -17,8 +17,8 @@ #import -#import -#import +#import +#import #import #import #import @@ -58,8 +58,13 @@ static vm_size_t RCTGetResidentMemorySize(void) return memoryUsageInByte; } -@interface RCTPerfMonitor - : NSObject +@interface RCTPerfMonitor : NSObject < + RCTBridgeModule, + RCTTurboModule, + RCTInvalidating, + RCTJSDispatcherModule, + UITableViewDataSource, + UITableViewDelegate> #if __has_include() @property (nonatomic, strong, readonly) RCTDevMenuItem *devMenuItem; @@ -68,7 +73,6 @@ @interface RCTPerfMonitor @property (nonatomic, strong, readonly) UIView *container; @property (nonatomic, strong, readonly) UILabel *memory; @property (nonatomic, strong, readonly) UILabel *heap; -@property (nonatomic, strong, readonly) UILabel *views; @property (nonatomic, strong, readonly) UITableView *metrics; @property (nonatomic, strong, readonly) RCTFPSGraph *jsGraph; @property (nonatomic, strong, readonly) RCTFPSGraph *uiGraph; @@ -85,7 +89,6 @@ @implementation RCTPerfMonitor { UIView *_container; UILabel *_memory; UILabel *_heap; - UILabel *_views; UILabel *_uiGraphLabel; UILabel *_jsGraphLabel; UITableView *_metrics; @@ -109,8 +112,9 @@ @implementation RCTPerfMonitor { NSArray *_perfLoggerMarks; } -@synthesize bridge = _bridge; +@synthesize dispatchToJSThread = _dispatchToJSThread; @synthesize moduleRegistry = _moduleRegistry; +@synthesize performanceLogger = _performanceLogger; RCT_EXPORT_MODULE() @@ -172,7 +176,7 @@ - (UIView *)container UIEdgeInsets safeInsets = RCTKeyWindow().safeAreaInsets; _container = - [[UIView alloc] initWithFrame:CGRectMake(safeInsets.left, safeInsets.top, 180, RCTPerfMonitorBarHeight)]; + [[UIView alloc] initWithFrame:CGRectMake(safeInsets.left, safeInsets.top, 136, RCTPerfMonitorBarHeight)]; _container.layer.borderWidth = 2; _container.layer.borderColor = [UIColor lightGrayColor].CGColor; [_container addGestureRecognizer:self.gestureRecognizer]; @@ -212,22 +216,10 @@ - (UILabel *)heap return _heap; } -- (UILabel *)views -{ - if (_views == nullptr) { - _views = [[UILabel alloc] initWithFrame:CGRectMake(88, 0, 44, RCTPerfMonitorBarHeight)]; - _views.font = [UIFont systemFontOfSize:12]; - _views.numberOfLines = 3; - _views.textAlignment = NSTextAlignmentCenter; - } - - return _views; -} - - (RCTFPSGraph *)uiGraph { if (_uiGraph == nullptr) { - _uiGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(134, 14, 40, 30) color:[UIColor lightGrayColor]]; + _uiGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(90, 14, 40, 30) color:[UIColor lightGrayColor]]; } return _uiGraph; } @@ -235,7 +227,7 @@ - (RCTFPSGraph *)uiGraph - (RCTFPSGraph *)jsGraph { if (_jsGraph == nullptr) { - _jsGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(178, 14, 40, 30) color:[UIColor lightGrayColor]]; + _jsGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(134, 14, 40, 30) color:[UIColor lightGrayColor]]; } return _jsGraph; } @@ -243,7 +235,7 @@ - (RCTFPSGraph *)jsGraph - (UILabel *)uiGraphLabel { if (_uiGraphLabel == nullptr) { - _uiGraphLabel = [[UILabel alloc] initWithFrame:CGRectMake(134, 3, 40, 10)]; + _uiGraphLabel = [[UILabel alloc] initWithFrame:CGRectMake(90, 3, 40, 10)]; _uiGraphLabel.font = [UIFont systemFontOfSize:11]; _uiGraphLabel.textAlignment = NSTextAlignmentCenter; _uiGraphLabel.text = @"UI"; @@ -255,7 +247,7 @@ - (UILabel *)uiGraphLabel - (UILabel *)jsGraphLabel { if (_jsGraphLabel == nullptr) { - _jsGraphLabel = [[UILabel alloc] initWithFrame:CGRectMake(178, 3, 38, 10)]; + _jsGraphLabel = [[UILabel alloc] initWithFrame:CGRectMake(134, 3, 38, 10)]; _jsGraphLabel.font = [UIFont systemFontOfSize:11]; _jsGraphLabel.textAlignment = NSTextAlignmentCenter; _jsGraphLabel.text = @"JS"; @@ -289,7 +281,6 @@ - (void)show [self.container addSubview:self.memory]; [self.container addSubview:self.heap]; - [self.container addSubview:self.views]; [self.container addSubview:self.uiGraph]; [self.container addSubview:self.uiGraphLabel]; @@ -309,12 +300,12 @@ - (void)show [self.container addSubview:self.jsGraph]; [self.container addSubview:self.jsGraphLabel]; - [_bridge - dispatchBlock:^{ - self->_jsDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(threadUpdate:)]; - [self->_jsDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; - } - queue:RCTJSThread]; + if (_dispatchToJSThread != nullptr) { + _dispatchToJSThread(^{ + self->_jsDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(threadUpdate:)]; + [self->_jsDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; + }); + } } - (void)hide @@ -415,15 +406,6 @@ - (void)parse:(NSString *)log - (void)updateStats { - NSDictionary *views = [_bridge.uiManager valueForKey:@"viewRegistry"]; - NSUInteger viewCount = views.count; - NSUInteger visibleViewCount = 0; - for (UIView *view in views.allValues) { - if ((view.window != nullptr) || (view.superview.window != nullptr)) { - visibleViewCount++; - } - } - // Ensure the container always stays on top of newly added views if ([_container.superview.subviews lastObject] != _container) { [_container.superview bringSubviewToFront:_container]; @@ -432,8 +414,6 @@ - (void)updateStats double mem = (double)RCTGetResidentMemorySize() / 1024 / 1024; self.memory.text = [NSString stringWithFormat:@"RAM\n%.2lf\nMB", mem]; self.heap.text = [NSString stringWithFormat:@"JSC\n%.2lf\nMB", (double)_heapSize / 1024]; - self.views.text = - [NSString stringWithFormat:@"Views\n%lu\n%lu", (unsigned long)visibleViewCount, (unsigned long)viewCount]; __weak __typeof__(self) weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ @@ -481,7 +461,7 @@ - (void)loadPerformanceLoggerData { NSUInteger i = 0; NSMutableArray *data = [NSMutableArray new]; - RCTPerformanceLogger *performanceLogger = [_bridge performanceLogger]; + RCTPerformanceLogger *performanceLogger = _performanceLogger; NSArray *values = [performanceLogger valuesForTags]; for (NSString *label in LabelsForRCTPerformanceLoggerTags()) { long long value = values[i + 1].longLongValue - values[i].longLongValue;