diff --git a/React/Base/RCTBatchedBridge.m b/React/Base/RCTBatchedBridge.m index 3493efac3..9f30f4040 100644 --- a/React/Base/RCTBatchedBridge.m +++ b/React/Base/RCTBatchedBridge.m @@ -61,6 +61,7 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void); @synthesize flowID = _flowID; @synthesize flowIDMap = _flowIDMap; +@synthesize flowIDMapLock = _flowIDMapLock; @synthesize loading = _loading; @synthesize valid = _valid; @@ -885,10 +886,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR @autoreleasepool { for (NSNumber *indexObj in calls) { NSUInteger index = indexObj.unsignedIntegerValue; - if (callID != -1 && _flowIDMap != NULL) { + if (RCT_DEV && callID != -1 && _flowIDMap != NULL && RCTProfileIsProfiling()) { + [self.flowIDMapLock lock]; int64_t newFlowID = (int64_t)CFDictionaryGetValue(_flowIDMap, (const void *)(_flowID + index)); _RCTProfileEndFlowEvent(@(newFlowID)); CFDictionaryRemoveValue(_flowIDMap, (const void *)(_flowID + index)); + [self.flowIDMapLock unlock]; } [self _handleRequestNumber:index moduleID:[moduleIDs[index] integerValue] diff --git a/React/Base/RCTBridge+Private.h b/React/Base/RCTBridge+Private.h index 19f33c1a3..8f093262c 100644 --- a/React/Base/RCTBridge+Private.h +++ b/React/Base/RCTBridge+Private.h @@ -16,6 +16,7 @@ // Used for the profiler flow events between JS and native @property (nonatomic, assign) int64_t flowID; @property (nonatomic, assign) CFMutableDictionaryRef flowIDMap; +@property (nonatomic, strong) NSLock *flowIDMapLock; + (instancetype)currentBridge; + (void)setCurrentBridge:(RCTBridge *)bridge; diff --git a/React/Executors/RCTJSCExecutor.m b/React/Executors/RCTJSCExecutor.m index 8bb5446d7..720990dbb 100644 --- a/React/Executors/RCTJSCExecutor.m +++ b/React/Executors/RCTJSCExecutor.m @@ -302,17 +302,26 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context) __weak RCTBridge *weakBridge = _bridge; #ifndef __clang_analyzer__ - weakBridge.flowIDMap = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + _bridge.flowIDMap = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); #endif + _bridge.flowIDMapLock = [NSLock new]; [self addSynchronousHookWithName:@"nativeTraceBeginAsyncFlow" usingBlock:^(__unused uint64_t tag, __unused NSString *name, int64_t cookie) { - int64_t newCookie = [_RCTProfileBeginFlowEvent() longLongValue]; - CFDictionarySetValue(weakBridge.flowIDMap, (const void *)cookie, (const void *)newCookie); + if (RCTProfileIsProfiling()) { + [weakBridge.flowIDMapLock lock]; + int64_t newCookie = [_RCTProfileBeginFlowEvent() longLongValue]; + CFDictionarySetValue(weakBridge.flowIDMap, (const void *)cookie, (const void *)newCookie); + [weakBridge.flowIDMapLock unlock]; + } }]; [self addSynchronousHookWithName:@"nativeTraceEndAsyncFlow" usingBlock:^(__unused uint64_t tag, __unused NSString *name, int64_t cookie) { - int64_t newCookie = (int64_t)CFDictionaryGetValue(weakBridge.flowIDMap, (const void *)cookie); - _RCTProfileEndFlowEvent(@(newCookie)); - CFDictionaryRemoveValue(weakBridge.flowIDMap, (const void *)cookie); + if (RCTProfileIsProfiling()) { + [weakBridge.flowIDMapLock lock]; + int64_t newCookie = (int64_t)CFDictionaryGetValue(weakBridge.flowIDMap, (const void *)cookie); + _RCTProfileEndFlowEvent(@(newCookie)); + CFDictionaryRemoveValue(weakBridge.flowIDMap, (const void *)cookie); + [weakBridge.flowIDMapLock unlock]; + } }]; [self executeBlockOnJavaScriptQueue:^{