Skip to content

Commit e588a71

Browse files
authored
Fix race condition in iOS React Native module init (#83)
* Lock in whenInitialized * Change back setCurrentView to not be within lock scope * Fix errors
1 parent b5441f7 commit e588a71

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

Modules/@babylonjs/react-native/EngineView.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export const EngineView: FunctionComponent<EngineViewProps> = (props: EngineView
117117
snapshotPromise.current = { promise: promise, resolve: resolveFunction };
118118
}
119119
else {
120-
throw "Resolution functions not initialized after snapshot promise creation.";
120+
throw new Error("Resolution functions not initialized after snapshot promise creation.");
121121
}
122122

123123
UIManager.dispatchViewManagerCommand(
@@ -149,9 +149,14 @@ export const EngineView: FunctionComponent<EngineViewProps> = (props: EngineView
149149
</View>
150150
);
151151
} else {
152+
const message = "Could not initialize Babylon Native.";
153+
if (!__DEV__) {
154+
throw new Error(message);
155+
}
156+
152157
return (
153158
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
154-
<Text style={{fontSize: 24}}>Could not initialize Babylon Native.</Text>
159+
<Text style={{fontSize: 24}}>{message}</Text>
155160
{ isRemoteDebuggingEnabled && <Text style={{fontSize: 12}}>React Native remote debugging does not work with Babylon Native.</Text> }
156161
</View>
157162
);

Modules/@babylonjs/react-native/ios/BabylonNativeInterop.mm

+12-8
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ + (void)setView:(RCTBridge*)bridge jsRunLoop:(NSRunLoop*)jsRunLoop mktView:(MTKV
4343

4444
[jsRunLoop performBlock:^{
4545
if (bridge != currentBridge) {
46-
currentBridge = bridge;
47-
[BabylonNativeInterop setCurrentNativeInstance:mtkView width:width height:height];
46+
[BabylonNativeInterop setCurrentNativeInstance:bridge mtkView:mtkView width:width height:height];
4847
} else if (currentNativeInstance) {
4948
if (mtkView != currentView) {
5049
[BabylonNativeInterop setCurrentView:mtkView];
@@ -104,6 +103,7 @@ + (void)reportTouchEvent:(NSSet<UITouch*>*)touches withEvent:(UIEvent*)event {
104103
}
105104

106105
+ (void)whenInitialized:(RCTBridge*)bridge resolve:(RCTPromiseResolveBlock)resolve {
106+
const std::lock_guard<std::mutex> lock(mapMutex);
107107
if (bridge == currentBridge) {
108108
resolve([NSNumber numberWithUnsignedLong:reinterpret_cast<uintptr_t>(currentNativeInstance.get())]);
109109
} else {
@@ -116,16 +116,20 @@ + (void)setCurrentView:(MTKView*)mtkView {
116116
activeTouches = [NSMutableArray new];
117117
}
118118

119-
+ (void)setCurrentNativeInstance:(MTKView*)mtkView width:(int)width height:(int)height {
119+
+ (void)setCurrentNativeInstance:(RCTBridge*)bridge mtkView:(MTKView*)mtkView width:(int)width height:(int)height {
120120
[BabylonNativeInterop setCurrentView:mtkView];
121121

122-
const std::lock_guard<std::mutex> lock(mapMutex);
122+
{
123+
const std::lock_guard<std::mutex> lock(mapMutex);
123124

124-
currentNativeInstance.reset();
125+
currentBridge = bridge;
125126

126-
jsi::Runtime* jsiRuntime = GetJSIRuntime(currentBridge);
127-
if (jsiRuntime) {
128-
currentNativeInstance = std::make_unique<Babylon::Native>(GetJSIRuntime(currentBridge), (__bridge void*)mtkView, width, height);
127+
currentNativeInstance.reset();
128+
129+
jsi::Runtime* jsiRuntime = GetJSIRuntime(currentBridge);
130+
if (jsiRuntime) {
131+
currentNativeInstance = std::make_unique<Babylon::Native>(GetJSIRuntime(currentBridge), (__bridge void*)mtkView, width, height);
132+
}
129133
}
130134

131135
auto initializationPromisesIterator = initializationPromises.find((__bridge void*)currentBridge);

0 commit comments

Comments
 (0)