diff --git a/ReactNative/RealmReact.mm b/ReactNative/RealmReact.mm index 574c917e..7d688741 100644 --- a/ReactNative/RealmReact.mm +++ b/ReactNative/RealmReact.mm @@ -58,13 +58,18 @@ JSGlobalContextRef RealmReactGetJSGlobalContextForExecutor(id executor, bool cre @end static std::mutex s_rpcMutex; -static __weak RealmReact *s_currentRealmModule = nil; #endif -@interface RealmReact () +@interface RealmReact () { + __weak NSThread *_currentJSThread; + __weak NSRunLoop *_currentJSRunLoop; +} @end +static __weak RealmReact *s_currentRealmModule = nil; + + @implementation RealmReact @synthesize bridge = _bridge; @@ -140,24 +145,41 @@ static __weak RealmReact *s_currentRealmModule = nil; _rpcServer.reset(); } -- (void)dealloc { - [self shutdownRPC]; -} + #endif +- (void)shutdown { + // block until JS thread exits + NSRunLoop *runLoop = _currentJSRunLoop; + if (runLoop) { + CFRunLoopStop([_currentJSRunLoop getCFRunLoop]); + while (_currentJSThread && !_currentJSThread.finished) { + [[NSRunLoop currentRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; + } + } + +#if DEBUG + // shutdown rpc if in chrome debug mode + [self shutdownRPC]; +#endif +} + +- (void)dealloc { + [self shutdown]; +} + - (void)setBridge:(RCTBridge *)bridge { _bridge = bridge; - + + // shutdown the last instance of this module + [s_currentRealmModule shutdown]; + s_currentRealmModule = self; + Ivar executorIvar = class_getInstanceVariable([bridge class], "_javaScriptExecutor"); id executor = object_getIvar(bridge, executorIvar); bool isDebugExecutor = [executor isMemberOfClass:NSClassFromString(@"RCTWebSocketExecutor")]; #if DEBUG - if (s_currentRealmModule) { - [s_currentRealmModule shutdownRPC]; - } - - s_currentRealmModule = self; if (isDebugExecutor) { [self startRPC]; return; @@ -169,6 +191,8 @@ static __weak RealmReact *s_currentRealmModule = nil; } [executor executeBlockOnJavaScriptQueue:^{ + _currentJSThread = [NSThread currentThread]; + _currentJSRunLoop = [NSRunLoop currentRunLoop]; JSGlobalContextRef ctx = RealmReactGetJSGlobalContextForExecutor(executor, true); RJSInitializeInContext(ctx); }]; diff --git a/src/object-store/shared_realm.cpp b/src/object-store/shared_realm.cpp index 09b4d188..d95b8bd2 100644 --- a/src/object-store/shared_realm.cpp +++ b/src/object-store/shared_realm.cpp @@ -287,8 +287,6 @@ void Realm::cancel_transaction() void Realm::invalidate() { verify_thread(); - check_read_write(this); - if (m_in_transaction) { cancel_transaction(); } @@ -384,6 +382,10 @@ void Realm::close() m_notifier->remove_realm(this); } + if (m_group) { + m_shared_group->end_read(); + } + m_group = nullptr; m_shared_group = nullptr; m_history = nullptr; diff --git a/src/object-store/shared_realm.hpp b/src/object-store/shared_realm.hpp index 81b14bf7..09685128 100644 --- a/src/object-store/shared_realm.hpp +++ b/src/object-store/shared_realm.hpp @@ -197,6 +197,12 @@ namespace realm { public: UnitializedRealmException(std::string message) : std::runtime_error(message) {} }; + + class ClosedRealmException : public std::runtime_error + { + public: + ClosedRealmException(std::string message) : std::runtime_error(message) {} + }; } #endif /* defined(REALM_REALM_HPP) */